From c457ab7bee35457a2ecc1536beed49ad6f033bb7 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 9 Sep 2025 08:24:23 -0400 Subject: [PATCH 001/297] initial push --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6a2224907..4120ea8f93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ All notable changes to `dash` will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). +## [bringyourownserver] +- [#3430] Adds support to bring your own server, eg (Quart, FastAPI, etc). + ## [UNRELEASED] ## Added From 4ebc657a49e6440d9977bc08c1afcc8916945230 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 9 Sep 2025 15:00:32 -0400 Subject: [PATCH 002/297] work to modularize the dash eco-system and decouple from Flask --- dash/_callback.py | 19 +- dash/dash.py | 257 ++++++----------------- dash/server_factories/__init__.py | 10 + dash/server_factories/base_factory.py | 47 +++++ dash/server_factories/fastapi_factory.py | 226 ++++++++++++++++++++ dash/server_factories/flask_factory.py | 188 +++++++++++++++++ 6 files changed, 550 insertions(+), 197 deletions(-) create mode 100644 dash/server_factories/__init__.py create mode 100644 dash/server_factories/base_factory.py create mode 100644 dash/server_factories/fastapi_factory.py create mode 100644 dash/server_factories/flask_factory.py diff --git a/dash/_callback.py b/dash/_callback.py index aacb8dbdde..bca8027fdd 100644 --- a/dash/_callback.py +++ b/dash/_callback.py @@ -6,7 +6,7 @@ import asyncio -import flask +from dash.server_factories import get_request_adapter from .dependencies import ( handle_callback_args, @@ -376,7 +376,7 @@ def _get_callback_manager( " and store results on redis.\n" ) - old_job = flask.request.args.getlist("oldJob") + old_job = get_request_adapter().get_args().getlist("oldJob") if old_job: for job in old_job: @@ -436,7 +436,7 @@ def _setup_background_callback( def _progress_background_callback(response, callback_manager, background): progress_outputs = background.get("progress") - cache_key = flask.request.args.get("cacheKey") + cache_key = get_request_adapter().get_args().get("cacheKey") if progress_outputs: # Get the progress before the result as it would be erased after the results. @@ -453,8 +453,8 @@ def _update_background_callback( """Set up the background callback and manage jobs.""" callback_manager = _get_callback_manager(kwargs, background) - cache_key = flask.request.args.get("cacheKey") - job_id = flask.request.args.get("job") + cache_key = get_request_adapter().get_args().get("cacheKey") + job_id = get_request_adapter().get_args().get("job") _progress_background_callback(response, callback_manager, background) @@ -474,8 +474,8 @@ def _handle_rest_background_callback( multi, has_update=False, ): - cache_key = flask.request.args.get("cacheKey") - job_id = flask.request.args.get("job") + cache_key = get_request_adapter().get_args().get("cacheKey") + job_id = get_request_adapter().get_args().get("job") # Must get job_running after get_result since get_results terminates it. job_running = callback_manager.job_running(job_id) if not job_running and output_value is callback_manager.UNDEFINED: @@ -688,11 +688,10 @@ def add_context(*args, **kwargs): ) response: dict = {"multi": True} - jsonResponse = None try: if background is not None: - if not flask.request.args.get("cacheKey"): + if not get_request_adapter().get_args().get("cacheKey"): return _setup_background_callback( kwargs, background, @@ -763,7 +762,7 @@ async def async_add_context(*args, **kwargs): try: if background is not None: - if not flask.request.args.get("cacheKey"): + if not get_request_adapter().get_args().get("cacheKey"): return _setup_background_callback( kwargs, background, diff --git a/dash/dash.py b/dash/dash.py index 8430259c27..56bf65c9e6 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -17,6 +17,7 @@ import hashlib import base64 import traceback +import inspect from urllib.parse import urlparse from typing import Any, Callable, Dict, Optional, Union, Sequence, Literal, List @@ -67,6 +68,8 @@ from . import _validate from . import _watch from . import _get_app +from .server_factories.flask_factory import FlaskServerFactory +from .server_factories.base_factory import BaseServerFactory from ._get_app import with_app_context, with_app_context_async, with_app_context_factory from ._grouping import map_grouping, grouping_len, update_args_group @@ -421,7 +424,7 @@ class Dash(ObsoleteChecker): _plotlyjs_url: str STARTUP_ROUTES: list = [] - server: flask.Flask + server: Any # Layout is a complex type which can be many things _layout: Any @@ -430,7 +433,7 @@ class Dash(ObsoleteChecker): def __init__( # pylint: disable=too-many-statements self, name: Optional[str] = None, - server: Union[bool, flask.Flask] = True, + server: Union[bool, Callable[[], Any]] = True, assets_folder: str = "assets", pages_folder: str = "pages", use_pages: Optional[bool] = None, @@ -466,6 +469,7 @@ def __init__( # pylint: disable=too-many-statements description: Optional[str] = None, on_error: Optional[Callable[[Exception], Any]] = None, use_async: Optional[bool] = None, + server_factory: Optional[BaseServerFactory] = None, **obsolete, ): @@ -488,16 +492,23 @@ def __init__( # pylint: disable=too-many-statements caller_name: str = name if name is not None else get_caller_name() + self.server_factory = server_factory or FlaskServerFactory() + # We have 3 cases: server is either True (we create the server), False # (defer server creation) or a Flask app instance (we use their server) - if isinstance(server, flask.Flask): + if callable(server) and not (hasattr(server, 'route') and hasattr(server, 'run')): + # Server factory function + self.server = server() + if name is None: + caller_name = getattr(self.server, "name", caller_name) + elif hasattr(server, 'route') and hasattr(server, 'run'): self.server = server if name is None: caller_name = getattr(server, "name", caller_name) elif isinstance(server, bool): - self.server = flask.Flask(caller_name) if server else None # type: ignore + self.server = self.server_factory.create_app(caller_name) if server else None else: - raise ValueError("server must be a Flask app or a boolean") + raise ValueError("server must be a Flask app, a boolean, or a server factory function") base_prefix, routes_prefix, requests_prefix = pathname_configs( url_base_pathname, routes_pathname_prefix, requests_pathname_prefix @@ -671,11 +682,8 @@ def _setup_hooks(self): if self._hooks.get_hooks("error"): self._on_error = self._hooks.HookErrorHandler(self._on_error) - def init_app(self, app: Optional[flask.Flask] = None, **kwargs) -> None: - """Initialize the parts of Dash that require a flask app.""" - + def init_app(self, app: Optional[Any] = None, **kwargs) -> None: config = self.config - config.update(kwargs) config.set_read_only( [ @@ -685,89 +693,58 @@ def init_app(self, app: Optional[flask.Flask] = None, **kwargs) -> None: ], "Read-only: can only be set in the Dash constructor or during init_app()", ) - if app is not None: self.server = app - bp_prefix = config.routes_pathname_prefix.replace("/", "_").replace(".", "_") assets_blueprint_name = f"{bp_prefix}dash_assets" - - self.server.register_blueprint( - flask.Blueprint( - assets_blueprint_name, - config.name, - static_folder=self.config.assets_folder, - static_url_path=config.routes_pathname_prefix - + self.config.assets_url_path.lstrip("/"), - ) + self.server_factory.register_assets_blueprint( + self.server, + assets_blueprint_name, + config.routes_pathname_prefix + self.config.assets_url_path.lstrip("/"), + self.config.assets_folder, ) - if config.compress: try: - # pylint: disable=import-outside-toplevel - from flask_compress import Compress # type: ignore[reportMissingImports] - - # gzip + from flask_compress import Compress Compress(self.server) - _flask_compress_version = parse_version( _get_distribution_version("flask_compress") ) - if not hasattr( self.server.config, "COMPRESS_ALGORITHM" ) and _flask_compress_version >= parse_version("1.6.0"): - # flask-compress==1.6.0 changed default to ['br', 'gzip'] - # and non-overridable default compression with Brotli is - # causing performance issues self.server.config["COMPRESS_ALGORITHM"] = ["gzip"] except ImportError as error: raise ImportError( "To use the compress option, you need to install dash[compress]" ) from error - - @self.server.errorhandler(PreventUpdate) - def _handle_error(_): - """Handle a halted callback and return an empty 204 response.""" - return "", 204 - - self.server.before_request(self._setup_server) - - # add a handler for components suites errors to return 404 - self.server.errorhandler(InvalidResourceError)(self._invalid_resources_handler) - + self.server_factory.register_error_handlers(self.server) + self.server_factory.before_request(self.server, self._setup_server) self._setup_routes() - _get_app.APP = self self.enable_pages() - self._setup_plotlyjs() def _add_url(self, name: str, view_func: RouteCallable, methods=("GET",)) -> None: full_name = self.config.routes_pathname_prefix + name - - self.server.add_url_rule( - full_name, view_func=view_func, endpoint=full_name, methods=list(methods) + self.server_factory.add_url_rule( + self.server, + full_name, + view_func=view_func, + endpoint=full_name, + methods=list(methods), ) - - # record the url in Dash.routes so that it can be accessed later - # e.g. for adding authentication with flask_login self.routes.append(full_name) def _setup_routes(self): - self._add_url( - "_dash-component-suites//", - self.serve_component_suites, - ) + self.server_factory.setup_component_suites(self.server, self) self._add_url("_dash-layout", self.serve_layout) self._add_url("_dash-dependencies", self.dependencies) - if self._use_async: - self._add_url("_dash-update-component", self.async_dispatch, ["POST"]) - else: - self._add_url("_dash-update-component", self.dispatch, ["POST"]) + self._add_url("_dash-update-component", self.server_factory.dispatch(self.server, self, self._use_async), ["POST"]) self._add_url("_reload-hash", self.serve_reload_hash) - self._add_url("_favicon.ico", self._serve_default_favicon) - self._add_url("", self.index) + self._add_url("_favicon.ico", self.server_factory._serve_default_favicon) + self.server_factory.setup_index(self.server, self) + self.server_factory.setup_catchall(self.server, self) if jupyter_dash.active: self._add_url( @@ -781,8 +758,6 @@ def _setup_routes(self): hook.data["methods"], ) - # catch-all for front-end routes, used by dcc.Location - self._add_url("", self.index) def setup_apis(self): """ @@ -902,7 +877,7 @@ def serve_layout(self): layout = hook(layout) # TODO - Set browser cache limit - pass hash into frontend - return flask.Response( + return self.server_factory.make_response( to_json(layout), mimetype="application/json", ) @@ -966,7 +941,7 @@ def serve_reload_hash(self): _reload.hard = False _reload.changed_assets = [] - return flask.jsonify( + return self.server_factory.jsonify( { "reloadHash": _hash, "hard": hard, @@ -1159,54 +1134,12 @@ def _generate_meta(self): return meta_tags + self.config.meta_tags - # Serve the JS bundles for each package - def serve_component_suites(self, package_name, fingerprinted_path): - path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) - - _validate.validate_js_path(self.registered_paths, package_name, path_in_pkg) - - extension = "." + path_in_pkg.split(".")[-1] - mimetype = mimetypes.types_map.get(extension, "application/octet-stream") - - package = sys.modules[package_name] - self.logger.debug( - "serving -- package: %s[%s] resource: %s => location: %s", - package_name, - package.__version__, - path_in_pkg, - package.__path__, - ) - - response = flask.Response( - pkgutil.get_data(package_name, path_in_pkg), mimetype=mimetype - ) - - if has_fingerprint: - # Fingerprinted resources are good forever (1 year) - # No need for ETag as the fingerprint changes with each build - response.cache_control.max_age = 31536000 # 1 year - else: - # Non-fingerprinted resources are given an ETag that - # will be used / check on future requests - response.add_etag() - tag = response.get_etag()[0] - - request_etag = flask.request.headers.get("If-None-Match") - - if f'"{tag}"' == request_etag: - response = flask.Response(None, status=304) - - return response - - @with_app_context - def index(self, *args, **kwargs): # pylint: disable=unused-argument + def render_index(self, *args, **kwargs): scripts = self._generate_scripts_html() css = self._generate_css_dist_html() config = self._generate_config_html() metas = self._generate_meta() renderer = self._generate_renderer() - - # use self.title instead of app.config.title for backwards compatibility title = self.title if self.use_pages and self.config.include_pages_meta: @@ -1314,7 +1247,7 @@ def interpolate_index(self, **kwargs): @with_app_context def dependencies(self): - return flask.Response( + return self.server_factory.make_response( to_json(self._callback_list), content_type="application/json", ) @@ -1417,8 +1350,11 @@ def callback(self, *_args, **_kwargs) -> Callable[..., Any]: **_kwargs, ) + def _inputs_to_vals(self, inputs): + return inputs_to_vals(inputs) + # pylint: disable=R0915 - def _initialize_context(self, body): + def _initialize_context(self, body, adapter): """Initialize the global context for the request.""" g = AttributeDict({}) g.inputs_list = body.get("inputs", []) @@ -1430,12 +1366,12 @@ def _initialize_context(self, body): {"prop_id": x, "value": g.input_values.get(x)} for x in body.get("changedPropIds", []) ] - g.dash_response = flask.Response(mimetype="application/json") - g.cookies = dict(**flask.request.cookies) - g.headers = dict(**flask.request.headers) - g.path = flask.request.full_path - g.remote = flask.request.remote_addr - g.origin = flask.request.origin + g.dash_response = self.server_factory.make_response(mimetype="application/json", data=None) + g.cookies = dict(adapter.get_cookies()) + g.headers = dict(adapter.get_headers()) + g.path = adapter.get_full_path() + g.remote = adapter.get_remote_addr() + g.origin = adapter.get_origin() g.updated_props = {} return g @@ -1499,11 +1435,6 @@ def _prepare_grouping(self, data_list, indices): def _execute_callback(self, func, args, outputs_list, g): """Execute the callback with the prepared arguments.""" - g.cookies = dict(**flask.request.cookies) - g.headers = dict(**flask.request.headers) - g.path = flask.request.full_path - g.remote = flask.request.remote_addr - g.origin = flask.request.origin g.custom_data = AttributeDict({}) for hook in self._hooks.get_hooks("custom_data"): @@ -1522,47 +1453,6 @@ def _execute_callback(self, func, args, outputs_list, g): ) return partial_func - @with_app_context_async - async def async_dispatch(self): - body = flask.request.get_json() - g = self._initialize_context(body) - func = self._prepare_callback(g, body) - args = inputs_to_vals(g.inputs_list + g.states_list) - - ctx = copy_context() - partial_func = self._execute_callback(func, args, g.outputs_list, g) - if asyncio.iscoroutine(func): - response_data = await ctx.run(partial_func) - else: - response_data = ctx.run(partial_func) - - if asyncio.iscoroutine(response_data): - response_data = await response_data - - g.dash_response.set_data(response_data) - return g.dash_response - - @with_app_context - def dispatch(self): - body = flask.request.get_json() - g = self._initialize_context(body) - func = self._prepare_callback(g, body) - args = inputs_to_vals(g.inputs_list + g.states_list) - - ctx = copy_context() - partial_func = self._execute_callback(func, args, g.outputs_list, g) - response_data = ctx.run(partial_func) - - if asyncio.iscoroutine(response_data): - raise Exception( - "You are trying to use a coroutine without dash[async]. " - "Please install the dependencies via `pip install dash[async]` and ensure " - "that `use_async=False` is not being passed to the app." - ) - - g.dash_response.set_data(response_data) - return g.dash_response - def _setup_server(self): if self._got_first_request["setup_server"]: return @@ -1695,12 +1585,6 @@ def _walk_assets_directory(self): def _invalid_resources_handler(err): return err.args[0], 404 - @staticmethod - def _serve_default_favicon(): - return flask.Response( - pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" - ) - def csp_hashes(self, hash_algorithm="sha256") -> Sequence[str]: """Calculates CSP hashes (sha + base64) of all inline scripts, such that one of the biggest benefits of CSP (disallowing general inline scripts) @@ -2112,14 +1996,19 @@ def enable_dev_tools( elif dev_tools.prune_errors: secret = gen_salt(20) - @self.server.errorhandler(Exception) - def _wrap_errors(error): - # find the callback invocation, if the error is from a callback - # and skip the traceback up to that point - # if the error didn't come from inside a callback, we won't - # skip anything. - tb = _get_traceback(secret, error) - return tb, 500 + if hasattr(self.server, "errorhandler"): + # Flask + @self.server.errorhandler(Exception) + def _wrap_errors(error): + tb = _get_traceback(secret, error) + return tb, 500 + elif hasattr(self.server, "exception_handler"): + # FastAPI + @self.server.exception_handler(Exception) + async def _wrap_errors(request, error): + tb = _get_traceback(secret, error) + from fastapi.responses import PlainTextResponse + return PlainTextResponse(tb, status_code=500) if debug and dev_tools.ui: @@ -2149,9 +2038,8 @@ def _after_request(response): return response - self.server.before_request(_before_request) - - self.server.after_request(_after_request) + self.server_factory.before_request(self.server, _before_request) + self.server_factory.after_request(self.server, _after_request) if ( debug @@ -2435,7 +2323,7 @@ def verify_url_part(served_part, url_part, part_name): server_url=jupyter_server_url, ) else: - self.server.run(host=host, port=port, debug=debug, **flask_run_options) + self.server_factory.run(self.server, host=host, port=port, debug=debug, **flask_run_options) def enable_pages(self) -> None: if not self.use_pages: @@ -2495,7 +2383,7 @@ async def update(pathname_, search_, **states): ) if callable(title): title = await execute_async_function( - title, **(path_variables or {}) + title, **{**(path_variables or {})} ) return layout, {"title": title} @@ -2559,7 +2447,7 @@ def update(pathname_, search_, **states): **{**(path_variables or {}), **query_parameters, **states} ) if callable(title): - title = title(**(path_variables or {})) + title = title(**{**(path_variables or {})}) return layout, {"title": title} @@ -2599,10 +2487,5 @@ def update(pathname_, search_, **states): Input(_ID_STORE, "data"), ) - def __call__(self, environ, start_response): - """ - This method makes instances of Dash WSGI-compliant callables. - It delegates the actual WSGI handling to the internal Flask app's - __call__ method. - """ - return self.server(environ, start_response) + def __call__(self, *args, **kwargs): + return self.server_factory.__call__(self.server, *args, **kwargs) diff --git a/dash/server_factories/__init__.py b/dash/server_factories/__init__.py new file mode 100644 index 0000000000..7d9874ec7a --- /dev/null +++ b/dash/server_factories/__init__.py @@ -0,0 +1,10 @@ +# python +import contextvars + +_request_adapter_var = contextvars.ContextVar("request_adapter") + +def set_request_adapter(adapter): + _request_adapter_var.set(adapter) + +def get_request_adapter(): + return _request_adapter_var.get() diff --git a/dash/server_factories/base_factory.py b/dash/server_factories/base_factory.py new file mode 100644 index 0000000000..f429357e03 --- /dev/null +++ b/dash/server_factories/base_factory.py @@ -0,0 +1,47 @@ +from abc import ABC, abstractmethod + +class BaseServerFactory(ABC): + def __call__(self, server, *args, **kwargs): + # Default: WSGI + return server(*args, **kwargs) + + @abstractmethod + def create_app(self, name="__main__", config=None): + pass + + @abstractmethod + def register_assets_blueprint(self, app, blueprint_name, assets_url_path, assets_folder): + pass + + @abstractmethod + def register_error_handlers(self, app): + pass + + @abstractmethod + def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): + pass + + @abstractmethod + def before_request(self, app, func): + pass + + @abstractmethod + def after_request(self, app, func): + pass + + @abstractmethod + def run(self, app, host, port, debug, **kwargs): + pass + + @abstractmethod + def make_response(self, data, mimetype=None, content_type=None): + pass + + @abstractmethod + def jsonify(self, obj): + pass + + @abstractmethod + def get_request_adapter(self): + pass + diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py new file mode 100644 index 0000000000..7592a51ce3 --- /dev/null +++ b/dash/server_factories/fastapi_factory.py @@ -0,0 +1,226 @@ +import traceback + +from fastapi import FastAPI, Request, Response, APIRouter +from fastapi.responses import JSONResponse +from dash.exceptions import PreventUpdate, InvalidResourceError +from dash.server_factories import set_request_adapter, get_request_adapter +from .base_factory import BaseServerFactory +import inspect +import pkgutil +from contextvars import copy_context + +class FastAPIServerFactory(BaseServerFactory): + def __call__(self, server, *args, **kwargs): + # ASGI: (scope, receive, send) + if ( + len(args) == 3 + and isinstance(args[0], dict) + and "type" in args[0] + ): + return server(*args, **kwargs) + raise TypeError("FastAPI app must be called with (scope, receive, send)") + + + def create_app(self, name="__main__", config=None): + app = FastAPI() + if config: + for key, value in config.items(): + setattr(app.state, key, value) + return app + + def register_assets_blueprint(self, app, blueprint_name, assets_url_path, assets_folder): + from fastapi.staticfiles import StaticFiles + try: + app.mount(assets_url_path, StaticFiles(directory=assets_folder), name=blueprint_name) + except RuntimeError: + # directory doesnt exist + pass + + def register_error_handlers(self, app): + @app.exception_handler(PreventUpdate) + async def _handle_error(request: Request, exc: PreventUpdate): + return Response(status_code=204) + + @app.exception_handler(InvalidResourceError) + async def _invalid_resources_handler(request: Request, exc: InvalidResourceError): + return Response(content=exc.args[0], status_code=404) + + def _html_response_wrapper(self, view_func): + async def wrapped(*args, **kwargs): + # If view_func is a function, call it; if it's a string, use it directly + html = view_func() if callable(view_func) else view_func + return Response(content=html, media_type="text/html") + + return wrapped + + def setup_index(self, app, dash_app): + async def index(): + return Response(content=dash_app.render_index(), media_type="text/html") + self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) + + def setup_catchall(self, app, dash_app): + async def catchall(path: str): + return Response(content=dash_app.render_index(), media_type="text/html") + + # self.add_url_rule(app, "/{path:path}", catchall, endpoint="catchall", methods=["GET"]) + + def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): + if rule == "": + rule = "/" + if isinstance(view_func, str): + # Wrap string or sync function to async FastAPI handler + view_func = self._html_response_wrapper(view_func) + app.add_api_route(rule, view_func, methods=methods or ["GET"], name=endpoint, include_in_schema=False) + + def before_request(self, app, func): + # FastAPI does not have before_request, but we can use middleware + app.middleware("http")(self._make_before_middleware(func)) + + def after_request(self, app, func): + # FastAPI does not have after_request, but we can use middleware + app.middleware("http")(self._make_after_middleware(func)) + + def run(self, app, host, port, debug, **kwargs): + import uvicorn + reload = debug + if reload: + # Assume app is created in 'main.py' as 'app' + # Adjust 'main:app' as needed for your project structure + uvicorn.run("app:app", host=host, port=port, reload=reload, **kwargs) + else: + uvicorn.run(app, host=host, port=port, reload=reload, **kwargs) + + def make_response(self, data, mimetype=None, content_type=None): + headers = {} + if mimetype: + headers["content-type"] = mimetype + if content_type: + headers["content-type"] = content_type + return Response(content=data, headers=headers) + + def jsonify(self, obj): + return JSONResponse(content=obj) + + def get_request_adapter(self): + return FastAPIRequestAdapter + + def _make_before_middleware(self, func): + pass + async def middleware(request, call_next): + if func is not None: + if inspect.iscoroutinefunction(func): + await func() + else: + func() + response = await call_next(request) + return response + + return middleware + + def _make_after_middleware(self, func): + pass + async def middleware(request, call_next): + response = await call_next(request) + await func() + return response + return middleware + + def serve_component_suites(self, dash_app, package_name, fingerprinted_path, request): + import sys + import mimetypes + import pkgutil + from dash.fingerprint import check_fingerprint + from dash import _validate + + path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) + _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) + extension = "." + path_in_pkg.split(".")[-1] + mimetype = mimetypes.types_map.get(extension, "application/octet-stream") + package = sys.modules[package_name] + dash_app.logger.debug( + "serving -- package: %s[%s] resource: %s => location: %s", + package_name, + package.__version__, + path_in_pkg, + package.__path__, + ) + data = pkgutil.get_data(package_name, path_in_pkg) + from starlette.responses import Response as StarletteResponse + headers = {} + if has_fingerprint: + headers["Cache-Control"] = "public, max-age=31536000" + return StarletteResponse(content=data, media_type=mimetype, headers=headers) + else: + import hashlib + etag = hashlib.md5(data).hexdigest() if data else "" + headers["ETag"] = etag + if request.headers.get("if-none-match") == etag: + return StarletteResponse(status_code=304) + return StarletteResponse(content=data, media_type=mimetype, headers=headers) + + def setup_component_suites(self, app, dash_app): + from fastapi import Request + async def serve(request: Request, package_name: str, fingerprinted_path: str): + return self.serve_component_suites(dash_app, package_name, fingerprinted_path, request) + + self.add_url_rule( + app, + "/_dash-component-suites/{package_name}/{fingerprinted_path:path}", + serve, + ) + + def dispatch(self, app, dash_app, use_async): + async def _dispatch(request: Request): + adapter = FastAPIRequestAdapter() + set_request_adapter(adapter) + adapter.set_request(request) + body = await request.json() + g = dash_app._initialize_context(body, adapter) + func = dash_app._prepare_callback(g, body) + args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) + ctx = copy_context() + partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) + response_data = ctx.run(partial_func) + if inspect.iscoroutine(response_data): + response_data = await response_data + # Instead of set_data, return a new Response + return Response(content=response_data, media_type="application/json") + + return _dispatch + + def _serve_default_favicon(self): + return Response( + content=pkgutil.get_data("dash", "favicon.ico"), + media_type="image/x-icon" + ) + +class FastAPIRequestAdapter: + def __init__(self): + self._request = None + + def set_request(self, request: Request): + self._request = request + + def get_args(self): + return self._request.query_params + + async def get_json(self): + return await self._request.json() + + def is_json(self): + return self._request.headers.get("content-type", "").startswith("application/json") + + def get_cookies(self, request=None): + return self._request.cookies + + def get_headers(self): + return self._request.headers + + def get_full_path(self): + return str(self._request.url) + + def get_remote_addr(self): + return self._request.client.host if self._request.client else None + + def get_origin(self): + return self._request.headers.get("origin") diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py new file mode 100644 index 0000000000..82b6b266a8 --- /dev/null +++ b/dash/server_factories/flask_factory.py @@ -0,0 +1,188 @@ +import flask +from dash.exceptions import PreventUpdate, InvalidResourceError +from dash.server_factories import set_request_adapter, get_request_adapter +from .base_factory import BaseServerFactory +from contextvars import copy_context +import asyncio +import pkgutil + +class FlaskServerFactory(BaseServerFactory): + def __call__(self, server, *args, **kwargs): + # Always WSGI + return server(*args, **kwargs) + + def create_app(self, name="__main__", config=None): + app = flask.Flask(name) + if config: + app.config.update(config) + return app + + def register_assets_blueprint(self, app, blueprint_name, assets_url_path, assets_folder): + bp = flask.Blueprint( + blueprint_name, + __name__, + static_folder=assets_folder, + static_url_path=assets_url_path, + ) + app.register_blueprint(bp) + + def register_error_handlers(self, app): + @app.errorhandler(PreventUpdate) + def _handle_error(_): + return "", 204 + + @app.errorhandler(InvalidResourceError) + def _invalid_resources_handler(err): + return err.args[0], 404 + + def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): + app.add_url_rule(rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"]) + + def before_request(self, app, func): + app.before_request(func) + + def after_request(self, app, func): + app.after_request(func) + + def run(self, app, host, port, debug, **kwargs): + app.run(host=host, port=port, debug=debug, **kwargs) + + def make_response(self, data, mimetype=None, content_type=None): + return flask.Response(data, mimetype=mimetype, content_type=content_type) + + def jsonify(self, obj): + return flask.jsonify(obj) + + def get_request_adapter(self): + return FlaskRequestAdapter + + def setup_catchall(self, app, dash_app): + def catchall(path, *args, **kwargs): + return dash_app.index(*args, **kwargs) + self.add_url_rule(app, "/", catchall, endpoint="catchall", methods=["GET"]) + + def setup_index(self, app, dash_app): + def index(*args, **kwargs): + return dash_app.render_index(dash_app, *args, **kwargs) + + self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) + + def serve_component_suites(self, dash_app, package_name, fingerprinted_path, request=None): + import sys + import mimetypes + import pkgutil + from dash.fingerprint import check_fingerprint + from dash import _validate + import flask + + path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) + _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) + extension = "." + path_in_pkg.split(".")[-1] + mimetype = mimetypes.types_map.get(extension, "application/octet-stream") + package = sys.modules[package_name] + dash_app.logger.debug( + "serving -- package: %s[%s] resource: %s => location: %s", + package_name, + package.__version__, + path_in_pkg, + package.__path__, + ) + data = pkgutil.get_data(package_name, path_in_pkg) + response = flask.Response(data, mimetype=mimetype) + if has_fingerprint: + response.cache_control.max_age = 31536000 # 1 year + else: + response.add_etag() + tag = response.get_etag()[0] + request_etag = flask.request.headers.get("If-None-Match") + if f'"{tag}"' == request_etag: + response = flask.Response(None, status=304) + return response + + def setup_component_suites(self, app, dash_app): + def serve(package_name, fingerprinted_path): + return self.serve_component_suites(dash_app, package_name, fingerprinted_path, flask.request) + + self.add_url_rule( + app, + "/_dash-component-suites//", + serve, + ) + + def dispatch(self, app, dash_app, use_async=False): + def _dispatch(): + adapter = FlaskRequestAdapter() + set_request_adapter(adapter) + body = flask.request.get_json() + g = dash_app._initialize_context(body, adapter) + func = dash_app._prepare_callback(g, body) + args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) + ctx = copy_context() + partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) + response_data = ctx.run(partial_func) + if asyncio.iscoroutine(response_data): + raise Exception( + "You are trying to use a coroutine without dash[async]. " + "Please install the dependencies via `pip install dash[async]` and ensure " + "that `use_async=False` is not being passed to the app." + ) + g.dash_response.set_data(response_data) + return g.dash_response + + async def _dispatch_async(): + adapter = FlaskRequestAdapter() + set_request_adapter(adapter) + body = flask.request.get_json() + g = dash_app._initialize_context(body, adapter) + func = dash_app._prepare_callback(g, body) + args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) + ctx = copy_context() + partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) + response_data = ctx.run(partial_func) + if asyncio.iscoroutine(response_data): + response_data = await response_data + g.dash_response.set_data(response_data) + return g.dash_response + + if use_async: + _dispatch = _dispatch_async + return _dispatch + + def _serve_default_favicon(): + import flask + return flask.Response( + pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" + ) + +class FlaskRequestAdapter: + @staticmethod + def get_args(): + return flask.request.args + + @staticmethod + def get_json(): + return flask.request.get_json() + + @staticmethod + def is_json(): + return flask.request.is_json + + @staticmethod + def get_cookies(): + return flask.request.cookies + + @staticmethod + def get_headers(): + return flask.request.headers + + @staticmethod + def get_full_path(): + return flask.request.full_path + + @staticmethod + def get_remote_addr(): + return flask.request.remote_addr + + @staticmethod + def get_origin(): + return getattr(flask.request, 'origin', None) From 9dff79140b93e65b2076e61ff821bc324a936f00 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 9 Sep 2025 15:28:31 -0400 Subject: [PATCH 003/297] fix favicon --- dash/server_factories/flask_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index 82b6b266a8..bdcc6aef87 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -148,7 +148,7 @@ async def _dispatch_async(): _dispatch = _dispatch_async return _dispatch - def _serve_default_favicon(): + def _serve_default_favicon(self): import flask return flask.Response( pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" From c319b18a18044bbbf1c2081731feeafbeff5fd2a Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 9 Sep 2025 15:29:37 -0400 Subject: [PATCH 004/297] removing changelog entry --- CHANGELOG.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4120ea8f93..a6a2224907 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,6 @@ All notable changes to `dash` will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). -## [bringyourownserver] -- [#3430] Adds support to bring your own server, eg (Quart, FastAPI, etc). - ## [UNRELEASED] ## Added From 7de2a41017a37ee54a7a2d6219cb4211e71b3a11 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 9 Sep 2025 15:51:45 -0400 Subject: [PATCH 005/297] fixing issue with debug true for FastAPI --- dash/server_factories/fastapi_factory.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py index 7592a51ce3..f893e61bc6 100644 --- a/dash/server_factories/fastapi_factory.py +++ b/dash/server_factories/fastapi_factory.py @@ -8,6 +8,7 @@ import inspect import pkgutil from contextvars import copy_context +import importlib.util class FastAPIServerFactory(BaseServerFactory): def __call__(self, server, *args, **kwargs): @@ -81,12 +82,15 @@ def after_request(self, app, func): app.middleware("http")(self._make_after_middleware(func)) def run(self, app, host, port, debug, **kwargs): + frame = inspect.stack()[2] import uvicorn + reload = debug if reload: - # Assume app is created in 'main.py' as 'app' - # Adjust 'main:app' as needed for your project structure - uvicorn.run("app:app", host=host, port=port, reload=reload, **kwargs) + # Dynamically determine the module name from the file path + file_path = frame.filename + module_name = importlib.util.spec_from_file_location("app", file_path).name + uvicorn.run(f"{module_name}:app.server", host=host, port=port, reload=reload, **kwargs) else: uvicorn.run(app, host=host, port=port, reload=reload, **kwargs) From 2cd769e51f2050aedcfd030feb3a2c4bed09938e Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 9 Sep 2025 16:04:10 -0400 Subject: [PATCH 006/297] fixing `catchall` for path routes --- dash/server_factories/flask_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index bdcc6aef87..4748fa317e 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -58,7 +58,7 @@ def get_request_adapter(self): def setup_catchall(self, app, dash_app): def catchall(path, *args, **kwargs): - return dash_app.index(*args, **kwargs) + return dash_app.render_index(*args, **kwargs) self.add_url_rule(app, "/", catchall, endpoint="catchall", methods=["GET"]) def setup_index(self, app, dash_app): From 686f32f64e45904ab13059dbf1b352df28a02601 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 9 Sep 2025 16:37:30 -0400 Subject: [PATCH 007/297] fixing pages for use with `fastapi` --- dash/_pages.py | 10 +++++----- dash/dash.py | 7 +++++-- dash/server_factories/fastapi_factory.py | 23 +++++++++++++++++++---- dash/server_factories/flask_factory.py | 10 ++++++++++ 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/dash/_pages.py b/dash/_pages.py index 45538546e8..b1cd0cbe69 100644 --- a/dash/_pages.py +++ b/dash/_pages.py @@ -389,15 +389,15 @@ def _path_to_page(path_id): return {}, None -def _page_meta_tags(app): - start_page, path_variables = _path_to_page(flask.request.path.strip("/")) +def _page_meta_tags(app, request): + request_url = request.get_path() + start_page, path_variables = _path_to_page(request_url.strip("/")) - # use the supplied image_url or create url based on image in the assets folder image = start_page.get("image", "") if image: image = app.get_asset_url(image) assets_image_url = ( - "".join([flask.request.url_root, image.lstrip("/")]) if image else None + "".join([request.url_root, image.lstrip("/")]) if image else None ) supplied_image_url = start_page.get("image_url") image_url = supplied_image_url if supplied_image_url else assets_image_url @@ -413,7 +413,7 @@ def _page_meta_tags(app): return [ {"name": "description", "content": description}, {"property": "twitter:card", "content": "summary_large_image"}, - {"property": "twitter:url", "content": flask.request.url}, + {"property": "twitter:url", "content": request_url}, {"property": "twitter:title", "content": title}, {"property": "twitter:description", "content": description}, {"property": "twitter:image", "content": image_url or ""}, diff --git a/dash/dash.py b/dash/dash.py index 56bf65c9e6..18fe56acca 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -44,6 +44,7 @@ ProxyError, DuplicateCallback, ) +from .server_factories import get_request_adapter from .version import __version__ from ._configs import get_combined_config, pathname_configs, pages_folder_config from ._utils import ( @@ -1141,9 +1142,10 @@ def render_index(self, *args, **kwargs): metas = self._generate_meta() renderer = self._generate_renderer() title = self.title + request = get_request_adapter() if self.use_pages and self.config.include_pages_meta: - metas = _page_meta_tags(self) + metas + metas = _page_meta_tags(self, request) + metas if self._favicon: favicon_mod_time = os.path.getmtime( @@ -2331,7 +2333,7 @@ def enable_pages(self) -> None: if self.pages_folder: _import_layouts_from_pages(self.config.pages_folder) - @self.server.before_request + def router(): if self._got_first_request["pages"]: return @@ -2487,5 +2489,6 @@ def update(pathname_, search_, **states): Input(_ID_STORE, "data"), ) + self.server_factory.before_request(self.server, router) def __call__(self, *args, **kwargs): return self.server_factory.__call__(self.server, *args, **kwargs) diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py index f893e61bc6..aa4ff5d523 100644 --- a/dash/server_factories/fastapi_factory.py +++ b/dash/server_factories/fastapi_factory.py @@ -55,15 +55,27 @@ async def wrapped(*args, **kwargs): return wrapped def setup_index(self, app, dash_app): - async def index(): + async def index(request: Request): + adapter = FastAPIRequestAdapter() + set_request_adapter(adapter) + adapter.set_request(request) return Response(content=dash_app.render_index(), media_type="text/html") self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) def setup_catchall(self, app, dash_app): - async def catchall(path: str): - return Response(content=dash_app.render_index(), media_type="text/html") + @dash_app.server.on_event("startup") + def _setup_catchall(): + from fastapi import Request, Response - # self.add_url_rule(app, "/{path:path}", catchall, endpoint="catchall", methods=["GET"]) + async def catchall(path: str, request: Request): + adapter = FastAPIRequestAdapter() + set_request_adapter(adapter) + adapter.set_request(request) + return Response(content=dash_app.render_index(), media_type="text/html") + + self.add_url_rule(app, "/{path:path}", catchall, endpoint="catchall", methods=["GET"]) + + pass # catchall needs to be last to not override other routes def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): if rule == "": @@ -228,3 +240,6 @@ def get_remote_addr(self): def get_origin(self): return self._request.headers.get("origin") + + def get_path(self): + return self._request.url.path # <-- Add this method diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index 4748fa317e..1c748e01ed 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -58,11 +58,17 @@ def get_request_adapter(self): def setup_catchall(self, app, dash_app): def catchall(path, *args, **kwargs): + adapter = FlaskRequestAdapter() + set_request_adapter(adapter) + adapter.set_request(flask.request) return dash_app.render_index(*args, **kwargs) self.add_url_rule(app, "/", catchall, endpoint="catchall", methods=["GET"]) def setup_index(self, app, dash_app): def index(*args, **kwargs): + adapter = FlaskRequestAdapter() + set_request_adapter(adapter) + adapter.set_request(flask.request) return dash_app.render_index(dash_app, *args, **kwargs) self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) @@ -186,3 +192,7 @@ def get_remote_addr(): @staticmethod def get_origin(): return getattr(flask.request, 'origin', None) + + @staticmethod + def get_path(): + return flask.request.path From 660e257604bc5e95681e6b7d495830c5ed5686ac Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Wed, 10 Sep 2025 10:04:52 -0400 Subject: [PATCH 008/297] fixing issue with flask pages --- dash/server_factories/flask_factory.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index 1c748e01ed..9bc7929685 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -60,7 +60,6 @@ def setup_catchall(self, app, dash_app): def catchall(path, *args, **kwargs): adapter = FlaskRequestAdapter() set_request_adapter(adapter) - adapter.set_request(flask.request) return dash_app.render_index(*args, **kwargs) self.add_url_rule(app, "/", catchall, endpoint="catchall", methods=["GET"]) @@ -68,7 +67,6 @@ def setup_index(self, app, dash_app): def index(*args, **kwargs): adapter = FlaskRequestAdapter() set_request_adapter(adapter) - adapter.set_request(flask.request) return dash_app.render_index(dash_app, *args, **kwargs) self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) From 0fa5c99de789f9161be40bfe72c05e4140906281 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 11 Sep 2025 10:20:21 -0400 Subject: [PATCH 009/297] fixing for lint --- dash/_pages.py | 4 +- dash/dash.py | 34 ++++++++---- dash/server_factories/__init__.py | 2 + dash/server_factories/base_factory.py | 6 ++- dash/server_factories/fastapi_factory.py | 68 +++++++++++++++++------- dash/server_factories/flask_factory.py | 26 ++++++--- 6 files changed, 102 insertions(+), 38 deletions(-) diff --git a/dash/_pages.py b/dash/_pages.py index b1cd0cbe69..2a3a116324 100644 --- a/dash/_pages.py +++ b/dash/_pages.py @@ -396,9 +396,7 @@ def _page_meta_tags(app, request): image = start_page.get("image", "") if image: image = app.get_asset_url(image) - assets_image_url = ( - "".join([request.url_root, image.lstrip("/")]) if image else None - ) + assets_image_url = "".join([request.url_root, image.lstrip("/")]) if image else None supplied_image_url = start_page.get("image_url") image_url = supplied_image_url if supplied_image_url else assets_image_url diff --git a/dash/dash.py b/dash/dash.py index 18fe56acca..f6f6e76e01 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -497,19 +497,25 @@ def __init__( # pylint: disable=too-many-statements # We have 3 cases: server is either True (we create the server), False # (defer server creation) or a Flask app instance (we use their server) - if callable(server) and not (hasattr(server, 'route') and hasattr(server, 'run')): + if callable(server) and not ( + hasattr(server, "route") and hasattr(server, "run") + ): # Server factory function self.server = server() if name is None: caller_name = getattr(self.server, "name", caller_name) - elif hasattr(server, 'route') and hasattr(server, 'run'): + elif hasattr(server, "route") and hasattr(server, "run"): self.server = server if name is None: caller_name = getattr(server, "name", caller_name) elif isinstance(server, bool): - self.server = self.server_factory.create_app(caller_name) if server else None + self.server = ( + self.server_factory.create_app(caller_name) if server else None + ) else: - raise ValueError("server must be a Flask app, a boolean, or a server factory function") + raise ValueError( + "server must be a Flask app, a boolean, or a server factory function" + ) base_prefix, routes_prefix, requests_prefix = pathname_configs( url_base_pathname, routes_pathname_prefix, requests_pathname_prefix @@ -707,6 +713,7 @@ def init_app(self, app: Optional[Any] = None, **kwargs) -> None: if config.compress: try: from flask_compress import Compress + Compress(self.server) _flask_compress_version = parse_version( _get_distribution_version("flask_compress") @@ -741,7 +748,11 @@ def _setup_routes(self): self.server_factory.setup_component_suites(self.server, self) self._add_url("_dash-layout", self.serve_layout) self._add_url("_dash-dependencies", self.dependencies) - self._add_url("_dash-update-component", self.server_factory.dispatch(self.server, self, self._use_async), ["POST"]) + self._add_url( + "_dash-update-component", + self.server_factory.dispatch(self.server, self, self._use_async), + ["POST"], + ) self._add_url("_reload-hash", self.serve_reload_hash) self._add_url("_favicon.ico", self.server_factory._serve_default_favicon) self.server_factory.setup_index(self.server, self) @@ -759,7 +770,6 @@ def _setup_routes(self): hook.data["methods"], ) - def setup_apis(self): """ Register API endpoints for all callbacks defined using `dash.callback`. @@ -1368,7 +1378,9 @@ def _initialize_context(self, body, adapter): {"prop_id": x, "value": g.input_values.get(x)} for x in body.get("changedPropIds", []) ] - g.dash_response = self.server_factory.make_response(mimetype="application/json", data=None) + g.dash_response = self.server_factory.make_response( + mimetype="application/json", data=None + ) g.cookies = dict(adapter.get_cookies()) g.headers = dict(adapter.get_headers()) g.path = adapter.get_full_path() @@ -2004,12 +2016,14 @@ def enable_dev_tools( def _wrap_errors(error): tb = _get_traceback(secret, error) return tb, 500 + elif hasattr(self.server, "exception_handler"): # FastAPI @self.server.exception_handler(Exception) async def _wrap_errors(request, error): tb = _get_traceback(secret, error) from fastapi.responses import PlainTextResponse + return PlainTextResponse(tb, status_code=500) if debug and dev_tools.ui: @@ -2325,7 +2339,9 @@ def verify_url_part(served_part, url_part, part_name): server_url=jupyter_server_url, ) else: - self.server_factory.run(self.server, host=host, port=port, debug=debug, **flask_run_options) + self.server_factory.run( + self.server, host=host, port=port, debug=debug, **flask_run_options + ) def enable_pages(self) -> None: if not self.use_pages: @@ -2333,7 +2349,6 @@ def enable_pages(self) -> None: if self.pages_folder: _import_layouts_from_pages(self.config.pages_folder) - def router(): if self._got_first_request["pages"]: return @@ -2490,5 +2505,6 @@ def update(pathname_, search_, **states): ) self.server_factory.before_request(self.server, router) + def __call__(self, *args, **kwargs): return self.server_factory.__call__(self.server, *args, **kwargs) diff --git a/dash/server_factories/__init__.py b/dash/server_factories/__init__.py index 7d9874ec7a..1bfd497935 100644 --- a/dash/server_factories/__init__.py +++ b/dash/server_factories/__init__.py @@ -3,8 +3,10 @@ _request_adapter_var = contextvars.ContextVar("request_adapter") + def set_request_adapter(adapter): _request_adapter_var.set(adapter) + def get_request_adapter(): return _request_adapter_var.get() diff --git a/dash/server_factories/base_factory.py b/dash/server_factories/base_factory.py index f429357e03..b44f6888cb 100644 --- a/dash/server_factories/base_factory.py +++ b/dash/server_factories/base_factory.py @@ -1,5 +1,6 @@ from abc import ABC, abstractmethod + class BaseServerFactory(ABC): def __call__(self, server, *args, **kwargs): # Default: WSGI @@ -10,7 +11,9 @@ def create_app(self, name="__main__", config=None): pass @abstractmethod - def register_assets_blueprint(self, app, blueprint_name, assets_url_path, assets_folder): + def register_assets_blueprint( + self, app, blueprint_name, assets_url_path, assets_folder + ): pass @abstractmethod @@ -44,4 +47,3 @@ def jsonify(self, obj): @abstractmethod def get_request_adapter(self): pass - diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py index aa4ff5d523..8d9efb2416 100644 --- a/dash/server_factories/fastapi_factory.py +++ b/dash/server_factories/fastapi_factory.py @@ -10,18 +10,14 @@ from contextvars import copy_context import importlib.util + class FastAPIServerFactory(BaseServerFactory): def __call__(self, server, *args, **kwargs): # ASGI: (scope, receive, send) - if ( - len(args) == 3 - and isinstance(args[0], dict) - and "type" in args[0] - ): + if len(args) == 3 and isinstance(args[0], dict) and "type" in args[0]: return server(*args, **kwargs) raise TypeError("FastAPI app must be called with (scope, receive, send)") - def create_app(self, name="__main__", config=None): app = FastAPI() if config: @@ -29,10 +25,17 @@ def create_app(self, name="__main__", config=None): setattr(app.state, key, value) return app - def register_assets_blueprint(self, app, blueprint_name, assets_url_path, assets_folder): + def register_assets_blueprint( + self, app, blueprint_name, assets_url_path, assets_folder + ): from fastapi.staticfiles import StaticFiles + try: - app.mount(assets_url_path, StaticFiles(directory=assets_folder), name=blueprint_name) + app.mount( + assets_url_path, + StaticFiles(directory=assets_folder), + name=blueprint_name, + ) except RuntimeError: # directory doesnt exist pass @@ -43,7 +46,9 @@ async def _handle_error(request: Request, exc: PreventUpdate): return Response(status_code=204) @app.exception_handler(InvalidResourceError) - async def _invalid_resources_handler(request: Request, exc: InvalidResourceError): + async def _invalid_resources_handler( + request: Request, exc: InvalidResourceError + ): return Response(content=exc.args[0], status_code=404) def _html_response_wrapper(self, view_func): @@ -60,6 +65,7 @@ async def index(request: Request): set_request_adapter(adapter) adapter.set_request(request) return Response(content=dash_app.render_index(), media_type="text/html") + self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) def setup_catchall(self, app, dash_app): @@ -73,9 +79,11 @@ async def catchall(path: str, request: Request): adapter.set_request(request) return Response(content=dash_app.render_index(), media_type="text/html") - self.add_url_rule(app, "/{path:path}", catchall, endpoint="catchall", methods=["GET"]) + self.add_url_rule( + app, "/{path:path}", catchall, endpoint="catchall", methods=["GET"] + ) - pass # catchall needs to be last to not override other routes + pass # catchall needs to be last to not override other routes def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): if rule == "": @@ -83,7 +91,13 @@ def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): if isinstance(view_func, str): # Wrap string or sync function to async FastAPI handler view_func = self._html_response_wrapper(view_func) - app.add_api_route(rule, view_func, methods=methods or ["GET"], name=endpoint, include_in_schema=False) + app.add_api_route( + rule, + view_func, + methods=methods or ["GET"], + name=endpoint, + include_in_schema=False, + ) def before_request(self, app, func): # FastAPI does not have before_request, but we can use middleware @@ -102,7 +116,13 @@ def run(self, app, host, port, debug, **kwargs): # Dynamically determine the module name from the file path file_path = frame.filename module_name = importlib.util.spec_from_file_location("app", file_path).name - uvicorn.run(f"{module_name}:app.server", host=host, port=port, reload=reload, **kwargs) + uvicorn.run( + f"{module_name}:app.server", + host=host, + port=port, + reload=reload, + **kwargs, + ) else: uvicorn.run(app, host=host, port=port, reload=reload, **kwargs) @@ -122,6 +142,7 @@ def get_request_adapter(self): def _make_before_middleware(self, func): pass + async def middleware(request, call_next): if func is not None: if inspect.iscoroutinefunction(func): @@ -135,13 +156,17 @@ async def middleware(request, call_next): def _make_after_middleware(self, func): pass + async def middleware(request, call_next): response = await call_next(request) await func() return response + return middleware - def serve_component_suites(self, dash_app, package_name, fingerprinted_path, request): + def serve_component_suites( + self, dash_app, package_name, fingerprinted_path, request + ): import sys import mimetypes import pkgutil @@ -162,12 +187,14 @@ def serve_component_suites(self, dash_app, package_name, fingerprinted_path, req ) data = pkgutil.get_data(package_name, path_in_pkg) from starlette.responses import Response as StarletteResponse + headers = {} if has_fingerprint: headers["Cache-Control"] = "public, max-age=31536000" return StarletteResponse(content=data, media_type=mimetype, headers=headers) else: import hashlib + etag = hashlib.md5(data).hexdigest() if data else "" headers["ETag"] = etag if request.headers.get("if-none-match") == etag: @@ -176,8 +203,11 @@ def serve_component_suites(self, dash_app, package_name, fingerprinted_path, req def setup_component_suites(self, app, dash_app): from fastapi import Request + async def serve(request: Request, package_name: str, fingerprinted_path: str): - return self.serve_component_suites(dash_app, package_name, fingerprinted_path, request) + return self.serve_component_suites( + dash_app, package_name, fingerprinted_path, request + ) self.add_url_rule( app, @@ -206,10 +236,10 @@ async def _dispatch(request: Request): def _serve_default_favicon(self): return Response( - content=pkgutil.get_data("dash", "favicon.ico"), - media_type="image/x-icon" + content=pkgutil.get_data("dash", "favicon.ico"), media_type="image/x-icon" ) + class FastAPIRequestAdapter: def __init__(self): self._request = None @@ -224,7 +254,9 @@ async def get_json(self): return await self._request.json() def is_json(self): - return self._request.headers.get("content-type", "").startswith("application/json") + return self._request.headers.get("content-type", "").startswith( + "application/json" + ) def get_cookies(self, request=None): return self._request.cookies diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index 9bc7929685..5eaaf44a36 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -6,6 +6,7 @@ import asyncio import pkgutil + class FlaskServerFactory(BaseServerFactory): def __call__(self, server, *args, **kwargs): # Always WSGI @@ -17,7 +18,9 @@ def create_app(self, name="__main__", config=None): app.config.update(config) return app - def register_assets_blueprint(self, app, blueprint_name, assets_url_path, assets_folder): + def register_assets_blueprint( + self, app, blueprint_name, assets_url_path, assets_folder + ): bp = flask.Blueprint( blueprint_name, __name__, @@ -36,7 +39,9 @@ def _invalid_resources_handler(err): return err.args[0], 404 def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): - app.add_url_rule(rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"]) + app.add_url_rule( + rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"] + ) def before_request(self, app, func): app.before_request(func) @@ -61,7 +66,10 @@ def catchall(path, *args, **kwargs): adapter = FlaskRequestAdapter() set_request_adapter(adapter) return dash_app.render_index(*args, **kwargs) - self.add_url_rule(app, "/", catchall, endpoint="catchall", methods=["GET"]) + + self.add_url_rule( + app, "/", catchall, endpoint="catchall", methods=["GET"] + ) def setup_index(self, app, dash_app): def index(*args, **kwargs): @@ -71,7 +79,9 @@ def index(*args, **kwargs): self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) - def serve_component_suites(self, dash_app, package_name, fingerprinted_path, request=None): + def serve_component_suites( + self, dash_app, package_name, fingerprinted_path, request=None + ): import sys import mimetypes import pkgutil @@ -105,7 +115,9 @@ def serve_component_suites(self, dash_app, package_name, fingerprinted_path, req def setup_component_suites(self, app, dash_app): def serve(package_name, fingerprinted_path): - return self.serve_component_suites(dash_app, package_name, fingerprinted_path, flask.request) + return self.serve_component_suites( + dash_app, package_name, fingerprinted_path, flask.request + ) self.add_url_rule( app, @@ -154,10 +166,12 @@ async def _dispatch_async(): def _serve_default_favicon(self): import flask + return flask.Response( pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" ) + class FlaskRequestAdapter: @staticmethod def get_args(): @@ -189,7 +203,7 @@ def get_remote_addr(): @staticmethod def get_origin(): - return getattr(flask.request, 'origin', None) + return getattr(flask.request, "origin", None) @staticmethod def get_path(): From 1088331323380bd58c27f3776d21d4e4132bfd3d Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 11 Sep 2025 13:33:16 -0400 Subject: [PATCH 010/297] fixing issue with failing test due to `endpoint` name --- dash/server_factories/flask_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index 5eaaf44a36..69173516b2 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -77,7 +77,7 @@ def index(*args, **kwargs): set_request_adapter(adapter) return dash_app.render_index(dash_app, *args, **kwargs) - self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) + self.add_url_rule(app, "/", index, endpoint="/", methods=["GET"]) def serve_component_suites( self, dash_app, package_name, fingerprinted_path, request=None From 4920e33cf68651bebc699f72f6da1e8eadbf925e Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 11 Sep 2025 13:33:43 -0400 Subject: [PATCH 011/297] fixing `run` command to trigger `devtools` properly --- dash/server_factories/fastapi_factory.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py index 8d9efb2416..1fa07a6ac6 100644 --- a/dash/server_factories/fastapi_factory.py +++ b/dash/server_factories/fastapi_factory.py @@ -12,6 +12,10 @@ class FastAPIServerFactory(BaseServerFactory): + def __init__(self): + self.config = {} + super().__init__() + def __call__(self, server, *args, **kwargs): # ASGI: (scope, receive, send) if len(args) == 3 and isinstance(args[0], dict) and "type" in args[0]: @@ -71,6 +75,7 @@ async def index(request: Request): def setup_catchall(self, app, dash_app): @dash_app.server.on_event("startup") def _setup_catchall(): + dash_app.enable_dev_tools(**self.config) # do this to make sure dev tools are enabled from fastapi import Request, Response async def catchall(path: str, request: Request): @@ -111,6 +116,9 @@ def run(self, app, host, port, debug, **kwargs): frame = inspect.stack()[2] import uvicorn + self.config = dict({'debug': debug} if debug else {}, **kwargs) + + reload = debug if reload: # Dynamically determine the module name from the file path From 9ffba5a58652cc7b28d253e46662ad8cbe0fb8bd Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 11 Sep 2025 14:51:02 -0400 Subject: [PATCH 012/297] fixing issue with lint and debug ui --- dash/dash.py | 69 +++--------- dash/server_factories/fastapi_factory.py | 136 ++++++++++++++--------- dash/server_factories/flask_factory.py | 68 ++++++++---- 3 files changed, 144 insertions(+), 129 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index f6f6e76e01..2151f31f77 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -4,7 +4,6 @@ import collections import importlib import warnings -from contextvars import copy_context from importlib.machinery import ModuleSpec from importlib.util import find_spec from importlib import metadata @@ -12,12 +11,10 @@ import threading import re import logging -import time import mimetypes import hashlib import base64 import traceback -import inspect from urllib.parse import urlparse from typing import Any, Callable, Dict, Optional, Union, Sequence, Literal, List @@ -30,7 +27,7 @@ from dash import html from dash import dash_table -from .fingerprint import build_fingerprint, check_fingerprint +from .fingerprint import build_fingerprint from .resources import Scripts, Css from .dependencies import ( Input, @@ -39,8 +36,6 @@ ) from .development.base_component import ComponentRegistry from .exceptions import ( - PreventUpdate, - InvalidResourceError, ProxyError, DuplicateCallback, ) @@ -72,7 +67,7 @@ from .server_factories.flask_factory import FlaskServerFactory from .server_factories.base_factory import BaseServerFactory -from ._get_app import with_app_context, with_app_context_async, with_app_context_factory +from ._get_app import with_app_context, with_app_context_factory from ._grouping import map_grouping, grouping_len, update_args_group from ._obsolete import ObsoleteChecker @@ -712,8 +707,9 @@ def init_app(self, app: Optional[Any] = None, **kwargs) -> None: ) if config.compress: try: - from flask_compress import Compress + import flask_compress # pylint: disable=import-outside-toplevel + Compress = flask_compress.Compress Compress(self.server) _flask_compress_version = parse_version( _get_distribution_version("flask_compress") @@ -754,7 +750,10 @@ def _setup_routes(self): ["POST"], ) self._add_url("_reload-hash", self.serve_reload_hash) - self._add_url("_favicon.ico", self.server_factory._serve_default_favicon) + self._add_url( + "_favicon.ico", + self.server_factory._serve_default_favicon, # pylint: disable=protected-access + ) self.server_factory.setup_index(self.server, self) self.server_factory.setup_catchall(self.server, self) @@ -1145,7 +1144,7 @@ def _generate_meta(self): return meta_tags + self.config.meta_tags - def render_index(self, *args, **kwargs): + def render_index(self, *_args, **_kwargs): scripts = self._generate_scripts_html() css = self._generate_css_dist_html() config = self._generate_config_html() @@ -1845,6 +1844,7 @@ def enable_dev_tools( dev_tools_silence_routes_logging: Optional[bool] = None, dev_tools_disable_version_check: Optional[bool] = None, dev_tools_prune_errors: Optional[bool] = None, + first_run: bool = True, ) -> bool: """Activate the dev tools, called by `run`. If your application is served by wsgi and you want to activate the dev tools, you can call @@ -2009,53 +2009,12 @@ def enable_dev_tools( ) elif dev_tools.prune_errors: secret = gen_salt(20) - - if hasattr(self.server, "errorhandler"): - # Flask - @self.server.errorhandler(Exception) - def _wrap_errors(error): - tb = _get_traceback(secret, error) - return tb, 500 - - elif hasattr(self.server, "exception_handler"): - # FastAPI - @self.server.exception_handler(Exception) - async def _wrap_errors(request, error): - tb = _get_traceback(secret, error) - from fastapi.responses import PlainTextResponse - - return PlainTextResponse(tb, status_code=500) + self.server_factory.register_prune_error_handler( + self.server, secret, _get_traceback + ) if debug and dev_tools.ui: - - def _before_request(): - flask.g.timing_information = { # pylint: disable=assigning-non-slot - "__dash_server": {"dur": time.time(), "desc": None} - } - - def _after_request(response): - timing_information = flask.g.get("timing_information", None) - if timing_information is None: - return response - - dash_total = timing_information.get("__dash_server", None) - if dash_total is not None: - dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) - - for name, info in timing_information.items(): - value = name - if info.get("desc") is not None: - value += f';desc="{info["desc"]}"' - - if info.get("dur") is not None: - value += f";dur={info['dur']}" - - response.headers.add("Server-Timing", value) - - return response - - self.server_factory.before_request(self.server, _before_request) - self.server_factory.after_request(self.server, _after_request) + self.server_factory.register_timing_hooks(self.server, first_run) if ( debug diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py index 1fa07a6ac6..918ca2175f 100644 --- a/dash/server_factories/fastapi_factory.py +++ b/dash/server_factories/fastapi_factory.py @@ -1,14 +1,22 @@ -import traceback - -from fastapi import FastAPI, Request, Response, APIRouter -from fastapi.responses import JSONResponse -from dash.exceptions import PreventUpdate, InvalidResourceError -from dash.server_factories import set_request_adapter, get_request_adapter -from .base_factory import BaseServerFactory +import sys +import mimetypes +import hashlib import inspect import pkgutil from contextvars import copy_context import importlib.util +import time +import uvicorn +from fastapi import FastAPI, Request, Response +from fastapi.responses import JSONResponse, PlainTextResponse +from fastapi.staticfiles import StaticFiles +from starlette.responses import Response as StarletteResponse +from starlette.datastructures import MutableHeaders +from dash.fingerprint import check_fingerprint +from dash import _validate +from dash.exceptions import PreventUpdate, InvalidResourceError +from dash.server_factories import set_request_adapter +from .base_factory import BaseServerFactory class FastAPIServerFactory(BaseServerFactory): @@ -32,8 +40,6 @@ def create_app(self, name="__main__", config=None): def register_assets_blueprint( self, app, blueprint_name, assets_url_path, assets_folder ): - from fastapi.staticfiles import StaticFiles - try: app.mount( assets_url_path, @@ -46,17 +52,21 @@ def register_assets_blueprint( def register_error_handlers(self, app): @app.exception_handler(PreventUpdate) - async def _handle_error(request: Request, exc: PreventUpdate): + async def _handle_error(_request, _exc): return Response(status_code=204) @app.exception_handler(InvalidResourceError) - async def _invalid_resources_handler( - request: Request, exc: InvalidResourceError - ): + async def _invalid_resources_handler(_request, exc): return Response(content=exc.args[0], status_code=404) + def register_prune_error_handler(self, app, secret, get_traceback_func): + @app.exception_handler(Exception) + async def _wrap_errors(_error_request, error): + tb = get_traceback_func(secret, error) + return PlainTextResponse(tb, status_code=500) + def _html_response_wrapper(self, view_func): - async def wrapped(*args, **kwargs): + async def wrapped(*_args, **_kwargs): # If view_func is a function, call it; if it's a string, use it directly html = view_func() if callable(view_func) else view_func return Response(content=html, media_type="text/html") @@ -75,10 +85,11 @@ async def index(request: Request): def setup_catchall(self, app, dash_app): @dash_app.server.on_event("startup") def _setup_catchall(): - dash_app.enable_dev_tools(**self.config) # do this to make sure dev tools are enabled - from fastapi import Request, Response + dash_app.enable_dev_tools( + **self.config, first_run=False + ) # do this to make sure dev tools are enabled - async def catchall(path: str, request: Request): + async def catchall(_path: str, request: Request): adapter = FastAPIRequestAdapter() set_request_adapter(adapter) adapter.set_request(request) @@ -88,8 +99,6 @@ async def catchall(path: str, request: Request): app, "/{path:path}", catchall, endpoint="catchall", methods=["GET"] ) - pass # catchall needs to be last to not override other routes - def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): if rule == "": rule = "/" @@ -114,11 +123,7 @@ def after_request(self, app, func): def run(self, app, host, port, debug, **kwargs): frame = inspect.stack()[2] - import uvicorn - - self.config = dict({'debug': debug} if debug else {}, **kwargs) - - + self.config = dict({"debug": debug} if debug else {}, **kwargs) reload = debug if reload: # Dynamically determine the module name from the file path @@ -149,8 +154,6 @@ def get_request_adapter(self): return FastAPIRequestAdapter def _make_before_middleware(self, func): - pass - async def middleware(request, call_next): if func is not None: if inspect.iscoroutinefunction(func): @@ -163,11 +166,13 @@ async def middleware(request, call_next): return middleware def _make_after_middleware(self, func): - pass - async def middleware(request, call_next): response = await call_next(request) - await func() + if func is not None: + if inspect.iscoroutinefunction(func): + await func() + else: + func() return response return middleware @@ -175,12 +180,6 @@ async def middleware(request, call_next): def serve_component_suites( self, dash_app, package_name, fingerprinted_path, request ): - import sys - import mimetypes - import pkgutil - from dash.fingerprint import check_fingerprint - from dash import _validate - path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) extension = "." + path_in_pkg.split(".")[-1] @@ -194,24 +193,17 @@ def serve_component_suites( package.__path__, ) data = pkgutil.get_data(package_name, path_in_pkg) - from starlette.responses import Response as StarletteResponse - headers = {} if has_fingerprint: headers["Cache-Control"] = "public, max-age=31536000" return StarletteResponse(content=data, media_type=mimetype, headers=headers) - else: - import hashlib - - etag = hashlib.md5(data).hexdigest() if data else "" - headers["ETag"] = etag - if request.headers.get("if-none-match") == etag: - return StarletteResponse(status_code=304) - return StarletteResponse(content=data, media_type=mimetype, headers=headers) + etag = hashlib.md5(data).hexdigest() if data else "" + headers["ETag"] = etag + if request.headers.get("if-none-match") == etag: + return StarletteResponse(status_code=304) + return StarletteResponse(content=data, media_type=mimetype, headers=headers) def setup_component_suites(self, app, dash_app): - from fastapi import Request - async def serve(request: Request, package_name: str, fingerprinted_path: str): return self.serve_component_suites( dash_app, package_name, fingerprinted_path, request @@ -223,17 +215,26 @@ async def serve(request: Request, package_name: str, fingerprinted_path: str): serve, ) - def dispatch(self, app, dash_app, use_async): + def dispatch(self, _app, dash_app, _use_async): async def _dispatch(request: Request): adapter = FastAPIRequestAdapter() set_request_adapter(adapter) adapter.set_request(request) + # pylint: disable=protected-access body = await request.json() - g = dash_app._initialize_context(body, adapter) - func = dash_app._prepare_callback(g, body) - args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) + g = dash_app._initialize_context( + body, adapter + ) # pylint: disable=protected-access + func = dash_app._prepare_callback( + g, body + ) # pylint: disable=protected-access + args = dash_app._inputs_to_vals( + g.inputs_list + g.states_list + ) # pylint: disable=protected-access ctx = copy_context() - partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) + partial_func = dash_app._execute_callback( + func, args, g.outputs_list, g + ) # pylint: disable=protected-access response_data = ctx.run(partial_func) if inspect.iscoroutine(response_data): response_data = await response_data @@ -247,6 +248,33 @@ def _serve_default_favicon(self): content=pkgutil.get_data("dash", "favicon.ico"), media_type="image/x-icon" ) + def register_timing_hooks(self, app, first_run): + if not first_run: + return + + @app.middleware("http") + async def timing_middleware(request, call_next): + # Before request + request.state.timing_information = { + "__dash_server": {"dur": time.time(), "desc": None} + } + response = await call_next(request) + # After request + timing_information = getattr(request.state, "timing_information", None) + if timing_information is not None: + dash_total = timing_information.get("__dash_server", None) + if dash_total is not None: + dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) + headers = MutableHeaders(response.headers) + for name, info in timing_information.items(): + value = name + if info.get("desc") is not None: + value += f';desc="{info["desc"]}"' + if info.get("dur") is not None: + value += f";dur={info['dur']}" + headers.append("Server-Timing", value) + return response + class FastAPIRequestAdapter: def __init__(self): @@ -266,7 +294,7 @@ def is_json(self): "application/json" ) - def get_cookies(self, request=None): + def get_cookies(self, _request=None): return self._request.cookies def get_headers(self): @@ -282,4 +310,4 @@ def get_origin(self): return self._request.headers.get("origin") def get_path(self): - return self._request.url.path # <-- Add this method + return self._request.url.path diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index 69173516b2..dafa4b24b4 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -1,10 +1,15 @@ -import flask -from dash.exceptions import PreventUpdate, InvalidResourceError -from dash.server_factories import set_request_adapter, get_request_adapter -from .base_factory import BaseServerFactory from contextvars import copy_context import asyncio import pkgutil +import sys +import mimetypes +import time +import flask +from dash.fingerprint import check_fingerprint +from dash import _validate +from dash.exceptions import PreventUpdate, InvalidResourceError +from dash.server_factories import set_request_adapter +from .base_factory import BaseServerFactory class FlaskServerFactory(BaseServerFactory): @@ -38,6 +43,12 @@ def _handle_error(_): def _invalid_resources_handler(err): return err.args[0], 404 + def register_prune_error_handler(self, app, secret, get_traceback_func): + @app.errorhandler(Exception) + def _wrap_errors(error): + tb = get_traceback_func(secret, error) + return tb, 500 + def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): app.add_url_rule( rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"] @@ -62,7 +73,7 @@ def get_request_adapter(self): return FlaskRequestAdapter def setup_catchall(self, app, dash_app): - def catchall(path, *args, **kwargs): + def catchall(_path, *args, **kwargs): adapter = FlaskRequestAdapter() set_request_adapter(adapter) return dash_app.render_index(*args, **kwargs) @@ -75,20 +86,11 @@ def setup_index(self, app, dash_app): def index(*args, **kwargs): adapter = FlaskRequestAdapter() set_request_adapter(adapter) - return dash_app.render_index(dash_app, *args, **kwargs) + return dash_app.render_index(*args, **kwargs) self.add_url_rule(app, "/", index, endpoint="/", methods=["GET"]) - def serve_component_suites( - self, dash_app, package_name, fingerprinted_path, request=None - ): - import sys - import mimetypes - import pkgutil - from dash.fingerprint import check_fingerprint - from dash import _validate - import flask - + def serve_component_suites(self, dash_app, package_name, fingerprinted_path): path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) extension = "." + path_in_pkg.split(".")[-1] @@ -116,7 +118,7 @@ def serve_component_suites( def setup_component_suites(self, app, dash_app): def serve(package_name, fingerprinted_path): return self.serve_component_suites( - dash_app, package_name, fingerprinted_path, flask.request + dash_app, package_name, fingerprinted_path ) self.add_url_rule( @@ -125,11 +127,12 @@ def serve(package_name, fingerprinted_path): serve, ) - def dispatch(self, app, dash_app, use_async=False): + def dispatch(self, _app, dash_app, use_async=False): def _dispatch(): adapter = FlaskRequestAdapter() set_request_adapter(adapter) body = flask.request.get_json() + # pylint: disable=protected-access g = dash_app._initialize_context(body, adapter) func = dash_app._prepare_callback(g, body) args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) @@ -149,6 +152,7 @@ async def _dispatch_async(): adapter = FlaskRequestAdapter() set_request_adapter(adapter) body = flask.request.get_json() + # pylint: disable=protected-access g = dash_app._initialize_context(body, adapter) func = dash_app._prepare_callback(g, body) args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) @@ -161,16 +165,40 @@ async def _dispatch_async(): return g.dash_response if use_async: - _dispatch = _dispatch_async + return _dispatch_async return _dispatch def _serve_default_favicon(self): - import flask return flask.Response( pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" ) + def register_timing_hooks(self, app, _first_run): + def _before_request(): + flask.g.timing_information = { + "__dash_server": {"dur": time.time(), "desc": None} + } + + def _after_request(response): + timing_information = flask.g.get("timing_information", None) + if timing_information is None: + return response + dash_total = timing_information.get("__dash_server", None) + if dash_total is not None: + dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) + for name, info in timing_information.items(): + value = name + if info.get("desc") is not None: + value += f';desc="{info["desc"]}"' + if info.get("dur") is not None: + value += f";dur={info['dur']}" + response.headers.add("Server-Timing", value) + return response + + self.before_request(app, _before_request) + self.after_request(app, _after_request) + class FlaskRequestAdapter: @staticmethod From 908aacd729695fd2ef8d79a6343d0ef21b6cea84 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 11 Sep 2025 15:39:56 -0400 Subject: [PATCH 013/297] fixing issue with `_app` when using dispatch, need to keep in context --- dash/server_factories/fastapi_factory.py | 4 +++- dash/server_factories/flask_factory.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py index 918ca2175f..ff21e61d72 100644 --- a/dash/server_factories/fastapi_factory.py +++ b/dash/server_factories/fastapi_factory.py @@ -215,7 +215,9 @@ async def serve(request: Request, package_name: str, fingerprinted_path: str): serve, ) - def dispatch(self, _app, dash_app, _use_async): + def dispatch( + self, app, dash_app, use_async=False + ): # pylint: disable=unused-argument async def _dispatch(request: Request): adapter = FastAPIRequestAdapter() set_request_adapter(adapter) diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index dafa4b24b4..b16135cfff 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -127,7 +127,9 @@ def serve(package_name, fingerprinted_path): serve, ) - def dispatch(self, _app, dash_app, use_async=False): + def dispatch( + self, app, dash_app, use_async=False + ): # pylint: disable=unused-argument def _dispatch(): adapter = FlaskRequestAdapter() set_request_adapter(adapter) From 9491c7fbfbc637029092413ffee155f56bcf4988 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 11 Sep 2025 15:58:55 -0400 Subject: [PATCH 014/297] fixing issue with catchall --- dash/server_factories/fastapi_factory.py | 2 +- dash/server_factories/flask_factory.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py index ff21e61d72..0853972d1f 100644 --- a/dash/server_factories/fastapi_factory.py +++ b/dash/server_factories/fastapi_factory.py @@ -89,7 +89,7 @@ def _setup_catchall(): **self.config, first_run=False ) # do this to make sure dev tools are enabled - async def catchall(_path: str, request: Request): + async def catchall(request: Request): adapter = FastAPIRequestAdapter() set_request_adapter(adapter) adapter.set_request(request) diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index b16135cfff..bb1204af19 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -73,7 +73,7 @@ def get_request_adapter(self): return FlaskRequestAdapter def setup_catchall(self, app, dash_app): - def catchall(_path, *args, **kwargs): + def catchall(*args, **kwargs): adapter = FlaskRequestAdapter() set_request_adapter(adapter) return dash_app.render_index(*args, **kwargs) From 39ad7bd9c837699393e05ebdcc12c0c95119bc8f Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 11 Sep 2025 16:18:17 -0400 Subject: [PATCH 015/297] fixing issue with args and cancelling callbacks --- dash/_callback_context.py | 8 ++++++++ dash/dash.py | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/dash/_callback_context.py b/dash/_callback_context.py index f64865c464..72b92e09e2 100644 --- a/dash/_callback_context.py +++ b/dash/_callback_context.py @@ -288,6 +288,14 @@ def path(self): """ return _get_from_context("path", "") + @property + @has_context + def args(self): + """ + Query parameters of the callback request as a dictionary-like object. + """ + return _get_from_context("args", "") + @property @has_context def remote(self): diff --git a/dash/dash.py b/dash/dash.py index 2151f31f77..d20672453c 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -70,6 +70,7 @@ from ._get_app import with_app_context, with_app_context_factory from ._grouping import map_grouping, grouping_len, update_args_group from ._obsolete import ObsoleteChecker +from ._callback_context import callback_context from . import _pages from ._pages import ( @@ -1382,6 +1383,7 @@ def _initialize_context(self, body, adapter): ) g.cookies = dict(adapter.get_cookies()) g.headers = dict(adapter.get_headers()) + g.args = adapter.get_args() g.path = adapter.get_full_path() g.remote = adapter.get_remote_addr() g.origin = adapter.get_origin() @@ -1529,7 +1531,7 @@ def _setup_server(self): manager=manager, ) def cancel_call(*_): - job_ids = flask.request.args.getlist("cancelJob") + job_ids = callback_context.args.getlist("cancelJob") executor = _callback.context_value.get().background_callback_manager if job_ids: for job_id in job_ids: From 7bf69a7583e1b216de132d6a622ded05d85f1ce8 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 11 Sep 2025 16:33:33 -0400 Subject: [PATCH 016/297] fixing issues with pages metadata and flaky tests --- dash/_pages.py | 4 +-- dash/server_factories/fastapi_factory.py | 28 +++++++++++++++---- dash/server_factories/flask_factory.py | 8 ++++++ .../multi_page/test_pages_relative_path.py | 3 +- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/dash/_pages.py b/dash/_pages.py index 2a3a116324..3fab86eb99 100644 --- a/dash/_pages.py +++ b/dash/_pages.py @@ -396,7 +396,7 @@ def _page_meta_tags(app, request): image = start_page.get("image", "") if image: image = app.get_asset_url(image) - assets_image_url = "".join([request.url_root, image.lstrip("/")]) if image else None + assets_image_url = "".join([request.get_root(), image.lstrip("/")]) if image else None supplied_image_url = start_page.get("image_url") image_url = supplied_image_url if supplied_image_url else assets_image_url @@ -411,7 +411,7 @@ def _page_meta_tags(app, request): return [ {"name": "description", "content": description}, {"property": "twitter:card", "content": "summary_large_image"}, - {"property": "twitter:url", "content": request_url}, + {"property": "twitter:url", "content": request.get_url()}, {"property": "twitter:title", "content": title}, {"property": "twitter:description", "content": description}, {"property": "twitter:image", "content": image_url or ""}, diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py index 0853972d1f..19d70b022e 100644 --- a/dash/server_factories/fastapi_factory.py +++ b/dash/server_factories/fastapi_factory.py @@ -6,12 +6,22 @@ from contextvars import copy_context import importlib.util import time -import uvicorn -from fastapi import FastAPI, Request, Response -from fastapi.responses import JSONResponse, PlainTextResponse -from fastapi.staticfiles import StaticFiles -from starlette.responses import Response as StarletteResponse -from starlette.datastructures import MutableHeaders + +try: + import uvicorn + from fastapi import FastAPI, Request, Response + from fastapi.responses import JSONResponse, PlainTextResponse + from fastapi.staticfiles import StaticFiles + from starlette.responses import Response as StarletteResponse + from starlette.datastructures import MutableHeaders +except ImportError: + uvicorn = None + FastAPI = Request = Response = None + JSONResponse = PlainTextResponse = None + StaticFiles = None + StarletteResponse = None + MutableHeaders = None + from dash.fingerprint import check_fingerprint from dash import _validate from dash.exceptions import PreventUpdate, InvalidResourceError @@ -285,6 +295,9 @@ def __init__(self): def set_request(self, request: Request): self._request = request + def get_root(self): + return str(self._request.base_url) + def get_args(self): return self._request.query_params @@ -305,6 +318,9 @@ def get_headers(self): def get_full_path(self): return str(self._request.url) + def get_url(self): + return str(self._request.url) + def get_remote_addr(self): return self._request.client.host if self._request.client else None diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index bb1204af19..8153ec4f92 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -207,6 +207,10 @@ class FlaskRequestAdapter: def get_args(): return flask.request.args + @staticmethod + def get_root(): + return flask.request.url_root + @staticmethod def get_json(): return flask.request.get_json() @@ -223,6 +227,10 @@ def get_cookies(): def get_headers(): return flask.request.headers + @staticmethod + def get_url(): + return flask.request.url + @staticmethod def get_full_path(): return flask.request.full_path diff --git a/tests/integration/multi_page/test_pages_relative_path.py b/tests/integration/multi_page/test_pages_relative_path.py index 6c505ac3f5..6fcbb6c6e0 100644 --- a/tests/integration/multi_page/test_pages_relative_path.py +++ b/tests/integration/multi_page/test_pages_relative_path.py @@ -2,6 +2,7 @@ import dash from dash import Dash, dcc, html +from dash.testing.wait import until def get_app(app): @@ -83,6 +84,6 @@ def test_pare003_absolute_path(dash_duo, clear_pages_state): for page in dash.page_registry.values(): dash_duo.find_element("#" + page["id"]).click() dash_duo.wait_for_text_to_equal("#text_" + page["id"], "text for " + page["id"]) - assert dash_duo.driver.title == page["title"], "check that page title updates" + until(lambda: dash_duo.driver.title == page["title"],timeout=3) assert dash_duo.get_logs() == [], "browser console should contain no error" From 10681dccfef11be7425b8fe11c2b8a21c148f20f Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 11 Sep 2025 16:53:27 -0400 Subject: [PATCH 017/297] fixing issues with relativate paths --- dash/server_factories/fastapi_factory.py | 5 ++--- dash/server_factories/flask_factory.py | 3 +-- tests/integration/multi_page/test_pages_relative_path.py | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py index 19d70b022e..914f591e17 100644 --- a/dash/server_factories/fastapi_factory.py +++ b/dash/server_factories/fastapi_factory.py @@ -219,9 +219,8 @@ async def serve(request: Request, package_name: str, fingerprinted_path: str): dash_app, package_name, fingerprinted_path, request ) - self.add_url_rule( - app, - "/_dash-component-suites/{package_name}/{fingerprinted_path:path}", + dash_app._add_url( + "/_dash-component-suites//", serve, ) diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index 8153ec4f92..684596ac23 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -121,8 +121,7 @@ def serve(package_name, fingerprinted_path): dash_app, package_name, fingerprinted_path ) - self.add_url_rule( - app, + dash_app._add_url( "/_dash-component-suites//", serve, ) diff --git a/tests/integration/multi_page/test_pages_relative_path.py b/tests/integration/multi_page/test_pages_relative_path.py index 6fcbb6c6e0..696ecc39a4 100644 --- a/tests/integration/multi_page/test_pages_relative_path.py +++ b/tests/integration/multi_page/test_pages_relative_path.py @@ -71,7 +71,7 @@ def test_pare002_relative_path_with_url_base_pathname( for page in dash.page_registry.values(): dash_br.find_element("#" + page["id"]).click() dash_br.wait_for_text_to_equal("#text_" + page["id"], "text for " + page["id"]) - assert dash_br.driver.title == page["title"], "check that page title updates" + until(lambda: dash_br.driver.title == page["title"], timeout=3) assert dash_br.get_logs() == [], "browser console should contain no error" From 4944d6d2b3060d43489f71c82bb7bdaf69242471 Mon Sep 17 00:00:00 2001 From: Christian Giessel Date: Thu, 11 Sep 2025 21:24:55 +0200 Subject: [PATCH 018/297] =?UTF-8?q?=E2=88=99=20-=20initial=20quart=20facto?= =?UTF-8?q?ry=20=E2=88=99=20-=20added=20types=20to=20BaseFactory=20to=20re?= =?UTF-8?q?move=20linting=20errors=20on=20create=20app=20in=20Flask=20and?= =?UTF-8?q?=20Quart=20Factory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dash/server_factories/base_factory.py | 25 +-- dash/server_factories/quart_factory.py | 238 +++++++++++++++++++++++++ 2 files changed, 251 insertions(+), 12 deletions(-) create mode 100644 dash/server_factories/quart_factory.py diff --git a/dash/server_factories/base_factory.py b/dash/server_factories/base_factory.py index b44f6888cb..12088947c2 100644 --- a/dash/server_factories/base_factory.py +++ b/dash/server_factories/base_factory.py @@ -1,49 +1,50 @@ from abc import ABC, abstractmethod +from typing import Any class BaseServerFactory(ABC): - def __call__(self, server, *args, **kwargs): + def __call__(self, server, *args, **kwargs) -> Any: # Default: WSGI return server(*args, **kwargs) @abstractmethod - def create_app(self, name="__main__", config=None): + def create_app(self, name: str = "__main__", config=None) -> Any: # pragma: no cover - interface pass @abstractmethod def register_assets_blueprint( - self, app, blueprint_name, assets_url_path, assets_folder - ): + self, app, blueprint_name: str, assets_url_path: str, assets_folder: str + ) -> None: # pragma: no cover - interface pass @abstractmethod - def register_error_handlers(self, app): + def register_error_handlers(self, app) -> None: # pragma: no cover - interface pass @abstractmethod - def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): + def add_url_rule(self, app, rule: str, view_func, endpoint=None, methods=None) -> None: # pragma: no cover - interface pass @abstractmethod - def before_request(self, app, func): + def before_request(self, app, func) -> None: # pragma: no cover - interface pass @abstractmethod - def after_request(self, app, func): + def after_request(self, app, func) -> None: # pragma: no cover - interface pass @abstractmethod - def run(self, app, host, port, debug, **kwargs): + def run(self, app, host: str, port: int, debug: bool, **kwargs) -> None: # pragma: no cover - interface pass @abstractmethod - def make_response(self, data, mimetype=None, content_type=None): + def make_response(self, data, mimetype=None, content_type=None) -> Any: # pragma: no cover - interface pass @abstractmethod - def jsonify(self, obj): + def jsonify(self, obj) -> Any: # pragma: no cover - interface pass @abstractmethod - def get_request_adapter(self): + def get_request_adapter(self) -> Any: # pragma: no cover - interface pass diff --git a/dash/server_factories/quart_factory.py b/dash/server_factories/quart_factory.py new file mode 100644 index 0000000000..977c9aea4c --- /dev/null +++ b/dash/server_factories/quart_factory.py @@ -0,0 +1,238 @@ +from .base_factory import BaseServerFactory +from quart import Quart, request, Response as QuartResponse, jsonify, send_from_directory +from dash.exceptions import PreventUpdate, InvalidResourceError +from dash.server_factories import set_request_adapter +from dash.fingerprint import check_fingerprint +from dash import _validate +from contextvars import copy_context +import inspect +import os +import pkgutil +import mimetypes +import hashlib +import sys + + +class QuartAPIServerFactory(BaseServerFactory): + """Quart implementation of the Dash server factory. + + All Quart/async specific imports are at the top-level (per user request) so + Quart must be installed when this module is imported. + """ + + def __init__(self) -> None: + self.config = {} + super().__init__() + + def __call__(self, server, *args, **kwargs): + # ASGI style (scope, receive, send) or standard call-through handled by BaseServerFactory + return super().__call__(server, *args, **kwargs) + + def create_app(self, name="__main__", config=None): + app = Quart(name) + if config: + for key, value in config.items(): + # Mirror Flask usage of config dict + app.config[key] = value + return app + + def register_assets_blueprint( + self, app, blueprint_name, assets_url_path, assets_folder + ): + if os.path.isdir(assets_folder): + route = f"{assets_url_path}/" + + @app.route(route) + async def serve_asset(filename): # pragma: no cover - simple passthrough + return await send_from_directory(assets_folder, filename) + + def register_error_handlers(self, app): + @app.errorhandler(PreventUpdate) + async def _prevent_update(_): + return "", 204 + + @app.errorhandler(InvalidResourceError) + async def _invalid_resource(err): + return err.args[0], 404 + + def _html_response_wrapper(self, view_func): + async def wrapped(*args, **kwargs): + html_val = view_func() if callable(view_func) else view_func + if inspect.iscoroutine(html_val): # handle async function returning html + html_val = await html_val + html = str(html_val) + return QuartResponse(html, content_type="text/html") + + return wrapped + + def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): + if rule == "": + rule = "/" + if isinstance(view_func, str) or not inspect.iscoroutinefunction(view_func): + # Wrap plain strings or sync callables in async handler returning HTML + if isinstance(view_func, str) or not inspect.iscoroutinefunction(view_func): + view_func = self._html_response_wrapper(view_func) + app.add_url_rule(rule, endpoint or rule, view_func, methods=methods or ["GET"]) + + # ---- Index & Catchall ------------------------------------------------ + def setup_index(self, app, dash_app): + async def index(): + adapter = QuartRequestAdapter() + set_request_adapter(adapter) + return QuartResponse(dash_app.render_index(), content_type="text/html") + + self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) + + def setup_catchall(self, app, dash_app): + @app.before_serving + async def _enable_dev_tools(): # pragma: no cover - environmental + dash_app.enable_dev_tools(**self.config) + + async def catchall(path): + adapter = QuartRequestAdapter() + set_request_adapter(adapter) + return QuartResponse(dash_app.render_index(), content_type="text/html") + + # Must be added after other routes + self.add_url_rule( + app, "/", catchall, endpoint="catchall", methods=["GET"] + ) + + # ---- Middleware-esque hooks ----------------------------------------- + def before_request(self, app, func): + app.before_request(func) + + def after_request(self, app, func): + # Quart after_request expects (response) -> response + @app.after_request + async def _after(response): + if func is not None: + result = func() + if inspect.iscoroutine(result): # Allow async hooks + await result + return response + + # ---- Running --------------------------------------------------------- + def run(self, app, host, port, debug, **kwargs): + self.config = dict({'debug': debug} if debug else {}, **kwargs) + app.run(host=host, port=port, debug=debug, **kwargs) + + # ---- Responses / JSON ------------------------------------------------ + def make_response(self, data, mimetype=None, content_type=None): + headers = {} + if mimetype: + headers["Content-Type"] = mimetype + if content_type: + headers["Content-Type"] = content_type + return QuartResponse(data, headers=headers) + + def jsonify(self, obj): + return jsonify(obj) + + def get_request_adapter(self): + return QuartRequestAdapter + + # ---- Component Suites ------------------------------------------------ + def serve_component_suites( + self, dash_app, package_name, fingerprinted_path, req + ): + path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) + _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) + extension = "." + path_in_pkg.split(".")[-1] + mimetype = mimetypes.types_map.get(extension, "application/octet-stream") + package = sys.modules[package_name] + dash_app.logger.debug( + "serving -- package: %s[%s] resource: %s => location: %s", + package_name, + getattr(package, "__version__", "unknown"), + path_in_pkg, + package.__path__, + ) + data = pkgutil.get_data(package_name, path_in_pkg) + headers = {} + if has_fingerprint: + headers["Cache-Control"] = "public, max-age=31536000" + return QuartResponse(data, content_type=mimetype, headers=headers) + etag = hashlib.md5(data).hexdigest() if data else "" + headers["ETag"] = etag + if req.headers.get("If-None-Match") == etag: + return QuartResponse(None, status=304) + return QuartResponse(data, content_type=mimetype, headers=headers) + + def setup_component_suites(self, app, dash_app): + async def serve(package_name, fingerprinted_path): + return self.serve_component_suites( + dash_app, package_name, fingerprinted_path, request + ) + + self.add_url_rule( + app, + "/_dash-component-suites//", + serve, + methods=["GET"], + ) + + # ---- Dispatch (Callbacks) ------------------------------------------- + def dispatch(self, app, dash_app, use_async=True): # Quart always async + async def _dispatch(): + adapter = QuartRequestAdapter() + set_request_adapter(adapter) + body = await request.get_json() + g = dash_app._initialize_context(body, adapter) + func = dash_app._prepare_callback(g, body) + args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) + ctx = copy_context() + partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) + response_data = ctx.run(partial_func) + if inspect.iscoroutine(response_data): # if user callback is async + response_data = await response_data + return QuartResponse(response_data, content_type="application/json") + + return _dispatch + + # ---- Favicon --------------------------------------------------------- + def _serve_default_favicon(self): + return QuartResponse( + pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" + ) + + +class QuartRequestAdapter: + """Adapter that normalizes Quart's request API to what Dash expects.""" + + @staticmethod + def get_args(): + return request.args + + @staticmethod + async def get_json(): + return await request.get_json() + + @staticmethod + def is_json(): + return request.is_json + + @staticmethod + def get_cookies(): + return request.cookies + + @staticmethod + def get_headers(): + return request.headers + + @staticmethod + def get_full_path(): + return request.full_path + + @staticmethod + def get_remote_addr(): + return request.remote_addr + + @staticmethod + def get_origin(): + return request.headers.get("Origin") + + @staticmethod + def get_path(): + return request.path + From 3b0f47e37d465a01ce6acd35a779458509d53aa1 Mon Sep 17 00:00:00 2001 From: Christian Giessel Date: Fri, 12 Sep 2025 15:28:49 +0200 Subject: [PATCH 019/297] Quart factory ready --- dash/server_factories/quart_factory.py | 154 +++++++++++++++++-------- 1 file changed, 107 insertions(+), 47 deletions(-) diff --git a/dash/server_factories/quart_factory.py b/dash/server_factories/quart_factory.py index 977c9aea4c..75376fcd7a 100644 --- a/dash/server_factories/quart_factory.py +++ b/dash/server_factories/quart_factory.py @@ -1,5 +1,5 @@ from .base_factory import BaseServerFactory -from quart import Quart, request, Response as QuartResponse, jsonify, send_from_directory +from quart import Quart, request, Response, jsonify, send_from_directory from dash.exceptions import PreventUpdate, InvalidResourceError from dash.server_factories import set_request_adapter from dash.fingerprint import check_fingerprint @@ -11,6 +11,7 @@ import mimetypes import hashlib import sys +import time class QuartAPIServerFactory(BaseServerFactory): @@ -39,12 +40,50 @@ def create_app(self, name="__main__", config=None): def register_assets_blueprint( self, app, blueprint_name, assets_url_path, assets_folder ): - if os.path.isdir(assets_folder): - route = f"{assets_url_path}/" + # Mirror Flask implementation using a blueprint serving static files + from quart import Blueprint + + bp = Blueprint( + blueprint_name, + __name__, + static_folder=assets_folder, + static_url_path=assets_url_path, + ) + app.register_blueprint(bp) + + def register_prune_error_handler(self, app, secret, get_traceback_func): + @app.errorhandler(Exception) + async def _wrap_errors(_error_request, error): + tb = get_traceback_func(secret, error) + return tb, 500 + + def register_timing_hooks(self, app, _first_run): # parity with Flask factory + from quart import g + + @app.before_request + async def _before_request(): # pragma: no cover - timing infra + g.timing_information = {"__dash_server": {"dur": time.time(), "desc": None}} - @app.route(route) - async def serve_asset(filename): # pragma: no cover - simple passthrough - return await send_from_directory(assets_folder, filename) + @app.after_request + async def _after_request(response): # pragma: no cover - timing infra + timing_information = getattr(g, "timing_information", None) + if timing_information is None: + return response + dash_total = timing_information.get("__dash_server", None) + if dash_total is not None: + dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) + for name, info in timing_information.items(): + value = name + if info.get("desc") is not None: + value += f';desc="{info["desc"]}"' + if info.get("dur") is not None: + value += f";dur={info['dur']}" + # Quart/Werkzeug headers expose 'add' (not 'append') + if hasattr(response.headers, "add"): + response.headers.add("Server-Timing", value) + else: # fallback just in case + response.headers["Server-Timing"] = value + return response def register_error_handlers(self, app): @app.errorhandler(PreventUpdate) @@ -61,49 +100,72 @@ async def wrapped(*args, **kwargs): if inspect.iscoroutine(html_val): # handle async function returning html html_val = await html_val html = str(html_val) - return QuartResponse(html, content_type="text/html") + return Response(html, content_type="text/html") return wrapped def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): - if rule == "": - rule = "/" - if isinstance(view_func, str) or not inspect.iscoroutinefunction(view_func): - # Wrap plain strings or sync callables in async handler returning HTML - if isinstance(view_func, str) or not inspect.iscoroutinefunction(view_func): - view_func = self._html_response_wrapper(view_func) - app.add_url_rule(rule, endpoint or rule, view_func, methods=methods or ["GET"]) - - # ---- Index & Catchall ------------------------------------------------ + app.add_url_rule( + rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"] + ) + + # def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): + # if rule == "": + # rule = "/" + # if isinstance(view_func, str): + # # Literal HTML content + # view_func = self._html_response_wrapper(view_func) + # elif not inspect.iscoroutinefunction(view_func): + # # Sync function: wrap to make async but preserve Response objects + # original = view_func + + # async def _async_adapter(*args, **kwargs): + # result = original(*args, **kwargs) + # # Pass through existing Response (Quart/Flask style) + # if isinstance(result, Response) or ( + # hasattr(result, "status_code") + # and hasattr(result, "headers") + # and hasattr(result, "get_data") + # ): + # return result + # # If it's bytes or str treat as HTML + # if isinstance(result, (str, bytes)): + # return Response(result, content_type="text/html") + # # Fallback: JSON encode arbitrary python objects + # try: + # import json + + # return Response( + # json.dumps(result), content_type="application/json" + # ) + # except Exception: # pragma: no cover + # return Response(str(result), content_type="text/plain") + + # view_func = _async_adapter + # app.add_url_rule(rule, endpoint or rule, view_func, methods=methods or ["GET"]) + def setup_index(self, app, dash_app): async def index(): adapter = QuartRequestAdapter() set_request_adapter(adapter) - return QuartResponse(dash_app.render_index(), content_type="text/html") + return Response(dash_app.render_index(), content_type="text/html") self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) def setup_catchall(self, app, dash_app): - @app.before_serving - async def _enable_dev_tools(): # pragma: no cover - environmental - dash_app.enable_dev_tools(**self.config) - async def catchall(path): adapter = QuartRequestAdapter() set_request_adapter(adapter) - return QuartResponse(dash_app.render_index(), content_type="text/html") + return Response(dash_app.render_index(), content_type="text/html") - # Must be added after other routes self.add_url_rule( app, "/", catchall, endpoint="catchall", methods=["GET"] ) - # ---- Middleware-esque hooks ----------------------------------------- def before_request(self, app, func): app.before_request(func) def after_request(self, app, func): - # Quart after_request expects (response) -> response @app.after_request async def _after(response): if func is not None: @@ -112,19 +174,24 @@ async def _after(response): await result return response - # ---- Running --------------------------------------------------------- def run(self, app, host, port, debug, **kwargs): - self.config = dict({'debug': debug} if debug else {}, **kwargs) - app.run(host=host, port=port, debug=debug, **kwargs) + # Store only dev tools related configuration (exclude server-only kwargs unsupported by Quart) + # Quart's run does NOT accept 'threaded' (Flask-specific). Drop silently (or log) if present. + unsupported = {"threaded", "processes"} + filtered_kwargs = {} + for k, v in kwargs.items(): + if k in unsupported: + continue + filtered_kwargs[k] = v + + # Keep a slim config for potential future use (dev tools already enabled in Dash.run) + self.config = {'debug': debug} + self.config.update({k: v for k, v in filtered_kwargs.items() if k.startswith('dev_tools_')}) + + app.run(host=host, port=port, debug=debug, **filtered_kwargs) - # ---- Responses / JSON ------------------------------------------------ def make_response(self, data, mimetype=None, content_type=None): - headers = {} - if mimetype: - headers["Content-Type"] = mimetype - if content_type: - headers["Content-Type"] = content_type - return QuartResponse(data, headers=headers) + return Response(data, mimetype=mimetype, content_type=content_type) def jsonify(self, obj): return jsonify(obj) @@ -132,7 +199,6 @@ def jsonify(self, obj): def get_request_adapter(self): return QuartRequestAdapter - # ---- Component Suites ------------------------------------------------ def serve_component_suites( self, dash_app, package_name, fingerprinted_path, req ): @@ -152,12 +218,9 @@ def serve_component_suites( headers = {} if has_fingerprint: headers["Cache-Control"] = "public, max-age=31536000" - return QuartResponse(data, content_type=mimetype, headers=headers) - etag = hashlib.md5(data).hexdigest() if data else "" - headers["ETag"] = etag - if req.headers.get("If-None-Match") == etag: - return QuartResponse(None, status=304) - return QuartResponse(data, content_type=mimetype, headers=headers) + return Response(data, content_type=mimetype, headers=headers) + + return Response(data, content_type=mimetype, headers=headers) def setup_component_suites(self, app, dash_app): async def serve(package_name, fingerprinted_path): @@ -172,7 +235,6 @@ async def serve(package_name, fingerprinted_path): methods=["GET"], ) - # ---- Dispatch (Callbacks) ------------------------------------------- def dispatch(self, app, dash_app, use_async=True): # Quart always async async def _dispatch(): adapter = QuartRequestAdapter() @@ -186,13 +248,12 @@ async def _dispatch(): response_data = ctx.run(partial_func) if inspect.iscoroutine(response_data): # if user callback is async response_data = await response_data - return QuartResponse(response_data, content_type="application/json") + return Response(response_data, content_type="application/json") return _dispatch - # ---- Favicon --------------------------------------------------------- def _serve_default_favicon(self): - return QuartResponse( + return Response( pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" ) @@ -235,4 +296,3 @@ def get_origin(): @staticmethod def get_path(): return request.path - From 1112f7743c7a91791f0720ee505959a80fd0c0cd Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 10:05:26 -0400 Subject: [PATCH 020/297] fixing for lint --- dash/_pages.py | 4 +++- dash/server_factories/fastapi_factory.py | 6 +++--- dash/server_factories/flask_factory.py | 6 +++--- tests/integration/multi_page/test_pages_relative_path.py | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/dash/_pages.py b/dash/_pages.py index 3fab86eb99..6c00e656c7 100644 --- a/dash/_pages.py +++ b/dash/_pages.py @@ -396,7 +396,9 @@ def _page_meta_tags(app, request): image = start_page.get("image", "") if image: image = app.get_asset_url(image) - assets_image_url = "".join([request.get_root(), image.lstrip("/")]) if image else None + assets_image_url = ( + "".join([request.get_root(), image.lstrip("/")]) if image else None + ) supplied_image_url = start_page.get("image_url") image_url = supplied_image_url if supplied_image_url else assets_image_url diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py index 914f591e17..eb4a9392f5 100644 --- a/dash/server_factories/fastapi_factory.py +++ b/dash/server_factories/fastapi_factory.py @@ -219,14 +219,14 @@ async def serve(request: Request, package_name: str, fingerprinted_path: str): dash_app, package_name, fingerprinted_path, request ) + # pylint: disable=protected-access dash_app._add_url( "/_dash-component-suites//", serve, ) - def dispatch( - self, app, dash_app, use_async=False - ): # pylint: disable=unused-argument + # pylint: disable=unused-argument + def dispatch(self, app, dash_app, use_async=False): async def _dispatch(request: Request): adapter = FastAPIRequestAdapter() set_request_adapter(adapter) diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index 684596ac23..c2221469fc 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -121,14 +121,14 @@ def serve(package_name, fingerprinted_path): dash_app, package_name, fingerprinted_path ) + # pylint: disable=protected-access dash_app._add_url( "/_dash-component-suites//", serve, ) - def dispatch( - self, app, dash_app, use_async=False - ): # pylint: disable=unused-argument + # pylint: disable=unused-argument + def dispatch(self, app, dash_app, use_async=False): def _dispatch(): adapter = FlaskRequestAdapter() set_request_adapter(adapter) diff --git a/tests/integration/multi_page/test_pages_relative_path.py b/tests/integration/multi_page/test_pages_relative_path.py index 696ecc39a4..24e7209a70 100644 --- a/tests/integration/multi_page/test_pages_relative_path.py +++ b/tests/integration/multi_page/test_pages_relative_path.py @@ -84,6 +84,6 @@ def test_pare003_absolute_path(dash_duo, clear_pages_state): for page in dash.page_registry.values(): dash_duo.find_element("#" + page["id"]).click() dash_duo.wait_for_text_to_equal("#text_" + page["id"], "text for " + page["id"]) - until(lambda: dash_duo.driver.title == page["title"],timeout=3) + until(lambda: dash_duo.driver.title == page["title"], timeout=3) assert dash_duo.get_logs() == [], "browser console should contain no error" From 8c52bbb9033588df0c764d6e3fd61e6c2defebd5 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 10:28:06 -0400 Subject: [PATCH 021/297] fixing issue with apps overwriting other paths --- dash/dash.py | 6 +++--- dash/server_factories/fastapi_factory.py | 16 ++++++++-------- dash/server_factories/flask_factory.py | 17 +++++++++-------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index d20672453c..4a06e9216e 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -742,7 +742,7 @@ def _add_url(self, name: str, view_func: RouteCallable, methods=("GET",)) -> Non self.routes.append(full_name) def _setup_routes(self): - self.server_factory.setup_component_suites(self.server, self) + self.server_factory.setup_component_suites(self) self._add_url("_dash-layout", self.serve_layout) self._add_url("_dash-dependencies", self.dependencies) self._add_url( @@ -755,8 +755,8 @@ def _setup_routes(self): "_favicon.ico", self.server_factory._serve_default_favicon, # pylint: disable=protected-access ) - self.server_factory.setup_index(self.server, self) - self.server_factory.setup_catchall(self.server, self) + self.server_factory.setup_index(self) + self.server_factory.setup_catchall(self) if jupyter_dash.active: self._add_url( diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py index eb4a9392f5..de1caf451c 100644 --- a/dash/server_factories/fastapi_factory.py +++ b/dash/server_factories/fastapi_factory.py @@ -83,16 +83,17 @@ async def wrapped(*_args, **_kwargs): return wrapped - def setup_index(self, app, dash_app): + def setup_index(self, dash_app): async def index(request: Request): adapter = FastAPIRequestAdapter() set_request_adapter(adapter) adapter.set_request(request) return Response(content=dash_app.render_index(), media_type="text/html") - self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) + # pylint: disable=protected-access + dash_app._add_url("", index, methods=["GET"]) - def setup_catchall(self, app, dash_app): + def setup_catchall(self, dash_app): @dash_app.server.on_event("startup") def _setup_catchall(): dash_app.enable_dev_tools( @@ -105,9 +106,8 @@ async def catchall(request: Request): adapter.set_request(request) return Response(content=dash_app.render_index(), media_type="text/html") - self.add_url_rule( - app, "/{path:path}", catchall, endpoint="catchall", methods=["GET"] - ) + # pylint: disable=protected-access + dash_app._add_url("{path:path}", catchall, methods=["GET"]) def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): if rule == "": @@ -213,7 +213,7 @@ def serve_component_suites( return StarletteResponse(status_code=304) return StarletteResponse(content=data, media_type=mimetype, headers=headers) - def setup_component_suites(self, app, dash_app): + def setup_component_suites(self, dash_app): async def serve(request: Request, package_name: str, fingerprinted_path: str): return self.serve_component_suites( dash_app, package_name, fingerprinted_path, request @@ -221,7 +221,7 @@ async def serve(request: Request, package_name: str, fingerprinted_path: str): # pylint: disable=protected-access dash_app._add_url( - "/_dash-component-suites//", + "_dash-component-suites//", serve, ) diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index c2221469fc..1ea561b076 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -50,6 +50,7 @@ def _wrap_errors(error): return tb, 500 def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): + print(rule, endpoint, methods) app.add_url_rule( rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"] ) @@ -72,23 +73,23 @@ def jsonify(self, obj): def get_request_adapter(self): return FlaskRequestAdapter - def setup_catchall(self, app, dash_app): + def setup_catchall(self, dash_app): def catchall(*args, **kwargs): adapter = FlaskRequestAdapter() set_request_adapter(adapter) return dash_app.render_index(*args, **kwargs) - self.add_url_rule( - app, "/", catchall, endpoint="catchall", methods=["GET"] - ) + # pylint: disable=protected-access + dash_app._add_url("", catchall, methods=["GET"]) - def setup_index(self, app, dash_app): + def setup_index(self, dash_app): def index(*args, **kwargs): adapter = FlaskRequestAdapter() set_request_adapter(adapter) return dash_app.render_index(*args, **kwargs) - self.add_url_rule(app, "/", index, endpoint="/", methods=["GET"]) + # pylint: disable=protected-access + dash_app._add_url("", index, methods=["GET"]) def serve_component_suites(self, dash_app, package_name, fingerprinted_path): path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) @@ -115,7 +116,7 @@ def serve_component_suites(self, dash_app, package_name, fingerprinted_path): response = flask.Response(None, status=304) return response - def setup_component_suites(self, app, dash_app): + def setup_component_suites(self, dash_app): def serve(package_name, fingerprinted_path): return self.serve_component_suites( dash_app, package_name, fingerprinted_path @@ -123,7 +124,7 @@ def serve(package_name, fingerprinted_path): # pylint: disable=protected-access dash_app._add_url( - "/_dash-component-suites//", + "_dash-component-suites//", serve, ) From aabeeb7801f47a4c2f1e54bb3278c20ec308f417 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 10:35:10 -0400 Subject: [PATCH 022/297] removing print --- dash/server_factories/flask_factory.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index 1ea561b076..6eebd735ac 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -50,7 +50,6 @@ def _wrap_errors(error): return tb, 500 def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): - print(rule, endpoint, methods) app.add_url_rule( rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"] ) From 5659cd73e98bda4ebb907480a56cf24207fb5f3a Mon Sep 17 00:00:00 2001 From: Christian Giessel Date: Fri, 12 Sep 2025 16:37:39 +0200 Subject: [PATCH 023/297] cleanup --- dash/server_factories/quart_factory.py | 58 ++------------------------ 1 file changed, 3 insertions(+), 55 deletions(-) diff --git a/dash/server_factories/quart_factory.py b/dash/server_factories/quart_factory.py index 75376fcd7a..685b8d70e4 100644 --- a/dash/server_factories/quart_factory.py +++ b/dash/server_factories/quart_factory.py @@ -1,15 +1,13 @@ from .base_factory import BaseServerFactory -from quart import Quart, request, Response, jsonify, send_from_directory +from quart import Quart, request, Response, jsonify from dash.exceptions import PreventUpdate, InvalidResourceError from dash.server_factories import set_request_adapter from dash.fingerprint import check_fingerprint from dash import _validate from contextvars import copy_context import inspect -import os import pkgutil import mimetypes -import hashlib import sys import time @@ -26,21 +24,18 @@ def __init__(self) -> None: super().__init__() def __call__(self, server, *args, **kwargs): - # ASGI style (scope, receive, send) or standard call-through handled by BaseServerFactory return super().__call__(server, *args, **kwargs) def create_app(self, name="__main__", config=None): app = Quart(name) if config: for key, value in config.items(): - # Mirror Flask usage of config dict app.config[key] = value return app def register_assets_blueprint( self, app, blueprint_name, assets_url_path, assets_folder ): - # Mirror Flask implementation using a blueprint serving static files from quart import Blueprint bp = Blueprint( @@ -109,41 +104,6 @@ def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"] ) - # def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): - # if rule == "": - # rule = "/" - # if isinstance(view_func, str): - # # Literal HTML content - # view_func = self._html_response_wrapper(view_func) - # elif not inspect.iscoroutinefunction(view_func): - # # Sync function: wrap to make async but preserve Response objects - # original = view_func - - # async def _async_adapter(*args, **kwargs): - # result = original(*args, **kwargs) - # # Pass through existing Response (Quart/Flask style) - # if isinstance(result, Response) or ( - # hasattr(result, "status_code") - # and hasattr(result, "headers") - # and hasattr(result, "get_data") - # ): - # return result - # # If it's bytes or str treat as HTML - # if isinstance(result, (str, bytes)): - # return Response(result, content_type="text/html") - # # Fallback: JSON encode arbitrary python objects - # try: - # import json - - # return Response( - # json.dumps(result), content_type="application/json" - # ) - # except Exception: # pragma: no cover - # return Response(str(result), content_type="text/plain") - - # view_func = _async_adapter - # app.add_url_rule(rule, endpoint or rule, view_func, methods=methods or ["GET"]) - def setup_index(self, app, dash_app): async def index(): adapter = QuartRequestAdapter() @@ -175,20 +135,8 @@ async def _after(response): return response def run(self, app, host, port, debug, **kwargs): - # Store only dev tools related configuration (exclude server-only kwargs unsupported by Quart) - # Quart's run does NOT accept 'threaded' (Flask-specific). Drop silently (or log) if present. - unsupported = {"threaded", "processes"} - filtered_kwargs = {} - for k, v in kwargs.items(): - if k in unsupported: - continue - filtered_kwargs[k] = v - - # Keep a slim config for potential future use (dev tools already enabled in Dash.run) - self.config = {'debug': debug} - self.config.update({k: v for k, v in filtered_kwargs.items() if k.startswith('dev_tools_')}) - - app.run(host=host, port=port, debug=debug, **filtered_kwargs) + self.config = dict({'debug': debug} if debug else {}, **kwargs) + app.run(host=host, port=port, debug=debug, **kwargs) def make_response(self, data, mimetype=None, content_type=None): return Response(data, mimetype=mimetype, content_type=content_type) From b05e37654f0f36eaa709514effe5900c6d94cf5a Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 11:07:10 -0400 Subject: [PATCH 024/297] reverting `render_index` -> `index` and making catch for outside of a `request` context --- dash/dash.py | 10 +++++++--- dash/server_factories/fastapi_factory.py | 4 ++-- dash/server_factories/flask_factory.py | 4 ++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index 4a06e9216e..973f1ec579 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -1145,16 +1145,20 @@ def _generate_meta(self): return meta_tags + self.config.meta_tags - def render_index(self, *_args, **_kwargs): + def index(self, *_args, **_kwargs): scripts = self._generate_scripts_html() css = self._generate_css_dist_html() config = self._generate_config_html() metas = self._generate_meta() renderer = self._generate_renderer() title = self.title - request = get_request_adapter() + try: + request = get_request_adapter() + except LookupError: + # no request context + request = None - if self.use_pages and self.config.include_pages_meta: + if self.use_pages and self.config.include_pages_meta and request: metas = _page_meta_tags(self, request) + metas if self._favicon: diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py index de1caf451c..cf08f85d7f 100644 --- a/dash/server_factories/fastapi_factory.py +++ b/dash/server_factories/fastapi_factory.py @@ -88,7 +88,7 @@ async def index(request: Request): adapter = FastAPIRequestAdapter() set_request_adapter(adapter) adapter.set_request(request) - return Response(content=dash_app.render_index(), media_type="text/html") + return Response(content=dash_app.index(), media_type="text/html") # pylint: disable=protected-access dash_app._add_url("", index, methods=["GET"]) @@ -104,7 +104,7 @@ async def catchall(request: Request): adapter = FastAPIRequestAdapter() set_request_adapter(adapter) adapter.set_request(request) - return Response(content=dash_app.render_index(), media_type="text/html") + return Response(content=dash_app.index(), media_type="text/html") # pylint: disable=protected-access dash_app._add_url("{path:path}", catchall, methods=["GET"]) diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index 6eebd735ac..9ba8a5017c 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -76,7 +76,7 @@ def setup_catchall(self, dash_app): def catchall(*args, **kwargs): adapter = FlaskRequestAdapter() set_request_adapter(adapter) - return dash_app.render_index(*args, **kwargs) + return dash_app.index(*args, **kwargs) # pylint: disable=protected-access dash_app._add_url("", catchall, methods=["GET"]) @@ -85,7 +85,7 @@ def setup_index(self, dash_app): def index(*args, **kwargs): adapter = FlaskRequestAdapter() set_request_adapter(adapter) - return dash_app.render_index(*args, **kwargs) + return dash_app.index(*args, **kwargs) # pylint: disable=protected-access dash_app._add_url("", index, methods=["GET"]) From ed0dc3b4fbdf78ea68ca1d21e510aca1bf4a3320 Mon Sep 17 00:00:00 2001 From: Christian Giessel Date: Thu, 11 Sep 2025 21:24:55 +0200 Subject: [PATCH 025/297] =?UTF-8?q?=E2=88=99=20-=20initial=20quart=20facto?= =?UTF-8?q?ry=20=E2=88=99=20-=20added=20types=20to=20BaseFactory=20to=20re?= =?UTF-8?q?move=20linting=20errors=20on=20create=20app=20in=20Flask=20and?= =?UTF-8?q?=20Quart=20Factory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dash/server_factories/base_factory.py | 25 +-- dash/server_factories/quart_factory.py | 238 +++++++++++++++++++++++++ 2 files changed, 251 insertions(+), 12 deletions(-) create mode 100644 dash/server_factories/quart_factory.py diff --git a/dash/server_factories/base_factory.py b/dash/server_factories/base_factory.py index b44f6888cb..12088947c2 100644 --- a/dash/server_factories/base_factory.py +++ b/dash/server_factories/base_factory.py @@ -1,49 +1,50 @@ from abc import ABC, abstractmethod +from typing import Any class BaseServerFactory(ABC): - def __call__(self, server, *args, **kwargs): + def __call__(self, server, *args, **kwargs) -> Any: # Default: WSGI return server(*args, **kwargs) @abstractmethod - def create_app(self, name="__main__", config=None): + def create_app(self, name: str = "__main__", config=None) -> Any: # pragma: no cover - interface pass @abstractmethod def register_assets_blueprint( - self, app, blueprint_name, assets_url_path, assets_folder - ): + self, app, blueprint_name: str, assets_url_path: str, assets_folder: str + ) -> None: # pragma: no cover - interface pass @abstractmethod - def register_error_handlers(self, app): + def register_error_handlers(self, app) -> None: # pragma: no cover - interface pass @abstractmethod - def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): + def add_url_rule(self, app, rule: str, view_func, endpoint=None, methods=None) -> None: # pragma: no cover - interface pass @abstractmethod - def before_request(self, app, func): + def before_request(self, app, func) -> None: # pragma: no cover - interface pass @abstractmethod - def after_request(self, app, func): + def after_request(self, app, func) -> None: # pragma: no cover - interface pass @abstractmethod - def run(self, app, host, port, debug, **kwargs): + def run(self, app, host: str, port: int, debug: bool, **kwargs) -> None: # pragma: no cover - interface pass @abstractmethod - def make_response(self, data, mimetype=None, content_type=None): + def make_response(self, data, mimetype=None, content_type=None) -> Any: # pragma: no cover - interface pass @abstractmethod - def jsonify(self, obj): + def jsonify(self, obj) -> Any: # pragma: no cover - interface pass @abstractmethod - def get_request_adapter(self): + def get_request_adapter(self) -> Any: # pragma: no cover - interface pass diff --git a/dash/server_factories/quart_factory.py b/dash/server_factories/quart_factory.py new file mode 100644 index 0000000000..977c9aea4c --- /dev/null +++ b/dash/server_factories/quart_factory.py @@ -0,0 +1,238 @@ +from .base_factory import BaseServerFactory +from quart import Quart, request, Response as QuartResponse, jsonify, send_from_directory +from dash.exceptions import PreventUpdate, InvalidResourceError +from dash.server_factories import set_request_adapter +from dash.fingerprint import check_fingerprint +from dash import _validate +from contextvars import copy_context +import inspect +import os +import pkgutil +import mimetypes +import hashlib +import sys + + +class QuartAPIServerFactory(BaseServerFactory): + """Quart implementation of the Dash server factory. + + All Quart/async specific imports are at the top-level (per user request) so + Quart must be installed when this module is imported. + """ + + def __init__(self) -> None: + self.config = {} + super().__init__() + + def __call__(self, server, *args, **kwargs): + # ASGI style (scope, receive, send) or standard call-through handled by BaseServerFactory + return super().__call__(server, *args, **kwargs) + + def create_app(self, name="__main__", config=None): + app = Quart(name) + if config: + for key, value in config.items(): + # Mirror Flask usage of config dict + app.config[key] = value + return app + + def register_assets_blueprint( + self, app, blueprint_name, assets_url_path, assets_folder + ): + if os.path.isdir(assets_folder): + route = f"{assets_url_path}/" + + @app.route(route) + async def serve_asset(filename): # pragma: no cover - simple passthrough + return await send_from_directory(assets_folder, filename) + + def register_error_handlers(self, app): + @app.errorhandler(PreventUpdate) + async def _prevent_update(_): + return "", 204 + + @app.errorhandler(InvalidResourceError) + async def _invalid_resource(err): + return err.args[0], 404 + + def _html_response_wrapper(self, view_func): + async def wrapped(*args, **kwargs): + html_val = view_func() if callable(view_func) else view_func + if inspect.iscoroutine(html_val): # handle async function returning html + html_val = await html_val + html = str(html_val) + return QuartResponse(html, content_type="text/html") + + return wrapped + + def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): + if rule == "": + rule = "/" + if isinstance(view_func, str) or not inspect.iscoroutinefunction(view_func): + # Wrap plain strings or sync callables in async handler returning HTML + if isinstance(view_func, str) or not inspect.iscoroutinefunction(view_func): + view_func = self._html_response_wrapper(view_func) + app.add_url_rule(rule, endpoint or rule, view_func, methods=methods or ["GET"]) + + # ---- Index & Catchall ------------------------------------------------ + def setup_index(self, app, dash_app): + async def index(): + adapter = QuartRequestAdapter() + set_request_adapter(adapter) + return QuartResponse(dash_app.render_index(), content_type="text/html") + + self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) + + def setup_catchall(self, app, dash_app): + @app.before_serving + async def _enable_dev_tools(): # pragma: no cover - environmental + dash_app.enable_dev_tools(**self.config) + + async def catchall(path): + adapter = QuartRequestAdapter() + set_request_adapter(adapter) + return QuartResponse(dash_app.render_index(), content_type="text/html") + + # Must be added after other routes + self.add_url_rule( + app, "/", catchall, endpoint="catchall", methods=["GET"] + ) + + # ---- Middleware-esque hooks ----------------------------------------- + def before_request(self, app, func): + app.before_request(func) + + def after_request(self, app, func): + # Quart after_request expects (response) -> response + @app.after_request + async def _after(response): + if func is not None: + result = func() + if inspect.iscoroutine(result): # Allow async hooks + await result + return response + + # ---- Running --------------------------------------------------------- + def run(self, app, host, port, debug, **kwargs): + self.config = dict({'debug': debug} if debug else {}, **kwargs) + app.run(host=host, port=port, debug=debug, **kwargs) + + # ---- Responses / JSON ------------------------------------------------ + def make_response(self, data, mimetype=None, content_type=None): + headers = {} + if mimetype: + headers["Content-Type"] = mimetype + if content_type: + headers["Content-Type"] = content_type + return QuartResponse(data, headers=headers) + + def jsonify(self, obj): + return jsonify(obj) + + def get_request_adapter(self): + return QuartRequestAdapter + + # ---- Component Suites ------------------------------------------------ + def serve_component_suites( + self, dash_app, package_name, fingerprinted_path, req + ): + path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) + _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) + extension = "." + path_in_pkg.split(".")[-1] + mimetype = mimetypes.types_map.get(extension, "application/octet-stream") + package = sys.modules[package_name] + dash_app.logger.debug( + "serving -- package: %s[%s] resource: %s => location: %s", + package_name, + getattr(package, "__version__", "unknown"), + path_in_pkg, + package.__path__, + ) + data = pkgutil.get_data(package_name, path_in_pkg) + headers = {} + if has_fingerprint: + headers["Cache-Control"] = "public, max-age=31536000" + return QuartResponse(data, content_type=mimetype, headers=headers) + etag = hashlib.md5(data).hexdigest() if data else "" + headers["ETag"] = etag + if req.headers.get("If-None-Match") == etag: + return QuartResponse(None, status=304) + return QuartResponse(data, content_type=mimetype, headers=headers) + + def setup_component_suites(self, app, dash_app): + async def serve(package_name, fingerprinted_path): + return self.serve_component_suites( + dash_app, package_name, fingerprinted_path, request + ) + + self.add_url_rule( + app, + "/_dash-component-suites//", + serve, + methods=["GET"], + ) + + # ---- Dispatch (Callbacks) ------------------------------------------- + def dispatch(self, app, dash_app, use_async=True): # Quart always async + async def _dispatch(): + adapter = QuartRequestAdapter() + set_request_adapter(adapter) + body = await request.get_json() + g = dash_app._initialize_context(body, adapter) + func = dash_app._prepare_callback(g, body) + args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) + ctx = copy_context() + partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) + response_data = ctx.run(partial_func) + if inspect.iscoroutine(response_data): # if user callback is async + response_data = await response_data + return QuartResponse(response_data, content_type="application/json") + + return _dispatch + + # ---- Favicon --------------------------------------------------------- + def _serve_default_favicon(self): + return QuartResponse( + pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" + ) + + +class QuartRequestAdapter: + """Adapter that normalizes Quart's request API to what Dash expects.""" + + @staticmethod + def get_args(): + return request.args + + @staticmethod + async def get_json(): + return await request.get_json() + + @staticmethod + def is_json(): + return request.is_json + + @staticmethod + def get_cookies(): + return request.cookies + + @staticmethod + def get_headers(): + return request.headers + + @staticmethod + def get_full_path(): + return request.full_path + + @staticmethod + def get_remote_addr(): + return request.remote_addr + + @staticmethod + def get_origin(): + return request.headers.get("Origin") + + @staticmethod + def get_path(): + return request.path + From 141527c8b8c25c7b1a47f7dc9eded53135e2ce94 Mon Sep 17 00:00:00 2001 From: Christian Giessel Date: Fri, 12 Sep 2025 15:28:49 +0200 Subject: [PATCH 026/297] Quart factory ready --- dash/server_factories/quart_factory.py | 154 +++++++++++++++++-------- 1 file changed, 107 insertions(+), 47 deletions(-) diff --git a/dash/server_factories/quart_factory.py b/dash/server_factories/quart_factory.py index 977c9aea4c..75376fcd7a 100644 --- a/dash/server_factories/quart_factory.py +++ b/dash/server_factories/quart_factory.py @@ -1,5 +1,5 @@ from .base_factory import BaseServerFactory -from quart import Quart, request, Response as QuartResponse, jsonify, send_from_directory +from quart import Quart, request, Response, jsonify, send_from_directory from dash.exceptions import PreventUpdate, InvalidResourceError from dash.server_factories import set_request_adapter from dash.fingerprint import check_fingerprint @@ -11,6 +11,7 @@ import mimetypes import hashlib import sys +import time class QuartAPIServerFactory(BaseServerFactory): @@ -39,12 +40,50 @@ def create_app(self, name="__main__", config=None): def register_assets_blueprint( self, app, blueprint_name, assets_url_path, assets_folder ): - if os.path.isdir(assets_folder): - route = f"{assets_url_path}/" + # Mirror Flask implementation using a blueprint serving static files + from quart import Blueprint + + bp = Blueprint( + blueprint_name, + __name__, + static_folder=assets_folder, + static_url_path=assets_url_path, + ) + app.register_blueprint(bp) + + def register_prune_error_handler(self, app, secret, get_traceback_func): + @app.errorhandler(Exception) + async def _wrap_errors(_error_request, error): + tb = get_traceback_func(secret, error) + return tb, 500 + + def register_timing_hooks(self, app, _first_run): # parity with Flask factory + from quart import g + + @app.before_request + async def _before_request(): # pragma: no cover - timing infra + g.timing_information = {"__dash_server": {"dur": time.time(), "desc": None}} - @app.route(route) - async def serve_asset(filename): # pragma: no cover - simple passthrough - return await send_from_directory(assets_folder, filename) + @app.after_request + async def _after_request(response): # pragma: no cover - timing infra + timing_information = getattr(g, "timing_information", None) + if timing_information is None: + return response + dash_total = timing_information.get("__dash_server", None) + if dash_total is not None: + dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) + for name, info in timing_information.items(): + value = name + if info.get("desc") is not None: + value += f';desc="{info["desc"]}"' + if info.get("dur") is not None: + value += f";dur={info['dur']}" + # Quart/Werkzeug headers expose 'add' (not 'append') + if hasattr(response.headers, "add"): + response.headers.add("Server-Timing", value) + else: # fallback just in case + response.headers["Server-Timing"] = value + return response def register_error_handlers(self, app): @app.errorhandler(PreventUpdate) @@ -61,49 +100,72 @@ async def wrapped(*args, **kwargs): if inspect.iscoroutine(html_val): # handle async function returning html html_val = await html_val html = str(html_val) - return QuartResponse(html, content_type="text/html") + return Response(html, content_type="text/html") return wrapped def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): - if rule == "": - rule = "/" - if isinstance(view_func, str) or not inspect.iscoroutinefunction(view_func): - # Wrap plain strings or sync callables in async handler returning HTML - if isinstance(view_func, str) or not inspect.iscoroutinefunction(view_func): - view_func = self._html_response_wrapper(view_func) - app.add_url_rule(rule, endpoint or rule, view_func, methods=methods or ["GET"]) - - # ---- Index & Catchall ------------------------------------------------ + app.add_url_rule( + rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"] + ) + + # def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): + # if rule == "": + # rule = "/" + # if isinstance(view_func, str): + # # Literal HTML content + # view_func = self._html_response_wrapper(view_func) + # elif not inspect.iscoroutinefunction(view_func): + # # Sync function: wrap to make async but preserve Response objects + # original = view_func + + # async def _async_adapter(*args, **kwargs): + # result = original(*args, **kwargs) + # # Pass through existing Response (Quart/Flask style) + # if isinstance(result, Response) or ( + # hasattr(result, "status_code") + # and hasattr(result, "headers") + # and hasattr(result, "get_data") + # ): + # return result + # # If it's bytes or str treat as HTML + # if isinstance(result, (str, bytes)): + # return Response(result, content_type="text/html") + # # Fallback: JSON encode arbitrary python objects + # try: + # import json + + # return Response( + # json.dumps(result), content_type="application/json" + # ) + # except Exception: # pragma: no cover + # return Response(str(result), content_type="text/plain") + + # view_func = _async_adapter + # app.add_url_rule(rule, endpoint or rule, view_func, methods=methods or ["GET"]) + def setup_index(self, app, dash_app): async def index(): adapter = QuartRequestAdapter() set_request_adapter(adapter) - return QuartResponse(dash_app.render_index(), content_type="text/html") + return Response(dash_app.render_index(), content_type="text/html") self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) def setup_catchall(self, app, dash_app): - @app.before_serving - async def _enable_dev_tools(): # pragma: no cover - environmental - dash_app.enable_dev_tools(**self.config) - async def catchall(path): adapter = QuartRequestAdapter() set_request_adapter(adapter) - return QuartResponse(dash_app.render_index(), content_type="text/html") + return Response(dash_app.render_index(), content_type="text/html") - # Must be added after other routes self.add_url_rule( app, "/", catchall, endpoint="catchall", methods=["GET"] ) - # ---- Middleware-esque hooks ----------------------------------------- def before_request(self, app, func): app.before_request(func) def after_request(self, app, func): - # Quart after_request expects (response) -> response @app.after_request async def _after(response): if func is not None: @@ -112,19 +174,24 @@ async def _after(response): await result return response - # ---- Running --------------------------------------------------------- def run(self, app, host, port, debug, **kwargs): - self.config = dict({'debug': debug} if debug else {}, **kwargs) - app.run(host=host, port=port, debug=debug, **kwargs) + # Store only dev tools related configuration (exclude server-only kwargs unsupported by Quart) + # Quart's run does NOT accept 'threaded' (Flask-specific). Drop silently (or log) if present. + unsupported = {"threaded", "processes"} + filtered_kwargs = {} + for k, v in kwargs.items(): + if k in unsupported: + continue + filtered_kwargs[k] = v + + # Keep a slim config for potential future use (dev tools already enabled in Dash.run) + self.config = {'debug': debug} + self.config.update({k: v for k, v in filtered_kwargs.items() if k.startswith('dev_tools_')}) + + app.run(host=host, port=port, debug=debug, **filtered_kwargs) - # ---- Responses / JSON ------------------------------------------------ def make_response(self, data, mimetype=None, content_type=None): - headers = {} - if mimetype: - headers["Content-Type"] = mimetype - if content_type: - headers["Content-Type"] = content_type - return QuartResponse(data, headers=headers) + return Response(data, mimetype=mimetype, content_type=content_type) def jsonify(self, obj): return jsonify(obj) @@ -132,7 +199,6 @@ def jsonify(self, obj): def get_request_adapter(self): return QuartRequestAdapter - # ---- Component Suites ------------------------------------------------ def serve_component_suites( self, dash_app, package_name, fingerprinted_path, req ): @@ -152,12 +218,9 @@ def serve_component_suites( headers = {} if has_fingerprint: headers["Cache-Control"] = "public, max-age=31536000" - return QuartResponse(data, content_type=mimetype, headers=headers) - etag = hashlib.md5(data).hexdigest() if data else "" - headers["ETag"] = etag - if req.headers.get("If-None-Match") == etag: - return QuartResponse(None, status=304) - return QuartResponse(data, content_type=mimetype, headers=headers) + return Response(data, content_type=mimetype, headers=headers) + + return Response(data, content_type=mimetype, headers=headers) def setup_component_suites(self, app, dash_app): async def serve(package_name, fingerprinted_path): @@ -172,7 +235,6 @@ async def serve(package_name, fingerprinted_path): methods=["GET"], ) - # ---- Dispatch (Callbacks) ------------------------------------------- def dispatch(self, app, dash_app, use_async=True): # Quart always async async def _dispatch(): adapter = QuartRequestAdapter() @@ -186,13 +248,12 @@ async def _dispatch(): response_data = ctx.run(partial_func) if inspect.iscoroutine(response_data): # if user callback is async response_data = await response_data - return QuartResponse(response_data, content_type="application/json") + return Response(response_data, content_type="application/json") return _dispatch - # ---- Favicon --------------------------------------------------------- def _serve_default_favicon(self): - return QuartResponse( + return Response( pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" ) @@ -235,4 +296,3 @@ def get_origin(): @staticmethod def get_path(): return request.path - From 3e38d4151414bca27449d03acf323b67f958e282 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 11:15:49 -0400 Subject: [PATCH 027/297] fixing `prune_errors` test --- tests/integration/devtools/test_devtools_error_handling.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/devtools/test_devtools_error_handling.py b/tests/integration/devtools/test_devtools_error_handling.py index 40d5731202..b481ef2fad 100644 --- a/tests/integration/devtools/test_devtools_error_handling.py +++ b/tests/integration/devtools/test_devtools_error_handling.py @@ -109,14 +109,14 @@ def test_dveh006_long_python_errors(dash_duo): assert "in bad_sub" not in error0 # dash and flask part of the traceback ARE included # since we set dev_tools_prune_errors=False - assert "dash.py" in error0 + assert "factory.py" in error0 assert "self.wsgi_app" in error0 error1 = get_error_html(dash_duo, 1) assert "in update_output" in error1 assert "in bad_sub" in error1 assert "ZeroDivisionError" in error1 - assert "dash.py" in error1 + assert "factory.py" in error1 assert "self.wsgi_app" in error1 From 381fb0c135b0f3b7a7106afe307d7e8a5866c65a Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 15:40:34 -0400 Subject: [PATCH 028/297] adjustments for flask api_endpoint declared in callback defs --- dash/dash.py | 26 ++------------------------ dash/server_factories/flask_factory.py | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index 973f1ec579..bed7ab43a4 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -793,30 +793,8 @@ def setup_apis(self): ) self.callback_api_paths[k] = _callback.GLOBAL_API_PATHS.pop(k) - def make_parse_body(func): - def _parse_body(): - if flask.request.is_json: - data = flask.request.get_json() - return flask.jsonify(func(**data)) - return flask.jsonify({}) - - return _parse_body - - def make_parse_body_async(func): - async def _parse_body_async(): - if flask.request.is_json: - data = flask.request.get_json() - result = await func(**data) - return flask.jsonify(result) - return flask.jsonify({}) - - return _parse_body_async - - for path, func in self.callback_api_paths.items(): - if asyncio.iscoroutinefunction(func): - self._add_url(path, make_parse_body_async(func), ["POST"]) - else: - self._add_url(path, make_parse_body(func), ["POST"]) + # Delegate to the server factory for route registration + self.server_factory.register_callback_api_routes(self.server, self.callback_api_paths) def _setup_plotlyjs(self): # pylint: disable=import-outside-toplevel diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py index 9ba8a5017c..a488a070e1 100644 --- a/dash/server_factories/flask_factory.py +++ b/dash/server_factories/flask_factory.py @@ -5,6 +5,7 @@ import mimetypes import time import flask +import inspect from dash.fingerprint import check_fingerprint from dash import _validate from dash.exceptions import PreventUpdate, InvalidResourceError @@ -200,6 +201,31 @@ def _after_request(response): self.before_request(app, _before_request) self.after_request(app, _after_request) + def register_callback_api_routes(self, app, callback_api_paths): + """ + Register callback API endpoints on the Flask app. + Each key in callback_api_paths is a route, each value is a handler (sync or async). + The view function parses the JSON body and passes it to the handler. + """ + for path, handler in callback_api_paths.items(): + endpoint = f"dash_callback_api_{path}" + route = path if path.startswith("/") else f"/{path}" + methods = ["POST"] + + if inspect.iscoroutinefunction(handler): + async def view_func(*args, handler=handler, **kwargs): + data = flask.request.get_json() + result = await handler(**data) if data else await handler() + return flask.jsonify(result) + else: + def view_func(*args, handler=handler, **kwargs): + data = flask.request.get_json() + result = handler(**data) if data else handler() + return flask.jsonify(result) + + # Flask 2.x+ supports async views natively + app.add_url_rule(route, endpoint=endpoint, view_func=view_func, methods=methods) + class FlaskRequestAdapter: @staticmethod From a27927a2dfde473d5eb2215fbb035a4b6597c44b Mon Sep 17 00:00:00 2001 From: Christian Giessel Date: Fri, 12 Sep 2025 21:49:49 +0200 Subject: [PATCH 029/297] updated QuartRequestAdapter & QuartFactory to latest changes --- dash/server_factories/quart_factory.py | 147 ++++++++----------------- 1 file changed, 47 insertions(+), 100 deletions(-) diff --git a/dash/server_factories/quart_factory.py b/dash/server_factories/quart_factory.py index 75376fcd7a..99c9c2e5a0 100644 --- a/dash/server_factories/quart_factory.py +++ b/dash/server_factories/quart_factory.py @@ -1,15 +1,13 @@ from .base_factory import BaseServerFactory -from quart import Quart, request, Response, jsonify, send_from_directory +from quart import Quart, Request, Response, jsonify, request from dash.exceptions import PreventUpdate, InvalidResourceError from dash.server_factories import set_request_adapter from dash.fingerprint import check_fingerprint from dash import _validate from contextvars import copy_context import inspect -import os import pkgutil import mimetypes -import hashlib import sys import time @@ -26,21 +24,18 @@ def __init__(self) -> None: super().__init__() def __call__(self, server, *args, **kwargs): - # ASGI style (scope, receive, send) or standard call-through handled by BaseServerFactory return super().__call__(server, *args, **kwargs) def create_app(self, name="__main__", config=None): app = Quart(name) if config: for key, value in config.items(): - # Mirror Flask usage of config dict app.config[key] = value return app def register_assets_blueprint( self, app, blueprint_name, assets_url_path, assets_folder ): - # Mirror Flask implementation using a blueprint serving static files from quart import Blueprint bp = Blueprint( @@ -109,58 +104,23 @@ def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"] ) - # def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): - # if rule == "": - # rule = "/" - # if isinstance(view_func, str): - # # Literal HTML content - # view_func = self._html_response_wrapper(view_func) - # elif not inspect.iscoroutinefunction(view_func): - # # Sync function: wrap to make async but preserve Response objects - # original = view_func - - # async def _async_adapter(*args, **kwargs): - # result = original(*args, **kwargs) - # # Pass through existing Response (Quart/Flask style) - # if isinstance(result, Response) or ( - # hasattr(result, "status_code") - # and hasattr(result, "headers") - # and hasattr(result, "get_data") - # ): - # return result - # # If it's bytes or str treat as HTML - # if isinstance(result, (str, bytes)): - # return Response(result, content_type="text/html") - # # Fallback: JSON encode arbitrary python objects - # try: - # import json - - # return Response( - # json.dumps(result), content_type="application/json" - # ) - # except Exception: # pragma: no cover - # return Response(str(result), content_type="text/plain") - - # view_func = _async_adapter - # app.add_url_rule(rule, endpoint or rule, view_func, methods=methods or ["GET"]) - - def setup_index(self, app, dash_app): + def setup_index(self, dash_app): async def index(): adapter = QuartRequestAdapter() set_request_adapter(adapter) - return Response(dash_app.render_index(), content_type="text/html") + adapter.set_request(request) + return Response(dash_app.index(), content_type="text/html") - self.add_url_rule(app, "/", index, endpoint="index", methods=["GET"]) + dash_app._add_url("", index, methods=["GET"]) - def setup_catchall(self, app, dash_app): - async def catchall(path): + def setup_catchall(self, dash_app): + async def catchall(path): # noqa: ARG001 - path is unused but kept for route signature adapter = QuartRequestAdapter() set_request_adapter(adapter) - return Response(dash_app.render_index(), content_type="text/html") + adapter.set_request(request) + return Response(dash_app.index(), content_type="text/html") - self.add_url_rule( - app, "/", catchall, endpoint="catchall", methods=["GET"] - ) + dash_app._add_url("", catchall, methods=["GET"]) def before_request(self, app, func): app.before_request(func) @@ -175,20 +135,8 @@ async def _after(response): return response def run(self, app, host, port, debug, **kwargs): - # Store only dev tools related configuration (exclude server-only kwargs unsupported by Quart) - # Quart's run does NOT accept 'threaded' (Flask-specific). Drop silently (or log) if present. - unsupported = {"threaded", "processes"} - filtered_kwargs = {} - for k, v in kwargs.items(): - if k in unsupported: - continue - filtered_kwargs[k] = v - - # Keep a slim config for potential future use (dev tools already enabled in Dash.run) - self.config = {'debug': debug} - self.config.update({k: v for k, v in filtered_kwargs.items() if k.startswith('dev_tools_')}) - - app.run(host=host, port=port, debug=debug, **filtered_kwargs) + self.config = {'debug': debug, **kwargs} if debug else kwargs + app.run(host=host, port=port, debug=debug, **kwargs) def make_response(self, data, mimetype=None, content_type=None): return Response(data, mimetype=mimetype, content_type=content_type) @@ -199,9 +147,7 @@ def jsonify(self, obj): def get_request_adapter(self): return QuartRequestAdapter - def serve_component_suites( - self, dash_app, package_name, fingerprinted_path, req - ): + def serve_component_suites(self, dash_app, package_name, fingerprinted_path, req): # noqa: ARG002 unused req preserved for interface parity path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) extension = "." + path_in_pkg.split(".")[-1] @@ -222,23 +168,22 @@ def serve_component_suites( return Response(data, content_type=mimetype, headers=headers) - def setup_component_suites(self, app, dash_app): + def setup_component_suites(self, dash_app): async def serve(package_name, fingerprinted_path): return self.serve_component_suites( dash_app, package_name, fingerprinted_path, request ) - self.add_url_rule( - app, - "/_dash-component-suites//", + dash_app._add_url( + "_dash-component-suites//", serve, - methods=["GET"], ) def dispatch(self, app, dash_app, use_async=True): # Quart always async async def _dispatch(): adapter = QuartRequestAdapter() set_request_adapter(adapter) + adapter.set_request(request) body = await request.get_json() g = dash_app._initialize_context(body, adapter) func = dash_app._prepare_callback(g, body) @@ -259,40 +204,42 @@ def _serve_default_favicon(self): class QuartRequestAdapter: - """Adapter that normalizes Quart's request API to what Dash expects.""" + def __init__(self) -> None: + self._request = None + + def set_request(self, request: Request) -> None: + self._request = request + + # Accessors (instance-based) + def get_root(self): + return self._request.root_url + + def get_args(self): + return self._request.args - @staticmethod - def get_args(): - return request.args + async def get_json(self): + return await self._request.get_json() - @staticmethod - async def get_json(): - return await request.get_json() + def is_json(self): + return self._request.is_json - @staticmethod - def is_json(): - return request.is_json + def get_cookies(self): + return self._request.cookies - @staticmethod - def get_cookies(): - return request.cookies + def get_headers(self): + return self._request.headers - @staticmethod - def get_headers(): - return request.headers + def get_full_path(self): + return self._request.full_path - @staticmethod - def get_full_path(): - return request.full_path + def get_url(self): + return str(self._request.url) - @staticmethod - def get_remote_addr(): - return request.remote_addr + def get_remote_addr(self): + return self._request.remote_addr - @staticmethod - def get_origin(): - return request.headers.get("Origin") + def get_origin(self): + return self._request.headers.get("origin") - @staticmethod - def get_path(): - return request.path + def get_path(self): + return self._request.path From 1824e110327740252dd944988763e0972371f7e9 Mon Sep 17 00:00:00 2001 From: Christian Giessel Date: Fri, 12 Sep 2025 22:06:43 +0200 Subject: [PATCH 030/297] Removed redundant Response return --- dash/server_factories/quart_factory.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dash/server_factories/quart_factory.py b/dash/server_factories/quart_factory.py index 99c9c2e5a0..53fa1cc469 100644 --- a/dash/server_factories/quart_factory.py +++ b/dash/server_factories/quart_factory.py @@ -164,7 +164,6 @@ def serve_component_suites(self, dash_app, package_name, fingerprinted_path, req headers = {} if has_fingerprint: headers["Cache-Control"] = "public, max-age=31536000" - return Response(data, content_type=mimetype, headers=headers) return Response(data, content_type=mimetype, headers=headers) From b14f6d276f039239725c7554decabd250c0f8975 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 16:21:18 -0400 Subject: [PATCH 031/297] fix for fastapi `api_endpoint` registering --- dash/server_factories/fastapi_factory.py | 48 ++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py index cf08f85d7f..1090c85050 100644 --- a/dash/server_factories/fastapi_factory.py +++ b/dash/server_factories/fastapi_factory.py @@ -14,13 +14,21 @@ from fastapi.staticfiles import StaticFiles from starlette.responses import Response as StarletteResponse from starlette.datastructures import MutableHeaders + from pydantic import create_model + from typing import Any, Optional except ImportError: uvicorn = None - FastAPI = Request = Response = None - JSONResponse = PlainTextResponse = None + FastAPI = None + Request = None + Response = None + JSONResponse = None + PlainTextResponse = None StaticFiles = None StarletteResponse = None MutableHeaders = None + create_model = None + Any = None + Optional = None from dash.fingerprint import check_fingerprint from dash import _validate @@ -109,7 +117,7 @@ async def catchall(request: Request): # pylint: disable=protected-access dash_app._add_url("{path:path}", catchall, methods=["GET"]) - def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): + def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None, include_in_schema=False): if rule == "": rule = "/" if isinstance(view_func, str): @@ -120,7 +128,7 @@ def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): view_func, methods=methods or ["GET"], name=endpoint, - include_in_schema=False, + include_in_schema=include_in_schema, ) def before_request(self, app, func): @@ -286,6 +294,38 @@ async def timing_middleware(request, call_next): headers.append("Server-Timing", value) return response + def register_callback_api_routes(self, app, callback_api_paths): + """ + Register callback API endpoints on the FastAPI app. + Each key in callback_api_paths is a route, each value is a handler (sync or async). + Dynamically creates a Pydantic model for the handler's parameters and uses it as the body parameter. + """ + for path, handler in callback_api_paths.items(): + endpoint = f"dash_callback_api_{path}" + route = path if path.startswith("/") else f"/{path}" + methods = ["POST"] + sig = inspect.signature(handler) + param_names = list(sig.parameters.keys()) + fields = {name: (Optional[Any], None) for name in param_names} + Model = create_model(f"Payload_{endpoint}", **fields) + + async def view_func(request: Request, body: Model): + kwargs = body.dict(exclude_unset=True) + if inspect.iscoroutinefunction(handler): + result = await handler(**kwargs) + else: + result = handler(**kwargs) + return JSONResponse(content=result) + + + app.add_api_route( + route, + view_func, + methods=methods, + name=endpoint, + include_in_schema=True, + ) + class FastAPIRequestAdapter: def __init__(self): From 5ef796bf7614bdf5aeb4a5bb3ad61c78f2b4bfb4 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:08:00 -0400 Subject: [PATCH 032/297] shifting from `server_factory` to `backend` --- dash/_callback.py | 2 +- .../quart_factory.py => backend/quart.py} | 30 +- dash/dash.py | 120 +++--- dash/server_factories/__init__.py | 12 - dash/server_factories/base_factory.py | 50 --- dash/server_factories/fastapi_factory.py | 370 ------------------ dash/server_factories/flask_factory.py | 273 ------------- 7 files changed, 103 insertions(+), 754 deletions(-) rename dash/{server_factories/quart_factory.py => backend/quart.py} (86%) delete mode 100644 dash/server_factories/__init__.py delete mode 100644 dash/server_factories/base_factory.py delete mode 100644 dash/server_factories/fastapi_factory.py delete mode 100644 dash/server_factories/flask_factory.py diff --git a/dash/_callback.py b/dash/_callback.py index bca8027fdd..6cc55b9162 100644 --- a/dash/_callback.py +++ b/dash/_callback.py @@ -6,7 +6,7 @@ import asyncio -from dash.server_factories import get_request_adapter +from dash.backend import get_request_adapter from .dependencies import ( handle_callback_args, diff --git a/dash/server_factories/quart_factory.py b/dash/backend/quart.py similarity index 86% rename from dash/server_factories/quart_factory.py rename to dash/backend/quart.py index 53fa1cc469..a2437811a4 100644 --- a/dash/server_factories/quart_factory.py +++ b/dash/backend/quart.py @@ -1,7 +1,7 @@ -from .base_factory import BaseServerFactory +from .base_server import BaseDashServer from quart import Quart, Request, Response, jsonify, request from dash.exceptions import PreventUpdate, InvalidResourceError -from dash.server_factories import set_request_adapter +from dash.backend import set_request_adapter from dash.fingerprint import check_fingerprint from dash import _validate from contextvars import copy_context @@ -12,7 +12,7 @@ import time -class QuartAPIServerFactory(BaseServerFactory): +class QuartDashServer(BaseDashServer): """Quart implementation of the Dash server factory. All Quart/async specific imports are at the top-level (per user request) so @@ -196,6 +196,30 @@ async def _dispatch(): return _dispatch + def register_callback_api_routes(self, app, callback_api_paths): + """ + Register callback API endpoints on the Quart app. + Each key in callback_api_paths is a route, each value is a handler (sync or async). + The view function parses the JSON body and passes it to the handler. + """ + for path, handler in callback_api_paths.items(): + endpoint = f"dash_callback_api_{path}" + route = path if path.startswith("/") else f"/{path}" + methods = ["POST"] + + if inspect.iscoroutinefunction(handler): + async def view_func(*args, handler=handler, **kwargs): + data = await request.get_json() + result = await handler(**data) if data else await handler() + return jsonify(result) + else: + async def view_func(*args, handler=handler, **kwargs): + data = await request.get_json() + result = handler(**data) if data else handler() + return jsonify(result) + + app.add_url_rule(route, endpoint=endpoint, view_func=view_func, methods=methods) + def _serve_default_favicon(self): return Response( pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" diff --git a/dash/dash.py b/dash/dash.py index bed7ab43a4..0e7cbb25fa 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -39,7 +39,7 @@ ProxyError, DuplicateCallback, ) -from .server_factories import get_request_adapter +from .backend import get_request_adapter, get_backend from .version import __version__ from ._configs import get_combined_config, pathname_configs, pages_folder_config from ._utils import ( @@ -64,8 +64,7 @@ from . import _validate from . import _watch from . import _get_app -from .server_factories.flask_factory import FlaskServerFactory -from .server_factories.base_factory import BaseServerFactory +from .backend.flask import FlaskDashServer from ._get_app import with_app_context, with_app_context_factory from ._grouping import map_grouping, grouping_len, update_args_group @@ -156,6 +155,27 @@ except: # noqa: E722 page_container = None +def _is_flask_instance(obj): + try: + from flask import Flask + return isinstance(obj, Flask) + except ImportError: + return False + +def _is_fastapi_instance(obj): + try: + from fastapi import FastAPI + return isinstance(obj, FastAPI) + except ImportError: + return False + +def _is_quart_instance(obj): + try: + from quart import Quart + return isinstance(obj, Quart) + except ImportError: + return False + def _get_traceback(secret, error: Exception): try: @@ -249,6 +269,12 @@ class Dash(ObsoleteChecker): ``flask.Flask``: use this pre-existing Flask server. :type server: boolean or flask.Flask + :param backend: The backend to use for the Dash app. Can be a string + (name of the backend) or a backend class. Default is None, which + selects the Flask backend. Currently, "flask" and "fastapi" backends + are supported. + :type backend: string or type + :param assets_folder: a path, relative to the current working directory, for extra files to be used in the browser. Default ``'assets'``. All .js and .css files will be loaded immediately unless excluded by @@ -431,6 +457,7 @@ def __init__( # pylint: disable=too-many-statements self, name: Optional[str] = None, server: Union[bool, Callable[[], Any]] = True, + backend: Union[str, type, None] = None, assets_folder: str = "assets", pages_folder: str = "pages", use_pages: Optional[bool] = None, @@ -466,7 +493,6 @@ def __init__( # pylint: disable=too-many-statements description: Optional[str] = None, on_error: Optional[Callable[[Exception], Any]] = None, use_async: Optional[bool] = None, - server_factory: Optional[BaseServerFactory] = None, **obsolete, ): @@ -489,29 +515,33 @@ def __init__( # pylint: disable=too-many-statements caller_name: str = name if name is not None else get_caller_name() - self.server_factory = server_factory or FlaskServerFactory() - - # We have 3 cases: server is either True (we create the server), False - # (defer server creation) or a Flask app instance (we use their server) - if callable(server) and not ( - hasattr(server, "route") and hasattr(server, "run") - ): - # Server factory function - self.server = server() - if name is None: - caller_name = getattr(self.server, "name", caller_name) - elif hasattr(server, "route") and hasattr(server, "run"): + # Determine backend + if backend is None: + backend_cls = FlaskDashServer + elif isinstance(backend, str): + backend_cls = get_backend(backend) + elif isinstance(backend, type): + backend_cls = backend + else: + raise ValueError("Invalid backend argument") + + # Determine server and backend instance + if server is not None and server is not True and server is not False: + # User provided a server instance (e.g., Flask, Quart, FastAPI) + if _is_flask_instance(server): + backend_cls = get_backend("flask") + elif _is_quart_instance(server): + backend_cls = get_backend("quart") + elif _is_fastapi_instance(server): + backend_cls = get_backend("fastapi") + else: + raise ValueError("Unsupported server type") + self.backend = backend_cls() self.server = server - if name is None: - caller_name = getattr(server, "name", caller_name) - elif isinstance(server, bool): - self.server = ( - self.server_factory.create_app(caller_name) if server else None - ) else: - raise ValueError( - "server must be a Flask app, a boolean, or a server factory function" - ) + # No server instance provided, create backend and let backend create server + self.backend = backend_cls() + self.server = server base_prefix, routes_prefix, requests_prefix = pathname_configs( url_base_pathname, routes_pathname_prefix, requests_pathname_prefix @@ -700,7 +730,7 @@ def init_app(self, app: Optional[Any] = None, **kwargs) -> None: self.server = app bp_prefix = config.routes_pathname_prefix.replace("/", "_").replace(".", "_") assets_blueprint_name = f"{bp_prefix}dash_assets" - self.server_factory.register_assets_blueprint( + self.backend.register_assets_blueprint( self.server, assets_blueprint_name, config.routes_pathname_prefix + self.config.assets_url_path.lstrip("/"), @@ -723,8 +753,8 @@ def init_app(self, app: Optional[Any] = None, **kwargs) -> None: raise ImportError( "To use the compress option, you need to install dash[compress]" ) from error - self.server_factory.register_error_handlers(self.server) - self.server_factory.before_request(self.server, self._setup_server) + self.backend.register_error_handlers(self.server) + self.backend.before_request(self.server, self._setup_server) self._setup_routes() _get_app.APP = self self.enable_pages() @@ -732,7 +762,7 @@ def init_app(self, app: Optional[Any] = None, **kwargs) -> None: def _add_url(self, name: str, view_func: RouteCallable, methods=("GET",)) -> None: full_name = self.config.routes_pathname_prefix + name - self.server_factory.add_url_rule( + self.backend.add_url_rule( self.server, full_name, view_func=view_func, @@ -742,21 +772,21 @@ def _add_url(self, name: str, view_func: RouteCallable, methods=("GET",)) -> Non self.routes.append(full_name) def _setup_routes(self): - self.server_factory.setup_component_suites(self) + self.backend.setup_component_suites(self) self._add_url("_dash-layout", self.serve_layout) self._add_url("_dash-dependencies", self.dependencies) self._add_url( "_dash-update-component", - self.server_factory.dispatch(self.server, self, self._use_async), + self.backend.dispatch(self.server, self, self._use_async), ["POST"], ) self._add_url("_reload-hash", self.serve_reload_hash) self._add_url( "_favicon.ico", - self.server_factory._serve_default_favicon, # pylint: disable=protected-access + self.backend._serve_default_favicon, # pylint: disable=protected-access ) - self.server_factory.setup_index(self) - self.server_factory.setup_catchall(self) + self.backend.setup_index(self) + self.backend.setup_catchall(self) if jupyter_dash.active: self._add_url( @@ -794,7 +824,7 @@ def setup_apis(self): self.callback_api_paths[k] = _callback.GLOBAL_API_PATHS.pop(k) # Delegate to the server factory for route registration - self.server_factory.register_callback_api_routes(self.server, self.callback_api_paths) + self.backend.register_callback_api_routes(self.server, self.callback_api_paths) def _setup_plotlyjs(self): # pylint: disable=import-outside-toplevel @@ -866,7 +896,7 @@ def serve_layout(self): layout = hook(layout) # TODO - Set browser cache limit - pass hash into frontend - return self.server_factory.make_response( + return self.backend.make_response( to_json(layout), mimetype="application/json", ) @@ -930,7 +960,7 @@ def serve_reload_hash(self): _reload.hard = False _reload.changed_assets = [] - return self.server_factory.jsonify( + return self.backend.jsonify( { "reloadHash": _hash, "hard": hard, @@ -1241,7 +1271,7 @@ def interpolate_index(self, **kwargs): @with_app_context def dependencies(self): - return self.server_factory.make_response( + return self.backend.make_response( to_json(self._callback_list), content_type="application/json", ) @@ -1360,7 +1390,7 @@ def _initialize_context(self, body, adapter): {"prop_id": x, "value": g.input_values.get(x)} for x in body.get("changedPropIds", []) ] - g.dash_response = self.server_factory.make_response( + g.dash_response = self.backend.make_response( mimetype="application/json", data=None ) g.cookies = dict(adapter.get_cookies()) @@ -1736,7 +1766,7 @@ def display_content(path): For nested URLs, slashes are still included: `app.strip_relative_path('/page-1/sub-page-1/')` will return - `page-1/sub-page-1` + `page-1/sub-page-1 ``` """ return _get_paths.app_strip_relative_path( @@ -1993,12 +2023,12 @@ def enable_dev_tools( ) elif dev_tools.prune_errors: secret = gen_salt(20) - self.server_factory.register_prune_error_handler( + self.backend.register_prune_error_handler( self.server, secret, _get_traceback ) if debug and dev_tools.ui: - self.server_factory.register_timing_hooks(self.server, first_run) + self.backend.register_timing_hooks(self.server, first_run) if ( debug @@ -2282,7 +2312,7 @@ def verify_url_part(served_part, url_part, part_name): server_url=jupyter_server_url, ) else: - self.server_factory.run( + self.backend.run( self.server, host=host, port=port, debug=debug, **flask_run_options ) @@ -2447,7 +2477,7 @@ def update(pathname_, search_, **states): Input(_ID_STORE, "data"), ) - self.server_factory.before_request(self.server, router) + self.backend.before_request(self.server, router) def __call__(self, *args, **kwargs): - return self.server_factory.__call__(self.server, *args, **kwargs) + return self.backend.__call__(self.server, *args, **kwargs) diff --git a/dash/server_factories/__init__.py b/dash/server_factories/__init__.py deleted file mode 100644 index 1bfd497935..0000000000 --- a/dash/server_factories/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -# python -import contextvars - -_request_adapter_var = contextvars.ContextVar("request_adapter") - - -def set_request_adapter(adapter): - _request_adapter_var.set(adapter) - - -def get_request_adapter(): - return _request_adapter_var.get() diff --git a/dash/server_factories/base_factory.py b/dash/server_factories/base_factory.py deleted file mode 100644 index 12088947c2..0000000000 --- a/dash/server_factories/base_factory.py +++ /dev/null @@ -1,50 +0,0 @@ -from abc import ABC, abstractmethod -from typing import Any - - -class BaseServerFactory(ABC): - def __call__(self, server, *args, **kwargs) -> Any: - # Default: WSGI - return server(*args, **kwargs) - - @abstractmethod - def create_app(self, name: str = "__main__", config=None) -> Any: # pragma: no cover - interface - pass - - @abstractmethod - def register_assets_blueprint( - self, app, blueprint_name: str, assets_url_path: str, assets_folder: str - ) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def register_error_handlers(self, app) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def add_url_rule(self, app, rule: str, view_func, endpoint=None, methods=None) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def before_request(self, app, func) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def after_request(self, app, func) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def run(self, app, host: str, port: int, debug: bool, **kwargs) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def make_response(self, data, mimetype=None, content_type=None) -> Any: # pragma: no cover - interface - pass - - @abstractmethod - def jsonify(self, obj) -> Any: # pragma: no cover - interface - pass - - @abstractmethod - def get_request_adapter(self) -> Any: # pragma: no cover - interface - pass diff --git a/dash/server_factories/fastapi_factory.py b/dash/server_factories/fastapi_factory.py deleted file mode 100644 index 1090c85050..0000000000 --- a/dash/server_factories/fastapi_factory.py +++ /dev/null @@ -1,370 +0,0 @@ -import sys -import mimetypes -import hashlib -import inspect -import pkgutil -from contextvars import copy_context -import importlib.util -import time - -try: - import uvicorn - from fastapi import FastAPI, Request, Response - from fastapi.responses import JSONResponse, PlainTextResponse - from fastapi.staticfiles import StaticFiles - from starlette.responses import Response as StarletteResponse - from starlette.datastructures import MutableHeaders - from pydantic import create_model - from typing import Any, Optional -except ImportError: - uvicorn = None - FastAPI = None - Request = None - Response = None - JSONResponse = None - PlainTextResponse = None - StaticFiles = None - StarletteResponse = None - MutableHeaders = None - create_model = None - Any = None - Optional = None - -from dash.fingerprint import check_fingerprint -from dash import _validate -from dash.exceptions import PreventUpdate, InvalidResourceError -from dash.server_factories import set_request_adapter -from .base_factory import BaseServerFactory - - -class FastAPIServerFactory(BaseServerFactory): - def __init__(self): - self.config = {} - super().__init__() - - def __call__(self, server, *args, **kwargs): - # ASGI: (scope, receive, send) - if len(args) == 3 and isinstance(args[0], dict) and "type" in args[0]: - return server(*args, **kwargs) - raise TypeError("FastAPI app must be called with (scope, receive, send)") - - def create_app(self, name="__main__", config=None): - app = FastAPI() - if config: - for key, value in config.items(): - setattr(app.state, key, value) - return app - - def register_assets_blueprint( - self, app, blueprint_name, assets_url_path, assets_folder - ): - try: - app.mount( - assets_url_path, - StaticFiles(directory=assets_folder), - name=blueprint_name, - ) - except RuntimeError: - # directory doesnt exist - pass - - def register_error_handlers(self, app): - @app.exception_handler(PreventUpdate) - async def _handle_error(_request, _exc): - return Response(status_code=204) - - @app.exception_handler(InvalidResourceError) - async def _invalid_resources_handler(_request, exc): - return Response(content=exc.args[0], status_code=404) - - def register_prune_error_handler(self, app, secret, get_traceback_func): - @app.exception_handler(Exception) - async def _wrap_errors(_error_request, error): - tb = get_traceback_func(secret, error) - return PlainTextResponse(tb, status_code=500) - - def _html_response_wrapper(self, view_func): - async def wrapped(*_args, **_kwargs): - # If view_func is a function, call it; if it's a string, use it directly - html = view_func() if callable(view_func) else view_func - return Response(content=html, media_type="text/html") - - return wrapped - - def setup_index(self, dash_app): - async def index(request: Request): - adapter = FastAPIRequestAdapter() - set_request_adapter(adapter) - adapter.set_request(request) - return Response(content=dash_app.index(), media_type="text/html") - - # pylint: disable=protected-access - dash_app._add_url("", index, methods=["GET"]) - - def setup_catchall(self, dash_app): - @dash_app.server.on_event("startup") - def _setup_catchall(): - dash_app.enable_dev_tools( - **self.config, first_run=False - ) # do this to make sure dev tools are enabled - - async def catchall(request: Request): - adapter = FastAPIRequestAdapter() - set_request_adapter(adapter) - adapter.set_request(request) - return Response(content=dash_app.index(), media_type="text/html") - - # pylint: disable=protected-access - dash_app._add_url("{path:path}", catchall, methods=["GET"]) - - def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None, include_in_schema=False): - if rule == "": - rule = "/" - if isinstance(view_func, str): - # Wrap string or sync function to async FastAPI handler - view_func = self._html_response_wrapper(view_func) - app.add_api_route( - rule, - view_func, - methods=methods or ["GET"], - name=endpoint, - include_in_schema=include_in_schema, - ) - - def before_request(self, app, func): - # FastAPI does not have before_request, but we can use middleware - app.middleware("http")(self._make_before_middleware(func)) - - def after_request(self, app, func): - # FastAPI does not have after_request, but we can use middleware - app.middleware("http")(self._make_after_middleware(func)) - - def run(self, app, host, port, debug, **kwargs): - frame = inspect.stack()[2] - self.config = dict({"debug": debug} if debug else {}, **kwargs) - reload = debug - if reload: - # Dynamically determine the module name from the file path - file_path = frame.filename - module_name = importlib.util.spec_from_file_location("app", file_path).name - uvicorn.run( - f"{module_name}:app.server", - host=host, - port=port, - reload=reload, - **kwargs, - ) - else: - uvicorn.run(app, host=host, port=port, reload=reload, **kwargs) - - def make_response(self, data, mimetype=None, content_type=None): - headers = {} - if mimetype: - headers["content-type"] = mimetype - if content_type: - headers["content-type"] = content_type - return Response(content=data, headers=headers) - - def jsonify(self, obj): - return JSONResponse(content=obj) - - def get_request_adapter(self): - return FastAPIRequestAdapter - - def _make_before_middleware(self, func): - async def middleware(request, call_next): - if func is not None: - if inspect.iscoroutinefunction(func): - await func() - else: - func() - response = await call_next(request) - return response - - return middleware - - def _make_after_middleware(self, func): - async def middleware(request, call_next): - response = await call_next(request) - if func is not None: - if inspect.iscoroutinefunction(func): - await func() - else: - func() - return response - - return middleware - - def serve_component_suites( - self, dash_app, package_name, fingerprinted_path, request - ): - path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) - _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) - extension = "." + path_in_pkg.split(".")[-1] - mimetype = mimetypes.types_map.get(extension, "application/octet-stream") - package = sys.modules[package_name] - dash_app.logger.debug( - "serving -- package: %s[%s] resource: %s => location: %s", - package_name, - package.__version__, - path_in_pkg, - package.__path__, - ) - data = pkgutil.get_data(package_name, path_in_pkg) - headers = {} - if has_fingerprint: - headers["Cache-Control"] = "public, max-age=31536000" - return StarletteResponse(content=data, media_type=mimetype, headers=headers) - etag = hashlib.md5(data).hexdigest() if data else "" - headers["ETag"] = etag - if request.headers.get("if-none-match") == etag: - return StarletteResponse(status_code=304) - return StarletteResponse(content=data, media_type=mimetype, headers=headers) - - def setup_component_suites(self, dash_app): - async def serve(request: Request, package_name: str, fingerprinted_path: str): - return self.serve_component_suites( - dash_app, package_name, fingerprinted_path, request - ) - - # pylint: disable=protected-access - dash_app._add_url( - "_dash-component-suites//", - serve, - ) - - # pylint: disable=unused-argument - def dispatch(self, app, dash_app, use_async=False): - async def _dispatch(request: Request): - adapter = FastAPIRequestAdapter() - set_request_adapter(adapter) - adapter.set_request(request) - # pylint: disable=protected-access - body = await request.json() - g = dash_app._initialize_context( - body, adapter - ) # pylint: disable=protected-access - func = dash_app._prepare_callback( - g, body - ) # pylint: disable=protected-access - args = dash_app._inputs_to_vals( - g.inputs_list + g.states_list - ) # pylint: disable=protected-access - ctx = copy_context() - partial_func = dash_app._execute_callback( - func, args, g.outputs_list, g - ) # pylint: disable=protected-access - response_data = ctx.run(partial_func) - if inspect.iscoroutine(response_data): - response_data = await response_data - # Instead of set_data, return a new Response - return Response(content=response_data, media_type="application/json") - - return _dispatch - - def _serve_default_favicon(self): - return Response( - content=pkgutil.get_data("dash", "favicon.ico"), media_type="image/x-icon" - ) - - def register_timing_hooks(self, app, first_run): - if not first_run: - return - - @app.middleware("http") - async def timing_middleware(request, call_next): - # Before request - request.state.timing_information = { - "__dash_server": {"dur": time.time(), "desc": None} - } - response = await call_next(request) - # After request - timing_information = getattr(request.state, "timing_information", None) - if timing_information is not None: - dash_total = timing_information.get("__dash_server", None) - if dash_total is not None: - dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) - headers = MutableHeaders(response.headers) - for name, info in timing_information.items(): - value = name - if info.get("desc") is not None: - value += f';desc="{info["desc"]}"' - if info.get("dur") is not None: - value += f";dur={info['dur']}" - headers.append("Server-Timing", value) - return response - - def register_callback_api_routes(self, app, callback_api_paths): - """ - Register callback API endpoints on the FastAPI app. - Each key in callback_api_paths is a route, each value is a handler (sync or async). - Dynamically creates a Pydantic model for the handler's parameters and uses it as the body parameter. - """ - for path, handler in callback_api_paths.items(): - endpoint = f"dash_callback_api_{path}" - route = path if path.startswith("/") else f"/{path}" - methods = ["POST"] - sig = inspect.signature(handler) - param_names = list(sig.parameters.keys()) - fields = {name: (Optional[Any], None) for name in param_names} - Model = create_model(f"Payload_{endpoint}", **fields) - - async def view_func(request: Request, body: Model): - kwargs = body.dict(exclude_unset=True) - if inspect.iscoroutinefunction(handler): - result = await handler(**kwargs) - else: - result = handler(**kwargs) - return JSONResponse(content=result) - - - app.add_api_route( - route, - view_func, - methods=methods, - name=endpoint, - include_in_schema=True, - ) - - -class FastAPIRequestAdapter: - def __init__(self): - self._request = None - - def set_request(self, request: Request): - self._request = request - - def get_root(self): - return str(self._request.base_url) - - def get_args(self): - return self._request.query_params - - async def get_json(self): - return await self._request.json() - - def is_json(self): - return self._request.headers.get("content-type", "").startswith( - "application/json" - ) - - def get_cookies(self, _request=None): - return self._request.cookies - - def get_headers(self): - return self._request.headers - - def get_full_path(self): - return str(self._request.url) - - def get_url(self): - return str(self._request.url) - - def get_remote_addr(self): - return self._request.client.host if self._request.client else None - - def get_origin(self): - return self._request.headers.get("origin") - - def get_path(self): - return self._request.url.path diff --git a/dash/server_factories/flask_factory.py b/dash/server_factories/flask_factory.py deleted file mode 100644 index a488a070e1..0000000000 --- a/dash/server_factories/flask_factory.py +++ /dev/null @@ -1,273 +0,0 @@ -from contextvars import copy_context -import asyncio -import pkgutil -import sys -import mimetypes -import time -import flask -import inspect -from dash.fingerprint import check_fingerprint -from dash import _validate -from dash.exceptions import PreventUpdate, InvalidResourceError -from dash.server_factories import set_request_adapter -from .base_factory import BaseServerFactory - - -class FlaskServerFactory(BaseServerFactory): - def __call__(self, server, *args, **kwargs): - # Always WSGI - return server(*args, **kwargs) - - def create_app(self, name="__main__", config=None): - app = flask.Flask(name) - if config: - app.config.update(config) - return app - - def register_assets_blueprint( - self, app, blueprint_name, assets_url_path, assets_folder - ): - bp = flask.Blueprint( - blueprint_name, - __name__, - static_folder=assets_folder, - static_url_path=assets_url_path, - ) - app.register_blueprint(bp) - - def register_error_handlers(self, app): - @app.errorhandler(PreventUpdate) - def _handle_error(_): - return "", 204 - - @app.errorhandler(InvalidResourceError) - def _invalid_resources_handler(err): - return err.args[0], 404 - - def register_prune_error_handler(self, app, secret, get_traceback_func): - @app.errorhandler(Exception) - def _wrap_errors(error): - tb = get_traceback_func(secret, error) - return tb, 500 - - def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): - app.add_url_rule( - rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"] - ) - - def before_request(self, app, func): - app.before_request(func) - - def after_request(self, app, func): - app.after_request(func) - - def run(self, app, host, port, debug, **kwargs): - app.run(host=host, port=port, debug=debug, **kwargs) - - def make_response(self, data, mimetype=None, content_type=None): - return flask.Response(data, mimetype=mimetype, content_type=content_type) - - def jsonify(self, obj): - return flask.jsonify(obj) - - def get_request_adapter(self): - return FlaskRequestAdapter - - def setup_catchall(self, dash_app): - def catchall(*args, **kwargs): - adapter = FlaskRequestAdapter() - set_request_adapter(adapter) - return dash_app.index(*args, **kwargs) - - # pylint: disable=protected-access - dash_app._add_url("", catchall, methods=["GET"]) - - def setup_index(self, dash_app): - def index(*args, **kwargs): - adapter = FlaskRequestAdapter() - set_request_adapter(adapter) - return dash_app.index(*args, **kwargs) - - # pylint: disable=protected-access - dash_app._add_url("", index, methods=["GET"]) - - def serve_component_suites(self, dash_app, package_name, fingerprinted_path): - path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) - _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) - extension = "." + path_in_pkg.split(".")[-1] - mimetype = mimetypes.types_map.get(extension, "application/octet-stream") - package = sys.modules[package_name] - dash_app.logger.debug( - "serving -- package: %s[%s] resource: %s => location: %s", - package_name, - package.__version__, - path_in_pkg, - package.__path__, - ) - data = pkgutil.get_data(package_name, path_in_pkg) - response = flask.Response(data, mimetype=mimetype) - if has_fingerprint: - response.cache_control.max_age = 31536000 # 1 year - else: - response.add_etag() - tag = response.get_etag()[0] - request_etag = flask.request.headers.get("If-None-Match") - if f'"{tag}"' == request_etag: - response = flask.Response(None, status=304) - return response - - def setup_component_suites(self, dash_app): - def serve(package_name, fingerprinted_path): - return self.serve_component_suites( - dash_app, package_name, fingerprinted_path - ) - - # pylint: disable=protected-access - dash_app._add_url( - "_dash-component-suites//", - serve, - ) - - # pylint: disable=unused-argument - def dispatch(self, app, dash_app, use_async=False): - def _dispatch(): - adapter = FlaskRequestAdapter() - set_request_adapter(adapter) - body = flask.request.get_json() - # pylint: disable=protected-access - g = dash_app._initialize_context(body, adapter) - func = dash_app._prepare_callback(g, body) - args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) - ctx = copy_context() - partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) - response_data = ctx.run(partial_func) - if asyncio.iscoroutine(response_data): - raise Exception( - "You are trying to use a coroutine without dash[async]. " - "Please install the dependencies via `pip install dash[async]` and ensure " - "that `use_async=False` is not being passed to the app." - ) - g.dash_response.set_data(response_data) - return g.dash_response - - async def _dispatch_async(): - adapter = FlaskRequestAdapter() - set_request_adapter(adapter) - body = flask.request.get_json() - # pylint: disable=protected-access - g = dash_app._initialize_context(body, adapter) - func = dash_app._prepare_callback(g, body) - args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) - ctx = copy_context() - partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) - response_data = ctx.run(partial_func) - if asyncio.iscoroutine(response_data): - response_data = await response_data - g.dash_response.set_data(response_data) - return g.dash_response - - if use_async: - return _dispatch_async - return _dispatch - - def _serve_default_favicon(self): - - return flask.Response( - pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" - ) - - def register_timing_hooks(self, app, _first_run): - def _before_request(): - flask.g.timing_information = { - "__dash_server": {"dur": time.time(), "desc": None} - } - - def _after_request(response): - timing_information = flask.g.get("timing_information", None) - if timing_information is None: - return response - dash_total = timing_information.get("__dash_server", None) - if dash_total is not None: - dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) - for name, info in timing_information.items(): - value = name - if info.get("desc") is not None: - value += f';desc="{info["desc"]}"' - if info.get("dur") is not None: - value += f";dur={info['dur']}" - response.headers.add("Server-Timing", value) - return response - - self.before_request(app, _before_request) - self.after_request(app, _after_request) - - def register_callback_api_routes(self, app, callback_api_paths): - """ - Register callback API endpoints on the Flask app. - Each key in callback_api_paths is a route, each value is a handler (sync or async). - The view function parses the JSON body and passes it to the handler. - """ - for path, handler in callback_api_paths.items(): - endpoint = f"dash_callback_api_{path}" - route = path if path.startswith("/") else f"/{path}" - methods = ["POST"] - - if inspect.iscoroutinefunction(handler): - async def view_func(*args, handler=handler, **kwargs): - data = flask.request.get_json() - result = await handler(**data) if data else await handler() - return flask.jsonify(result) - else: - def view_func(*args, handler=handler, **kwargs): - data = flask.request.get_json() - result = handler(**data) if data else handler() - return flask.jsonify(result) - - # Flask 2.x+ supports async views natively - app.add_url_rule(route, endpoint=endpoint, view_func=view_func, methods=methods) - - -class FlaskRequestAdapter: - @staticmethod - def get_args(): - return flask.request.args - - @staticmethod - def get_root(): - return flask.request.url_root - - @staticmethod - def get_json(): - return flask.request.get_json() - - @staticmethod - def is_json(): - return flask.request.is_json - - @staticmethod - def get_cookies(): - return flask.request.cookies - - @staticmethod - def get_headers(): - return flask.request.headers - - @staticmethod - def get_url(): - return flask.request.url - - @staticmethod - def get_full_path(): - return flask.request.full_path - - @staticmethod - def get_remote_addr(): - return flask.request.remote_addr - - @staticmethod - def get_origin(): - return getattr(flask.request, "origin", None) - - @staticmethod - def get_path(): - return flask.request.path From a4ca566d6810cce00ced20ea5d1b975c39cdc36a Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:13:23 -0400 Subject: [PATCH 033/297] adding missing files --- dash/backend/__init__.py | 13 ++ dash/backend/base_server.py | 50 +++++ dash/backend/fastapi.py | 370 ++++++++++++++++++++++++++++++++++++ dash/backend/flask.py | 273 ++++++++++++++++++++++++++ dash/backend/registry.py | 22 +++ 5 files changed, 728 insertions(+) create mode 100644 dash/backend/__init__.py create mode 100644 dash/backend/base_server.py create mode 100644 dash/backend/fastapi.py create mode 100644 dash/backend/flask.py create mode 100644 dash/backend/registry.py diff --git a/dash/backend/__init__.py b/dash/backend/__init__.py new file mode 100644 index 0000000000..497f2dca2d --- /dev/null +++ b/dash/backend/__init__.py @@ -0,0 +1,13 @@ +# python +import contextvars +from .registry import * + +_request_adapter_var = contextvars.ContextVar("request_adapter") + + +def set_request_adapter(adapter): + _request_adapter_var.set(adapter) + + +def get_request_adapter(): + return _request_adapter_var.get() diff --git a/dash/backend/base_server.py b/dash/backend/base_server.py new file mode 100644 index 0000000000..8c902f4248 --- /dev/null +++ b/dash/backend/base_server.py @@ -0,0 +1,50 @@ +from abc import ABC, abstractmethod +from typing import Any + + +class BaseDashServer(ABC): + def __call__(self, server, *args, **kwargs) -> Any: + # Default: WSGI + return server(*args, **kwargs) + + @abstractmethod + def create_app(self, name: str = "__main__", config=None) -> Any: # pragma: no cover - interface + pass + + @abstractmethod + def register_assets_blueprint( + self, app, blueprint_name: str, assets_url_path: str, assets_folder: str + ) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def register_error_handlers(self, app) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def add_url_rule(self, app, rule: str, view_func, endpoint=None, methods=None) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def before_request(self, app, func) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def after_request(self, app, func) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def run(self, app, host: str, port: int, debug: bool, **kwargs) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def make_response(self, data, mimetype=None, content_type=None) -> Any: # pragma: no cover - interface + pass + + @abstractmethod + def jsonify(self, obj) -> Any: # pragma: no cover - interface + pass + + @abstractmethod + def get_request_adapter(self) -> Any: # pragma: no cover - interface + pass diff --git a/dash/backend/fastapi.py b/dash/backend/fastapi.py new file mode 100644 index 0000000000..b2feeb446f --- /dev/null +++ b/dash/backend/fastapi.py @@ -0,0 +1,370 @@ +import sys +import mimetypes +import hashlib +import inspect +import pkgutil +from contextvars import copy_context +import importlib.util +import time + +try: + import uvicorn + from fastapi import FastAPI, Request, Response + from fastapi.responses import JSONResponse, PlainTextResponse + from fastapi.staticfiles import StaticFiles + from starlette.responses import Response as StarletteResponse + from starlette.datastructures import MutableHeaders + from pydantic import create_model + from typing import Any, Optional +except ImportError: + uvicorn = None + FastAPI = None + Request = None + Response = None + JSONResponse = None + PlainTextResponse = None + StaticFiles = None + StarletteResponse = None + MutableHeaders = None + create_model = None + Any = None + Optional = None + +from dash.fingerprint import check_fingerprint +from dash import _validate +from dash.exceptions import PreventUpdate, InvalidResourceError +from dash.backend import set_request_adapter +from .base_server import BaseDashServer + + +class FastAPIDashServer(BaseDashServer): + def __init__(self): + self.config = {} + super().__init__() + + def __call__(self, server, *args, **kwargs): + # ASGI: (scope, receive, send) + if len(args) == 3 and isinstance(args[0], dict) and "type" in args[0]: + return server(*args, **kwargs) + raise TypeError("FastAPI app must be called with (scope, receive, send)") + + def create_app(self, name="__main__", config=None): + app = FastAPI() + if config: + for key, value in config.items(): + setattr(app.state, key, value) + return app + + def register_assets_blueprint( + self, app, blueprint_name, assets_url_path, assets_folder + ): + try: + app.mount( + assets_url_path, + StaticFiles(directory=assets_folder), + name=blueprint_name, + ) + except RuntimeError: + # directory doesnt exist + pass + + def register_error_handlers(self, app): + @app.exception_handler(PreventUpdate) + async def _handle_error(_request, _exc): + return Response(status_code=204) + + @app.exception_handler(InvalidResourceError) + async def _invalid_resources_handler(_request, exc): + return Response(content=exc.args[0], status_code=404) + + def register_prune_error_handler(self, app, secret, get_traceback_func): + @app.exception_handler(Exception) + async def _wrap_errors(_error_request, error): + tb = get_traceback_func(secret, error) + return PlainTextResponse(tb, status_code=500) + + def _html_response_wrapper(self, view_func): + async def wrapped(*_args, **_kwargs): + # If view_func is a function, call it; if it's a string, use it directly + html = view_func() if callable(view_func) else view_func + return Response(content=html, media_type="text/html") + + return wrapped + + def setup_index(self, dash_app): + async def index(request: Request): + adapter = FastAPIRequestAdapter() + set_request_adapter(adapter) + adapter.set_request(request) + return Response(content=dash_app.index(), media_type="text/html") + + # pylint: disable=protected-access + dash_app._add_url("", index, methods=["GET"]) + + def setup_catchall(self, dash_app): + @dash_app.server.on_event("startup") + def _setup_catchall(): + dash_app.enable_dev_tools( + **self.config, first_run=False + ) # do this to make sure dev tools are enabled + + async def catchall(request: Request): + adapter = FastAPIRequestAdapter() + set_request_adapter(adapter) + adapter.set_request(request) + return Response(content=dash_app.index(), media_type="text/html") + + # pylint: disable=protected-access + dash_app._add_url("{path:path}", catchall, methods=["GET"]) + + def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None, include_in_schema=False): + if rule == "": + rule = "/" + if isinstance(view_func, str): + # Wrap string or sync function to async FastAPI handler + view_func = self._html_response_wrapper(view_func) + app.add_api_route( + rule, + view_func, + methods=methods or ["GET"], + name=endpoint, + include_in_schema=include_in_schema, + ) + + def before_request(self, app, func): + # FastAPI does not have before_request, but we can use middleware + app.middleware("http")(self._make_before_middleware(func)) + + def after_request(self, app, func): + # FastAPI does not have after_request, but we can use middleware + app.middleware("http")(self._make_after_middleware(func)) + + def run(self, app, host, port, debug, **kwargs): + frame = inspect.stack()[2] + self.config = dict({"debug": debug} if debug else {}, **kwargs) + reload = debug + if reload: + # Dynamically determine the module name from the file path + file_path = frame.filename + module_name = importlib.util.spec_from_file_location("app", file_path).name + uvicorn.run( + f"{module_name}:app.server", + host=host, + port=port, + reload=reload, + **kwargs, + ) + else: + uvicorn.run(app, host=host, port=port, reload=reload, **kwargs) + + def make_response(self, data, mimetype=None, content_type=None): + headers = {} + if mimetype: + headers["content-type"] = mimetype + if content_type: + headers["content-type"] = content_type + return Response(content=data, headers=headers) + + def jsonify(self, obj): + return JSONResponse(content=obj) + + def get_request_adapter(self): + return FastAPIRequestAdapter + + def _make_before_middleware(self, func): + async def middleware(request, call_next): + if func is not None: + if inspect.iscoroutinefunction(func): + await func() + else: + func() + response = await call_next(request) + return response + + return middleware + + def _make_after_middleware(self, func): + async def middleware(request, call_next): + response = await call_next(request) + if func is not None: + if inspect.iscoroutinefunction(func): + await func() + else: + func() + return response + + return middleware + + def serve_component_suites( + self, dash_app, package_name, fingerprinted_path, request + ): + path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) + _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) + extension = "." + path_in_pkg.split(".")[-1] + mimetype = mimetypes.types_map.get(extension, "application/octet-stream") + package = sys.modules[package_name] + dash_app.logger.debug( + "serving -- package: %s[%s] resource: %s => location: %s", + package_name, + package.__version__, + path_in_pkg, + package.__path__, + ) + data = pkgutil.get_data(package_name, path_in_pkg) + headers = {} + if has_fingerprint: + headers["Cache-Control"] = "public, max-age=31536000" + return StarletteResponse(content=data, media_type=mimetype, headers=headers) + etag = hashlib.md5(data).hexdigest() if data else "" + headers["ETag"] = etag + if request.headers.get("if-none-match") == etag: + return StarletteResponse(status_code=304) + return StarletteResponse(content=data, media_type=mimetype, headers=headers) + + def setup_component_suites(self, dash_app): + async def serve(request: Request, package_name: str, fingerprinted_path: str): + return self.serve_component_suites( + dash_app, package_name, fingerprinted_path, request + ) + + # pylint: disable=protected-access + dash_app._add_url( + "_dash-component-suites//", + serve, + ) + + # pylint: disable=unused-argument + def dispatch(self, app, dash_app, use_async=False): + async def _dispatch(request: Request): + adapter = FastAPIRequestAdapter() + set_request_adapter(adapter) + adapter.set_request(request) + # pylint: disable=protected-access + body = await request.json() + g = dash_app._initialize_context( + body, adapter + ) # pylint: disable=protected-access + func = dash_app._prepare_callback( + g, body + ) # pylint: disable=protected-access + args = dash_app._inputs_to_vals( + g.inputs_list + g.states_list + ) # pylint: disable=protected-access + ctx = copy_context() + partial_func = dash_app._execute_callback( + func, args, g.outputs_list, g + ) # pylint: disable=protected-access + response_data = ctx.run(partial_func) + if inspect.iscoroutine(response_data): + response_data = await response_data + # Instead of set_data, return a new Response + return Response(content=response_data, media_type="application/json") + + return _dispatch + + def _serve_default_favicon(self): + return Response( + content=pkgutil.get_data("dash", "favicon.ico"), media_type="image/x-icon" + ) + + def register_timing_hooks(self, app, first_run): + if not first_run: + return + + @app.middleware("http") + async def timing_middleware(request, call_next): + # Before request + request.state.timing_information = { + "__dash_server": {"dur": time.time(), "desc": None} + } + response = await call_next(request) + # After request + timing_information = getattr(request.state, "timing_information", None) + if timing_information is not None: + dash_total = timing_information.get("__dash_server", None) + if dash_total is not None: + dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) + headers = MutableHeaders(response.headers) + for name, info in timing_information.items(): + value = name + if info.get("desc") is not None: + value += f';desc="{info["desc"]}"' + if info.get("dur") is not None: + value += f";dur={info['dur']}" + headers.append("Server-Timing", value) + return response + + def register_callback_api_routes(self, app, callback_api_paths): + """ + Register callback API endpoints on the FastAPI app. + Each key in callback_api_paths is a route, each value is a handler (sync or async). + Dynamically creates a Pydantic model for the handler's parameters and uses it as the body parameter. + """ + for path, handler in callback_api_paths.items(): + endpoint = f"dash_callback_api_{path}" + route = path if path.startswith("/") else f"/{path}" + methods = ["POST"] + sig = inspect.signature(handler) + param_names = list(sig.parameters.keys()) + fields = {name: (Optional[Any], None) for name in param_names} + Model = create_model(f"Payload_{endpoint}", **fields) + + async def view_func(request: Request, body: Model): + kwargs = body.dict(exclude_unset=True) + if inspect.iscoroutinefunction(handler): + result = await handler(**kwargs) + else: + result = handler(**kwargs) + return JSONResponse(content=result) + + + app.add_api_route( + route, + view_func, + methods=methods, + name=endpoint, + include_in_schema=True, + ) + + +class FastAPIRequestAdapter: + def __init__(self): + self._request = None + + def set_request(self, request: Request): + self._request = request + + def get_root(self): + return str(self._request.base_url) + + def get_args(self): + return self._request.query_params + + async def get_json(self): + return await self._request.json() + + def is_json(self): + return self._request.headers.get("content-type", "").startswith( + "application/json" + ) + + def get_cookies(self, _request=None): + return self._request.cookies + + def get_headers(self): + return self._request.headers + + def get_full_path(self): + return str(self._request.url) + + def get_url(self): + return str(self._request.url) + + def get_remote_addr(self): + return self._request.client.host if self._request.client else None + + def get_origin(self): + return self._request.headers.get("origin") + + def get_path(self): + return self._request.url.path diff --git a/dash/backend/flask.py b/dash/backend/flask.py new file mode 100644 index 0000000000..2d7d01af32 --- /dev/null +++ b/dash/backend/flask.py @@ -0,0 +1,273 @@ +from contextvars import copy_context +import asyncio +import pkgutil +import sys +import mimetypes +import time +import flask +import inspect +from dash.fingerprint import check_fingerprint +from dash import _validate +from dash.exceptions import PreventUpdate, InvalidResourceError +from dash.backend import set_request_adapter +from .base_server import BaseDashServer + + +class FlaskDashServer(BaseDashServer): + def __call__(self, server, *args, **kwargs): + # Always WSGI + return server(*args, **kwargs) + + def create_app(self, name="__main__", config=None): + app = flask.Flask(name) + if config: + app.config.update(config) + return app + + def register_assets_blueprint( + self, app, blueprint_name, assets_url_path, assets_folder + ): + bp = flask.Blueprint( + blueprint_name, + __name__, + static_folder=assets_folder, + static_url_path=assets_url_path, + ) + app.register_blueprint(bp) + + def register_error_handlers(self, app): + @app.errorhandler(PreventUpdate) + def _handle_error(_): + return "", 204 + + @app.errorhandler(InvalidResourceError) + def _invalid_resources_handler(err): + return err.args[0], 404 + + def register_prune_error_handler(self, app, secret, get_traceback_func): + @app.errorhandler(Exception) + def _wrap_errors(error): + tb = get_traceback_func(secret, error) + return tb, 500 + + def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): + app.add_url_rule( + rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"] + ) + + def before_request(self, app, func): + app.before_request(func) + + def after_request(self, app, func): + app.after_request(func) + + def run(self, app, host, port, debug, **kwargs): + app.run(host=host, port=port, debug=debug, **kwargs) + + def make_response(self, data, mimetype=None, content_type=None): + return flask.Response(data, mimetype=mimetype, content_type=content_type) + + def jsonify(self, obj): + return flask.jsonify(obj) + + def get_request_adapter(self): + return FlaskRequestAdapter + + def setup_catchall(self, dash_app): + def catchall(*args, **kwargs): + adapter = FlaskRequestAdapter() + set_request_adapter(adapter) + return dash_app.index(*args, **kwargs) + + # pylint: disable=protected-access + dash_app._add_url("", catchall, methods=["GET"]) + + def setup_index(self, dash_app): + def index(*args, **kwargs): + adapter = FlaskRequestAdapter() + set_request_adapter(adapter) + return dash_app.index(*args, **kwargs) + + # pylint: disable=protected-access + dash_app._add_url("", index, methods=["GET"]) + + def serve_component_suites(self, dash_app, package_name, fingerprinted_path): + path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) + _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) + extension = "." + path_in_pkg.split(".")[-1] + mimetype = mimetypes.types_map.get(extension, "application/octet-stream") + package = sys.modules[package_name] + dash_app.logger.debug( + "serving -- package: %s[%s] resource: %s => location: %s", + package_name, + package.__version__, + path_in_pkg, + package.__path__, + ) + data = pkgutil.get_data(package_name, path_in_pkg) + response = flask.Response(data, mimetype=mimetype) + if has_fingerprint: + response.cache_control.max_age = 31536000 # 1 year + else: + response.add_etag() + tag = response.get_etag()[0] + request_etag = flask.request.headers.get("If-None-Match") + if f'"{tag}"' == request_etag: + response = flask.Response(None, status=304) + return response + + def setup_component_suites(self, dash_app): + def serve(package_name, fingerprinted_path): + return self.serve_component_suites( + dash_app, package_name, fingerprinted_path + ) + + # pylint: disable=protected-access + dash_app._add_url( + "_dash-component-suites//", + serve, + ) + + # pylint: disable=unused-argument + def dispatch(self, app, dash_app, use_async=False): + def _dispatch(): + adapter = FlaskRequestAdapter() + set_request_adapter(adapter) + body = flask.request.get_json() + # pylint: disable=protected-access + g = dash_app._initialize_context(body, adapter) + func = dash_app._prepare_callback(g, body) + args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) + ctx = copy_context() + partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) + response_data = ctx.run(partial_func) + if asyncio.iscoroutine(response_data): + raise Exception( + "You are trying to use a coroutine without dash[async]. " + "Please install the dependencies via `pip install dash[async]` and ensure " + "that `use_async=False` is not being passed to the app." + ) + g.dash_response.set_data(response_data) + return g.dash_response + + async def _dispatch_async(): + adapter = FlaskRequestAdapter() + set_request_adapter(adapter) + body = flask.request.get_json() + # pylint: disable=protected-access + g = dash_app._initialize_context(body, adapter) + func = dash_app._prepare_callback(g, body) + args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) + ctx = copy_context() + partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) + response_data = ctx.run(partial_func) + if asyncio.iscoroutine(response_data): + response_data = await response_data + g.dash_response.set_data(response_data) + return g.dash_response + + if use_async: + return _dispatch_async + return _dispatch + + def _serve_default_favicon(self): + + return flask.Response( + pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" + ) + + def register_timing_hooks(self, app, _first_run): + def _before_request(): + flask.g.timing_information = { + "__dash_server": {"dur": time.time(), "desc": None} + } + + def _after_request(response): + timing_information = flask.g.get("timing_information", None) + if timing_information is None: + return response + dash_total = timing_information.get("__dash_server", None) + if dash_total is not None: + dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) + for name, info in timing_information.items(): + value = name + if info.get("desc") is not None: + value += f';desc="{info["desc"]}"' + if info.get("dur") is not None: + value += f";dur={info['dur']}" + response.headers.add("Server-Timing", value) + return response + + self.before_request(app, _before_request) + self.after_request(app, _after_request) + + def register_callback_api_routes(self, app, callback_api_paths): + """ + Register callback API endpoints on the Flask app. + Each key in callback_api_paths is a route, each value is a handler (sync or async). + The view function parses the JSON body and passes it to the handler. + """ + for path, handler in callback_api_paths.items(): + endpoint = f"dash_callback_api_{path}" + route = path if path.startswith("/") else f"/{path}" + methods = ["POST"] + + if inspect.iscoroutinefunction(handler): + async def view_func(*args, handler=handler, **kwargs): + data = flask.request.get_json() + result = await handler(**data) if data else await handler() + return flask.jsonify(result) + else: + def view_func(*args, handler=handler, **kwargs): + data = flask.request.get_json() + result = handler(**data) if data else handler() + return flask.jsonify(result) + + # Flask 2.x+ supports async views natively + app.add_url_rule(route, endpoint=endpoint, view_func=view_func, methods=methods) + + +class FlaskRequestAdapter: + @staticmethod + def get_args(): + return flask.request.args + + @staticmethod + def get_root(): + return flask.request.url_root + + @staticmethod + def get_json(): + return flask.request.get_json() + + @staticmethod + def is_json(): + return flask.request.is_json + + @staticmethod + def get_cookies(): + return flask.request.cookies + + @staticmethod + def get_headers(): + return flask.request.headers + + @staticmethod + def get_url(): + return flask.request.url + + @staticmethod + def get_full_path(): + return flask.request.full_path + + @staticmethod + def get_remote_addr(): + return flask.request.remote_addr + + @staticmethod + def get_origin(): + return getattr(flask.request, "origin", None) + + @staticmethod + def get_path(): + return flask.request.path diff --git a/dash/backend/registry.py b/dash/backend/registry.py new file mode 100644 index 0000000000..1b80da879f --- /dev/null +++ b/dash/backend/registry.py @@ -0,0 +1,22 @@ +import importlib + +_backend_imports = { + 'flask': ('dash.backend.flask', 'FlaskDashServer'), + 'fastapi': ('dash.backend.fastapi', 'FastAPIDashServer'), + 'quart': ('dash.backend.quart', 'QuartDashServer'), +} + +def register_backend(name, module_path, class_name): + """Register a new backend by name.""" + _backend_imports[name.lower()] = (module_path, class_name) + +def get_backend(name): + try: + module_name, class_name = _backend_imports[name.lower()] + module = importlib.import_module(module_name) + return getattr(module, class_name) + except KeyError: + raise ValueError(f"Unknown backend: {name}") + except (ImportError, AttributeError) as e: + raise ImportError(f"Could not import backend '{name}': {e}") + From 708773f3d4f21cc1ef61fdc244010959c9c8567b Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:15:24 -0400 Subject: [PATCH 034/297] fixing issue with server not declared --- dash/dash.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dash/dash.py b/dash/dash.py index 0e7cbb25fa..22f79873bb 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -540,8 +540,10 @@ def __init__( # pylint: disable=too-many-statements self.server = server else: # No server instance provided, create backend and let backend create server + if server is True and backend_cls is None: + backend_cls = FlaskDashServer self.backend = backend_cls() - self.server = server + self.server = self.backend.create_app(caller_name) # type: ignore base_prefix, routes_prefix, requests_prefix = pathname_configs( url_base_pathname, routes_pathname_prefix, requests_pathname_prefix From b7bcebaf442e10455987dd72b02c98a1e680578f Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:16:50 -0400 Subject: [PATCH 035/297] Update dash/dash.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- dash/dash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/dash.py b/dash/dash.py index 22f79873bb..2000114067 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -526,7 +526,7 @@ def __init__( # pylint: disable=too-many-statements raise ValueError("Invalid backend argument") # Determine server and backend instance - if server is not None and server is not True and server is not False: + if server not in (None, True, False): # User provided a server instance (e.g., Flask, Quart, FastAPI) if _is_flask_instance(server): backend_cls = get_backend("flask") From 9873079800f773ef09581159312b7f0b48209f67 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:17:01 -0400 Subject: [PATCH 036/297] Update dash/dash.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- dash/dash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/dash.py b/dash/dash.py index 2000114067..af9ab03139 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -1768,7 +1768,7 @@ def display_content(path): For nested URLs, slashes are still included: `app.strip_relative_path('/page-1/sub-page-1/')` will return - `page-1/sub-page-1 + `page-1/sub-page-1` ``` """ return _get_paths.app_strip_relative_path( From 9f4d291689c05cada98f4ad9fe380aa718ae56ac Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:17:16 -0400 Subject: [PATCH 037/297] Update dash/backend/quart.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- dash/backend/quart.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/dash/backend/quart.py b/dash/backend/quart.py index a2437811a4..5bb568fe72 100644 --- a/dash/backend/quart.py +++ b/dash/backend/quart.py @@ -207,17 +207,21 @@ def register_callback_api_routes(self, app, callback_api_paths): route = path if path.startswith("/") else f"/{path}" methods = ["POST"] - if inspect.iscoroutinefunction(handler): - async def view_func(*args, handler=handler, **kwargs): - data = await request.get_json() - result = await handler(**data) if data else await handler() - return jsonify(result) - else: - async def view_func(*args, handler=handler, **kwargs): - data = await request.get_json() - result = handler(**data) if data else handler() - return jsonify(result) - + def _make_view_func(handler): + if inspect.iscoroutinefunction(handler): + async def async_view_func(*args, **kwargs): + data = await request.get_json() + result = await handler(**data) if data else await handler() + return jsonify(result) + return async_view_func + else: + async def sync_view_func(*args, **kwargs): + data = await request.get_json() + result = handler(**data) if data else handler() + return jsonify(result) + return sync_view_func + + view_func = _make_view_func(handler) app.add_url_rule(route, endpoint=endpoint, view_func=view_func, methods=methods) def _serve_default_favicon(self): From da86e8666b731375bf251a0f76fd5eb8d360b6a9 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:17:52 -0400 Subject: [PATCH 038/297] Update dash/dash.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- dash/dash.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index af9ab03139..242f4cbd91 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -540,8 +540,6 @@ def __init__( # pylint: disable=too-many-statements self.server = server else: # No server instance provided, create backend and let backend create server - if server is True and backend_cls is None: - backend_cls = FlaskDashServer self.backend = backend_cls() self.server = self.backend.create_app(caller_name) # type: ignore From 4c60740a5f98e2e2612cbb8c0dbf22d324345255 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:22:44 -0400 Subject: [PATCH 039/297] Update dash/dash.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- dash/dash.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index 242f4cbd91..0e7be84128 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -529,13 +529,33 @@ def __init__( # pylint: disable=too-many-statements if server not in (None, True, False): # User provided a server instance (e.g., Flask, Quart, FastAPI) if _is_flask_instance(server): - backend_cls = get_backend("flask") + inferred_backend = "flask" elif _is_quart_instance(server): - backend_cls = get_backend("quart") + inferred_backend = "quart" elif _is_fastapi_instance(server): - backend_cls = get_backend("fastapi") + inferred_backend = "fastapi" else: raise ValueError("Unsupported server type") + # Validate that backend matches server type if both are provided + if backend is not None: + if isinstance(backend, str): + requested_backend = backend + elif isinstance(backend, type): + # get_backend returns the backend class for a string + # So we compare the class names + requested_backend = get_backend(inferred_backend).__name__.lower() + backend_name = backend.__name__.lower() + if backend_name != requested_backend: + raise ValueError( + f"Conflict between provided backend '{backend_name}' and server type '{inferred_backend}'." + ) + else: + raise ValueError("Invalid backend argument") + if isinstance(backend, str) and backend.lower() != inferred_backend: + raise ValueError( + f"Conflict between provided backend '{backend}' and server type '{inferred_backend}'." + ) + backend_cls = get_backend(inferred_backend) self.backend = backend_cls() self.server = server else: From 84cb5e52de9e5046009ce4913f160cbaf435cac0 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:25:37 -0400 Subject: [PATCH 040/297] update for caller_name --- dash/dash.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dash/dash.py b/dash/dash.py index 0e7be84128..4aa18bd9c0 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -558,6 +558,9 @@ def __init__( # pylint: disable=too-many-statements backend_cls = get_backend(inferred_backend) self.backend = backend_cls() self.server = server + # Update caller_name from server's name attribute if available + if hasattr(server, "name"): + caller_name = server.name else: # No server instance provided, create backend and let backend create server self.backend = backend_cls() From 29cf8232684cd881034ad5986c8de51bc580a9e4 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:27:30 -0400 Subject: [PATCH 041/297] Update dash/dash.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- dash/dash.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index 4aa18bd9c0..05249fe583 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -543,11 +543,10 @@ def __init__( # pylint: disable=too-many-statements elif isinstance(backend, type): # get_backend returns the backend class for a string # So we compare the class names - requested_backend = get_backend(inferred_backend).__name__.lower() - backend_name = backend.__name__.lower() - if backend_name != requested_backend: + expected_backend_cls = get_backend(inferred_backend) + if backend is not expected_backend_cls: raise ValueError( - f"Conflict between provided backend '{backend_name}' and server type '{inferred_backend}'." + f"Conflict between provided backend '{backend.__name__}' and server type '{inferred_backend}'." ) else: raise ValueError("Invalid backend argument") From 5d0f4dced2c362eb89c1211ca31a296aa69eda26 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:30:45 -0400 Subject: [PATCH 042/297] Update dash/dash.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- dash/dash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/dash.py b/dash/dash.py index 05249fe583..ce44c936ef 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -271,7 +271,7 @@ class Dash(ObsoleteChecker): :param backend: The backend to use for the Dash app. Can be a string (name of the backend) or a backend class. Default is None, which - selects the Flask backend. Currently, "flask" and "fastapi" backends + selects the Flask backend. Currently, "flask", "fastapi", and "quart" backends are supported. :type backend: string or type From 86f452873a4c8c9068296154578e7a05121d5f4d Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:33:10 -0400 Subject: [PATCH 043/297] adjustments for matching types --- dash/dash.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index 05249fe583..db77f3f4fb 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -538,9 +538,7 @@ def __init__( # pylint: disable=too-many-statements raise ValueError("Unsupported server type") # Validate that backend matches server type if both are provided if backend is not None: - if isinstance(backend, str): - requested_backend = backend - elif isinstance(backend, type): + if isinstance(backend, type): # get_backend returns the backend class for a string # So we compare the class names expected_backend_cls = get_backend(inferred_backend) @@ -548,9 +546,9 @@ def __init__( # pylint: disable=too-many-statements raise ValueError( f"Conflict between provided backend '{backend.__name__}' and server type '{inferred_backend}'." ) - else: + elif not isinstance(backend, str): raise ValueError("Invalid backend argument") - if isinstance(backend, str) and backend.lower() != inferred_backend: + elif backend.lower() != inferred_backend: raise ValueError( f"Conflict between provided backend '{backend}' and server type '{inferred_backend}'." ) From 2a88385f46fa57758f2ba1023526db892cbcadf7 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:33:38 -0400 Subject: [PATCH 044/297] Update dash/backend/registry.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- dash/backend/registry.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dash/backend/registry.py b/dash/backend/registry.py index 1b80da879f..4aac7142ef 100644 --- a/dash/backend/registry.py +++ b/dash/backend/registry.py @@ -17,6 +17,8 @@ def get_backend(name): return getattr(module, class_name) except KeyError: raise ValueError(f"Unknown backend: {name}") - except (ImportError, AttributeError) as e: - raise ImportError(f"Could not import backend '{name}': {e}") + except ImportError as e: + raise ImportError(f"Could not import module '{module_name}' for backend '{name}': {e}") + except AttributeError as e: + raise AttributeError(f"Module '{module_name}' does not have class '{class_name}' for backend '{name}': {e}") From bc51c0d0269cf0fba3d25e4f07a26cfad0f3bf06 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:35:54 -0400 Subject: [PATCH 045/297] Update dash/backend/registry.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- dash/backend/registry.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dash/backend/registry.py b/dash/backend/registry.py index 4aac7142ef..fb9c99cc2d 100644 --- a/dash/backend/registry.py +++ b/dash/backend/registry.py @@ -15,10 +15,10 @@ def get_backend(name): module_name, class_name = _backend_imports[name.lower()] module = importlib.import_module(module_name) return getattr(module, class_name) - except KeyError: - raise ValueError(f"Unknown backend: {name}") + except KeyError as e: + raise ValueError(f"Unknown backend: {name}") from e except ImportError as e: - raise ImportError(f"Could not import module '{module_name}' for backend '{name}': {e}") + raise ImportError(f"Could not import module '{module_name}' for backend '{name}': {e}") from e except AttributeError as e: - raise AttributeError(f"Module '{module_name}' does not have class '{class_name}' for backend '{name}': {e}") + raise AttributeError(f"Module '{module_name}' does not have class '{class_name}' for backend '{name}': {e}") from e From 1b4d0d3f767ab0ca6ffd2829d5b75c03642fbcef Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:38:03 -0400 Subject: [PATCH 046/297] fixing another type check --- dash/dash.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dash/dash.py b/dash/dash.py index aa9e4c51ca..a95f969faa 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -542,7 +542,10 @@ def __init__( # pylint: disable=too-many-statements # get_backend returns the backend class for a string # So we compare the class names expected_backend_cls = get_backend(inferred_backend) - if backend is not expected_backend_cls: + if ( + backend.__module__ != expected_backend_cls.__module__ + or backend.__name__ != expected_backend_cls.__name__ + ): raise ValueError( f"Conflict between provided backend '{backend.__name__}' and server type '{inferred_backend}'." ) From f867f98fd791ec790d755f75eb0a6e5b8a986117 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 21:03:26 -0400 Subject: [PATCH 047/297] fixing for lint --- dash/backend/__init__.py | 4 +- dash/backend/base_server.py | 16 +++++-- dash/backend/fastapi.py | 10 ++-- dash/backend/flask.py | 9 +++- dash/backend/quart.py | 91 +++++++++++++++++++++++-------------- dash/backend/registry.py | 17 ++++--- dash/dash.py | 11 ++++- 7 files changed, 108 insertions(+), 50 deletions(-) diff --git a/dash/backend/__init__.py b/dash/backend/__init__.py index 497f2dca2d..eb1d47bc3f 100644 --- a/dash/backend/__init__.py +++ b/dash/backend/__init__.py @@ -1,6 +1,8 @@ # python import contextvars -from .registry import * +from .registry import get_backend # pylint: disable=unused-import + +__all__ = ["set_request_adapter", "get_request_adapter", "get_backend"] _request_adapter_var = contextvars.ContextVar("request_adapter") diff --git a/dash/backend/base_server.py b/dash/backend/base_server.py index 8c902f4248..4855f86ad6 100644 --- a/dash/backend/base_server.py +++ b/dash/backend/base_server.py @@ -8,7 +8,9 @@ def __call__(self, server, *args, **kwargs) -> Any: return server(*args, **kwargs) @abstractmethod - def create_app(self, name: str = "__main__", config=None) -> Any: # pragma: no cover - interface + def create_app( + self, name: str = "__main__", config=None + ) -> Any: # pragma: no cover - interface pass @abstractmethod @@ -22,7 +24,9 @@ def register_error_handlers(self, app) -> None: # pragma: no cover - interface pass @abstractmethod - def add_url_rule(self, app, rule: str, view_func, endpoint=None, methods=None) -> None: # pragma: no cover - interface + def add_url_rule( + self, app, rule: str, view_func, endpoint=None, methods=None + ) -> None: # pragma: no cover - interface pass @abstractmethod @@ -34,11 +38,15 @@ def after_request(self, app, func) -> None: # pragma: no cover - interface pass @abstractmethod - def run(self, app, host: str, port: int, debug: bool, **kwargs) -> None: # pragma: no cover - interface + def run( + self, app, host: str, port: int, debug: bool, **kwargs + ) -> None: # pragma: no cover - interface pass @abstractmethod - def make_response(self, data, mimetype=None, content_type=None) -> Any: # pragma: no cover - interface + def make_response( + self, data, mimetype=None, content_type=None + ) -> Any: # pragma: no cover - interface pass @abstractmethod diff --git a/dash/backend/fastapi.py b/dash/backend/fastapi.py index b2feeb446f..d283e90346 100644 --- a/dash/backend/fastapi.py +++ b/dash/backend/fastapi.py @@ -117,7 +117,9 @@ async def catchall(request: Request): # pylint: disable=protected-access dash_app._add_url("{path:path}", catchall, methods=["GET"]) - def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None, include_in_schema=False): + def add_url_rule( + self, app, rule, view_func, endpoint=None, methods=None, include_in_schema=False + ): if rule == "": rule = "/" if isinstance(view_func, str): @@ -307,8 +309,11 @@ def register_callback_api_routes(self, app, callback_api_paths): sig = inspect.signature(handler) param_names = list(sig.parameters.keys()) fields = {name: (Optional[Any], None) for name in param_names} - Model = create_model(f"Payload_{endpoint}", **fields) + Model = create_model( + f"Payload_{endpoint}", **fields + ) # pylint: disable=cell-var-from-loop + # pylint: disable=cell-var-from-loop async def view_func(request: Request, body: Model): kwargs = body.dict(exclude_unset=True) if inspect.iscoroutinefunction(handler): @@ -317,7 +322,6 @@ async def view_func(request: Request, body: Model): result = handler(**kwargs) return JSONResponse(content=result) - app.add_api_route( route, view_func, diff --git a/dash/backend/flask.py b/dash/backend/flask.py index 2d7d01af32..b48225a3c5 100644 --- a/dash/backend/flask.py +++ b/dash/backend/flask.py @@ -4,8 +4,8 @@ import sys import mimetypes import time -import flask import inspect +import flask from dash.fingerprint import check_fingerprint from dash import _validate from dash.exceptions import PreventUpdate, InvalidResourceError @@ -213,18 +213,23 @@ def register_callback_api_routes(self, app, callback_api_paths): methods = ["POST"] if inspect.iscoroutinefunction(handler): + async def view_func(*args, handler=handler, **kwargs): data = flask.request.get_json() result = await handler(**data) if data else await handler() return flask.jsonify(result) + else: + def view_func(*args, handler=handler, **kwargs): data = flask.request.get_json() result = handler(**data) if data else handler() return flask.jsonify(result) # Flask 2.x+ supports async views natively - app.add_url_rule(route, endpoint=endpoint, view_func=view_func, methods=methods) + app.add_url_rule( + route, endpoint=endpoint, view_func=view_func, methods=methods + ) class FlaskRequestAdapter: diff --git a/dash/backend/quart.py b/dash/backend/quart.py index 5bb568fe72..c3d42dadee 100644 --- a/dash/backend/quart.py +++ b/dash/backend/quart.py @@ -1,15 +1,25 @@ -from .base_server import BaseDashServer -from quart import Quart, Request, Response, jsonify, request -from dash.exceptions import PreventUpdate, InvalidResourceError -from dash.backend import set_request_adapter -from dash.fingerprint import check_fingerprint -from dash import _validate -from contextvars import copy_context import inspect import pkgutil import mimetypes import sys import time +from contextvars import copy_context + +try: + import quart + from quart import Quart, Response, jsonify, request, Blueprint +except ImportError: + quart = None + Quart = None + Response = None + jsonify = None + request = None + Blueprint = None +from dash.exceptions import PreventUpdate, InvalidResourceError +from dash.backend import set_request_adapter +from dash.fingerprint import check_fingerprint +from dash import _validate +from .base_server import BaseDashServer class QuartDashServer(BaseDashServer): @@ -24,7 +34,7 @@ def __init__(self) -> None: super().__init__() def __call__(self, server, *args, **kwargs): - return super().__call__(server, *args, **kwargs) + return server(*args, **kwargs) def create_app(self, name="__main__", config=None): app = Quart(name) @@ -36,8 +46,6 @@ def create_app(self, name="__main__", config=None): def register_assets_blueprint( self, app, blueprint_name, assets_url_path, assets_folder ): - from quart import Blueprint - bp = Blueprint( blueprint_name, __name__, @@ -53,15 +61,15 @@ async def _wrap_errors(_error_request, error): return tb, 500 def register_timing_hooks(self, app, _first_run): # parity with Flask factory - from quart import g - @app.before_request async def _before_request(): # pragma: no cover - timing infra - g.timing_information = {"__dash_server": {"dur": time.time(), "desc": None}} + quart.g.timing_information = { + "__dash_server": {"dur": time.time(), "desc": None} + } @app.after_request async def _after_request(response): # pragma: no cover - timing infra - timing_information = getattr(g, "timing_information", None) + timing_information = getattr(quart.g, "timing_information", None) if timing_information is None: return response dash_total = timing_information.get("__dash_server", None) @@ -90,7 +98,7 @@ async def _invalid_resource(err): return err.args[0], 404 def _html_response_wrapper(self, view_func): - async def wrapped(*args, **kwargs): + async def wrapped(*_args, **_kwargs): html_val = view_func() if callable(view_func) else view_func if inspect.iscoroutine(html_val): # handle async function returning html html_val = await html_val @@ -105,21 +113,25 @@ def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): ) def setup_index(self, dash_app): - async def index(): + async def index(*args, **kwargs): adapter = QuartRequestAdapter() set_request_adapter(adapter) - adapter.set_request(request) - return Response(dash_app.index(), content_type="text/html") + adapter.set_request() + return Response(dash_app.index(*args, **kwargs), content_type="text/html") + # pylint: disable=protected-access dash_app._add_url("", index, methods=["GET"]) def setup_catchall(self, dash_app): - async def catchall(path): # noqa: ARG001 - path is unused but kept for route signature + async def catchall( + path, *args, **kwargs + ): # noqa: ARG001 - path is unused but kept for route signature, pylint: disable=unused-argument adapter = QuartRequestAdapter() set_request_adapter(adapter) - adapter.set_request(request) - return Response(dash_app.index(), content_type="text/html") + adapter.set_request() + return Response(dash_app.index(*args, **kwargs), content_type="text/html") + # pylint: disable=protected-access dash_app._add_url("", catchall, methods=["GET"]) def before_request(self, app, func): @@ -135,7 +147,7 @@ async def _after(response): return response def run(self, app, host, port, debug, **kwargs): - self.config = {'debug': debug, **kwargs} if debug else kwargs + self.config = {"debug": debug, **kwargs} if debug else kwargs app.run(host=host, port=port, debug=debug, **kwargs) def make_response(self, data, mimetype=None, content_type=None): @@ -147,7 +159,9 @@ def jsonify(self, obj): def get_request_adapter(self): return QuartRequestAdapter - def serve_component_suites(self, dash_app, package_name, fingerprinted_path, req): # noqa: ARG002 unused req preserved for interface parity + def serve_component_suites( + self, dash_app, package_name, fingerprinted_path + ): # noqa: ARG002 unused req preserved for interface parity path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) extension = "." + path_in_pkg.split(".")[-1] @@ -170,24 +184,30 @@ def serve_component_suites(self, dash_app, package_name, fingerprinted_path, req def setup_component_suites(self, dash_app): async def serve(package_name, fingerprinted_path): return self.serve_component_suites( - dash_app, package_name, fingerprinted_path, request + dash_app, package_name, fingerprinted_path ) + # pylint: disable=protected-access dash_app._add_url( "_dash-component-suites//", serve, ) + # pylint: disable=unused-argument def dispatch(self, app, dash_app, use_async=True): # Quart always async async def _dispatch(): adapter = QuartRequestAdapter() set_request_adapter(adapter) - adapter.set_request(request) + adapter.set_request() body = await request.get_json() + # pylint: disable=protected-access g = dash_app._initialize_context(body, adapter) + # pylint: disable=protected-access func = dash_app._prepare_callback(g, body) + # pylint: disable=protected-access args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) ctx = copy_context() + # pylint: disable=protected-access partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) response_data = ctx.run(partial_func) if inspect.iscoroutine(response_data): # if user callback is async @@ -209,20 +229,25 @@ def register_callback_api_routes(self, app, callback_api_paths): def _make_view_func(handler): if inspect.iscoroutinefunction(handler): + async def async_view_func(*args, **kwargs): data = await request.get_json() result = await handler(**data) if data else await handler() return jsonify(result) + return async_view_func - else: - async def sync_view_func(*args, **kwargs): - data = await request.get_json() - result = handler(**data) if data else handler() - return jsonify(result) - return sync_view_func + + async def sync_view_func(*args, **kwargs): + data = await request.get_json() + result = handler(**data) if data else handler() + return jsonify(result) + + return sync_view_func view_func = _make_view_func(handler) - app.add_url_rule(route, endpoint=endpoint, view_func=view_func, methods=methods) + app.add_url_rule( + route, endpoint=endpoint, view_func=view_func, methods=methods + ) def _serve_default_favicon(self): return Response( @@ -234,7 +259,7 @@ class QuartRequestAdapter: def __init__(self) -> None: self._request = None - def set_request(self, request: Request) -> None: + def set_request(self) -> None: self._request = request # Accessors (instance-based) diff --git a/dash/backend/registry.py b/dash/backend/registry.py index fb9c99cc2d..4aae9fafc5 100644 --- a/dash/backend/registry.py +++ b/dash/backend/registry.py @@ -1,15 +1,17 @@ import importlib _backend_imports = { - 'flask': ('dash.backend.flask', 'FlaskDashServer'), - 'fastapi': ('dash.backend.fastapi', 'FastAPIDashServer'), - 'quart': ('dash.backend.quart', 'QuartDashServer'), + "flask": ("dash.backend.flask", "FlaskDashServer"), + "fastapi": ("dash.backend.fastapi", "FastAPIDashServer"), + "quart": ("dash.backend.quart", "QuartDashServer"), } + def register_backend(name, module_path, class_name): """Register a new backend by name.""" _backend_imports[name.lower()] = (module_path, class_name) + def get_backend(name): try: module_name, class_name = _backend_imports[name.lower()] @@ -18,7 +20,10 @@ def get_backend(name): except KeyError as e: raise ValueError(f"Unknown backend: {name}") from e except ImportError as e: - raise ImportError(f"Could not import module '{module_name}' for backend '{name}': {e}") from e + raise ImportError( + f"Could not import module '{module_name}' for backend '{name}': {e}" + ) from e except AttributeError as e: - raise AttributeError(f"Module '{module_name}' does not have class '{class_name}' for backend '{name}': {e}") from e - + raise AttributeError( + f"Module '{module_name}' does not have class '{class_name}' for backend '{name}': {e}" + ) from e diff --git a/dash/dash.py b/dash/dash.py index a95f969faa..18c933f08c 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -155,23 +155,32 @@ except: # noqa: E722 page_container = None + def _is_flask_instance(obj): try: + # pylint: disable=import-outside-toplevel from flask import Flask + return isinstance(obj, Flask) except ImportError: return False + def _is_fastapi_instance(obj): try: + # pylint: disable=import-outside-toplevel from fastapi import FastAPI + return isinstance(obj, FastAPI) except ImportError: return False + def _is_quart_instance(obj): try: + # pylint: disable=import-outside-toplevel from quart import Quart + return isinstance(obj, Quart) except ImportError: return False @@ -453,7 +462,7 @@ class Dash(ObsoleteChecker): _layout: Any _extra_components: Any - def __init__( # pylint: disable=too-many-statements + def __init__( # pylint: disable=too-many-statements, too-many-branches self, name: Optional[str] = None, server: Union[bool, Callable[[], Any]] = True, From 0ed81ce67c38bb49056b9ea90564217349ba2825 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 12 Sep 2025 21:06:32 -0400 Subject: [PATCH 048/297] fixing failing test --- tests/integration/devtools/test_devtools_error_handling.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/devtools/test_devtools_error_handling.py b/tests/integration/devtools/test_devtools_error_handling.py index b481ef2fad..005bf8c335 100644 --- a/tests/integration/devtools/test_devtools_error_handling.py +++ b/tests/integration/devtools/test_devtools_error_handling.py @@ -109,14 +109,14 @@ def test_dveh006_long_python_errors(dash_duo): assert "in bad_sub" not in error0 # dash and flask part of the traceback ARE included # since we set dev_tools_prune_errors=False - assert "factory.py" in error0 + assert "backend" in error0 and "flask.py" in error0 assert "self.wsgi_app" in error0 error1 = get_error_html(dash_duo, 1) assert "in update_output" in error1 assert "in bad_sub" in error1 assert "ZeroDivisionError" in error1 - assert "factory.py" in error1 + assert "backend" in error1 and "flask.py" in error1 assert "self.wsgi_app" in error1 From 6bd342a4feed571dcb87a3eeba1e96c06be35226 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sat, 13 Sep 2025 00:20:12 -0400 Subject: [PATCH 049/297] fixing issue with fastapi and component suites --- dash/backend/fastapi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/backend/fastapi.py b/dash/backend/fastapi.py index d283e90346..56f2761a3d 100644 --- a/dash/backend/fastapi.py +++ b/dash/backend/fastapi.py @@ -231,7 +231,7 @@ async def serve(request: Request, package_name: str, fingerprinted_path: str): # pylint: disable=protected-access dash_app._add_url( - "_dash-component-suites//", + "_dash-component-suites/{package_name}/{fingerprinted_path:path}", serve, ) From b1c99537c08a1d71ee544d5defaf9f021b2895b8 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sat, 13 Sep 2025 00:29:10 -0400 Subject: [PATCH 050/297] adjustments to fix issues with caller_name and init the app a couple of times --- dash/dash.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index 18c933f08c..19f789e7c0 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -567,9 +567,6 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches backend_cls = get_backend(inferred_backend) self.backend = backend_cls() self.server = server - # Update caller_name from server's name attribute if available - if hasattr(server, "name"): - caller_name = server.name else: # No server instance provided, create backend and let backend create server self.backend = backend_cls() @@ -703,9 +700,6 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches # tracks internally if a function already handled at least one request. self._got_first_request = {"pages": False, "setup_server": False} - if self.server is not None: - self.init_app() - self.logger.setLevel(logging.INFO) if self.__class__.__name__ == "JupyterDash": From bd40b56c9dd797d365d840945b69c749010d4ec8 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sat, 13 Sep 2025 07:52:35 -0400 Subject: [PATCH 051/297] adjustments for failing tests --- dash/_pages.py | 4 ++-- dash/_utils.py | 5 +++++ dash/dash.py | 10 ++++++++++ tests/integration/multi_page/test_pages_layout.py | 3 ++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/dash/_pages.py b/dash/_pages.py index 6c00e656c7..acb26e8791 100644 --- a/dash/_pages.py +++ b/dash/_pages.py @@ -390,8 +390,8 @@ def _path_to_page(path_id): def _page_meta_tags(app, request): - request_url = request.get_path() - start_page, path_variables = _path_to_page(request_url.strip("/")) + request_path = request.get_path() + start_page, path_variables = _path_to_page(request_path.strip("/")) image = start_page.get("image", "") if image: diff --git a/dash/_utils.py b/dash/_utils.py index f118e61538..ef6c63c281 100644 --- a/dash/_utils.py +++ b/dash/_utils.py @@ -104,6 +104,11 @@ def set_read_only(self, names, msg="Attribute is read-only"): else: object.__setattr__(self, "_read_only", new_read_only) + def unset_read_only(self, keys): + if hasattr(self, "_read_only"): + for key in keys: + self._read_only.pop(key, None) + def finalize(self, msg="Object is final: No new keys may be added."): """Prevent any new keys being set.""" object.__setattr__(self, "_final", msg) diff --git a/dash/dash.py b/dash/dash.py index 19f789e7c0..c84b4476df 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -565,6 +565,8 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches f"Conflict between provided backend '{backend}' and server type '{inferred_backend}'." ) backend_cls = get_backend(inferred_backend) + if name is None: + caller_name = getattr(server, "name", caller_name) self.backend = backend_cls() self.server = server else: @@ -700,6 +702,9 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches # tracks internally if a function already handled at least one request. self._got_first_request = {"pages": False, "setup_server": False} + if self.server is not None: + self.init_app() + self.logger.setLevel(logging.INFO) if self.__class__.__name__ == "JupyterDash": @@ -743,6 +748,11 @@ def _setup_hooks(self): def init_app(self, app: Optional[Any] = None, **kwargs) -> None: config = self.config + config.unset_read_only([ + "url_base_pathname", + "routes_pathname_prefix", + "requests_pathname_prefix", + ]) config.update(kwargs) config.set_read_only( [ diff --git a/tests/integration/multi_page/test_pages_layout.py b/tests/integration/multi_page/test_pages_layout.py index 48751021b9..a209ae4517 100644 --- a/tests/integration/multi_page/test_pages_layout.py +++ b/tests/integration/multi_page/test_pages_layout.py @@ -3,6 +3,7 @@ from dash import Dash, Input, State, dcc, html, Output from dash.dash import _ID_LOCATION from dash.exceptions import NoLayoutException +from dash.testing.wait import until def get_app(path1="/", path2="/layout2"): @@ -57,7 +58,7 @@ def test_pala001_layout(dash_duo, clear_pages_state): for page in dash.page_registry.values(): dash_duo.find_element("#" + page["id"]).click() dash_duo.wait_for_text_to_equal("#text_" + page["id"], "text for " + page["id"]) - assert dash_duo.driver.title == page["title"], "check that page title updates" + until(lambda: dash_duo.driver.title == page["title"], timeout=3) # test redirects dash_duo.wait_for_page(url=f"{dash_duo.server_url}/v2") From 4e50430bd5abf0772afcaeb82aef2b08b4881642 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sat, 13 Sep 2025 08:18:59 -0400 Subject: [PATCH 052/297] format dash --- dash/dash.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index c84b4476df..747901bd9a 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -748,11 +748,13 @@ def _setup_hooks(self): def init_app(self, app: Optional[Any] = None, **kwargs) -> None: config = self.config - config.unset_read_only([ - "url_base_pathname", - "routes_pathname_prefix", - "requests_pathname_prefix", - ]) + config.unset_read_only( + [ + "url_base_pathname", + "routes_pathname_prefix", + "requests_pathname_prefix", + ] + ) config.update(kwargs) config.set_read_only( [ From 0d32e651e3d88cf9b2874422bfb5a6925d6d3518 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sun, 14 Sep 2025 09:01:33 -0400 Subject: [PATCH 053/297] removing `FlaskDashServer` from import and using `get_backend('flask')` instead --- dash/dash.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index 747901bd9a..d9ac42bddf 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -64,7 +64,6 @@ from . import _validate from . import _watch from . import _get_app -from .backend.flask import FlaskDashServer from ._get_app import with_app_context, with_app_context_factory from ._grouping import map_grouping, grouping_len, update_args_group @@ -526,7 +525,7 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches # Determine backend if backend is None: - backend_cls = FlaskDashServer + backend_cls = get_backend('flask') elif isinstance(backend, str): backend_cls = get_backend(backend) elif isinstance(backend, type): From 1b3f61ea5d924015f4f1959b6f7cff56ccc134d6 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sun, 14 Sep 2025 09:07:53 -0400 Subject: [PATCH 054/297] reverting change to callable(title) process --- dash/dash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/dash.py b/dash/dash.py index d9ac42bddf..1963884072 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -2474,7 +2474,7 @@ def update(pathname_, search_, **states): **{**(path_variables or {}), **query_parameters, **states} ) if callable(title): - title = title(**{**(path_variables or {})}) + title = title(**(path_variables or {})) return layout, {"title": title} From c6805b5b6ac70b05ef0a73ce697fcf77f8a2d753 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sun, 14 Sep 2025 17:11:11 -0400 Subject: [PATCH 055/297] fixing for lint --- dash/dash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/dash.py b/dash/dash.py index 1963884072..18ad1c2367 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -525,7 +525,7 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches # Determine backend if backend is None: - backend_cls = get_backend('flask') + backend_cls = get_backend("flask") elif isinstance(backend, str): backend_cls = get_backend(backend) elif isinstance(backend, type): From 8c7808962c3c7914ab82df2ea74d5691704a35c7 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 16 Sep 2025 16:18:30 -0400 Subject: [PATCH 056/297] adding custom error handling per backend, tests and adjustments to the flow. Made endpoints for downloading the reqs --- .github/workflows/testing.yml | 103 +++++++++ dash/backend/fastapi.py | 184 ++++++++++++--- dash/backend/flask.py | 54 ++++- dash/backend/quart.py | 121 +++++++++- .../error/FrontEnd/FrontEndError.react.js | 44 ++-- dash/dash.py | 68 +----- dash/testing/application_runners.py | 20 +- package.json | 2 +- requirements/fastapi.txt | 2 + requirements/quart.txt | 1 + tests/backend_tests/__init__.py | 0 .../backend_tests/test_preconfig_backends.py | 211 ++++++++++++++++++ 12 files changed, 688 insertions(+), 122 deletions(-) create mode 100644 requirements/fastapi.txt create mode 100644 requirements/quart.txt create mode 100644 tests/backend_tests/__init__.py create mode 100644 tests/backend_tests/test_preconfig_backends.py diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 1fc0df1845..068fe777d1 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -271,6 +271,109 @@ jobs: cd bgtests pytest --headless --nopercyfinalize tests/async_tests -v -s + backend-tests: + name: Run Backend Callback Tests (Python ${{ matrix.python-version }}) + needs: [build, changes_filter] + if: | + (github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev')) || + needs.changes_filter.outputs.backend_tests_changed == 'true' + timeout-minutes: 30 + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.9", "3.12"] + + services: + redis: + image: redis:6 + ports: + - 6379:6379 + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + env: + REDIS_URL: redis://localhost:6379 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install Node.js dependencies + run: npm ci + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + + - name: Download built Dash packages + uses: actions/download-artifact@v4 + with: + name: dash-packages + path: packages/ + + - name: Install Dash packages + run: | + python -m pip install --upgrade pip wheel + python -m pip install "setuptools<78.0.0" + python -m pip install "selenium==4.32.0" + find packages -name dash-*.whl -print -exec sh -c 'pip install "{}[async,ci,testing,dev,celery,diskcache, fastapi, quart]"' \; + + - name: Install Google Chrome + run: | + sudo apt-get update + sudo apt-get install -y google-chrome-stable + + - name: Install ChromeDriver + run: | + echo "Determining Chrome version..." + CHROME_BROWSER_VERSION=$(google-chrome --version) + echo "Installed Chrome Browser version: $CHROME_BROWSER_VERSION" + CHROME_MAJOR_VERSION=$(echo "$CHROME_BROWSER_VERSION" | cut -f 3 -d ' ' | cut -f 1 -d '.') + echo "Detected Chrome Major version: $CHROME_MAJOR_VERSION" + if [ "$CHROME_MAJOR_VERSION" -ge 115 ]; then + echo "Fetching ChromeDriver version for Chrome $CHROME_MAJOR_VERSION using CfT endpoint..." + CHROMEDRIVER_VERSION_STRING=$(curl -sS "https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_${CHROME_MAJOR_VERSION}") + if [ -z "$CHROMEDRIVER_VERSION_STRING" ]; then + echo "Could not automatically find ChromeDriver version for Chrome $CHROME_MAJOR_VERSION via LATEST_RELEASE. Please check CfT endpoints." + exit 1 + fi + CHROMEDRIVER_URL="https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/${CHROMEDRIVER_VERSION_STRING}/linux64/chromedriver-linux64.zip" + else + echo "Fetching ChromeDriver version for Chrome $CHROME_MAJOR_VERSION using older method..." + CHROMEDRIVER_VERSION_STRING=$(curl -sS "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_${CHROME_MAJOR_VERSION}") + CHROMEDRIVER_URL="https://chromedriver.storage.googleapis.com/${CHROMEDRIVER_VERSION_STRING}/chromedriver_linux64.zip" + fi + echo "Using ChromeDriver version string: $CHROMEDRIVER_VERSION_STRING" + echo "Downloading ChromeDriver from: $CHROMEDRIVER_URL" + wget -q -O chromedriver.zip "$CHROMEDRIVER_URL" + unzip -o chromedriver.zip -d /tmp/ + sudo mv /tmp/chromedriver-linux64/chromedriver /usr/local/bin/chromedriver || sudo mv /tmp/chromedriver /usr/local/bin/chromedriver + sudo chmod +x /usr/local/bin/chromedriver + echo "/usr/local/bin" >> $GITHUB_PATH + shell: bash + + - name: Build/Setup test components + run: npm run setup-tests.py + + - name: Run Backend Callback Tests + run: | + mkdir bgtests + cp -r tests bgtests/tests + cd bgtests + touch __init__.py + pytest --headless --nopercyfinalize tests/backend_tests -v -s + table-unit: name: Table Unit/Lint Tests (Python ${{ matrix.python-version }}) needs: [build, changes_filter] diff --git a/dash/backend/fastapi.py b/dash/backend/fastapi.py index 56f2761a3d..0afcfabd07 100644 --- a/dash/backend/fastapi.py +++ b/dash/backend/fastapi.py @@ -6,6 +6,7 @@ from contextvars import copy_context import importlib.util import time +import traceback try: import uvicorn @@ -32,14 +33,28 @@ from dash.fingerprint import check_fingerprint from dash import _validate -from dash.exceptions import PreventUpdate, InvalidResourceError +from dash.exceptions import PreventUpdate, InvalidResourceError, InvalidCallbackReturnValue, BackgroundCallbackError from dash.backend import set_request_adapter from .base_server import BaseDashServer +import json +import os + +CONFIG_PATH = "dash_config.json" + +def save_config(config): + with open(CONFIG_PATH, "w") as f: + json.dump(config, f) + +def load_config(): + if os.path.exists(CONFIG_PATH): + with open(CONFIG_PATH, "r") as f: + return json.load(f) + return {} class FastAPIDashServer(BaseDashServer): def __init__(self): - self.config = {} + self.error_handling_mode = "prune" super().__init__() def __call__(self, server, *args, **kwargs): @@ -69,19 +84,120 @@ def register_assets_blueprint( pass def register_error_handlers(self, app): - @app.exception_handler(PreventUpdate) - async def _handle_error(_request, _exc): - return Response(status_code=204) + self.error_handling_mode = "prune" + # FastAPI uses exception handlers, but we will handle errors in middleware + pass + + def _get_traceback(self, secret, error: Exception): + tb = error.__traceback__ + errors = traceback.format_exception(type(error), error, tb) + pass_errs = [] + callback_handled = False + for err in errors: + if self.error_handling_mode == "prune": + if not callback_handled: + if 'callback invoked' in str(err) and '_callback.py' in str(err): + callback_handled = True + continue + pass_errs.append(err) + formatted_tb = "".join(pass_errs) + error_type = type(error).__name__ + error_msg = str(error) + + # Parse traceback lines to group by file + import re + file_cards = [] + pattern = re.compile(r' File "(.+)", line (\d+), in (\w+)') + lines = formatted_tb.split('\n') + current_file = None + card_lines = [] + + for i, line in enumerate(lines[:-1]): # Skip the last line (error message) + match = pattern.match(line) + if match: + if current_file and card_lines: + file_cards.append((current_file, card_lines)) + current_file = f'{match.group(1)} (line {match.group(2)}, in {match.group(3)})' + card_lines = [line] + elif current_file: + card_lines.append(line) + if current_file and card_lines: + file_cards.append((current_file, card_lines)) + + cards_html = "" + for filename, card in file_cards: + cards_html += f""" +
+
{filename}
+
"""+ '\n'.join(card) + """
+
+ """ + + html = f""" + + + + {error_type}: {error_msg} // FastAPI Debugger + + + +
+

{error_type}

+
+

{error_type}: {error_msg}

+
+

Traceback (most recent call last)

+ {cards_html} +
{error_type}: {error_msg}
+
+

This is the Copy/Paste friendly version of the traceback.

+ +
+
+ The debugger caught an exception in your ASGI application. You can now + look at the traceback which led to the error. +
+ +
+ + + """ + return html - @app.exception_handler(InvalidResourceError) - async def _invalid_resources_handler(_request, exc): - return Response(content=exc.args[0], status_code=404) + def register_prune_error_handler(self, _app, _secret, prune_errors): + if prune_errors: + self.error_handling_mode = "prune" + else: + self.error_handling_mode = "raise" - def register_prune_error_handler(self, app, secret, get_traceback_func): - @app.exception_handler(Exception) - async def _wrap_errors(_error_request, error): - tb = get_traceback_func(secret, error) - return PlainTextResponse(tb, status_code=500) def _html_response_wrapper(self, view_func): async def wrapped(*_args, **_kwargs): @@ -104,9 +220,10 @@ async def index(request: Request): def setup_catchall(self, dash_app): @dash_app.server.on_event("startup") def _setup_catchall(): + config = load_config() dash_app.enable_dev_tools( - **self.config, first_run=False - ) # do this to make sure dev tools are enabled + **config, first_run=False + ) async def catchall(request: Request): adapter = FastAPIRequestAdapter() @@ -141,11 +258,15 @@ def after_request(self, app, func): # FastAPI does not have after_request, but we can use middleware app.middleware("http")(self._make_after_middleware(func)) - def run(self, app, host, port, debug, **kwargs): + def run(self, dash_app, app, host, port, debug, **kwargs): frame = inspect.stack()[2] - self.config = dict({"debug": debug} if debug else {}, **kwargs) - reload = debug - if reload: + config = dict({"debug": debug} if debug else {}, **{ + f'dev_tools_{k}': v for k, v in dash_app._dev_tools.items()}) + save_config(config) + if debug: + if kwargs.get('reload') is None: + kwargs['reload'] = True + if kwargs.get('reload'): # Dynamically determine the module name from the file path file_path = frame.filename module_name = importlib.util.spec_from_file_location("app", file_path).name @@ -153,11 +274,10 @@ def run(self, app, host, port, debug, **kwargs): f"{module_name}:app.server", host=host, port=port, - reload=reload, **kwargs, ) else: - uvicorn.run(app, host=host, port=port, reload=reload, **kwargs) + uvicorn.run(app, host=host, port=port, **kwargs) def make_response(self, data, mimetype=None, content_type=None): headers = {} @@ -175,13 +295,21 @@ def get_request_adapter(self): def _make_before_middleware(self, func): async def middleware(request, call_next): - if func is not None: - if inspect.iscoroutinefunction(func): - await func() - else: - func() - response = await call_next(request) - return response + try: + response = await call_next(request) + return response + except PreventUpdate: + # No content, nothing to update + return Response(status_code=204) + except Exception as e: + if self.error_handling_mode in ["raise", "prune"]: + # Prune the traceback to remove internal Dash calls + tb = self._get_traceback(None, e) + return Response(content=tb, media_type='text/html', status_code=500) + return JSONResponse( + status_code=500, + content={"error": "InternalServerError", "message": str(e.args[0])}, + ) return middleware diff --git a/dash/backend/flask.py b/dash/backend/flask.py index b48225a3c5..75526e6feb 100644 --- a/dash/backend/flask.py +++ b/dash/backend/flask.py @@ -11,6 +11,7 @@ from dash.exceptions import PreventUpdate, InvalidResourceError from dash.backend import set_request_adapter from .base_server import BaseDashServer +import traceback class FlaskDashServer(BaseDashServer): @@ -44,11 +45,52 @@ def _handle_error(_): def _invalid_resources_handler(err): return err.args[0], 404 - def register_prune_error_handler(self, app, secret, get_traceback_func): - @app.errorhandler(Exception) - def _wrap_errors(error): - tb = get_traceback_func(secret, error) - return tb, 500 + def _get_traceback(self, secret, error: Exception): + try: + from werkzeug.debug import tbtools + except ImportError: + tbtools = None + + def _get_skip(error): + from dash._callback import _invoke_callback, _async_invoke_callback + + tb = error.__traceback__ + skip = 1 + while tb.tb_next is not None: + skip += 1 + tb = tb.tb_next + if tb.tb_frame.f_code in [ + _invoke_callback.__code__, + _async_invoke_callback.__code__, + ]: + return skip + return skip + + def _do_skip(error): + from dash._callback import _invoke_callback, _async_invoke_callback + + tb = error.__traceback__ + while tb.tb_next is not None: + if tb.tb_frame.f_code in [ + _invoke_callback.__code__, + _async_invoke_callback.__code__, + ]: + return tb.tb_next + tb = tb.tb_next + return error.__traceback__ + + if hasattr(tbtools, "get_current_traceback"): + return tbtools.get_current_traceback(skip=_get_skip(error)).render_full() + if hasattr(tbtools, "DebugTraceback"): + return tbtools.DebugTraceback(error, skip=_get_skip(error)).render_debugger_html(True, secret, True) + return "".join(traceback.format_exception(type(error), error, _do_skip(error))) + + def register_prune_error_handler(self, app, secret, prune_errors): + if prune_errors: + @app.errorhandler(Exception) + def _wrap_errors(error): + tb = self._get_traceback(secret, error) + return tb, 500 def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): app.add_url_rule( @@ -61,7 +103,7 @@ def before_request(self, app, func): def after_request(self, app, func): app.after_request(func) - def run(self, app, host, port, debug, **kwargs): + def run(self, _dash_app, app, host, port, debug, **kwargs): app.run(host=host, port=port, debug=debug, **kwargs) def make_response(self, data, mimetype=None, content_type=None): diff --git a/dash/backend/quart.py b/dash/backend/quart.py index c3d42dadee..40f30108b2 100644 --- a/dash/backend/quart.py +++ b/dash/backend/quart.py @@ -4,6 +4,7 @@ import sys import time from contextvars import copy_context +import traceback try: import quart @@ -31,6 +32,7 @@ class QuartDashServer(BaseDashServer): def __init__(self) -> None: self.config = {} + self.error_handling_mode = "prune" super().__init__() def __call__(self, server, *args, **kwargs): @@ -54,11 +56,120 @@ def register_assets_blueprint( ) app.register_blueprint(bp) - def register_prune_error_handler(self, app, secret, get_traceback_func): + def _get_traceback(self, secret, error: Exception): + tb = error.__traceback__ + errors = traceback.format_exception(type(error), error, tb) + pass_errs = [] + callback_handled = False + for err in errors: + if self.error_handling_mode == "prune": + if not callback_handled: + if 'callback invoked' in str(err) and '_callback.py' in str(err): + callback_handled = True + continue + pass_errs.append(err) + formatted_tb = "".join(pass_errs) + error_type = type(error).__name__ + error_msg = str(error) + + # Parse traceback lines to group by file + import re + file_cards = [] + pattern = re.compile(r' File "(.+)", line (\d+), in (\w+)') + lines = formatted_tb.split('\n') + current_file = None + card_lines = [] + + for i, line in enumerate(lines[:-1]): # Skip the last line (error message) + match = pattern.match(line) + if match: + if current_file and card_lines: + file_cards.append((current_file, card_lines)) + current_file = f'{match.group(1)} (line {match.group(2)}, in {match.group(3)})' + card_lines = [line] + elif current_file: + card_lines.append(line) + if current_file and card_lines: + file_cards.append((current_file, card_lines)) + + cards_html = "" + for filename, card in file_cards: + cards_html += f""" +
+
{filename}
+
""" + '\n'.join(card) + """
+
+ """ + + html = f""" + + + + {error_type}: {error_msg} // Quart Debugger + + + +
+

{error_type}

+
+

{error_type}: {error_msg}

+
+

Traceback (most recent call last)

+ {cards_html} +
{error_type}: {error_msg}
+
+

This is the Copy/Paste friendly version of the traceback.

+ +
+
+ The debugger caught an exception in your ASGI application. You can now + look at the traceback which led to the error. +
+ +
+ + + """ + return html + + def register_prune_error_handler(self, app, secret, prune_errors): + if prune_errors: + self.error_handling_mode = "prune" + else: + self.error_handling_mode = "raise" + @app.errorhandler(Exception) - async def _wrap_errors(_error_request, error): - tb = get_traceback_func(secret, error) - return tb, 500 + async def _wrap_errors(error): + tb = self._get_traceback(secret, error) + return Response(tb, status=500, content_type='text/html') def register_timing_hooks(self, app, _first_run): # parity with Flask factory @app.before_request @@ -146,7 +257,7 @@ async def _after(response): await result return response - def run(self, app, host, port, debug, **kwargs): + def run(self, _dash_app, app, host, port, debug, **kwargs): self.config = {"debug": debug, **kwargs} if debug else kwargs app.run(host=host, port=port, debug=debug, **kwargs) diff --git a/dash/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js b/dash/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js index 176cb2c6f8..ab5430e7da 100644 --- a/dash/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js +++ b/dash/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js @@ -121,13 +121,17 @@ function BackendError({error, base}) { const MAX_MESSAGE_LENGTH = 40; /* eslint-disable no-inline-comments */ function UnconnectedErrorContent({error, base}) { + // Helper to detect full HTML document + const isFullHtmlDoc = typeof error.html === 'string' && + error.html.trim().toLowerCase().startsWith(' - {/* - * 40 is a rough heuristic - if longer than 40 then the - * message might overflow into ellipses in the title above & - * will need to be displayed in full in this error body - */} + {/* Frontend error message */} {typeof error.message !== 'string' || error.message.length < MAX_MESSAGE_LENGTH ? null : (
@@ -137,6 +141,7 @@ function UnconnectedErrorContent({error, base}) {
)} + {/* Frontend stack trace */} {typeof error.stack !== 'string' ? null : (
@@ -149,7 +154,6 @@ function UnconnectedErrorContent({error, base}) { browser's console.) - {error.stack.split('\n').map((line, i) => (

{line}

))} @@ -157,24 +161,30 @@ function UnconnectedErrorContent({error, base}) {
)} - {/* Backend Error */} - {typeof error.html !== 'string' ? null : error.html - .substring(0, '
- {/* Embed werkzeug debugger in an iframe to prevent - CSS leaking - werkzeug HTML includes a bunch - of CSS on base html elements like `` - */}
- ) : ( + ) : isHtmlFragment ? ( + // Backend error: HTML fragment +
+
+
+ ) : typeof error.html === 'string' ? ( + // Backend error: plain text
-
{error.html}
+
+
{error.html}
+
- )} + ) : null}
); } diff --git a/dash/dash.py b/dash/dash.py index 18ad1c2367..fa1aa45ea5 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -185,63 +185,6 @@ def _is_quart_instance(obj): return False -def _get_traceback(secret, error: Exception): - try: - # pylint: disable=import-outside-toplevel - from werkzeug.debug import tbtools - except ImportError: - tbtools = None - - def _get_skip(error): - from dash._callback import ( # pylint: disable=import-outside-toplevel - _invoke_callback, - _async_invoke_callback, - ) - - tb = error.__traceback__ - skip = 1 - while tb.tb_next is not None: - skip += 1 - tb = tb.tb_next - if tb.tb_frame.f_code in [ - _invoke_callback.__code__, - _async_invoke_callback.__code__, - ]: - return skip - - return skip - - def _do_skip(error): - from dash._callback import ( # pylint: disable=import-outside-toplevel - _invoke_callback, - _async_invoke_callback, - ) - - tb = error.__traceback__ - while tb.tb_next is not None: - if tb.tb_frame.f_code in [ - _invoke_callback.__code__, - _async_invoke_callback.__code__, - ]: - return tb.tb_next - tb = tb.tb_next - return error.__traceback__ - - # werkzeug<2.1.0 - if hasattr(tbtools, "get_current_traceback"): - return tbtools.get_current_traceback( # type: ignore - skip=_get_skip(error) - ).render_full() - - if hasattr(tbtools, "DebugTraceback"): - # pylint: disable=no-member - return tbtools.DebugTraceback( # type: ignore - error, skip=_get_skip(error) - ).render_debugger_html(True, secret, True) - - return "".join(traceback.format_exception(type(error), error, _do_skip(error))) - - # Singleton signal to not update an output, alternative to PreventUpdate no_update = _callback.NoUpdate() # pylint: disable=protected-access @@ -2058,11 +2001,10 @@ def enable_dev_tools( jupyter_dash.configure_callback_exception_handling( self, dev_tools.prune_errors ) - elif dev_tools.prune_errors: - secret = gen_salt(20) - self.backend.register_prune_error_handler( - self.server, secret, _get_traceback - ) + secret = gen_salt(20) + self.backend.register_prune_error_handler( + self.server, secret, dev_tools.prune_errors + ) if debug and dev_tools.ui: self.backend.register_timing_hooks(self.server, first_run) @@ -2350,7 +2292,7 @@ def verify_url_part(served_part, url_part, part_name): ) else: self.backend.run( - self.server, host=host, port=port, debug=debug, **flask_run_options + self, self.server, host=host, port=port, debug=debug, **flask_run_options ) def enable_pages(self) -> None: diff --git a/dash/testing/application_runners.py b/dash/testing/application_runners.py index dc88afe844..df036aabfa 100644 --- a/dash/testing/application_runners.py +++ b/dash/testing/application_runners.py @@ -171,7 +171,15 @@ def run(): self.port = options["port"] try: - app.run(threaded=True, **options) + module = app.server.__class__.__module__ + # FastAPI support + if not module.startswith("flask"): + app.run( + **options + ) + # Dash/Flask fallback + else: + app.run(threaded=True, **options) except SystemExit: logger.info("Server stopped") except Exception as error: @@ -229,7 +237,15 @@ def target(): options = kwargs.copy() try: - app.run(threaded=True, **options) + module = app.server.__class__.__module__ + # FastAPI support + if not module.startswith("flask"): + app.run( + **options + ) + # Dash/Flask fallback + else: + app.run(threaded=True, **options) except SystemExit: logger.info("Server stopped") raise diff --git a/package.json b/package.json index e78e279c1b..b7416dbb34 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "setup-tests.R": "run-s private::test.R.deploy-*", "citest.integration": "run-s setup-tests.py private::test.integration-*", "citest.unit": "run-s private::test.unit-**", - "test": "pytest && cd dash/dash-renderer && npm run test", + "test": "pytest --ignore=tests/backend_tests && cd dash/dash-renderer && npm run test", "first-build": "cd dash/dash-renderer && npm i && cd ../../ && cd components/dash-html-components && npm i && npm run extract && cd ../../ && npm run build" }, "devDependencies": { diff --git a/requirements/fastapi.txt b/requirements/fastapi.txt new file mode 100644 index 0000000000..97dc7cd8c1 --- /dev/null +++ b/requirements/fastapi.txt @@ -0,0 +1,2 @@ +fastapi +uvicorn diff --git a/requirements/quart.txt b/requirements/quart.txt new file mode 100644 index 0000000000..60af440c9c --- /dev/null +++ b/requirements/quart.txt @@ -0,0 +1 @@ +quart diff --git a/tests/backend_tests/__init__.py b/tests/backend_tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/backend_tests/test_preconfig_backends.py b/tests/backend_tests/test_preconfig_backends.py new file mode 100644 index 0000000000..4868406814 --- /dev/null +++ b/tests/backend_tests/test_preconfig_backends.py @@ -0,0 +1,211 @@ +import pytest +from dash import Dash, Input, Output, html, dcc + +@pytest.mark.parametrize( + "backend,fixture,input_value", + [ + ( + "fastapi", + "dash_duo", + "Hello FastAPI!" + ), + ( + "quart", + "dash_duo_mp", + "Hello Quart!" + ), + ] +) +def test_backend_basic_callback(request, backend, fixture, input_value): + dash_duo = request.getfixturevalue(fixture) + if backend == "fastapi": + from fastapi import FastAPI + server = FastAPI() + else: + import quart + server = quart.Quart(__name__) + app = Dash(__name__, server=server) + app.layout = html.Div([ + dcc.Input(id="input", value=input_value, type="text"), + html.Div(id="output") + ]) + + @app.callback(Output("output", "children"), Input("input", "value")) + def update_output(value): + return f"You typed: {value}" + + dash_duo.start_server(app) + dash_duo.wait_for_text_to_equal("#output", f"You typed: {input_value}") + dash_duo.find_element("#input").clear() + dash_duo.find_element("#input").send_keys(f"{backend.title()} Test") + dash_duo.wait_for_text_to_equal("#output", f"You typed: {backend.title()} Test") + assert dash_duo.get_logs() == [] + +@pytest.mark.parametrize( + "backend,fixture,start_server_kwargs", + [ + ( + "fastapi", + "dash_duo", + {"debug": True, "reload": False, "dev_tools_ui": True}, + ), + ( + "quart", + "dash_duo_mp", + { + "debug": True, + "use_reloader": False, + "dev_tools_hot_reload": False, + }, + ), + ] +) +def test_backend_error_handling(request, backend, fixture, start_server_kwargs): + dash_duo = request.getfixturevalue(fixture) + app = Dash(__name__, backend=backend) + app.layout = html.Div([ + html.Button(id="btn", children="Error", n_clicks=0), + html.Div(id="output") + ]) + + @app.callback(Output("output", "children"), Input("btn", "n_clicks")) + def error_callback(n): + if n and n > 0: + return 1 / 0 # Intentional error + return "No error" + + dash_duo.start_server(app, **start_server_kwargs) + dash_duo.wait_for_text_to_equal("#output", "No error") + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal(dash_duo.devtools_error_count_locator, "1") + +def get_error_html(dash_duo, index): + # error is in an iframe so is annoying to read out - get it from the store + return dash_duo.driver.execute_script( + "return store.getState().error.backEnd[{}].error.html;".format(index) + ) + +@pytest.mark.parametrize( + "backend,fixture,start_server_kwargs, error_msg", + [ + ( + "fastapi", + "dash_duo", + {"debug": True, "dev_tools_ui": True, "dev_tools_prune_errors": False, + "reload": False}, + "fastapi.py" + ), + ( + "quart", + "dash_duo_mp", + { + "debug": True, + "use_reloader": False, + "dev_tools_hot_reload": False, + "dev_tools_prune_errors": False, + }, + "quart.py" + ), + ] +) +def test_backend_error_handling_no_prune(request, backend, fixture, start_server_kwargs, error_msg): + dash_duo = request.getfixturevalue(fixture) + app = Dash(__name__, backend=backend) + app.layout = html.Div([ + html.Button(id="btn", children="Error", n_clicks=0), + html.Div(id="output") + ]) + + @app.callback(Output("output", "children"), Input("btn", "n_clicks")) + def error_callback(n): + if n and n > 0: + return 1 / 0 # Intentional error + return "No error" + + dash_duo.start_server(app, **start_server_kwargs) + dash_duo.wait_for_text_to_equal("#output", "No error") + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal(dash_duo.devtools_error_count_locator, "1") + + error0 = get_error_html(dash_duo, 0) + assert "in error_callback" in error0 + assert "ZeroDivisionError" in error0 + assert "backend" in error0 and error_msg in error0 + +@pytest.mark.parametrize( + "backend,fixture,start_server_kwargs, error_msg", + [ + ( + "fastapi", + "dash_duo", + {"debug": True, + "reload": False}, + "fastapi.py" + ), + ( + "quart", + "dash_duo_mp", + { + "debug": True, + "use_reloader": False, + "dev_tools_hot_reload": False, + }, + "quart.py" + ), + ] +) +def test_backend_error_handling_prune(request, backend, fixture, start_server_kwargs, error_msg): + dash_duo = request.getfixturevalue(fixture) + app = Dash(__name__, backend=backend) + app.layout = html.Div([ + html.Button(id="btn", children="Error", n_clicks=0), + html.Div(id="output") + ]) + + @app.callback(Output("output", "children"), Input("btn", "n_clicks")) + def error_callback(n): + if n and n > 0: + return 1 / 0 # Intentional error + return "No error" + + dash_duo.start_server(app, **start_server_kwargs) + dash_duo.wait_for_text_to_equal("#output", "No error") + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal(dash_duo.devtools_error_count_locator, "1") + + error0 = get_error_html(dash_duo, 0) + assert "in error_callback" in error0 + assert "ZeroDivisionError" in error0 + assert "dash/backend" not in error0 and error_msg not in error0 + +@pytest.mark.parametrize( + "backend,fixture,input_value", + [ + ("fastapi", "dash_duo", "Background FastAPI!"), + ("quart", "dash_duo_mp", "Background Quart!"), + ] +) +def test_backend_background_callback(request, backend, fixture, input_value): + dash_duo = request.getfixturevalue(fixture) + import diskcache + cache = diskcache.Cache("./cache") + from dash.background_callback import DiskcacheManager + background_callback_manager = DiskcacheManager(cache) + + + app = Dash(__name__, backend=backend, background_callback_manager=background_callback_manager) + app.layout = html.Div([ + dcc.Input(id="input", value=input_value, type="text"), + html.Div(id="output") + ]) + + @app.callback(Output("output", "children"), Input("input", "value"), background=True) + def update_output_bg(value): + return f"Background typed: {value}" + + dash_duo.start_server(app) + dash_duo.wait_for_text_to_equal("#output", f"Background typed: {input_value}") + dash_duo.find_element("#input").clear() + dash_duo.find_element("#input").send_keys(f"{backend.title()} BG Test") + dash_duo.wait_for_text_to_equal("#output", f"Background typed: {backend.title()} BG Test") + assert dash_duo.get_logs() == [] From 5211f6fb43f335b5c99e37859f5f2f5ec2dbe729 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 16 Sep 2025 16:20:56 -0400 Subject: [PATCH 057/297] adjusments for formatting --- dash/backend/fastapi.py | 46 ++++--- dash/backend/flask.py | 5 +- dash/backend/quart.py | 19 ++- .../error/FrontEnd/FrontEndError.react.js | 7 +- dash/dash.py | 7 +- dash/testing/application_runners.py | 8 +- .../backend_tests/test_preconfig_backends.py | 112 +++++++++--------- 7 files changed, 118 insertions(+), 86 deletions(-) diff --git a/dash/backend/fastapi.py b/dash/backend/fastapi.py index 0afcfabd07..a76a5a47ec 100644 --- a/dash/backend/fastapi.py +++ b/dash/backend/fastapi.py @@ -33,7 +33,12 @@ from dash.fingerprint import check_fingerprint from dash import _validate -from dash.exceptions import PreventUpdate, InvalidResourceError, InvalidCallbackReturnValue, BackgroundCallbackError +from dash.exceptions import ( + PreventUpdate, + InvalidResourceError, + InvalidCallbackReturnValue, + BackgroundCallbackError, +) from dash.backend import set_request_adapter from .base_server import BaseDashServer @@ -42,16 +47,19 @@ CONFIG_PATH = "dash_config.json" + def save_config(config): with open(CONFIG_PATH, "w") as f: json.dump(config, f) + def load_config(): if os.path.exists(CONFIG_PATH): with open(CONFIG_PATH, "r") as f: return json.load(f) return {} + class FastAPIDashServer(BaseDashServer): def __init__(self): self.error_handling_mode = "prune" @@ -96,7 +104,7 @@ def _get_traceback(self, secret, error: Exception): for err in errors: if self.error_handling_mode == "prune": if not callback_handled: - if 'callback invoked' in str(err) and '_callback.py' in str(err): + if "callback invoked" in str(err) and "_callback.py" in str(err): callback_handled = True continue pass_errs.append(err) @@ -106,9 +114,10 @@ def _get_traceback(self, secret, error: Exception): # Parse traceback lines to group by file import re + file_cards = [] pattern = re.compile(r' File "(.+)", line (\d+), in (\w+)') - lines = formatted_tb.split('\n') + lines = formatted_tb.split("\n") current_file = None card_lines = [] @@ -117,7 +126,9 @@ def _get_traceback(self, secret, error: Exception): if match: if current_file and card_lines: file_cards.append((current_file, card_lines)) - current_file = f'{match.group(1)} (line {match.group(2)}, in {match.group(3)})' + current_file = ( + f"{match.group(1)} (line {match.group(2)}, in {match.group(3)})" + ) card_lines = [line] elif current_file: card_lines.append(line) @@ -126,12 +137,16 @@ def _get_traceback(self, secret, error: Exception): cards_html = "" for filename, card in file_cards: - cards_html += f""" + cards_html += ( + f"""
{filename}
-
"""+ '\n'.join(card) + """
+
"""
+                + "\n".join(card)
+                + """
""" + ) html = f""" @@ -198,7 +213,6 @@ def register_prune_error_handler(self, _app, _secret, prune_errors): else: self.error_handling_mode = "raise" - def _html_response_wrapper(self, view_func): async def wrapped(*_args, **_kwargs): # If view_func is a function, call it; if it's a string, use it directly @@ -221,9 +235,7 @@ def setup_catchall(self, dash_app): @dash_app.server.on_event("startup") def _setup_catchall(): config = load_config() - dash_app.enable_dev_tools( - **config, first_run=False - ) + dash_app.enable_dev_tools(**config, first_run=False) async def catchall(request: Request): adapter = FastAPIRequestAdapter() @@ -260,13 +272,15 @@ def after_request(self, app, func): def run(self, dash_app, app, host, port, debug, **kwargs): frame = inspect.stack()[2] - config = dict({"debug": debug} if debug else {}, **{ - f'dev_tools_{k}': v for k, v in dash_app._dev_tools.items()}) + config = dict( + {"debug": debug} if debug else {}, + **{f"dev_tools_{k}": v for k, v in dash_app._dev_tools.items()}, + ) save_config(config) if debug: - if kwargs.get('reload') is None: - kwargs['reload'] = True - if kwargs.get('reload'): + if kwargs.get("reload") is None: + kwargs["reload"] = True + if kwargs.get("reload"): # Dynamically determine the module name from the file path file_path = frame.filename module_name = importlib.util.spec_from_file_location("app", file_path).name @@ -305,7 +319,7 @@ async def middleware(request, call_next): if self.error_handling_mode in ["raise", "prune"]: # Prune the traceback to remove internal Dash calls tb = self._get_traceback(None, e) - return Response(content=tb, media_type='text/html', status_code=500) + return Response(content=tb, media_type="text/html", status_code=500) return JSONResponse( status_code=500, content={"error": "InternalServerError", "message": str(e.args[0])}, diff --git a/dash/backend/flask.py b/dash/backend/flask.py index 75526e6feb..542da93129 100644 --- a/dash/backend/flask.py +++ b/dash/backend/flask.py @@ -82,11 +82,14 @@ def _do_skip(error): if hasattr(tbtools, "get_current_traceback"): return tbtools.get_current_traceback(skip=_get_skip(error)).render_full() if hasattr(tbtools, "DebugTraceback"): - return tbtools.DebugTraceback(error, skip=_get_skip(error)).render_debugger_html(True, secret, True) + return tbtools.DebugTraceback( + error, skip=_get_skip(error) + ).render_debugger_html(True, secret, True) return "".join(traceback.format_exception(type(error), error, _do_skip(error))) def register_prune_error_handler(self, app, secret, prune_errors): if prune_errors: + @app.errorhandler(Exception) def _wrap_errors(error): tb = self._get_traceback(secret, error) diff --git a/dash/backend/quart.py b/dash/backend/quart.py index 40f30108b2..71a2053a61 100644 --- a/dash/backend/quart.py +++ b/dash/backend/quart.py @@ -64,7 +64,7 @@ def _get_traceback(self, secret, error: Exception): for err in errors: if self.error_handling_mode == "prune": if not callback_handled: - if 'callback invoked' in str(err) and '_callback.py' in str(err): + if "callback invoked" in str(err) and "_callback.py" in str(err): callback_handled = True continue pass_errs.append(err) @@ -74,9 +74,10 @@ def _get_traceback(self, secret, error: Exception): # Parse traceback lines to group by file import re + file_cards = [] pattern = re.compile(r' File "(.+)", line (\d+), in (\w+)') - lines = formatted_tb.split('\n') + lines = formatted_tb.split("\n") current_file = None card_lines = [] @@ -85,7 +86,9 @@ def _get_traceback(self, secret, error: Exception): if match: if current_file and card_lines: file_cards.append((current_file, card_lines)) - current_file = f'{match.group(1)} (line {match.group(2)}, in {match.group(3)})' + current_file = ( + f"{match.group(1)} (line {match.group(2)}, in {match.group(3)})" + ) card_lines = [line] elif current_file: card_lines.append(line) @@ -94,12 +97,16 @@ def _get_traceback(self, secret, error: Exception): cards_html = "" for filename, card in file_cards: - cards_html += f""" + cards_html += ( + f"""
{filename}
-
""" + '\n'.join(card) + """
+
"""
+                + "\n".join(card)
+                + """
""" + ) html = f""" @@ -169,7 +176,7 @@ def register_prune_error_handler(self, app, secret, prune_errors): @app.errorhandler(Exception) async def _wrap_errors(error): tb = self._get_traceback(secret, error) - return Response(tb, status=500, content_type='text/html') + return Response(tb, status=500, content_type="text/html") def register_timing_hooks(self, app, _first_run): # parity with Flask factory @app.before_request diff --git a/dash/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js b/dash/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js index ab5430e7da..db4c6ddd2b 100644 --- a/dash/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js +++ b/dash/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js @@ -122,12 +122,13 @@ const MAX_MESSAGE_LENGTH = 40; /* eslint-disable no-inline-comments */ function UnconnectedErrorContent({error, base}) { // Helper to detect full HTML document - const isFullHtmlDoc = typeof error.html === 'string' && + const isFullHtmlDoc = + typeof error.html === 'string' && error.html.trim().toLowerCase().startsWith(' diff --git a/dash/dash.py b/dash/dash.py index fa1aa45ea5..994453f4a2 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -2292,7 +2292,12 @@ def verify_url_part(served_part, url_part, part_name): ) else: self.backend.run( - self, self.server, host=host, port=port, debug=debug, **flask_run_options + self, + self.server, + host=host, + port=port, + debug=debug, + **flask_run_options, ) def enable_pages(self) -> None: diff --git a/dash/testing/application_runners.py b/dash/testing/application_runners.py index df036aabfa..2956f1a4c0 100644 --- a/dash/testing/application_runners.py +++ b/dash/testing/application_runners.py @@ -174,9 +174,7 @@ def run(): module = app.server.__class__.__module__ # FastAPI support if not module.startswith("flask"): - app.run( - **options - ) + app.run(**options) # Dash/Flask fallback else: app.run(threaded=True, **options) @@ -240,9 +238,7 @@ def target(): module = app.server.__class__.__module__ # FastAPI support if not module.startswith("flask"): - app.run( - **options - ) + app.run(**options) # Dash/Flask fallback else: app.run(threaded=True, **options) diff --git a/tests/backend_tests/test_preconfig_backends.py b/tests/backend_tests/test_preconfig_backends.py index 4868406814..5fbd28dfd9 100644 --- a/tests/backend_tests/test_preconfig_backends.py +++ b/tests/backend_tests/test_preconfig_backends.py @@ -1,34 +1,28 @@ import pytest from dash import Dash, Input, Output, html, dcc + @pytest.mark.parametrize( "backend,fixture,input_value", [ - ( - "fastapi", - "dash_duo", - "Hello FastAPI!" - ), - ( - "quart", - "dash_duo_mp", - "Hello Quart!" - ), - ] + ("fastapi", "dash_duo", "Hello FastAPI!"), + ("quart", "dash_duo_mp", "Hello Quart!"), + ], ) def test_backend_basic_callback(request, backend, fixture, input_value): dash_duo = request.getfixturevalue(fixture) if backend == "fastapi": from fastapi import FastAPI + server = FastAPI() else: import quart + server = quart.Quart(__name__) app = Dash(__name__, server=server) - app.layout = html.Div([ - dcc.Input(id="input", value=input_value, type="text"), - html.Div(id="output") - ]) + app.layout = html.Div( + [dcc.Input(id="input", value=input_value, type="text"), html.Div(id="output")] + ) @app.callback(Output("output", "children"), Input("input", "value")) def update_output(value): @@ -41,6 +35,7 @@ def update_output(value): dash_duo.wait_for_text_to_equal("#output", f"You typed: {backend.title()} Test") assert dash_duo.get_logs() == [] + @pytest.mark.parametrize( "backend,fixture,start_server_kwargs", [ @@ -58,15 +53,14 @@ def update_output(value): "dev_tools_hot_reload": False, }, ), - ] + ], ) def test_backend_error_handling(request, backend, fixture, start_server_kwargs): dash_duo = request.getfixturevalue(fixture) app = Dash(__name__, backend=backend) - app.layout = html.Div([ - html.Button(id="btn", children="Error", n_clicks=0), - html.Div(id="output") - ]) + app.layout = html.Div( + [html.Button(id="btn", children="Error", n_clicks=0), html.Div(id="output")] + ) @app.callback(Output("output", "children"), Input("btn", "n_clicks")) def error_callback(n): @@ -79,21 +73,27 @@ def error_callback(n): dash_duo.find_element("#btn").click() dash_duo.wait_for_text_to_equal(dash_duo.devtools_error_count_locator, "1") + def get_error_html(dash_duo, index): # error is in an iframe so is annoying to read out - get it from the store return dash_duo.driver.execute_script( "return store.getState().error.backEnd[{}].error.html;".format(index) ) + @pytest.mark.parametrize( "backend,fixture,start_server_kwargs, error_msg", [ ( "fastapi", "dash_duo", - {"debug": True, "dev_tools_ui": True, "dev_tools_prune_errors": False, - "reload": False}, - "fastapi.py" + { + "debug": True, + "dev_tools_ui": True, + "dev_tools_prune_errors": False, + "reload": False, + }, + "fastapi.py", ), ( "quart", @@ -104,17 +104,18 @@ def get_error_html(dash_duo, index): "dev_tools_hot_reload": False, "dev_tools_prune_errors": False, }, - "quart.py" + "quart.py", ), - ] + ], ) -def test_backend_error_handling_no_prune(request, backend, fixture, start_server_kwargs, error_msg): +def test_backend_error_handling_no_prune( + request, backend, fixture, start_server_kwargs, error_msg +): dash_duo = request.getfixturevalue(fixture) app = Dash(__name__, backend=backend) - app.layout = html.Div([ - html.Button(id="btn", children="Error", n_clicks=0), - html.Div(id="output") - ]) + app.layout = html.Div( + [html.Button(id="btn", children="Error", n_clicks=0), html.Div(id="output")] + ) @app.callback(Output("output", "children"), Input("btn", "n_clicks")) def error_callback(n): @@ -132,16 +133,11 @@ def error_callback(n): assert "ZeroDivisionError" in error0 assert "backend" in error0 and error_msg in error0 + @pytest.mark.parametrize( "backend,fixture,start_server_kwargs, error_msg", [ - ( - "fastapi", - "dash_duo", - {"debug": True, - "reload": False}, - "fastapi.py" - ), + ("fastapi", "dash_duo", {"debug": True, "reload": False}, "fastapi.py"), ( "quart", "dash_duo_mp", @@ -150,17 +146,18 @@ def error_callback(n): "use_reloader": False, "dev_tools_hot_reload": False, }, - "quart.py" + "quart.py", ), - ] + ], ) -def test_backend_error_handling_prune(request, backend, fixture, start_server_kwargs, error_msg): +def test_backend_error_handling_prune( + request, backend, fixture, start_server_kwargs, error_msg +): dash_duo = request.getfixturevalue(fixture) app = Dash(__name__, backend=backend) - app.layout = html.Div([ - html.Button(id="btn", children="Error", n_clicks=0), - html.Div(id="output") - ]) + app.layout = html.Div( + [html.Button(id="btn", children="Error", n_clicks=0), html.Div(id="output")] + ) @app.callback(Output("output", "children"), Input("btn", "n_clicks")) def error_callback(n): @@ -178,28 +175,35 @@ def error_callback(n): assert "ZeroDivisionError" in error0 assert "dash/backend" not in error0 and error_msg not in error0 + @pytest.mark.parametrize( "backend,fixture,input_value", [ ("fastapi", "dash_duo", "Background FastAPI!"), ("quart", "dash_duo_mp", "Background Quart!"), - ] + ], ) def test_backend_background_callback(request, backend, fixture, input_value): dash_duo = request.getfixturevalue(fixture) import diskcache + cache = diskcache.Cache("./cache") from dash.background_callback import DiskcacheManager - background_callback_manager = DiskcacheManager(cache) + background_callback_manager = DiskcacheManager(cache) - app = Dash(__name__, backend=backend, background_callback_manager=background_callback_manager) - app.layout = html.Div([ - dcc.Input(id="input", value=input_value, type="text"), - html.Div(id="output") - ]) + app = Dash( + __name__, + backend=backend, + background_callback_manager=background_callback_manager, + ) + app.layout = html.Div( + [dcc.Input(id="input", value=input_value, type="text"), html.Div(id="output")] + ) - @app.callback(Output("output", "children"), Input("input", "value"), background=True) + @app.callback( + Output("output", "children"), Input("input", "value"), background=True + ) def update_output_bg(value): return f"Background typed: {value}" @@ -207,5 +211,7 @@ def update_output_bg(value): dash_duo.wait_for_text_to_equal("#output", f"Background typed: {input_value}") dash_duo.find_element("#input").clear() dash_duo.find_element("#input").send_keys(f"{backend.title()} BG Test") - dash_duo.wait_for_text_to_equal("#output", f"Background typed: {backend.title()} BG Test") + dash_duo.wait_for_text_to_equal( + "#output", f"Background typed: {backend.title()} BG Test" + ) assert dash_duo.get_logs() == [] From 6a34208f92d20cf3a7283407c1ac68528d5c9d8a Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 16 Sep 2025 16:36:28 -0400 Subject: [PATCH 058/297] adjustment to retest backend --- .github/workflows/testing.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 068fe777d1..48bfe0c305 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -17,6 +17,7 @@ jobs: # This output will be 'true' if files in the 'table_related_paths' list changed, 'false' otherwise. table_paths_changed: ${{ steps.filter.outputs.table_related_paths }} background_cb_changed: ${{ steps.filter.outputs.background_paths }} + backend_cb_changed: ${{ steps.filter.outputs.backend_paths }} steps: - name: Checkout repository uses: actions/checkout@v4 @@ -37,6 +38,9 @@ jobs: - 'tests/background_callback/**' - 'tests/async_tests/**' - 'requirements/**' + backend_paths: + - 'dash/backend/**' + - 'tests/backend/**' build: name: Build Dash Package @@ -276,7 +280,7 @@ jobs: needs: [build, changes_filter] if: | (github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev')) || - needs.changes_filter.outputs.backend_tests_changed == 'true' + needs.changes_filter.outputs.backend_cb_changed == 'true' timeout-minutes: 30 runs-on: ubuntu-latest strategy: From 1a2b53124b11b16b014ed941d822377659d01a5a Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 16 Sep 2025 16:44:12 -0400 Subject: [PATCH 059/297] adding missing reqs association --- .github/workflows/testing.yml | 2 +- setup.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 48bfe0c305..be5caf4929 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -331,7 +331,7 @@ jobs: python -m pip install --upgrade pip wheel python -m pip install "setuptools<78.0.0" python -m pip install "selenium==4.32.0" - find packages -name dash-*.whl -print -exec sh -c 'pip install "{}[async,ci,testing,dev,celery,diskcache, fastapi, quart]"' \; + find packages -name dash-*.whl -print -exec sh -c 'pip install "{}[async,ci,testing,dev,celery,diskcache,fastapi,quart]"' \; - name: Install Google Chrome run: | diff --git a/setup.py b/setup.py index 7ed781c20d..950bcbe14d 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,9 @@ def read_req_file(req_type): "testing": read_req_file("testing"), "celery": read_req_file("celery"), "diskcache": read_req_file("diskcache"), - "compress": read_req_file("compress") + "compress": read_req_file("compress"), + "fastapi": read_req_file("fastapi"), + "quart": read_req_file("quart"), }, entry_points={ "console_scripts": [ From 465e45e469324a25498f32fc5979ba190205f328 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 16 Sep 2025 16:59:36 -0400 Subject: [PATCH 060/297] fixing minor linting issues --- dash/backend/fastapi.py | 27 +++++++++++---------------- dash/backend/flask.py | 11 +++++------ dash/backend/quart.py | 7 +++---- dash/dash.py | 1 - 4 files changed, 19 insertions(+), 27 deletions(-) diff --git a/dash/backend/fastapi.py b/dash/backend/fastapi.py index a76a5a47ec..8c402cb187 100644 --- a/dash/backend/fastapi.py +++ b/dash/backend/fastapi.py @@ -7,11 +7,12 @@ import importlib.util import time import traceback +import re try: import uvicorn from fastapi import FastAPI, Request, Response - from fastapi.responses import JSONResponse, PlainTextResponse + from fastapi.responses import JSONResponse from fastapi.staticfiles import StaticFiles from starlette.responses import Response as StarletteResponse from starlette.datastructures import MutableHeaders @@ -23,7 +24,6 @@ Request = None Response = None JSONResponse = None - PlainTextResponse = None StaticFiles = None StarletteResponse = None MutableHeaders = None @@ -31,20 +31,17 @@ Any = None Optional = None + +import json +import os from dash.fingerprint import check_fingerprint from dash import _validate from dash.exceptions import ( PreventUpdate, - InvalidResourceError, - InvalidCallbackReturnValue, - BackgroundCallbackError, ) from dash.backend import set_request_adapter from .base_server import BaseDashServer -import json -import os - CONFIG_PATH = "dash_config.json" @@ -93,10 +90,8 @@ def register_assets_blueprint( def register_error_handlers(self, app): self.error_handling_mode = "prune" - # FastAPI uses exception handlers, but we will handle errors in middleware - pass - def _get_traceback(self, secret, error: Exception): + def _get_traceback(self, _secret, error: Exception): tb = error.__traceback__ errors = traceback.format_exception(type(error), error, tb) pass_errs = [] @@ -113,15 +108,13 @@ def _get_traceback(self, secret, error: Exception): error_msg = str(error) # Parse traceback lines to group by file - import re - file_cards = [] pattern = re.compile(r' File "(.+)", line (\d+), in (\w+)') lines = formatted_tb.split("\n") current_file = None card_lines = [] - for i, line in enumerate(lines[:-1]): # Skip the last line (error message) + for line in lines[:-1]: # Skip the last line (error message) match = pattern.match(line) if match: if current_file and card_lines: @@ -274,7 +267,9 @@ def run(self, dash_app, app, host, port, debug, **kwargs): frame = inspect.stack()[2] config = dict( {"debug": debug} if debug else {}, - **{f"dev_tools_{k}": v for k, v in dash_app._dev_tools.items()}, + **{ + f"dev_tools_{k}": v for k, v in dash_app._dev_tools.items() + }, # pylint: disable=protected-access ) save_config(config) if debug: @@ -307,7 +302,7 @@ def jsonify(self, obj): def get_request_adapter(self): return FastAPIRequestAdapter - def _make_before_middleware(self, func): + def _make_before_middleware(self, _func): async def middleware(request, call_next): try: response = await call_next(request) diff --git a/dash/backend/flask.py b/dash/backend/flask.py index 542da93129..cf544ef5bc 100644 --- a/dash/backend/flask.py +++ b/dash/backend/flask.py @@ -5,13 +5,14 @@ import mimetypes import time import inspect +import traceback import flask from dash.fingerprint import check_fingerprint from dash import _validate +from dash._callback import _invoke_callback, _async_invoke_callback from dash.exceptions import PreventUpdate, InvalidResourceError from dash.backend import set_request_adapter from .base_server import BaseDashServer -import traceback class FlaskDashServer(BaseDashServer): @@ -47,13 +48,13 @@ def _invalid_resources_handler(err): def _get_traceback(self, secret, error: Exception): try: - from werkzeug.debug import tbtools + from werkzeug.debug import ( + tbtools, + ) # pylint: disable=import-outside-toplevel except ImportError: tbtools = None def _get_skip(error): - from dash._callback import _invoke_callback, _async_invoke_callback - tb = error.__traceback__ skip = 1 while tb.tb_next is not None: @@ -67,8 +68,6 @@ def _get_skip(error): return skip def _do_skip(error): - from dash._callback import _invoke_callback, _async_invoke_callback - tb = error.__traceback__ while tb.tb_next is not None: if tb.tb_frame.f_code in [ diff --git a/dash/backend/quart.py b/dash/backend/quart.py index 71a2053a61..830d7dd3b9 100644 --- a/dash/backend/quart.py +++ b/dash/backend/quart.py @@ -5,6 +5,7 @@ import time from contextvars import copy_context import traceback +import re try: import quart @@ -56,7 +57,7 @@ def register_assets_blueprint( ) app.register_blueprint(bp) - def _get_traceback(self, secret, error: Exception): + def _get_traceback(self, _secret, error: Exception): tb = error.__traceback__ errors = traceback.format_exception(type(error), error, tb) pass_errs = [] @@ -73,15 +74,13 @@ def _get_traceback(self, secret, error: Exception): error_msg = str(error) # Parse traceback lines to group by file - import re - file_cards = [] pattern = re.compile(r' File "(.+)", line (\d+), in (\w+)') lines = formatted_tb.split("\n") current_file = None card_lines = [] - for i, line in enumerate(lines[:-1]): # Skip the last line (error message) + for line in lines[:-1]: # Skip the last line (error message) match = pattern.match(line) if match: if current_file and card_lines: diff --git a/dash/dash.py b/dash/dash.py index 994453f4a2..6bba3aadfd 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -14,7 +14,6 @@ import mimetypes import hashlib import base64 -import traceback from urllib.parse import urlparse from typing import Any, Callable, Dict, Optional, Union, Sequence, Literal, List From c43a5835d78dff075e80e8df420f53aa9c37e18c Mon Sep 17 00:00:00 2001 From: chgiesse <83552131+chgiesse@users.noreply.github.com> Date: Wed, 17 Sep 2025 16:16:39 +0200 Subject: [PATCH 061/297] Add global Request Adapter (#6) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ∙ - remove contextvar from flask and quart only FastApi now relies on that ∙ - backend __init__ now holds the global request adapter and backend which get set on app initialisation ∙ request adapter and server can now be call from everywhere after the app initialised ∙ - added normal top level imports because the modules get matching loaded - but bad Import Error message when quart or equivilent are not installed ∙ - added _ as prefix to backends to avoid importing errors with their underlying ∙ - Can now move to remove unnecessary passing of the server object ∙ * Moved get_server_type to backends * ∙ moved async validation to validation ∙ replaced request.get_path with request.path ∙ * Moved custom backend check to _validation.py * Removed server injection of server methods - they use self.server now * removed use_async from dispatch server methods and use dash_app._use_async removed remaining set request process from flask * adding custom error handling per backend, tests and adjustments to the flow. Made endpoints for downloading the reqs * adjusments for formatting * adjustment to retest backend * Added Dash app as type to servers * adding missing reqs association * Addedd basic typing to servers * fixing minor linting issues * Fixed weird AI shit * Cleanup before heavy pull * Merged latest changes * f rebase * f rebase * Added Dash app as type to servers * Addedd basic typing to servers --------- Co-authored-by: Christian Giessel Co-authored-by: BSd3v <82055130+BSd3v@users.noreply.github.com> --- dash/_callback.py | 41 +-- dash/_pages.py | 32 ++- dash/_validate.py | 39 +++ dash/backend/__init__.py | 15 - dash/backend/base_server.py | 58 ---- dash/backend/registry.py | 29 -- dash/backends/__init__.py | 88 ++++++ .../fastapi.py => backends/_fastapi.py} | 264 +++++++++++------- dash/{backend/flask.py => backends/_flask.py} | 264 ++++++++++-------- dash/{backend/quart.py => backends/_quart.py} | 240 +++++++++------- dash/backends/base_server.py | 119 ++++++++ dash/dash.py | 210 +++++--------- dash_config.json | 1 + quart_app.py | 23 ++ 14 files changed, 831 insertions(+), 592 deletions(-) delete mode 100644 dash/backend/__init__.py delete mode 100644 dash/backend/base_server.py delete mode 100644 dash/backend/registry.py create mode 100644 dash/backends/__init__.py rename dash/{backend/fastapi.py => backends/_fastapi.py} (72%) rename dash/{backend/flask.py => backends/_flask.py} (55%) rename dash/{backend/quart.py => backends/_quart.py} (68%) create mode 100644 dash/backends/base_server.py create mode 100644 dash_config.json create mode 100644 quart_app.py diff --git a/dash/_callback.py b/dash/_callback.py index 6cc55b9162..4a714caeac 100644 --- a/dash/_callback.py +++ b/dash/_callback.py @@ -1,12 +1,8 @@ +from typing import Callable, Optional, Any, List, Tuple, Union +from functools import wraps import collections import hashlib -from functools import wraps - -from typing import Callable, Optional, Any, List, Tuple, Union - - import asyncio -from dash.backend import get_request_adapter from .dependencies import ( handle_callback_args, @@ -39,10 +35,11 @@ clean_property_name, ) -from . import _validate from .background_callback.managers import BaseBackgroundCallbackManager from ._callback_context import context_value from ._no_update import NoUpdate +from . import _validate +from . import backends async def _async_invoke_callback( @@ -176,7 +173,6 @@ def callback( Note that the endpoint will not appear in the list of registered callbacks in the Dash devtools. """ - background_spec = None config_prevent_initial_callbacks = _kwargs.pop( @@ -376,7 +372,8 @@ def _get_callback_manager( " and store results on redis.\n" ) - old_job = get_request_adapter().get_args().getlist("oldJob") + adapter = backends.request_adapter() + old_job = adapter.args.getlist("oldJob") if hasattr(adapter.args, "getlist") else [] if old_job: for job in old_job: @@ -390,6 +387,8 @@ def _setup_background_callback( ): """Set up the background callback and manage jobs.""" callback_manager = _get_callback_manager(kwargs, background) + if not callback_manager: + return to_json({"error": "No background callback manager configured"}) progress_outputs = background.get("progress") @@ -397,14 +396,11 @@ def _setup_background_callback( cache_key = callback_manager.build_cache_key( func, - # Inputs provided as dict is kwargs. func_args if func_args else func_kwargs, background.get("cache_args_to_ignore", []), None if cache_ignore_triggered else callback_ctx.get("triggered_inputs", []), ) - job_fn = callback_manager.func_registry.get(background_key) - ctx_value = AttributeDict(**context_value.get()) ctx_value.ignore_register_page = True ctx_value.pop("background_callback_manager") @@ -436,7 +432,8 @@ def _setup_background_callback( def _progress_background_callback(response, callback_manager, background): progress_outputs = background.get("progress") - cache_key = get_request_adapter().get_args().get("cacheKey") + adapter = backends.request_adapter() + cache_key = adapter.args.get("cacheKey") if progress_outputs: # Get the progress before the result as it would be erased after the results. @@ -453,8 +450,9 @@ def _update_background_callback( """Set up the background callback and manage jobs.""" callback_manager = _get_callback_manager(kwargs, background) - cache_key = get_request_adapter().get_args().get("cacheKey") - job_id = get_request_adapter().get_args().get("job") + adapter = backends.request_adapter() + cache_key = adapter.args.get("cacheKey") if adapter else None + job_id = adapter.args.get("job") if adapter else None _progress_background_callback(response, callback_manager, background) @@ -474,8 +472,9 @@ def _handle_rest_background_callback( multi, has_update=False, ): - cache_key = get_request_adapter().get_args().get("cacheKey") - job_id = get_request_adapter().get_args().get("job") + adapter = backends.request_adapter() + cache_key = adapter.args.get("cacheKey") if adapter else None + job_id = adapter.args.get("job") if adapter else None # Must get job_running after get_result since get_results terminates it. job_running = callback_manager.job_running(job_id) if not job_running and output_value is callback_manager.UNDEFINED: @@ -688,10 +687,11 @@ def add_context(*args, **kwargs): ) response: dict = {"multi": True} - jsonResponse = None + jsonResponse: Optional[str] = None try: if background is not None: - if not get_request_adapter().get_args().get("cacheKey"): + adapter = backends.request_adapter() + if not (adapter and adapter.args.get("cacheKey")): return _setup_background_callback( kwargs, background, @@ -762,7 +762,8 @@ async def async_add_context(*args, **kwargs): try: if background is not None: - if not get_request_adapter().get_args().get("cacheKey"): + adapter = backends.request_adapter() + if not (adapter and adapter.args.get("cacheKey")): return _setup_background_callback( kwargs, background, diff --git a/dash/_pages.py b/dash/_pages.py index acb26e8791..19a797bcf2 100644 --- a/dash/_pages.py +++ b/dash/_pages.py @@ -318,18 +318,22 @@ def register_page( ) page.update( supplied_title=title, - title=title - if title is not None - else CONFIG.title - if CONFIG.title != "Dash" - else page["name"], + title=( + title + if title is not None + else CONFIG.title + if CONFIG.title != "Dash" + else page["name"] + ), ) page.update( - description=description - if description - else CONFIG.description - if CONFIG.description - else "", + description=( + description + if description + else CONFIG.description + if CONFIG.description + else "" + ), order=order, supplied_order=order, supplied_layout=layout, @@ -390,15 +394,13 @@ def _path_to_page(path_id): def _page_meta_tags(app, request): - request_path = request.get_path() + request_path = request.path start_page, path_variables = _path_to_page(request_path.strip("/")) image = start_page.get("image", "") if image: image = app.get_asset_url(image) - assets_image_url = ( - "".join([request.get_root(), image.lstrip("/")]) if image else None - ) + assets_image_url = "".join([request.root, image.lstrip("/")]) if image else None supplied_image_url = start_page.get("image_url") image_url = supplied_image_url if supplied_image_url else assets_image_url @@ -413,7 +415,7 @@ def _page_meta_tags(app, request): return [ {"name": "description", "content": description}, {"property": "twitter:card", "content": "summary_large_image"}, - {"property": "twitter:url", "content": request.get_url()}, + {"property": "twitter:url", "content": request.url}, {"property": "twitter:title", "content": title}, {"property": "twitter:description", "content": description}, {"property": "twitter:image", "content": image_url or ""}, diff --git a/dash/_validate.py b/dash/_validate.py index dea19d64c2..76661cef6b 100644 --- a/dash/_validate.py +++ b/dash/_validate.py @@ -8,6 +8,7 @@ from ._grouping import grouping_len, map_grouping from ._no_update import NoUpdate from .development.base_component import Component +from . import backends from . import exceptions from ._utils import ( patch_collections_abc, @@ -585,3 +586,41 @@ def _valid(out): return _valid(output) + + +def check_async(use_async): + if use_async is None: + try: + import asgiref # pylint: disable=unused-import, import-outside-toplevel # noqa + + use_async = True + except ImportError: + pass + elif use_async: + try: + import asgiref # pylint: disable=unused-import, import-outside-toplevel # noqa + except ImportError as exc: + raise Exception( + "You are trying to use dash[async] without having installed the requirements please install via: `pip install dash[async]`" + ) from exc + + +def check_backend(backend, inferred_backend): + if backend is not None: + if isinstance(backend, type): + # get_backend returns the backend class for a string + # So we compare the class names + expected_backend_cls, _ = backends.get_backend(inferred_backend) + if ( + backend.__module__ != expected_backend_cls.__module__ + or backend.__name__ != expected_backend_cls.__name__ + ): + raise ValueError( + f"Conflict between provided backend '{backend.__name__}' and server type '{inferred_backend}'." + ) + elif not isinstance(backend, str): + raise ValueError("Invalid backend argument") + elif backend.lower() != inferred_backend: + raise ValueError( + f"Conflict between provided backend '{backend}' and server type '{inferred_backend}'." + ) diff --git a/dash/backend/__init__.py b/dash/backend/__init__.py deleted file mode 100644 index eb1d47bc3f..0000000000 --- a/dash/backend/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# python -import contextvars -from .registry import get_backend # pylint: disable=unused-import - -__all__ = ["set_request_adapter", "get_request_adapter", "get_backend"] - -_request_adapter_var = contextvars.ContextVar("request_adapter") - - -def set_request_adapter(adapter): - _request_adapter_var.set(adapter) - - -def get_request_adapter(): - return _request_adapter_var.get() diff --git a/dash/backend/base_server.py b/dash/backend/base_server.py deleted file mode 100644 index 4855f86ad6..0000000000 --- a/dash/backend/base_server.py +++ /dev/null @@ -1,58 +0,0 @@ -from abc import ABC, abstractmethod -from typing import Any - - -class BaseDashServer(ABC): - def __call__(self, server, *args, **kwargs) -> Any: - # Default: WSGI - return server(*args, **kwargs) - - @abstractmethod - def create_app( - self, name: str = "__main__", config=None - ) -> Any: # pragma: no cover - interface - pass - - @abstractmethod - def register_assets_blueprint( - self, app, blueprint_name: str, assets_url_path: str, assets_folder: str - ) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def register_error_handlers(self, app) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def add_url_rule( - self, app, rule: str, view_func, endpoint=None, methods=None - ) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def before_request(self, app, func) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def after_request(self, app, func) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def run( - self, app, host: str, port: int, debug: bool, **kwargs - ) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def make_response( - self, data, mimetype=None, content_type=None - ) -> Any: # pragma: no cover - interface - pass - - @abstractmethod - def jsonify(self, obj) -> Any: # pragma: no cover - interface - pass - - @abstractmethod - def get_request_adapter(self) -> Any: # pragma: no cover - interface - pass diff --git a/dash/backend/registry.py b/dash/backend/registry.py deleted file mode 100644 index 4aae9fafc5..0000000000 --- a/dash/backend/registry.py +++ /dev/null @@ -1,29 +0,0 @@ -import importlib - -_backend_imports = { - "flask": ("dash.backend.flask", "FlaskDashServer"), - "fastapi": ("dash.backend.fastapi", "FastAPIDashServer"), - "quart": ("dash.backend.quart", "QuartDashServer"), -} - - -def register_backend(name, module_path, class_name): - """Register a new backend by name.""" - _backend_imports[name.lower()] = (module_path, class_name) - - -def get_backend(name): - try: - module_name, class_name = _backend_imports[name.lower()] - module = importlib.import_module(module_name) - return getattr(module, class_name) - except KeyError as e: - raise ValueError(f"Unknown backend: {name}") from e - except ImportError as e: - raise ImportError( - f"Could not import module '{module_name}' for backend '{name}': {e}" - ) from e - except AttributeError as e: - raise AttributeError( - f"Module '{module_name}' does not have class '{class_name}' for backend '{name}': {e}" - ) from e diff --git a/dash/backends/__init__.py b/dash/backends/__init__.py new file mode 100644 index 0000000000..940c8f18bd --- /dev/null +++ b/dash/backends/__init__.py @@ -0,0 +1,88 @@ +from .base_server import BaseDashServer, RequestAdapter + +from typing import Literal, Any +import importlib + + +request_adapter: RequestAdapter +backend: BaseDashServer + + +_backend_imports = { + "flask": ("dash.backends._flask", "FlaskDashServer", "FlaskRequestAdapter"), + "fastapi": ("dash.backends._fastapi", "FastAPIDashServer", "FastAPIRequestAdapter"), + "quart": ("dash.backends._quart", "QuartDashServer", "QuartRequestAdapter"), +} + + +request_adapter: RequestAdapter +backend: BaseDashServer + + +def get_backend( + name: Literal["flask", "fastapi", "quart"] | str +) -> tuple[BaseDashServer, RequestAdapter]: + module_name, server_class, request_class = _backend_imports[name.lower()] + try: + module = importlib.import_module(module_name) + server = getattr(module, server_class) + request_adapter = getattr(module, request_class) + return server, request_adapter + except KeyError as e: + raise ValueError(f"Unknown backend: {name}") from e + except ImportError as e: + raise ImportError( + f"Could not import module '{module_name}' for backend '{name}': {e}" + ) from e + except AttributeError as e: + raise AttributeError( + f"Module '{module_name}' does not have class '{server_class}' for backend '{name}': {e}" + ) from e + + +def _is_flask_instance(obj): + try: + # pylint: disable=import-outside-toplevel + from flask import Flask + + return isinstance(obj, Flask) + except ImportError: + return False + + +def _is_fastapi_instance(obj): + try: + # pylint: disable=import-outside-toplevel + from fastapi import FastAPI + + return isinstance(obj, FastAPI) + except ImportError: + return False + + +def _is_quart_instance(obj): + try: + # pylint: disable=import-outside-toplevel + from quart import Quart + + return isinstance(obj, Quart) + except ImportError: + return False + + +def get_server_type(server): + if _is_flask_instance(server): + return "flask" + if _is_quart_instance(server): + return "quart" + if _is_fastapi_instance(server): + return "fastapi" + raise ValueError("Invalid backend argument") + + +__all__ = [ + "get_backend", + "request_adapter", + "backend", + "get_server_type", +] diff --git a/dash/backend/fastapi.py b/dash/backends/_fastapi.py similarity index 72% rename from dash/backend/fastapi.py rename to dash/backends/_fastapi.py index 8c402cb187..f3f9f2df33 100644 --- a/dash/backend/fastapi.py +++ b/dash/backends/_fastapi.py @@ -1,46 +1,71 @@ +from __future__ import annotations + +from contextvars import copy_context, ContextVar +from typing import TYPE_CHECKING, Any, Callable, Dict import sys import mimetypes import hashlib import inspect import pkgutil -from contextvars import copy_context -import importlib.util import time import traceback -import re - -try: - import uvicorn - from fastapi import FastAPI, Request, Response - from fastapi.responses import JSONResponse - from fastapi.staticfiles import StaticFiles - from starlette.responses import Response as StarletteResponse - from starlette.datastructures import MutableHeaders - from pydantic import create_model - from typing import Any, Optional -except ImportError: - uvicorn = None - FastAPI = None - Request = None - Response = None - JSONResponse = None - StaticFiles = None - StarletteResponse = None - MutableHeaders = None - create_model = None - Any = None - Optional = None - - +from importlib.util import spec_from_file_location import json import os +import re + from dash.fingerprint import check_fingerprint from dash import _validate -from dash.exceptions import ( - PreventUpdate, -) -from dash.backend import set_request_adapter -from .base_server import BaseDashServer +from dash.exceptions import PreventUpdate +from .base_server import BaseDashServer, RequestAdapter + +from fastapi import FastAPI, Request, Response, Body +from fastapi.responses import JSONResponse +from fastapi.staticfiles import StaticFiles +from starlette.responses import Response as StarletteResponse +from starlette.datastructures import MutableHeaders +from starlette.types import ASGIApp, Scope, Receive, Send +import uvicorn + +if TYPE_CHECKING: # pragma: no cover - typing only + from dash.dash import Dash + + +_current_request_var = ContextVar("dash_current_request", default=None) + + +def set_current_request(req): + return _current_request_var.set(req) + + +def reset_current_request(token): + _current_request_var.reset(token) + + +def get_current_request() -> Request: + req = _current_request_var.get() + if req is None: + raise RuntimeError("No active request in context") + return req + + +class CurrentRequestMiddleware: + def __init__(self, app: ASGIApp) -> None: # type: ignore[name-defined] + self.app = app + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: # type: ignore[name-defined] + # non-http/ws scopes pass through (lifespan etc.) + if scope["type"] not in ("http", "websocket"): + await self.app(scope, receive, send) + return + + request = Request(scope, receive=receive) + token = set_current_request(request) + try: + await self.app(scope, receive, send) + finally: + reset_current_request(token) + CONFIG_PATH = "dash_config.json" @@ -58,28 +83,35 @@ def load_config(): class FastAPIDashServer(BaseDashServer): - def __init__(self): + + def __init__(self, server: FastAPI): + self.config = {} + self.server_type = "fastapi" + self.server: FastAPI = server self.error_handling_mode = "prune" super().__init__() - def __call__(self, server, *args, **kwargs): + def __call__(self, *args: Any, **kwargs: Any): # ASGI: (scope, receive, send) if len(args) == 3 and isinstance(args[0], dict) and "type" in args[0]: - return server(*args, **kwargs) + return self.server(*args, **kwargs) raise TypeError("FastAPI app must be called with (scope, receive, send)") - def create_app(self, name="__main__", config=None): + @staticmethod + def create_app(name: str = "__main__", config: Dict[str, Any] | None = None): app = FastAPI() + app.add_middleware(CurrentRequestMiddleware) + if config: for key, value in config.items(): setattr(app.state, key, value) return app def register_assets_blueprint( - self, app, blueprint_name, assets_url_path, assets_folder + self, blueprint_name: str, assets_url_path: str, assets_folder: str ): try: - app.mount( + self.server.mount( assets_url_path, StaticFiles(directory=assets_folder), name=blueprint_name, @@ -88,7 +120,7 @@ def register_assets_blueprint( # directory doesnt exist pass - def register_error_handlers(self, app): + def register_error_handlers(self): self.error_handling_mode = "prune" def _get_traceback(self, _secret, error: Exception): @@ -200,13 +232,13 @@ def _get_traceback(self, _secret, error: Exception): """ return html - def register_prune_error_handler(self, _app, _secret, prune_errors): + def register_prune_error_handler(self, _secret, prune_errors): if prune_errors: self.error_handling_mode = "prune" else: self.error_handling_mode = "raise" - def _html_response_wrapper(self, view_func): + def _html_response_wrapper(self, view_func: Callable[..., Any] | str): async def wrapped(*_args, **_kwargs): # If view_func is a function, call it; if it's a string, use it directly html = view_func() if callable(view_func) else view_func @@ -214,40 +246,40 @@ async def wrapped(*_args, **_kwargs): return wrapped - def setup_index(self, dash_app): + def setup_index(self, dash_app: Dash): async def index(request: Request): - adapter = FastAPIRequestAdapter() - set_request_adapter(adapter) - adapter.set_request(request) return Response(content=dash_app.index(), media_type="text/html") # pylint: disable=protected-access dash_app._add_url("", index, methods=["GET"]) - def setup_catchall(self, dash_app): - @dash_app.server.on_event("startup") + def setup_catchall(self, dash_app: Dash): + @self.server.on_event("startup") def _setup_catchall(): - config = load_config() - dash_app.enable_dev_tools(**config, first_run=False) + dash_app.enable_dev_tools( + **self.config, first_run=False + ) # do this to make sure dev tools are enabled async def catchall(request: Request): - adapter = FastAPIRequestAdapter() - set_request_adapter(adapter) - adapter.set_request(request) return Response(content=dash_app.index(), media_type="text/html") # pylint: disable=protected-access dash_app._add_url("{path:path}", catchall, methods=["GET"]) def add_url_rule( - self, app, rule, view_func, endpoint=None, methods=None, include_in_schema=False + self, + rule: str, + view_func: Callable[..., Any] | str, + endpoint: str | None = None, + methods: list[str] | None = None, + include_in_schema: bool = False, ): if rule == "": rule = "/" if isinstance(view_func, str): # Wrap string or sync function to async FastAPI handler view_func = self._html_response_wrapper(view_func) - app.add_api_route( + self.server.add_api_route( rule, view_func, methods=methods or ["GET"], @@ -255,15 +287,15 @@ def add_url_rule( include_in_schema=include_in_schema, ) - def before_request(self, app, func): + def before_request(self, func: Callable[[], Any] | None): # FastAPI does not have before_request, but we can use middleware - app.middleware("http")(self._make_before_middleware(func)) + self.server.middleware("http")(self._make_before_middleware(func)) - def after_request(self, app, func): + def after_request(self, func: Callable[[], Any] | None): # FastAPI does not have after_request, but we can use middleware - app.middleware("http")(self._make_after_middleware(func)) + self.server.middleware("http")(self._make_after_middleware(func)) - def run(self, dash_app, app, host, port, debug, **kwargs): + def run(self, dash_app: Dash, host, port, debug, **kwargs): frame = inspect.stack()[2] config = dict( {"debug": debug} if debug else {}, @@ -278,7 +310,8 @@ def run(self, dash_app, app, host, port, debug, **kwargs): if kwargs.get("reload"): # Dynamically determine the module name from the file path file_path = frame.filename - module_name = importlib.util.spec_from_file_location("app", file_path).name + spec = spec_from_file_location("app", file_path) + module_name = spec.name if spec and getattr(spec, "name", None) else "app" uvicorn.run( f"{module_name}:app.server", host=host, @@ -286,9 +319,14 @@ def run(self, dash_app, app, host, port, debug, **kwargs): **kwargs, ) else: - uvicorn.run(app, host=host, port=port, **kwargs) + uvicorn.run(self.server, host=host, port=port, **kwargs) - def make_response(self, data, mimetype=None, content_type=None): + def make_response( + self, + data: str | bytes | bytearray, + mimetype: str | None = None, + content_type: str | None = None, + ): headers = {} if mimetype: headers["content-type"] = mimetype @@ -296,13 +334,10 @@ def make_response(self, data, mimetype=None, content_type=None): headers["content-type"] = content_type return Response(content=data, headers=headers) - def jsonify(self, obj): + def jsonify(self, obj: Any): return JSONResponse(content=obj) - def get_request_adapter(self): - return FastAPIRequestAdapter - - def _make_before_middleware(self, _func): + def _make_before_middleware(self, func: Callable[[], Any] | None): async def middleware(request, call_next): try: response = await call_next(request) @@ -322,7 +357,7 @@ async def middleware(request, call_next): return middleware - def _make_after_middleware(self, func): + def _make_after_middleware(self, func: Callable[[], Any] | None): async def middleware(request, call_next): response = await call_next(request) if func is not None: @@ -335,8 +370,13 @@ async def middleware(request, call_next): return middleware def serve_component_suites( - self, dash_app, package_name, fingerprinted_path, request + self, + dash_app: Dash, + package_name: str, + fingerprinted_path: str, + request: Request, ): + path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) extension = "." + path_in_pkg.split(".")[-1] @@ -360,7 +400,7 @@ def serve_component_suites( return StarletteResponse(status_code=304) return StarletteResponse(content=data, media_type=mimetype, headers=headers) - def setup_component_suites(self, dash_app): + def setup_component_suites(self, dash_app: Dash): async def serve(request: Request, package_name: str, fingerprinted_path: str): return self.serve_component_suites( dash_app, package_name, fingerprinted_path, request @@ -373,16 +413,12 @@ async def serve(request: Request, package_name: str, fingerprinted_path: str): ) # pylint: disable=unused-argument - def dispatch(self, app, dash_app, use_async=False): + def dispatch(self, dash_app: Dash): + async def _dispatch(request: Request): - adapter = FastAPIRequestAdapter() - set_request_adapter(adapter) - adapter.set_request(request) # pylint: disable=protected-access body = await request.json() - g = dash_app._initialize_context( - body, adapter - ) # pylint: disable=protected-access + g = dash_app._initialize_context(body) # pylint: disable=protected-access func = dash_app._prepare_callback( g, body ) # pylint: disable=protected-access @@ -406,12 +442,12 @@ def _serve_default_favicon(self): content=pkgutil.get_data("dash", "favicon.ico"), media_type="image/x-icon" ) - def register_timing_hooks(self, app, first_run): + def register_timing_hooks(self, first_run: bool): if not first_run: return - @app.middleware("http") - async def timing_middleware(request, call_next): + @self.server.middleware("http") + async def timing_middleware(request: Request, call_next): # Before request request.state.timing_information = { "__dash_server": {"dur": time.time(), "desc": None} @@ -433,11 +469,11 @@ async def timing_middleware(request, call_next): headers.append("Server-Timing", value) return response - def register_callback_api_routes(self, app, callback_api_paths): + def register_callback_api_routes(self, callback_api_paths: Dict[str, Callable[..., Any]]): """ Register callback API endpoints on the FastAPI app. Each key in callback_api_paths is a route, each value is a handler (sync or async). - Dynamically creates a Pydantic model for the handler's parameters and uses it as the body parameter. + Accepts a JSON body (dict) and filters keys based on the handler's signature. """ for path, handler in callback_api_paths.items(): endpoint = f"dash_callback_api_{path}" @@ -445,21 +481,19 @@ def register_callback_api_routes(self, app, callback_api_paths): methods = ["POST"] sig = inspect.signature(handler) param_names = list(sig.parameters.keys()) - fields = {name: (Optional[Any], None) for name in param_names} - Model = create_model( - f"Payload_{endpoint}", **fields - ) # pylint: disable=cell-var-from-loop - - # pylint: disable=cell-var-from-loop - async def view_func(request: Request, body: Model): - kwargs = body.dict(exclude_unset=True) + + async def view_func(request: Request, body: dict = Body(...)): + # Only pass expected params; ignore extras + kwargs = { + k: v for k, v in body.items() if k in param_names and v is not None + } if inspect.iscoroutinefunction(handler): result = await handler(**kwargs) else: result = handler(**kwargs) return JSONResponse(content=result) - app.add_api_route( + self.server.add_api_route( route, view_func, methods=methods, @@ -468,44 +502,58 @@ async def view_func(request: Request, body: Model): ) -class FastAPIRequestAdapter: +class FastAPIRequestAdapter(RequestAdapter): + def __init__(self): - self._request = None + self._request: Request = get_current_request() + super().__init__() - def set_request(self, request: Request): - self._request = request + def __call__(self): + self._request = get_current_request() + return self - def get_root(self): + @property + def root(self): return str(self._request.base_url) - def get_args(self): + @property + def args(self): return self._request.query_params - async def get_json(self): - return await self._request.json() - + @property def is_json(self): return self._request.headers.get("content-type", "").startswith( "application/json" ) - def get_cookies(self, _request=None): + @property + def cookies(self): return self._request.cookies - def get_headers(self): + @property + def headers(self): return self._request.headers - def get_full_path(self): + @property + def full_path(self): return str(self._request.url) - def get_url(self): + @property + def url(self): return str(self._request.url) - def get_remote_addr(self): - return self._request.client.host if self._request.client else None + @property + def remote_addr(self): + client = getattr(self._request, "client", None) + return getattr(client, "host", None) - def get_origin(self): + @property + def origin(self): return self._request.headers.get("origin") - def get_path(self): + @property + def path(self): return self._request.url.path + + async def get_json(self): # async method retained + return await self._request.json() diff --git a/dash/backend/flask.py b/dash/backends/_flask.py similarity index 55% rename from dash/backend/flask.py rename to dash/backends/_flask.py index cf544ef5bc..5a1385d574 100644 --- a/dash/backend/flask.py +++ b/dash/backends/_flask.py @@ -1,4 +1,7 @@ +from __future__ import annotations + from contextvars import copy_context +from typing import TYPE_CHECKING, Any, Callable, Dict import asyncio import pkgutil import sys @@ -6,43 +9,60 @@ import time import inspect import traceback -import flask +from flask import ( + Flask, + Blueprint, + Response, + request, + jsonify, + g as flask_g, +) + from dash.fingerprint import check_fingerprint from dash import _validate -from dash._callback import _invoke_callback, _async_invoke_callback from dash.exceptions import PreventUpdate, InvalidResourceError -from dash.backend import set_request_adapter -from .base_server import BaseDashServer +from dash._callback import _invoke_callback, _async_invoke_callback +from .base_server import BaseDashServer, RequestAdapter + +if TYPE_CHECKING: # pragma: no cover - typing only + from dash import Dash class FlaskDashServer(BaseDashServer): - def __call__(self, server, *args, **kwargs): + + def __init__(self, server: Flask) -> None: + self.server: Flask = server + self.server_type = "flask" + super().__init__() + + def __call__(self, *args: Any, **kwargs: Any): # Always WSGI - return server(*args, **kwargs) + return self.server(*args, **kwargs) - def create_app(self, name="__main__", config=None): - app = flask.Flask(name) + @staticmethod + def create_app(name: str = "__main__", config: Dict[str, Any] | None = None): + app = Flask(name) if config: app.config.update(config) return app def register_assets_blueprint( - self, app, blueprint_name, assets_url_path, assets_folder + self, blueprint_name: str, assets_url_path: str, assets_folder: str ): - bp = flask.Blueprint( + bp = Blueprint( blueprint_name, __name__, static_folder=assets_folder, static_url_path=assets_url_path, ) - app.register_blueprint(bp) + self.server.register_blueprint(bp) - def register_error_handlers(self, app): - @app.errorhandler(PreventUpdate) + def register_error_handlers(self): + @self.server.errorhandler(PreventUpdate) def _handle_error(_): return "", 204 - @app.errorhandler(InvalidResourceError) + @self.server.errorhandler(InvalidResourceError) def _invalid_resources_handler(err): return err.args[0], 404 @@ -86,56 +106,64 @@ def _do_skip(error): ).render_debugger_html(True, secret, True) return "".join(traceback.format_exception(type(error), error, _do_skip(error))) - def register_prune_error_handler(self, app, secret, prune_errors): + def register_prune_error_handler(self, secret, prune_errors): if prune_errors: - @app.errorhandler(Exception) + @self.server.errorhandler(Exception) def _wrap_errors(error): tb = self._get_traceback(secret, error) return tb, 500 - def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): - app.add_url_rule( + def add_url_rule( + self, + rule: str, + view_func: Callable[..., Any], + endpoint: str | None = None, + methods: list[str] | None = None, + ): + self.server.add_url_rule( rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"] ) - def before_request(self, app, func): - app.before_request(func) - - def after_request(self, app, func): - app.after_request(func) + def before_request(self, func: Callable[[], Any]): + # Flask expects a callable; user responsibility not to pass None + self.server.before_request(func) - def run(self, _dash_app, app, host, port, debug, **kwargs): - app.run(host=host, port=port, debug=debug, **kwargs) + def after_request(self, func: Callable[[Any], Any]): + # Flask after_request expects a function(response) -> response + self.server.after_request(func) - def make_response(self, data, mimetype=None, content_type=None): - return flask.Response(data, mimetype=mimetype, content_type=content_type) + def run(self, dash_app: Dash, host: str, port: int, debug: bool, **kwargs: Any): + self.server.run(host=host, port=port, debug=debug, **kwargs) - def jsonify(self, obj): - return flask.jsonify(obj) + def make_response( + self, + data: str | bytes | bytearray, + mimetype: str | None = None, + content_type: str | None = None, + ): + return Response(data, mimetype=mimetype, content_type=content_type) - def get_request_adapter(self): - return FlaskRequestAdapter + def jsonify(self, obj: Any): + return jsonify(obj) - def setup_catchall(self, dash_app): + def setup_catchall(self, dash_app: Dash): def catchall(*args, **kwargs): - adapter = FlaskRequestAdapter() - set_request_adapter(adapter) return dash_app.index(*args, **kwargs) # pylint: disable=protected-access dash_app._add_url("", catchall, methods=["GET"]) - def setup_index(self, dash_app): + def setup_index(self, dash_app: Dash): def index(*args, **kwargs): - adapter = FlaskRequestAdapter() - set_request_adapter(adapter) return dash_app.index(*args, **kwargs) # pylint: disable=protected-access dash_app._add_url("", index, methods=["GET"]) - def serve_component_suites(self, dash_app, package_name, fingerprinted_path): + def serve_component_suites( + self, dash_app: Dash, package_name: str, fingerprinted_path: str + ): path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) extension = "." + path_in_pkg.split(".")[-1] @@ -149,18 +177,18 @@ def serve_component_suites(self, dash_app, package_name, fingerprinted_path): package.__path__, ) data = pkgutil.get_data(package_name, path_in_pkg) - response = flask.Response(data, mimetype=mimetype) + response = Response(data, mimetype=mimetype) if has_fingerprint: response.cache_control.max_age = 31536000 # 1 year else: response.add_etag() tag = response.get_etag()[0] - request_etag = flask.request.headers.get("If-None-Match") + request_etag = request.headers.get("If-None-Match") if f'"{tag}"' == request_etag: - response = flask.Response(None, status=304) + response = Response(None, status=304) return response - def setup_component_suites(self, dash_app): + def setup_component_suites(self, dash_app: Dash): def serve(package_name, fingerprinted_path): return self.serve_component_suites( dash_app, package_name, fingerprinted_path @@ -173,17 +201,15 @@ def serve(package_name, fingerprinted_path): ) # pylint: disable=unused-argument - def dispatch(self, app, dash_app, use_async=False): + def dispatch(self, dash_app: Dash): def _dispatch(): - adapter = FlaskRequestAdapter() - set_request_adapter(adapter) - body = flask.request.get_json() + body = request.get_json() # pylint: disable=protected-access - g = dash_app._initialize_context(body, adapter) - func = dash_app._prepare_callback(g, body) - args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) + cb_ctx = dash_app._initialize_context(body) + func = dash_app._prepare_callback(cb_ctx, body) + args = dash_app._inputs_to_vals(cb_ctx.inputs_list + cb_ctx.states_list) ctx = copy_context() - partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) + partial_func = dash_app._execute_callback(func, args, cb_ctx.outputs_list, cb_ctx) response_data = ctx.run(partial_func) if asyncio.iscoroutine(response_data): raise Exception( @@ -191,43 +217,41 @@ def _dispatch(): "Please install the dependencies via `pip install dash[async]` and ensure " "that `use_async=False` is not being passed to the app." ) - g.dash_response.set_data(response_data) - return g.dash_response + cb_ctx.dash_response.set_data(response_data) + return cb_ctx.dash_response async def _dispatch_async(): - adapter = FlaskRequestAdapter() - set_request_adapter(adapter) - body = flask.request.get_json() + body = request.get_json() # pylint: disable=protected-access - g = dash_app._initialize_context(body, adapter) - func = dash_app._prepare_callback(g, body) - args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) + cb_ctx = dash_app._initialize_context(body) + func = dash_app._prepare_callback(cb_ctx, body) + args = dash_app._inputs_to_vals(cb_ctx.inputs_list + cb_ctx.states_list) ctx = copy_context() - partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) + partial_func = dash_app._execute_callback(func, args, cb_ctx.outputs_list, cb_ctx) response_data = ctx.run(partial_func) if asyncio.iscoroutine(response_data): response_data = await response_data - g.dash_response.set_data(response_data) - return g.dash_response + cb_ctx.dash_response.set_data(response_data) + return cb_ctx.dash_response - if use_async: + if dash_app._use_async: return _dispatch_async return _dispatch def _serve_default_favicon(self): - - return flask.Response( + return Response( pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" ) - def register_timing_hooks(self, app, _first_run): - def _before_request(): - flask.g.timing_information = { + def register_timing_hooks(self, _first_run: bool): + # Define timing hooks inside method scope and register them + def _before_request() -> None: + flask_g.timing_information = { # type: ignore[attr-defined] "__dash_server": {"dur": time.time(), "desc": None} } - def _after_request(response): - timing_information = flask.g.get("timing_information", None) + def _after_request(response: Response): # type: ignore[name-defined] + timing_information = flask_g.get("timing_information", None) # type: ignore[attr-defined] if timing_information is None: return response dash_total = timing_information.get("__dash_server", None) @@ -242,10 +266,10 @@ def _after_request(response): response.headers.add("Server-Timing", value) return response - self.before_request(app, _before_request) - self.after_request(app, _after_request) + self.before_request(_before_request) + self.after_request(_after_request) - def register_callback_api_routes(self, app, callback_api_paths): + def register_callback_api_routes(self, callback_api_paths: Dict[str, Callable[..., Any]]): """ Register callback API endpoints on the Flask app. Each key in callback_api_paths is a route, each value is a handler (sync or async). @@ -258,65 +282,79 @@ def register_callback_api_routes(self, app, callback_api_paths): if inspect.iscoroutinefunction(handler): - async def view_func(*args, handler=handler, **kwargs): - data = flask.request.get_json() + async def _async_view_func(*args, handler=handler, **kwargs): + data = request.get_json() result = await handler(**data) if data else await handler() - return flask.jsonify(result) + return jsonify(result) + view_func = _async_view_func else: - def view_func(*args, handler=handler, **kwargs): - data = flask.request.get_json() + def _sync_view_func(*args, handler=handler, **kwargs): + data = request.get_json() result = handler(**data) if data else handler() - return flask.jsonify(result) + return jsonify(result) + + view_func = _sync_view_func + + view_func = _sync_view_func # Flask 2.x+ supports async views natively - app.add_url_rule( + self.server.add_url_rule( route, endpoint=endpoint, view_func=view_func, methods=methods ) -class FlaskRequestAdapter: - @staticmethod - def get_args(): - return flask.request.args +class FlaskRequestAdapter(RequestAdapter): + """Flask implementation using property-based accessors.""" - @staticmethod - def get_root(): - return flask.request.url_root + def __init__(self) -> None: + # Store the request LocalProxy so we can reference it consistently + self._request = request + super().__init__() - @staticmethod - def get_json(): - return flask.request.get_json() + def __call__(self, *args: Any, **kwds: Any): + return self - @staticmethod - def is_json(): - return flask.request.is_json + @property + def args(self): + return self._request.args - @staticmethod - def get_cookies(): - return flask.request.cookies + @property + def root(self): + return self._request.url_root - @staticmethod - def get_headers(): - return flask.request.headers + def get_json(self): # kept as method + return self._request.get_json() - @staticmethod - def get_url(): - return flask.request.url + @property + def is_json(self): + return self._request.is_json - @staticmethod - def get_full_path(): - return flask.request.full_path + @property + def cookies(self): + return self._request.cookies - @staticmethod - def get_remote_addr(): - return flask.request.remote_addr + @property + def headers(self): + return self._request.headers - @staticmethod - def get_origin(): - return getattr(flask.request, "origin", None) + @property + def url(self): + return self._request.url - @staticmethod - def get_path(): - return flask.request.path + @property + def full_path(self): + return self._request.full_path + + @property + def remote_addr(self): + return self._request.remote_addr + + @property + def origin(self): + return getattr(self._request, "origin", None) + + @property + def path(self): + return self._request.path diff --git a/dash/backend/quart.py b/dash/backends/_quart.py similarity index 68% rename from dash/backend/quart.py rename to dash/backends/_quart.py index 830d7dd3b9..a462d07af6 100644 --- a/dash/backend/quart.py +++ b/dash/backends/_quart.py @@ -1,61 +1,68 @@ +from __future__ import annotations +from contextvars import copy_context +import typing as _t +import traceback +import mimetypes import inspect import pkgutil -import mimetypes -import sys import time -from contextvars import copy_context -import traceback +import sys import re -try: - import quart - from quart import Quart, Response, jsonify, request, Blueprint -except ImportError: - quart = None - Quart = None - Response = None - jsonify = None - request = None - Blueprint = None +# Attempt top-level Quart imports; allow absence if user not using quart backend +from quart import ( + Quart, + Response, + jsonify, + request, + Blueprint, + g, +) + +if _t.TYPE_CHECKING: + from dash import Dash + from dash.exceptions import PreventUpdate, InvalidResourceError -from dash.backend import set_request_adapter from dash.fingerprint import check_fingerprint from dash import _validate from .base_server import BaseDashServer class QuartDashServer(BaseDashServer): - """Quart implementation of the Dash server factory. - - All Quart/async specific imports are at the top-level (per user request) so - Quart must be installed when this module is imported. - """ - def __init__(self) -> None: + def __init__(self, server: Quart) -> None: + self.server_type = "quart" + self.server: Quart = server self.config = {} self.error_handling_mode = "prune" super().__init__() - def __call__(self, server, *args, **kwargs): - return server(*args, **kwargs) + def __call__(self, *args: Any, **kwargs: Any): # type: ignore[name-defined] + return self.server(*args, **kwargs) - def create_app(self, name="__main__", config=None): - app = Quart(name) + @staticmethod + def create_app(name: str = "__main__", config: _t.Optional[_t.Dict[str, _t.Any]] = None): + if Quart is None: + raise RuntimeError( + "Quart is not installed. Install with 'pip install quart' to use the quart backend." + ) + app = Quart(name) # type: ignore if config: for key, value in config.items(): app.config[key] = value return app def register_assets_blueprint( - self, app, blueprint_name, assets_url_path, assets_folder + self, blueprint_name: str, assets_url_path: str, assets_folder: str # type: ignore[name-defined] ): + bp = Blueprint( blueprint_name, __name__, static_folder=assets_folder, static_url_path=assets_url_path, ) - app.register_blueprint(bp) + self.server.register_blueprint(bp) def _get_traceback(self, _secret, error: Exception): tb = error.__traceback__ @@ -166,27 +173,30 @@ def _get_traceback(self, _secret, error: Exception): """ return html - def register_prune_error_handler(self, app, secret, prune_errors): + def register_prune_error_handler(self, secret, prune_errors): if prune_errors: self.error_handling_mode = "prune" else: self.error_handling_mode = "raise" - @app.errorhandler(Exception) + @self.server.errorhandler(Exception) async def _wrap_errors(error): tb = self._get_traceback(secret, error) return Response(tb, status=500, content_type="text/html") - def register_timing_hooks(self, app, _first_run): # parity with Flask factory - @app.before_request + def register_timing_hooks(self, _first_run: bool): # type: ignore[name-defined] parity with Flask factory + @self.server.before_request async def _before_request(): # pragma: no cover - timing infra - quart.g.timing_information = { - "__dash_server": {"dur": time.time(), "desc": None} - } + if g is not None: + g.timing_information = { # type: ignore[attr-defined] + "__dash_server": {"dur": time.time(), "desc": None} + } - @app.after_request + @self.server.after_request async def _after_request(response): # pragma: no cover - timing infra - timing_information = getattr(quart.g, "timing_information", None) + timing_information = ( + getattr(g, "timing_information", None) if g is not None else None + ) if timing_information is None: return response dash_total = timing_information.get("__dash_server", None) @@ -205,16 +215,17 @@ async def _after_request(response): # pragma: no cover - timing infra response.headers["Server-Timing"] = value return response - def register_error_handlers(self, app): - @app.errorhandler(PreventUpdate) + def register_error_handlers(self): # type: ignore[name-defined] + @self.server.errorhandler(PreventUpdate) async def _prevent_update(_): return "", 204 - @app.errorhandler(InvalidResourceError) + @self.server.errorhandler(InvalidResourceError) async def _invalid_resource(err): return err.args[0], 404 - def _html_response_wrapper(self, view_func): + def _html_response_wrapper(self, view_func: _t.Callable[..., _t.Any] | str): + async def wrapped(*_args, **_kwargs): html_val = view_func() if callable(view_func) else view_func if inspect.iscoroutine(html_val): # handle async function returning html @@ -224,38 +235,40 @@ async def wrapped(*_args, **_kwargs): return wrapped - def add_url_rule(self, app, rule, view_func, endpoint=None, methods=None): - app.add_url_rule( + def add_url_rule( + self, + rule: str, + view_func: _t.Callable[..., _t.Any], + endpoint: str | None = None, + methods: list[str] | None = None, + ): + self.server.add_url_rule( rule, view_func=view_func, endpoint=endpoint, methods=methods or ["GET"] ) - def setup_index(self, dash_app): + def setup_index(self, dash_app: Dash): # type: ignore[name-defined] + async def index(*args, **kwargs): - adapter = QuartRequestAdapter() - set_request_adapter(adapter) - adapter.set_request() - return Response(dash_app.index(*args, **kwargs), content_type="text/html") + return Response(dash_app.index(*args, **kwargs), content_type="text/html") # type: ignore[arg-type] # pylint: disable=protected-access dash_app._add_url("", index, methods=["GET"]) - def setup_catchall(self, dash_app): + def setup_catchall(self, dash_app: Dash): + async def catchall( - path, *args, **kwargs + path: str, *args, **kwargs ): # noqa: ARG001 - path is unused but kept for route signature, pylint: disable=unused-argument - adapter = QuartRequestAdapter() - set_request_adapter(adapter) - adapter.set_request() - return Response(dash_app.index(*args, **kwargs), content_type="text/html") + return Response(dash_app.index(*args, **kwargs), content_type="text/html") # type: ignore[arg-type] # pylint: disable=protected-access dash_app._add_url("", catchall, methods=["GET"]) - def before_request(self, app, func): - app.before_request(func) + def before_request(self, func: _t.Callable[[], _t.Any]): + self.server.before_request(func) - def after_request(self, app, func): - @app.after_request + def after_request(self, func: _t.Callable[[], _t.Any]): + @self.server.after_request async def _after(response): if func is not None: result = func() @@ -263,21 +276,25 @@ async def _after(response): await result return response - def run(self, _dash_app, app, host, port, debug, **kwargs): + def run(self, dash_app: Dash, host: str, port: int, debug: bool, **kwargs: _t.Any): self.config = {"debug": debug, **kwargs} if debug else kwargs - app.run(host=host, port=port, debug=debug, **kwargs) + self.server.run(host=host, port=port, debug=debug, **kwargs) - def make_response(self, data, mimetype=None, content_type=None): + def make_response( + self, + data: str | bytes | bytearray, + mimetype: str | None = None, + content_type: str | None = None, + ): + if Response is None: + raise RuntimeError("Quart not installed; cannot generate Response") return Response(data, mimetype=mimetype, content_type=content_type) def jsonify(self, obj): return jsonify(obj) - def get_request_adapter(self): - return QuartRequestAdapter - def serve_component_suites( - self, dash_app, package_name, fingerprinted_path + self, dash_app: Dash, package_name: str, fingerprinted_path: str ): # noqa: ARG002 unused req preserved for interface parity path_in_pkg, has_fingerprint = check_fingerprint(fingerprinted_path) _validate.validate_js_path(dash_app.registered_paths, package_name, path_in_pkg) @@ -296,9 +313,11 @@ def serve_component_suites( if has_fingerprint: headers["Cache-Control"] = "public, max-age=31536000" + if Response is None: + raise RuntimeError("Quart not installed; cannot generate Response") return Response(data, content_type=mimetype, headers=headers) - def setup_component_suites(self, dash_app): + def setup_component_suites(self, dash_app: Dash): async def serve(package_name, fingerprinted_path): return self.serve_component_suites( dash_app, package_name, fingerprinted_path @@ -311,14 +330,13 @@ async def serve(package_name, fingerprinted_path): ) # pylint: disable=unused-argument - def dispatch(self, app, dash_app, use_async=True): # Quart always async + def dispatch(self, dash_app: Dash): # type: ignore[name-defined] Quart always async + async def _dispatch(): adapter = QuartRequestAdapter() - set_request_adapter(adapter) - adapter.set_request() - body = await request.get_json() + body = await adapter.get_json() # pylint: disable=protected-access - g = dash_app._initialize_context(body, adapter) + g = dash_app._initialize_context(body) # pylint: disable=protected-access func = dash_app._prepare_callback(g, body) # pylint: disable=protected-access @@ -329,11 +347,11 @@ async def _dispatch(): response_data = ctx.run(partial_func) if inspect.iscoroutine(response_data): # if user callback is async response_data = await response_data - return Response(response_data, content_type="application/json") + return Response(response_data, content_type="application/json") # type: ignore[arg-type] return _dispatch - def register_callback_api_routes(self, app, callback_api_paths): + def register_callback_api_routes(self, callback_api_paths: _t.Dict[str, _t.Callable[..., _t.Any]]): """ Register callback API endpoints on the Quart app. Each key in callback_api_paths is a route, each value is a handler (sync or async). @@ -348,25 +366,33 @@ def _make_view_func(handler): if inspect.iscoroutinefunction(handler): async def async_view_func(*args, **kwargs): + if request is None: + raise RuntimeError( + "Quart not installed; request unavailable" + ) data = await request.get_json() result = await handler(**data) if data else await handler() - return jsonify(result) + return jsonify(result) # type: ignore[arg-type] return async_view_func async def sync_view_func(*args, **kwargs): + if request is None: + raise RuntimeError("Quart not installed; request unavailable") data = await request.get_json() result = handler(**data) if data else handler() - return jsonify(result) + return jsonify(result) # type: ignore[arg-type] return sync_view_func view_func = _make_view_func(handler) - app.add_url_rule( + self.server.add_url_rule( route, endpoint=endpoint, view_func=view_func, methods=methods ) def _serve_default_favicon(self): + if Response is None: + raise RuntimeError("Quart not installed; cannot generate Response") return Response( pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" ) @@ -374,41 +400,53 @@ def _serve_default_favicon(self): class QuartRequestAdapter: def __init__(self) -> None: - self._request = None + self._request = request # type: ignore[assignment] + if self._request is None: + raise RuntimeError("Quart not installed; cannot access request context") - def set_request(self) -> None: - self._request = request + @property + def request(self) -> _t.Any: + return self._request - # Accessors (instance-based) - def get_root(self): - return self._request.root_url + @property + def root(self): + return self.request.root_url - def get_args(self): - return self._request.args - - async def get_json(self): - return await self._request.get_json() + @property + def args(self): + return self.request.args + @property def is_json(self): - return self._request.is_json + return self.request.is_json + + @property + def cookies(self): + return self.request.cookies - def get_cookies(self): - return self._request.cookies + @property + def headers(self): + return self.request.headers - def get_headers(self): - return self._request.headers + @property + def full_path(self): + return self.request.full_path - def get_full_path(self): - return self._request.full_path + @property + def url(self): + return str(self.request.url) - def get_url(self): - return str(self._request.url) + @property + def remote_addr(self): + return self.request.remote_addr - def get_remote_addr(self): - return self._request.remote_addr + @property + def origin(self): + return self.request.headers.get("origin") - def get_origin(self): - return self._request.headers.get("origin") + @property + def path(self): + return self.request.path - def get_path(self): - return self._request.path + async def get_json(self): + return await self.request.get_json() diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py new file mode 100644 index 0000000000..1c47548ad0 --- /dev/null +++ b/dash/backends/base_server.py @@ -0,0 +1,119 @@ +from abc import ABC, abstractmethod +from typing import Any + + +class BaseDashServer(ABC): + server_type: str + server: Any + config: dict[str, Any] + + def __call__(self, *args, **kwargs) -> Any: + # Default: WSGI + return self.server(*args, **kwargs) + + @staticmethod + @abstractmethod + def create_app( + name: str = "__main__", config=None + ) -> Any: # pragma: no cover - interface + pass + + @abstractmethod + def register_assets_blueprint( + self, blueprint_name: str, assets_url_path: str, assets_folder: str + ) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def register_error_handlers(self) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def add_url_rule( + self, rule: str, view_func, endpoint=None, methods=None + ) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def before_request(self, func) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def after_request(self, func) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def run( + self, dash_app, host: str, port: int, debug: bool, **kwargs + ) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def make_response( + self, data, mimetype=None, content_type=None + ) -> Any: # pragma: no cover - interface + pass + + @abstractmethod + def jsonify(self, obj) -> Any: # pragma: no cover - interface + pass + + +class RequestAdapter(ABC): + def __call__(self) -> Any: + return self + + # Properties to be implemented in concrete adapters + @property # pragma: no cover - interface + @abstractmethod + def root(self) -> str: + raise NotImplementedError() + + @property # pragma: no cover - interface + @abstractmethod + def args(self): + raise NotImplementedError() + + @abstractmethod # kept as method (may be sync or async) + def get_json(self): # pragma: no cover - interface + raise NotImplementedError() + + @property # pragma: no cover - interface + @abstractmethod + def is_json(self) -> bool: + raise NotImplementedError() + + @property # pragma: no cover - interface + @abstractmethod + def cookies(self): + raise NotImplementedError() + + @property # pragma: no cover - interface + @abstractmethod + def headers(self): + raise NotImplementedError() + + @property # pragma: no cover - interface + @abstractmethod + def full_path(self) -> str: + raise NotImplementedError() + + @property # pragma: no cover - interface + @abstractmethod + def url(self) -> str: + raise NotImplementedError() + + @property # pragma: no cover - interface + @abstractmethod + def remote_addr(self): + raise NotImplementedError() + + @property # pragma: no cover - interface + @abstractmethod + def origin(self): + raise NotImplementedError() + + @property # pragma: no cover - interface + @abstractmethod + def path(self) -> str: + raise NotImplementedError() diff --git a/dash/dash.py b/dash/dash.py index 6bba3aadfd..1ed05657dc 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -25,7 +25,6 @@ from dash import dcc from dash import html from dash import dash_table - from .fingerprint import build_fingerprint from .resources import Scripts, Css from .dependencies import ( @@ -38,7 +37,7 @@ ProxyError, DuplicateCallback, ) -from .backend import get_request_adapter, get_backend +from .backends import get_backend from .version import __version__ from ._configs import get_combined_config, pathname_configs, pages_folder_config from ._utils import ( @@ -63,6 +62,7 @@ from . import _validate from . import _watch from . import _get_app +from . import backends from ._get_app import with_app_context, with_app_context_factory from ._grouping import map_grouping, grouping_len, update_args_group @@ -154,36 +154,6 @@ page_container = None -def _is_flask_instance(obj): - try: - # pylint: disable=import-outside-toplevel - from flask import Flask - - return isinstance(obj, Flask) - except ImportError: - return False - - -def _is_fastapi_instance(obj): - try: - # pylint: disable=import-outside-toplevel - from fastapi import FastAPI - - return isinstance(obj, FastAPI) - except ImportError: - return False - - -def _is_quart_instance(obj): - try: - # pylint: disable=import-outside-toplevel - from quart import Quart - - return isinstance(obj, Quart) - except ImportError: - return False - - # Singleton signal to not update an output, alternative to PreventUpdate no_update = _callback.NoUpdate() # pylint: disable=protected-access @@ -446,74 +416,41 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches **obsolete, ): - if use_async is None: - try: - import asgiref # pylint: disable=unused-import, import-outside-toplevel # noqa - - use_async = True - except ImportError: - pass - elif use_async: - try: - import asgiref # pylint: disable=unused-import, import-outside-toplevel # noqa - except ImportError as exc: - raise Exception( - "You are trying to use dash[async] without having installed the requirements please install via: `pip install dash[async]`" - ) from exc - + _validate.check_async(use_async) _validate.check_obsolete(obsolete) caller_name: str = name if name is not None else get_caller_name() # Determine backend if backend is None: - backend_cls = get_backend("flask") + backend_cls, request_cls = get_backend("flask") elif isinstance(backend, str): - backend_cls = get_backend(backend) + backend_cls, request_cls = get_backend(backend) elif isinstance(backend, type): backend_cls = backend + _, request_cls = get_backend(backend.server_type) else: raise ValueError("Invalid backend argument") # Determine server and backend instance if server not in (None, True, False): # User provided a server instance (e.g., Flask, Quart, FastAPI) - if _is_flask_instance(server): - inferred_backend = "flask" - elif _is_quart_instance(server): - inferred_backend = "quart" - elif _is_fastapi_instance(server): - inferred_backend = "fastapi" - else: - raise ValueError("Unsupported server type") - # Validate that backend matches server type if both are provided - if backend is not None: - if isinstance(backend, type): - # get_backend returns the backend class for a string - # So we compare the class names - expected_backend_cls = get_backend(inferred_backend) - if ( - backend.__module__ != expected_backend_cls.__module__ - or backend.__name__ != expected_backend_cls.__name__ - ): - raise ValueError( - f"Conflict between provided backend '{backend.__name__}' and server type '{inferred_backend}'." - ) - elif not isinstance(backend, str): - raise ValueError("Invalid backend argument") - elif backend.lower() != inferred_backend: - raise ValueError( - f"Conflict between provided backend '{backend}' and server type '{inferred_backend}'." - ) - backend_cls = get_backend(inferred_backend) + inferred_backend = backends.get_server_type(server) + _validate.check_backend(backend, inferred_backend) + backend_cls, request_cls = get_backend(inferred_backend) if name is None: caller_name = getattr(server, "name", caller_name) - self.backend = backend_cls() + + self.backend = backend_cls(server) self.server = server + backends.backend = self.backend # type: ignore + backends.request_adapter = request_cls else: # No server instance provided, create backend and let backend create server - self.backend = backend_cls() - self.server = self.backend.create_app(caller_name) # type: ignore + self.server = backend_cls.create_app(caller_name) # type: ignore + self.backend = backend_cls(self.server) + backends.backend = self.backend + backends.request_adapter = request_cls base_prefix, routes_prefix, requests_prefix = pathname_configs( url_base_pathname, routes_pathname_prefix, requests_pathname_prefix @@ -710,7 +647,6 @@ def init_app(self, app: Optional[Any] = None, **kwargs) -> None: bp_prefix = config.routes_pathname_prefix.replace("/", "_").replace(".", "_") assets_blueprint_name = f"{bp_prefix}dash_assets" self.backend.register_assets_blueprint( - self.server, assets_blueprint_name, config.routes_pathname_prefix + self.config.assets_url_path.lstrip("/"), self.config.assets_folder, @@ -732,8 +668,9 @@ def init_app(self, app: Optional[Any] = None, **kwargs) -> None: raise ImportError( "To use the compress option, you need to install dash[compress]" ) from error - self.backend.register_error_handlers(self.server) - self.backend.before_request(self.server, self._setup_server) + + self.backend.register_error_handlers() + self.backend.before_request(self._setup_server) self._setup_routes() _get_app.APP = self self.enable_pages() @@ -742,7 +679,6 @@ def init_app(self, app: Optional[Any] = None, **kwargs) -> None: def _add_url(self, name: str, view_func: RouteCallable, methods=("GET",)) -> None: full_name = self.config.routes_pathname_prefix + name self.backend.add_url_rule( - self.server, full_name, view_func=view_func, endpoint=full_name, @@ -756,7 +692,7 @@ def _setup_routes(self): self._add_url("_dash-dependencies", self.dependencies) self._add_url( "_dash-update-component", - self.backend.dispatch(self.server, self, self._use_async), + self.backend.dispatch(self), ["POST"], ) self._add_url("_reload-hash", self.serve_reload_hash) @@ -803,7 +739,7 @@ def setup_apis(self): self.callback_api_paths[k] = _callback.GLOBAL_API_PATHS.pop(k) # Delegate to the server factory for route registration - self.backend.register_callback_api_routes(self.server, self.callback_api_paths) + self.backend.register_callback_api_routes(self.callback_api_paths) def _setup_plotlyjs(self): # pylint: disable=import-outside-toplevel @@ -1043,9 +979,11 @@ def _generate_css_dist_html(self): return "\n".join( [ - format_tag("link", link, opened=True) - if isinstance(link, dict) - else f'' + ( + format_tag("link", link, opened=True) + if isinstance(link, dict) + else f'' + ) for link in (external_links + links) ] ) @@ -1099,9 +1037,11 @@ def _generate_scripts_html(self) -> str: return "\n".join( [ - format_tag("script", src) - if isinstance(src, dict) - else f'' + ( + format_tag("script", src) + if isinstance(src, dict) + else f'' + ) for src in srcs ] + [f"" for src in self._inline_scripts] @@ -1139,11 +1079,8 @@ def index(self, *_args, **_kwargs): metas = self._generate_meta() renderer = self._generate_renderer() title = self.title - try: - request = get_request_adapter() - except LookupError: - # no request context - request = None + # Refactored: direct access to global request adapter + request = backends.request_adapter() if self.use_pages and self.config.include_pages_meta and request: metas = _page_meta_tags(self, request) + metas @@ -1357,8 +1294,9 @@ def _inputs_to_vals(self, inputs): return inputs_to_vals(inputs) # pylint: disable=R0915 - def _initialize_context(self, body, adapter): + def _initialize_context(self, body): """Initialize the global context for the request.""" + adapter = backends.request_adapter() g = AttributeDict({}) g.inputs_list = body.get("inputs", []) g.states_list = body.get("state", []) @@ -1372,12 +1310,12 @@ def _initialize_context(self, body, adapter): g.dash_response = self.backend.make_response( mimetype="application/json", data=None ) - g.cookies = dict(adapter.get_cookies()) - g.headers = dict(adapter.get_headers()) - g.args = adapter.get_args() - g.path = adapter.get_full_path() - g.remote = adapter.get_remote_addr() - g.origin = adapter.get_origin() + g.cookies = dict(adapter.cookies) + g.headers = dict(adapter.headers) + g.args = adapter.args + g.path = adapter.full_path + g.remote = adapter.remote_addr + g.origin = adapter.origin g.updated_props = {} return g @@ -1964,15 +1902,21 @@ def enable_dev_tools( packages[index] = dash_spec component_packages_dist = [ - dash_test_path # type: ignore[reportPossiblyUnboundVariable] - if isinstance(package, ModuleSpec) - else os.path.dirname(package.path) # type: ignore[reportAttributeAccessIssue] - if hasattr(package, "path") - else os.path.dirname( - package._path[0] # type: ignore[reportAttributeAccessIssue]; pylint: disable=protected-access - ) - if hasattr(package, "_path") - else package.filename # type: ignore[reportAttributeAccessIssue] + ( + dash_test_path # type: ignore[reportPossiblyUnboundVariable] + if isinstance(package, ModuleSpec) + else ( + os.path.dirname(package.path) # type: ignore[reportAttributeAccessIssue] + if hasattr(package, "path") + else ( + os.path.dirname( + package._path[0] # type: ignore[reportAttributeAccessIssue]; pylint: disable=protected-access + ) + if hasattr(package, "_path") + else package.filename + ) + ) + ) # type: ignore[reportAttributeAccessIssue] for package in packages ] @@ -2000,13 +1944,14 @@ def enable_dev_tools( jupyter_dash.configure_callback_exception_handling( self, dev_tools.prune_errors ) - secret = gen_salt(20) - self.backend.register_prune_error_handler( - self.server, secret, dev_tools.prune_errors - ) + elif dev_tools.prune_errors: + secret = gen_salt(20) + self.backend.register_prune_error_handler( + secret, dev_tools.prune_errors + ) if debug and dev_tools.ui: - self.backend.register_timing_hooks(self.server, first_run) + self.backend.register_timing_hooks(first_run) if ( debug @@ -2290,13 +2235,8 @@ def verify_url_part(served_part, url_part, part_name): server_url=jupyter_server_url, ) else: - self.backend.run( - self, - self.server, - host=host, - port=port, - debug=debug, - **flask_run_options, + backends.backend.run( + dash_app=self, host=host, port=port, debug=debug, **flask_run_options ) def enable_pages(self) -> None: @@ -2368,9 +2308,11 @@ async def update(pathname_, search_, **states): if not self.config.suppress_callback_exceptions: self.validation_layout = html.Div( [ - asyncio.run(execute_async_function(page["layout"])) - if callable(page["layout"]) - else page["layout"] + ( + asyncio.run(execute_async_function(page["layout"])) + if callable(page["layout"]) + else page["layout"] + ) for page in _pages.PAGE_REGISTRY.values() ] + [ @@ -2439,9 +2381,11 @@ def update(pathname_, search_, **states): ] self.validation_layout = html.Div( [ - page["layout"]() - if callable(page["layout"]) - else page["layout"] + ( + page["layout"]() + if callable(page["layout"]) + else page["layout"] + ) for page in _pages.PAGE_REGISTRY.values() ] + layout @@ -2460,7 +2404,7 @@ def update(pathname_, search_, **states): Input(_ID_STORE, "data"), ) - self.backend.before_request(self.server, router) + self.backend.before_request(router) def __call__(self, *args, **kwargs): - return self.backend.__call__(self.server, *args, **kwargs) + return self.backend.__call__(*args, **kwargs) diff --git a/dash_config.json b/dash_config.json new file mode 100644 index 0000000000..3afa0d11f1 --- /dev/null +++ b/dash_config.json @@ -0,0 +1 @@ +{"debug": true, "dev_tools_ui": true, "dev_tools_props_check": true, "dev_tools_serve_dev_bundles": true, "dev_tools_hot_reload": true, "dev_tools_silence_routes_logging": true, "dev_tools_prune_errors": true, "dev_tools_hot_reload_interval": 3.0, "dev_tools_hot_reload_watch_interval": 0.5, "dev_tools_hot_reload_max_retry": 8, "dev_tools_disable_version_check": false} \ No newline at end of file diff --git a/quart_app.py b/quart_app.py new file mode 100644 index 0000000000..54d40add56 --- /dev/null +++ b/quart_app.py @@ -0,0 +1,23 @@ +from dash import Dash, html, Input, Output +from dash import dcc +from dash import backends + +app = Dash(__name__, backend="quart") + +app.layout = html.Div( + [ + html.H2("Quart Server Factory Example"), + html.Div("Type below to see async callback update."), + dcc.Input(id="text", value="hello", autoComplete="off"), + html.Div(id="echo"), + ] +) + + +@app.callback(Output("echo", "children"), Input("text", "value")) +def update_echo(val): + return f"You typed: {val}" if val else "Type something" + + +if __name__ == "__main__": + app.run(debug=True) From c4795ed3b544964c259fe21cb81746911fb7e6aa Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Wed, 17 Sep 2025 10:58:06 -0400 Subject: [PATCH 062/297] fixes for failing tests --- .gitignore | 1 + dash/backends/_fastapi.py | 5 +++-- dash/dash.py | 9 ++++----- dash_config.json | 2 +- tests/backend_tests/test_preconfig_backends.py | 12 ++++++------ 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 89029448fe..06e855e2dc 100644 --- a/.gitignore +++ b/.gitignore @@ -93,3 +93,4 @@ packages/ !components/dash-core-components/tests/integration/upload/upload-assets/upft001.csv !components/dash-table/tests/assets/*.csv !components/dash-table/tests/selenium/assets/*.csv +dash_config.json diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index f3f9f2df33..57cf18b6ec 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -52,6 +52,7 @@ def get_current_request() -> Request: class CurrentRequestMiddleware: def __init__(self, app: ASGIApp) -> None: # type: ignore[name-defined] self.app = app + print('loaded CurrentRequestMiddleware') async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: # type: ignore[name-defined] # non-http/ws scopes pass through (lifespan etc.) @@ -100,7 +101,6 @@ def __call__(self, *args: Any, **kwargs: Any): @staticmethod def create_app(name: str = "__main__", config: Dict[str, Any] | None = None): app = FastAPI() - app.add_middleware(CurrentRequestMiddleware) if config: for key, value in config.items(): @@ -257,7 +257,7 @@ def setup_catchall(self, dash_app: Dash): @self.server.on_event("startup") def _setup_catchall(): dash_app.enable_dev_tools( - **self.config, first_run=False + **load_config(), first_run=False ) # do this to make sure dev tools are enabled async def catchall(request: Request): @@ -289,6 +289,7 @@ def add_url_rule( def before_request(self, func: Callable[[], Any] | None): # FastAPI does not have before_request, but we can use middleware + self.server.add_middleware(CurrentRequestMiddleware) self.server.middleware("http")(self._make_before_middleware(func)) def after_request(self, func: Callable[[], Any] | None): diff --git a/dash/dash.py b/dash/dash.py index 1ed05657dc..3ab830e8a3 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -1944,11 +1944,10 @@ def enable_dev_tools( jupyter_dash.configure_callback_exception_handling( self, dev_tools.prune_errors ) - elif dev_tools.prune_errors: - secret = gen_salt(20) - self.backend.register_prune_error_handler( - secret, dev_tools.prune_errors - ) + secret = gen_salt(20) + self.backend.register_prune_error_handler( + secret, dev_tools.prune_errors + ) if debug and dev_tools.ui: self.backend.register_timing_hooks(first_run) diff --git a/dash_config.json b/dash_config.json index 3afa0d11f1..e4af4373cb 100644 --- a/dash_config.json +++ b/dash_config.json @@ -1 +1 @@ -{"debug": true, "dev_tools_ui": true, "dev_tools_props_check": true, "dev_tools_serve_dev_bundles": true, "dev_tools_hot_reload": true, "dev_tools_silence_routes_logging": true, "dev_tools_prune_errors": true, "dev_tools_hot_reload_interval": 3.0, "dev_tools_hot_reload_watch_interval": 0.5, "dev_tools_hot_reload_max_retry": 8, "dev_tools_disable_version_check": false} \ No newline at end of file +{"dev_tools_ui": false, "dev_tools_props_check": false, "dev_tools_serve_dev_bundles": false, "dev_tools_hot_reload": false, "dev_tools_silence_routes_logging": false, "dev_tools_prune_errors": false, "dev_tools_hot_reload_interval": 3.0, "dev_tools_hot_reload_watch_interval": 0.5, "dev_tools_hot_reload_max_retry": 8, "dev_tools_disable_version_check": true} \ No newline at end of file diff --git a/tests/backend_tests/test_preconfig_backends.py b/tests/backend_tests/test_preconfig_backends.py index 5fbd28dfd9..4c4ccc7083 100644 --- a/tests/backend_tests/test_preconfig_backends.py +++ b/tests/backend_tests/test_preconfig_backends.py @@ -30,7 +30,7 @@ def update_output(value): dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#output", f"You typed: {input_value}") - dash_duo.find_element("#input").clear() + dash_duo.clear_input(dash_duo.find_element("#input")) dash_duo.find_element("#input").send_keys(f"{backend.title()} Test") dash_duo.wait_for_text_to_equal("#output", f"You typed: {backend.title()} Test") assert dash_duo.get_logs() == [] @@ -93,7 +93,7 @@ def get_error_html(dash_duo, index): "dev_tools_prune_errors": False, "reload": False, }, - "fastapi.py", + "_fastapi.py", ), ( "quart", @@ -104,7 +104,7 @@ def get_error_html(dash_duo, index): "dev_tools_hot_reload": False, "dev_tools_prune_errors": False, }, - "quart.py", + "_quart.py", ), ], ) @@ -131,7 +131,7 @@ def error_callback(n): error0 = get_error_html(dash_duo, 0) assert "in error_callback" in error0 assert "ZeroDivisionError" in error0 - assert "backend" in error0 and error_msg in error0 + assert "backends/" in error0 and error_msg in error0 @pytest.mark.parametrize( @@ -173,7 +173,7 @@ def error_callback(n): error0 = get_error_html(dash_duo, 0) assert "in error_callback" in error0 assert "ZeroDivisionError" in error0 - assert "dash/backend" not in error0 and error_msg not in error0 + assert "dash/backends/" not in error0 and error_msg not in error0 @pytest.mark.parametrize( @@ -209,7 +209,7 @@ def update_output_bg(value): dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#output", f"Background typed: {input_value}") - dash_duo.find_element("#input").clear() + dash_duo.clear_input(dash_duo.find_element("#input")) dash_duo.find_element("#input").send_keys(f"{backend.title()} BG Test") dash_duo.wait_for_text_to_equal( "#output", f"Background typed: {backend.title()} BG Test" From 567d0f8d592e4281047794100c80a3728aa6b128 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Wed, 17 Sep 2025 11:05:33 -0400 Subject: [PATCH 063/297] fixing formatting --- dash/backends/_fastapi.py | 9 ++++----- dash/backends/_flask.py | 13 +++++++++---- dash/backends/_quart.py | 13 ++++++------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 57cf18b6ec..540238f727 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -52,7 +52,7 @@ def get_current_request() -> Request: class CurrentRequestMiddleware: def __init__(self, app: ASGIApp) -> None: # type: ignore[name-defined] self.app = app - print('loaded CurrentRequestMiddleware') + print("loaded CurrentRequestMiddleware") async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: # type: ignore[name-defined] # non-http/ws scopes pass through (lifespan etc.) @@ -84,7 +84,6 @@ def load_config(): class FastAPIDashServer(BaseDashServer): - def __init__(self, server: FastAPI): self.config = {} self.server_type = "fastapi" @@ -415,7 +414,6 @@ async def serve(request: Request, package_name: str, fingerprinted_path: str): # pylint: disable=unused-argument def dispatch(self, dash_app: Dash): - async def _dispatch(request: Request): # pylint: disable=protected-access body = await request.json() @@ -470,7 +468,9 @@ async def timing_middleware(request: Request, call_next): headers.append("Server-Timing", value) return response - def register_callback_api_routes(self, callback_api_paths: Dict[str, Callable[..., Any]]): + def register_callback_api_routes( + self, callback_api_paths: Dict[str, Callable[..., Any]] + ): """ Register callback API endpoints on the FastAPI app. Each key in callback_api_paths is a route, each value is a handler (sync or async). @@ -504,7 +504,6 @@ async def view_func(request: Request, body: dict = Body(...)): class FastAPIRequestAdapter(RequestAdapter): - def __init__(self): self._request: Request = get_current_request() super().__init__() diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index 5a1385d574..138234a4bc 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -29,7 +29,6 @@ class FlaskDashServer(BaseDashServer): - def __init__(self, server: Flask) -> None: self.server: Flask = server self.server_type = "flask" @@ -209,7 +208,9 @@ def _dispatch(): func = dash_app._prepare_callback(cb_ctx, body) args = dash_app._inputs_to_vals(cb_ctx.inputs_list + cb_ctx.states_list) ctx = copy_context() - partial_func = dash_app._execute_callback(func, args, cb_ctx.outputs_list, cb_ctx) + partial_func = dash_app._execute_callback( + func, args, cb_ctx.outputs_list, cb_ctx + ) response_data = ctx.run(partial_func) if asyncio.iscoroutine(response_data): raise Exception( @@ -227,7 +228,9 @@ async def _dispatch_async(): func = dash_app._prepare_callback(cb_ctx, body) args = dash_app._inputs_to_vals(cb_ctx.inputs_list + cb_ctx.states_list) ctx = copy_context() - partial_func = dash_app._execute_callback(func, args, cb_ctx.outputs_list, cb_ctx) + partial_func = dash_app._execute_callback( + func, args, cb_ctx.outputs_list, cb_ctx + ) response_data = ctx.run(partial_func) if asyncio.iscoroutine(response_data): response_data = await response_data @@ -269,7 +272,9 @@ def _after_request(response: Response): # type: ignore[name-defined] self.before_request(_before_request) self.after_request(_after_request) - def register_callback_api_routes(self, callback_api_paths: Dict[str, Callable[..., Any]]): + def register_callback_api_routes( + self, callback_api_paths: Dict[str, Callable[..., Any]] + ): """ Register callback API endpoints on the Flask app. Each key in callback_api_paths is a route, each value is a handler (sync or async). diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index a462d07af6..ff544c2c91 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -29,7 +29,6 @@ class QuartDashServer(BaseDashServer): - def __init__(self, server: Quart) -> None: self.server_type = "quart" self.server: Quart = server @@ -41,7 +40,9 @@ def __call__(self, *args: Any, **kwargs: Any): # type: ignore[name-defined] return self.server(*args, **kwargs) @staticmethod - def create_app(name: str = "__main__", config: _t.Optional[_t.Dict[str, _t.Any]] = None): + def create_app( + name: str = "__main__", config: _t.Optional[_t.Dict[str, _t.Any]] = None + ): if Quart is None: raise RuntimeError( "Quart is not installed. Install with 'pip install quart' to use the quart backend." @@ -225,7 +226,6 @@ async def _invalid_resource(err): return err.args[0], 404 def _html_response_wrapper(self, view_func: _t.Callable[..., _t.Any] | str): - async def wrapped(*_args, **_kwargs): html_val = view_func() if callable(view_func) else view_func if inspect.iscoroutine(html_val): # handle async function returning html @@ -247,7 +247,6 @@ def add_url_rule( ) def setup_index(self, dash_app: Dash): # type: ignore[name-defined] - async def index(*args, **kwargs): return Response(dash_app.index(*args, **kwargs), content_type="text/html") # type: ignore[arg-type] @@ -255,7 +254,6 @@ async def index(*args, **kwargs): dash_app._add_url("", index, methods=["GET"]) def setup_catchall(self, dash_app: Dash): - async def catchall( path: str, *args, **kwargs ): # noqa: ARG001 - path is unused but kept for route signature, pylint: disable=unused-argument @@ -331,7 +329,6 @@ async def serve(package_name, fingerprinted_path): # pylint: disable=unused-argument def dispatch(self, dash_app: Dash): # type: ignore[name-defined] Quart always async - async def _dispatch(): adapter = QuartRequestAdapter() body = await adapter.get_json() @@ -351,7 +348,9 @@ async def _dispatch(): return _dispatch - def register_callback_api_routes(self, callback_api_paths: _t.Dict[str, _t.Callable[..., _t.Any]]): + def register_callback_api_routes( + self, callback_api_paths: _t.Dict[str, _t.Callable[..., _t.Any]] + ): """ Register callback API endpoints on the Quart app. Each key in callback_api_paths is a route, each value is a handler (sync or async). From a855c6db89e167ca01d87e79fc394e4bfd58c280 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Wed, 17 Sep 2025 11:26:05 -0400 Subject: [PATCH 064/297] fixing issues --- dash/backends/__init__.py | 6 +----- dash/backends/_fastapi.py | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/dash/backends/__init__.py b/dash/backends/__init__.py index 940c8f18bd..e4d4141bb8 100644 --- a/dash/backends/__init__.py +++ b/dash/backends/__init__.py @@ -15,12 +15,8 @@ } -request_adapter: RequestAdapter -backend: BaseDashServer - - def get_backend( - name: Literal["flask", "fastapi", "quart"] | str + name: str ) -> tuple[BaseDashServer, RequestAdapter]: module_name, server_class, request_class = _backend_imports[name.lower()] try: diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 540238f727..be2308d5f5 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -52,7 +52,6 @@ def get_current_request() -> Request: class CurrentRequestMiddleware: def __init__(self, app: ASGIApp) -> None: # type: ignore[name-defined] self.app = app - print("loaded CurrentRequestMiddleware") async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: # type: ignore[name-defined] # non-http/ws scopes pass through (lifespan etc.) From 79afb0bab2d7d058cc8770b6de65eb7dcab656dd Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Wed, 17 Sep 2025 11:54:41 -0400 Subject: [PATCH 065/297] fixing async validation --- .github/workflows/testing.yml | 4 ++-- dash/_validate.py | 1 + dash/backends/__init__.py | 5 +---- dash/backends/_quart.py | 1 + dash/dash.py | 6 ++---- 5 files changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index be5caf4929..c47e188222 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -39,8 +39,8 @@ jobs: - 'tests/async_tests/**' - 'requirements/**' backend_paths: - - 'dash/backend/**' - - 'tests/backend/**' + - 'dash/backends/**' + - 'tests/backend_tests/**' build: name: Build Dash Package diff --git a/dash/_validate.py b/dash/_validate.py index 76661cef6b..d595cba0fc 100644 --- a/dash/_validate.py +++ b/dash/_validate.py @@ -603,6 +603,7 @@ def check_async(use_async): raise Exception( "You are trying to use dash[async] without having installed the requirements please install via: `pip install dash[async]`" ) from exc + return use_async or False def check_backend(backend, inferred_backend): diff --git a/dash/backends/__init__.py b/dash/backends/__init__.py index e4d4141bb8..b845abb1ad 100644 --- a/dash/backends/__init__.py +++ b/dash/backends/__init__.py @@ -1,6 +1,5 @@ from .base_server import BaseDashServer, RequestAdapter -from typing import Literal, Any import importlib @@ -15,9 +14,7 @@ } -def get_backend( - name: str -) -> tuple[BaseDashServer, RequestAdapter]: +def get_backend(name: str) -> tuple[BaseDashServer, RequestAdapter]: module_name, server_class, request_class = _backend_imports[name.lower()] try: module = importlib.import_module(module_name) diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index ff544c2c91..c5759026d4 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -26,6 +26,7 @@ from dash.fingerprint import check_fingerprint from dash import _validate from .base_server import BaseDashServer +from typing import Any class QuartDashServer(BaseDashServer): diff --git a/dash/dash.py b/dash/dash.py index 3ab830e8a3..52dd219627 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -416,7 +416,7 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches **obsolete, ): - _validate.check_async(use_async) + use_async = _validate.check_async(use_async) _validate.check_obsolete(obsolete) caller_name: str = name if name is not None else get_caller_name() @@ -1945,9 +1945,7 @@ def enable_dev_tools( self, dev_tools.prune_errors ) secret = gen_salt(20) - self.backend.register_prune_error_handler( - secret, dev_tools.prune_errors - ) + self.backend.register_prune_error_handler(secret, dev_tools.prune_errors) if debug and dev_tools.ui: self.backend.register_timing_hooks(first_run) From 77e22a3ca21ddc4f5d1a0f50964204f7dc92fb46 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Wed, 17 Sep 2025 12:29:37 -0400 Subject: [PATCH 066/297] adjustments for request_adapter --- dash/backends/__init__.py | 2 +- dash/backends/_fastapi.py | 1 + dash/backends/_flask.py | 1 + dash/backends/_quart.py | 1 + dash/backends/base_server.py | 1 + dash/dash.py | 11 +++++------ 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/dash/backends/__init__.py b/dash/backends/__init__.py index b845abb1ad..c8ac9321d0 100644 --- a/dash/backends/__init__.py +++ b/dash/backends/__init__.py @@ -19,7 +19,7 @@ def get_backend(name: str) -> tuple[BaseDashServer, RequestAdapter]: try: module = importlib.import_module(module_name) server = getattr(module, server_class) - request_adapter = getattr(module, request_class) + request_adapter = server.request_adapter # type: ignore return server, request_adapter except KeyError as e: raise ValueError(f"Unknown backend: {name}") from e diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index be2308d5f5..3f50f96f57 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -88,6 +88,7 @@ def __init__(self, server: FastAPI): self.server_type = "fastapi" self.server: FastAPI = server self.error_handling_mode = "prune" + self.request_adapter = FastAPIRequestAdapter super().__init__() def __call__(self, *args: Any, **kwargs: Any): diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index 138234a4bc..b4bab46ff2 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -32,6 +32,7 @@ class FlaskDashServer(BaseDashServer): def __init__(self, server: Flask) -> None: self.server: Flask = server self.server_type = "flask" + self.request_adapter = FlaskRequestAdapter super().__init__() def __call__(self, *args: Any, **kwargs: Any): diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index c5759026d4..8e509a08e0 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -35,6 +35,7 @@ def __init__(self, server: Quart) -> None: self.server: Quart = server self.config = {} self.error_handling_mode = "prune" + self.request_adapter = QuartRequestAdapter super().__init__() def __call__(self, *args: Any, **kwargs: Any): # type: ignore[name-defined] diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index 1c47548ad0..cf2b62c2e7 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -6,6 +6,7 @@ class BaseDashServer(ABC): server_type: str server: Any config: dict[str, Any] + request_adapter: Any def __call__(self, *args, **kwargs) -> Any: # Default: WSGI diff --git a/dash/dash.py b/dash/dash.py index 52dd219627..2d71766b4e 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -423,12 +423,11 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches # Determine backend if backend is None: - backend_cls, request_cls = get_backend("flask") + backend_cls = get_backend("flask") elif isinstance(backend, str): - backend_cls, request_cls = get_backend(backend) + backend_cls = get_backend(backend) elif isinstance(backend, type): backend_cls = backend - _, request_cls = get_backend(backend.server_type) else: raise ValueError("Invalid backend argument") @@ -437,20 +436,20 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches # User provided a server instance (e.g., Flask, Quart, FastAPI) inferred_backend = backends.get_server_type(server) _validate.check_backend(backend, inferred_backend) - backend_cls, request_cls = get_backend(inferred_backend) + backend_cls = get_backend(inferred_backend) if name is None: caller_name = getattr(server, "name", caller_name) self.backend = backend_cls(server) self.server = server backends.backend = self.backend # type: ignore - backends.request_adapter = request_cls + backends.request_adapter = self.backend.request_adapter # type: ignore else: # No server instance provided, create backend and let backend create server self.server = backend_cls.create_app(caller_name) # type: ignore self.backend = backend_cls(self.server) backends.backend = self.backend - backends.request_adapter = request_cls + backends.request_adapter = self.backend.request_adapter # type: ignore base_prefix, routes_prefix, requests_prefix = pathname_configs( url_base_pathname, routes_pathname_prefix, requests_pathname_prefix From f7331d3f7e97dc52ebc1289d71e95111d49b3bb8 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Wed, 17 Sep 2025 12:31:35 -0400 Subject: [PATCH 067/297] adding test for custom dash server --- tests/backend_tests/test_custom_backend.py | 243 +++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 tests/backend_tests/test_custom_backend.py diff --git a/tests/backend_tests/test_custom_backend.py b/tests/backend_tests/test_custom_backend.py new file mode 100644 index 0000000000..aa590599b5 --- /dev/null +++ b/tests/backend_tests/test_custom_backend.py @@ -0,0 +1,243 @@ +import pytest +from dash import Dash, Input, Output, html, dcc +from fastapi import FastAPI +import traceback +import re +from dash.backends._fastapi import FastAPIDashServer + + +class CustomDashServer(FastAPIDashServer): + def _get_traceback(self, _secret, error: Exception): + tb = error.__traceback__ + errors = traceback.format_exception(type(error), error, tb) + pass_errs = [] + callback_handled = False + for err in errors: + if self.error_handling_mode == "prune": + if not callback_handled: + if "callback invoked" in str(err) and "_callback.py" in str(err): + callback_handled = True + continue + pass_errs.append(err) + formatted_tb = "".join(pass_errs) + error_type = type(error).__name__ + error_msg = str(error) + # Parse traceback lines to group by file + file_cards = [] + pattern = re.compile(r' File "(.+)", line (\d+), in (\w+)') + lines = formatted_tb.split("\n") + current_file = None + card_lines = [] + for line in lines[:-1]: # Skip the last line (error message) + match = pattern.match(line) + if match: + if current_file and card_lines: + file_cards.append((current_file, card_lines)) + current_file = ( + f"{match.group(1)} (line {match.group(2)}, in {match.group(3)})" + ) + card_lines = [line] + elif current_file: + card_lines.append(line) + if current_file and card_lines: + file_cards.append((current_file, card_lines)) + cards_html = "" + for filename, card in file_cards: + cards_html += ( + f""" +
+
{filename}
+
"""
+                + "\n".join(card)
+                + """
+
+ """ + ) + html = f""" + + + + {error_type}: {error_msg} // Custom Debugger + + + +
+

{error_type}: {error_msg}

+ {cards_html} +
+ + + """ + return html + + +@pytest.mark.parametrize( + "fixture,input_value", + [ + ("dash_duo", "Hello CustomBackend!"), + ], +) +def test_custom_backend_basic_callback(request, fixture, input_value): + dash_duo = request.getfixturevalue(fixture) + app = Dash(__name__, backend=CustomDashServer) + app.layout = html.Div( + [dcc.Input(id="input", value=input_value, type="text"), html.Div(id="output")] + ) + + @app.callback(Output("output", "children"), Input("input", "value")) + def update_output(value): + return f"You typed: {value}" + + dash_duo.start_server(app) + dash_duo.wait_for_text_to_equal("#output", f"You typed: {input_value}") + dash_duo.clear_input(dash_duo.find_element("#input")) + dash_duo.find_element("#input").send_keys("CustomBackend Test") + dash_duo.wait_for_text_to_equal("#output", "You typed: CustomBackend Test") + assert dash_duo.get_logs() == [] + + +@pytest.mark.parametrize( + "fixture,start_server_kwargs", + [ + ("dash_duo", {"debug": True, "reload": False, "dev_tools_ui": True}), + ], +) +def test_custom_backend_error_handling(request, fixture, start_server_kwargs): + dash_duo = request.getfixturevalue(fixture) + app = Dash(__name__, backend=CustomDashServer) + app.layout = html.Div( + [html.Button(id="btn", children="Error", n_clicks=0), html.Div(id="output")] + ) + + @app.callback(Output("output", "children"), Input("btn", "n_clicks")) + def error_callback(n): + if n and n > 0: + return 1 / 0 # Intentional error + return "No error" + + dash_duo.start_server(app, **start_server_kwargs) + dash_duo.wait_for_text_to_equal("#output", "No error") + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal(dash_duo.devtools_error_count_locator, "1") + + +def get_error_html(dash_duo, index): + # error is in an iframe so is annoying to read out - get it from the store + return dash_duo.driver.execute_script( + "return store.getState().error.backEnd[{}].error.html;".format(index) + ) + + +@pytest.mark.parametrize( + "fixture,start_server_kwargs", + [ + ( + "dash_duo", + { + "debug": True, + "dev_tools_ui": True, + "dev_tools_prune_errors": False, + "reload": False, + }, + ), + ], +) +def test_custom_backend_error_handling_no_prune(request, fixture, start_server_kwargs): + dash_duo = request.getfixturevalue(fixture) + app = Dash(__name__, backend=CustomDashServer) + app.layout = html.Div( + [html.Button(id="btn", children="Error", n_clicks=0), html.Div(id="output")] + ) + + @app.callback(Output("output", "children"), Input("btn", "n_clicks")) + def error_callback(n): + if n and n > 0: + return 1 / 0 # Intentional error + return "No error" + + dash_duo.start_server(app, **start_server_kwargs) + dash_duo.wait_for_text_to_equal("#output", "No error") + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal(dash_duo.devtools_error_count_locator, "1") + + error0 = get_error_html(dash_duo, 0) + assert "Custom Debugger" in error0 + assert "in error_callback" in error0 + assert "ZeroDivisionError" in error0 + assert "_callback.py" in error0 + + +@pytest.mark.parametrize( + "fixture,start_server_kwargs, error_msg", + [ + ("dash_duo", {"debug": True, "reload": False}, "custombackend.py"), + ], +) +def test_custom_backend_error_handling_prune( + request, fixture, start_server_kwargs, error_msg +): + dash_duo = request.getfixturevalue(fixture) + app = Dash(__name__, backend=CustomDashServer) + app.layout = html.Div( + [html.Button(id="btn", children="Error", n_clicks=0), html.Div(id="output")] + ) + + @app.callback(Output("output", "children"), Input("btn", "n_clicks")) + def error_callback(n): + if n and n > 0: + return 1 / 0 # Intentional error + return "No error" + + dash_duo.start_server(app, **start_server_kwargs) + dash_duo.wait_for_text_to_equal("#output", "No error") + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal(dash_duo.devtools_error_count_locator, "1") + + error0 = get_error_html(dash_duo, 0) + assert "Custom Debugger" in error0 + assert "in error_callback" in error0 + assert "ZeroDivisionError" in error0 + assert "_callback.py" not in error0 + + +@pytest.mark.parametrize( + "fixture,input_value", + [ + ("dash_duo", "Background CustomBackend!"), + ], +) +def test_custom_backend_background_callback(request, fixture, input_value): + dash_duo = request.getfixturevalue(fixture) + import diskcache + + cache = diskcache.Cache("./cache") + from dash.background_callback import DiskcacheManager + + background_callback_manager = DiskcacheManager(cache) + + app = Dash( + __name__, + backend=CustomDashServer, + background_callback_manager=background_callback_manager, + ) + app.layout = html.Div( + [dcc.Input(id="input", value=input_value, type="text"), html.Div(id="output")] + ) + + @app.callback( + Output("output", "children"), Input("input", "value"), background=True + ) + def update_output_bg(value): + return f"Background typed: {value}" + + dash_duo.start_server(app) + dash_duo.wait_for_text_to_equal("#output", f"Background typed: {input_value}") + dash_duo.clear_input(dash_duo.find_element("#input")) + dash_duo.find_element("#input").send_keys("CustomBackend BG Test") + dash_duo.wait_for_text_to_equal( + "#output", "Background typed: CustomBackend BG Test" + ) + assert dash_duo.get_logs() == [] From 8b58cf4e10b4a2f6c04bf988e5a752fc123757e8 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Wed, 17 Sep 2025 12:50:15 -0400 Subject: [PATCH 068/297] fixing issue with `request_adapter` --- dash/backends/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dash/backends/__init__.py b/dash/backends/__init__.py index c8ac9321d0..c264af4824 100644 --- a/dash/backends/__init__.py +++ b/dash/backends/__init__.py @@ -19,8 +19,7 @@ def get_backend(name: str) -> tuple[BaseDashServer, RequestAdapter]: try: module = importlib.import_module(module_name) server = getattr(module, server_class) - request_adapter = server.request_adapter # type: ignore - return server, request_adapter + return server except KeyError as e: raise ValueError(f"Unknown backend: {name}") from e except ImportError as e: From b7d4af2bc744a9f58a31a94b005acb969bf7d6b9 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:30:00 -0400 Subject: [PATCH 069/297] adjusting error handling for fastapi --- dash/backends/_fastapi.py | 33 +++++++++++++++++++-------------- dash/backends/_quart.py | 4 +++- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 3f50f96f57..8fc08b7a89 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -70,24 +70,29 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: # CONFIG_PATH = "dash_config.json" -def save_config(config): - with open(CONFIG_PATH, "w") as f: - json.dump(config, f) +# Internal config helpers (local to this file) +_CONFIG_PATH = "dash_config.json" +def _save_config(config): + with open(_CONFIG_PATH, "w") as f: + json.dump(config, f) -def load_config(): - if os.path.exists(CONFIG_PATH): - with open(CONFIG_PATH, "r") as f: - return json.load(f) +def _load_config(): + try: + if os.path.exists(_CONFIG_PATH): + with open(_CONFIG_PATH, "r") as f: + return json.load(f) + except Exception: + pass # ignore errors return {} class FastAPIDashServer(BaseDashServer): def __init__(self, server: FastAPI): - self.config = {} + _save_config({"debug": False}) # ensure config file exists self.server_type = "fastapi" self.server: FastAPI = server - self.error_handling_mode = "prune" + self.error_handling_mode = "ignore" self.request_adapter = FastAPIRequestAdapter super().__init__() @@ -120,7 +125,7 @@ def register_assets_blueprint( pass def register_error_handlers(self): - self.error_handling_mode = "prune" + self.error_handling_mode = "ignore" def _get_traceback(self, _secret, error: Exception): tb = error.__traceback__ @@ -256,7 +261,7 @@ def setup_catchall(self, dash_app: Dash): @self.server.on_event("startup") def _setup_catchall(): dash_app.enable_dev_tools( - **load_config(), first_run=False + **_load_config(), first_run=False ) # do this to make sure dev tools are enabled async def catchall(request: Request): @@ -298,12 +303,12 @@ def after_request(self, func: Callable[[], Any] | None): def run(self, dash_app: Dash, host, port, debug, **kwargs): frame = inspect.stack()[2] config = dict( - {"debug": debug} if debug else {}, + {"debug": debug} if debug else {"debug": False}, **{ f"dev_tools_{k}": v for k, v in dash_app._dev_tools.items() }, # pylint: disable=protected-access ) - save_config(config) + _save_config(config) if debug: if kwargs.get("reload") is None: kwargs["reload"] = True @@ -352,7 +357,7 @@ async def middleware(request, call_next): return Response(content=tb, media_type="text/html", status_code=500) return JSONResponse( status_code=500, - content={"error": "InternalServerError", "message": str(e.args[0])}, + content={"error": "InternalServerError", "message": "An internal server error occurred."}, ) return middleware diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 8e509a08e0..eae8df9117 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -34,7 +34,7 @@ def __init__(self, server: Quart) -> None: self.server_type = "quart" self.server: Quart = server self.config = {} - self.error_handling_mode = "prune" + self.error_handling_mode = "ignore" self.request_adapter = QuartRequestAdapter super().__init__() @@ -184,6 +184,8 @@ def register_prune_error_handler(self, secret, prune_errors): @self.server.errorhandler(Exception) async def _wrap_errors(error): + if self.error_handling_mode == "ignore": + return Response("Internal server error.", status=500, content_type="text/plain") tb = self._get_traceback(secret, error) return Response(tb, status=500, content_type="text/html") From 4cf4686f4f62aa93210b907bed7c360e7e883f1c Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Wed, 17 Sep 2025 14:02:45 -0400 Subject: [PATCH 070/297] adjustments for handling issues with `debug` for `fastapi` --- dash/backends/_fastapi.py | 22 ++++++++++++++-------- dash_config.json | 1 - 2 files changed, 14 insertions(+), 9 deletions(-) delete mode 100644 dash_config.json diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 8fc08b7a89..36249fbf8c 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -66,30 +66,32 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: # finally: reset_current_request(token) - -CONFIG_PATH = "dash_config.json" - - # Internal config helpers (local to this file) -_CONFIG_PATH = "dash_config.json" +_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "dash_config.json") def _save_config(config): with open(_CONFIG_PATH, "w") as f: json.dump(config, f) def _load_config(): + resp = {"debug": False} try: if os.path.exists(_CONFIG_PATH): with open(_CONFIG_PATH, "r") as f: - return json.load(f) + resp = json.load(f) except Exception: pass # ignore errors - return {} + return resp + +def _remove_config(): + try: + os.remove(_CONFIG_PATH) + except FileNotFoundError: + pass class FastAPIDashServer(BaseDashServer): def __init__(self, server: FastAPI): - _save_config({"debug": False}) # ensure config file exists self.server_type = "fastapi" self.server: FastAPI = server self.error_handling_mode = "ignore" @@ -258,6 +260,10 @@ async def index(request: Request): dash_app._add_url("", index, methods=["GET"]) def setup_catchall(self, dash_app: Dash): + @self.server.on_event("shutdown") + def cleanup_config(): + _remove_config() + @self.server.on_event("startup") def _setup_catchall(): dash_app.enable_dev_tools( diff --git a/dash_config.json b/dash_config.json deleted file mode 100644 index e4af4373cb..0000000000 --- a/dash_config.json +++ /dev/null @@ -1 +0,0 @@ -{"dev_tools_ui": false, "dev_tools_props_check": false, "dev_tools_serve_dev_bundles": false, "dev_tools_hot_reload": false, "dev_tools_silence_routes_logging": false, "dev_tools_prune_errors": false, "dev_tools_hot_reload_interval": 3.0, "dev_tools_hot_reload_watch_interval": 0.5, "dev_tools_hot_reload_max_retry": 8, "dev_tools_disable_version_check": true} \ No newline at end of file From dfe0ac7f106dd1ea300c36adb3faf922a665b406 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Wed, 17 Sep 2025 16:17:50 -0400 Subject: [PATCH 071/297] fixing for lint --- dash/backends/__init__.py | 15 +- dash/backends/_fastapi.py | 226 +++++++-------------- dash/backends/_flask.py | 10 +- dash/backends/_quart.py | 158 +++----------- dash/backends/_utils.py | 108 ++++++++++ dash/testing/application_runners.py | 8 +- tests/backend_tests/test_custom_backend.py | 7 +- 7 files changed, 229 insertions(+), 303 deletions(-) create mode 100644 dash/backends/_utils.py diff --git a/dash/backends/__init__.py b/dash/backends/__init__.py index c264af4824..e8b007a50b 100644 --- a/dash/backends/__init__.py +++ b/dash/backends/__init__.py @@ -1,21 +1,19 @@ -from .base_server import BaseDashServer, RequestAdapter - import importlib +from .base_server import BaseDashServer -request_adapter: RequestAdapter backend: BaseDashServer _backend_imports = { - "flask": ("dash.backends._flask", "FlaskDashServer", "FlaskRequestAdapter"), - "fastapi": ("dash.backends._fastapi", "FastAPIDashServer", "FastAPIRequestAdapter"), - "quart": ("dash.backends._quart", "QuartDashServer", "QuartRequestAdapter"), + "flask": ("dash.backends._flask", "FlaskDashServer"), + "fastapi": ("dash.backends._fastapi", "FastAPIDashServer"), + "quart": ("dash.backends._quart", "QuartDashServer"), } -def get_backend(name: str) -> tuple[BaseDashServer, RequestAdapter]: - module_name, server_class, request_class = _backend_imports[name.lower()] +def get_backend(name: str) -> BaseDashServer: + module_name, server_class = _backend_imports[name.lower()] try: module = importlib.import_module(module_name) server = getattr(module, server_class) @@ -74,7 +72,6 @@ def get_server_type(server): __all__ = [ "get_backend", - "request_adapter", "backend", "get_server_type", ] diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 36249fbf8c..dc7805501b 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -1,5 +1,6 @@ from __future__ import annotations +import asyncio from contextvars import copy_context, ContextVar from typing import TYPE_CHECKING, Any, Callable, Dict import sys @@ -8,27 +9,41 @@ import inspect import pkgutil import time -import traceback from importlib.util import spec_from_file_location import json import os -import re + +try: + from fastapi import FastAPI, Request, Response, Body + from fastapi.responses import JSONResponse + from fastapi.staticfiles import StaticFiles + from starlette.responses import Response as StarletteResponse + from starlette.datastructures import MutableHeaders + from starlette.types import ASGIApp, Scope, Receive, Send + import uvicorn +except ImportError: + FastAPI = None + Request = None + Response = None + Body = None + JSONResponse = None + StaticFiles = None + StarletteResponse = None + MutableHeaders = None + ASGIApp = None + Scope = None + Receive = None + Send = None + uvicorn = None from dash.fingerprint import check_fingerprint from dash import _validate from dash.exceptions import PreventUpdate from .base_server import BaseDashServer, RequestAdapter - -from fastapi import FastAPI, Request, Response, Body -from fastapi.responses import JSONResponse -from fastapi.staticfiles import StaticFiles -from starlette.responses import Response as StarletteResponse -from starlette.datastructures import MutableHeaders -from starlette.types import ASGIApp, Scope, Receive, Send -import uvicorn +from ._utils import format_traceback_html if TYPE_CHECKING: # pragma: no cover - typing only - from dash.dash import Dash + from dash import Dash _current_request_var = ContextVar("dash_current_request", default=None) @@ -49,7 +64,7 @@ def get_current_request() -> Request: return req -class CurrentRequestMiddleware: +class CurrentRequestMiddleware: # pylint: disable=too-few-public-methods def __init__(self, app: ASGIApp) -> None: # type: ignore[name-defined] self.app = app @@ -66,23 +81,27 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: # finally: reset_current_request(token) + # Internal config helpers (local to this file) _CONFIG_PATH = os.path.join(os.path.dirname(__file__), "dash_config.json") + def _save_config(config): - with open(_CONFIG_PATH, "w") as f: + with open(_CONFIG_PATH, "w", encoding="utf-8") as f: json.dump(config, f) + def _load_config(): resp = {"debug": False} try: if os.path.exists(_CONFIG_PATH): - with open(_CONFIG_PATH, "r") as f: + with open(_CONFIG_PATH, "r", encoding="utf-8") as f: resp = json.load(f) - except Exception: + except (json.JSONDecodeError, OSError): pass # ignore errors return resp + def _remove_config(): try: os.remove(_CONFIG_PATH) @@ -130,113 +149,9 @@ def register_error_handlers(self): self.error_handling_mode = "ignore" def _get_traceback(self, _secret, error: Exception): - tb = error.__traceback__ - errors = traceback.format_exception(type(error), error, tb) - pass_errs = [] - callback_handled = False - for err in errors: - if self.error_handling_mode == "prune": - if not callback_handled: - if "callback invoked" in str(err) and "_callback.py" in str(err): - callback_handled = True - continue - pass_errs.append(err) - formatted_tb = "".join(pass_errs) - error_type = type(error).__name__ - error_msg = str(error) - - # Parse traceback lines to group by file - file_cards = [] - pattern = re.compile(r' File "(.+)", line (\d+), in (\w+)') - lines = formatted_tb.split("\n") - current_file = None - card_lines = [] - - for line in lines[:-1]: # Skip the last line (error message) - match = pattern.match(line) - if match: - if current_file and card_lines: - file_cards.append((current_file, card_lines)) - current_file = ( - f"{match.group(1)} (line {match.group(2)}, in {match.group(3)})" - ) - card_lines = [line] - elif current_file: - card_lines.append(line) - if current_file and card_lines: - file_cards.append((current_file, card_lines)) - - cards_html = "" - for filename, card in file_cards: - cards_html += ( - f""" -
-
{filename}
-
"""
-                + "\n".join(card)
-                + """
-
- """ - ) - - html = f""" - - - - {error_type}: {error_msg} // FastAPI Debugger - - - -
-

{error_type}

-
-

{error_type}: {error_msg}

-
-

Traceback (most recent call last)

- {cards_html} -
{error_type}: {error_msg}
-
-

This is the Copy/Paste friendly version of the traceback.

- -
-
- The debugger caught an exception in your ASGI application. You can now - look at the traceback which led to the error. -
- -
- - - """ - return html + return format_traceback_html( + error, self.error_handling_mode, "FastAPI Debugger", "FastAPI" + ) def register_prune_error_handler(self, _secret, prune_errors): if prune_errors: @@ -253,7 +168,7 @@ async def wrapped(*_args, **_kwargs): return wrapped def setup_index(self, dash_app: Dash): - async def index(request: Request): + async def index(_request: Request): return Response(content=dash_app.index(), media_type="text/html") # pylint: disable=protected-access @@ -270,7 +185,7 @@ def _setup_catchall(): **_load_config(), first_run=False ) # do this to make sure dev tools are enabled - async def catchall(request: Request): + async def catchall(_request: Request): return Response(content=dash_app.index(), media_type="text/html") # pylint: disable=protected-access @@ -308,11 +223,10 @@ def after_request(self, func: Callable[[], Any] | None): def run(self, dash_app: Dash, host, port, debug, **kwargs): frame = inspect.stack()[2] + dev_tools = dash_app._dev_tools # pylint: disable=protected-access config = dict( {"debug": debug} if debug else {"debug": False}, - **{ - f"dev_tools_{k}": v for k, v in dash_app._dev_tools.items() - }, # pylint: disable=protected-access + **{f"dev_tools_{k}": v for k, v in dev_tools.items()}, ) _save_config(config) if debug: @@ -348,7 +262,7 @@ def make_response( def jsonify(self, obj: Any): return JSONResponse(content=obj) - def _make_before_middleware(self, func: Callable[[], Any] | None): + def _make_before_middleware(self, _func: Callable[[], Any] | None): async def middleware(request, call_next): try: response = await call_next(request) @@ -356,14 +270,18 @@ async def middleware(request, call_next): except PreventUpdate: # No content, nothing to update return Response(status_code=204) - except Exception as e: + except (Exception) as e: # pylint: disable=broad-except + # Handle exceptions based on error_handling_mode if self.error_handling_mode in ["raise", "prune"]: # Prune the traceback to remove internal Dash calls tb = self._get_traceback(None, e) return Response(content=tb, media_type="text/html", status_code=500) return JSONResponse( status_code=500, - content={"error": "InternalServerError", "message": "An internal server error occurred."}, + content={ + "error": "InternalServerError", + "message": "An internal server error occurred.", + }, ) return middleware @@ -417,27 +335,25 @@ async def serve(request: Request, package_name: str, fingerprinted_path: str): dash_app, package_name, fingerprinted_path, request ) - # pylint: disable=protected-access - dash_app._add_url( - "_dash-component-suites/{package_name}/{fingerprinted_path:path}", - serve, - ) + name = "_dash-component-suites/{package_name}/{fingerprinted_path:path}" + dash_app._add_url(name, serve) # pylint: disable=protected-access - # pylint: disable=unused-argument def dispatch(self, dash_app: Dash): async def _dispatch(request: Request): # pylint: disable=protected-access body = await request.json() - g = dash_app._initialize_context(body) # pylint: disable=protected-access + cb_ctx = dash_app._initialize_context( + body + ) # pylint: disable=protected-access func = dash_app._prepare_callback( - g, body + cb_ctx, body ) # pylint: disable=protected-access args = dash_app._inputs_to_vals( - g.inputs_list + g.states_list + cb_ctx.inputs_list + cb_ctx.states_list ) # pylint: disable=protected-access ctx = copy_context() partial_func = dash_app._execute_callback( - func, args, g.outputs_list, g + func, args, cb_ctx.outputs_list, cb_ctx ) # pylint: disable=protected-access response_data = ctx.run(partial_func) if inspect.iscoroutine(response_data): @@ -494,20 +410,24 @@ def register_callback_api_routes( sig = inspect.signature(handler) param_names = list(sig.parameters.keys()) - async def view_func(request: Request, body: dict = Body(...)): - # Only pass expected params; ignore extras - kwargs = { - k: v for k, v in body.items() if k in param_names and v is not None - } - if inspect.iscoroutinefunction(handler): - result = await handler(**kwargs) - else: - result = handler(**kwargs) - return JSONResponse(content=result) + def make_view_func(handler, param_names): + async def view_func(_request: Request, body: dict = Body(...)): + kwargs = { + k: v + for k, v in body.items() + if k in param_names and v is not None + } + if inspect.iscoroutinefunction(handler): + result = await handler(**kwargs) + else: + result = handler(**kwargs) + return JSONResponse(content=result) + + return view_func self.server.add_api_route( route, - view_func, + make_view_func(handler, param_names), methods=methods, name=endpoint, include_in_schema=True, @@ -566,5 +486,5 @@ def origin(self): def path(self): return self._request.url.path - async def get_json(self): # async method retained - return await self._request.json() + def get_json(self): + return asyncio.run(self._request.json()) diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index b4bab46ff2..d9abe9c7ed 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -17,6 +17,7 @@ jsonify, g as flask_g, ) +from werkzeug.debug import tbtools from dash.fingerprint import check_fingerprint from dash import _validate @@ -67,13 +68,6 @@ def _invalid_resources_handler(err): return err.args[0], 404 def _get_traceback(self, secret, error: Exception): - try: - from werkzeug.debug import ( - tbtools, - ) # pylint: disable=import-outside-toplevel - except ImportError: - tbtools = None - def _get_skip(error): tb = error.__traceback__ skip = 1 @@ -238,7 +232,7 @@ async def _dispatch_async(): cb_ctx.dash_response.set_data(response_data) return cb_ctx.dash_response - if dash_app._use_async: + if dash_app._use_async: # pylint: disable=protected-access return _dispatch_async return _dispatch diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index eae8df9117..f417bc0d2e 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -1,32 +1,36 @@ from __future__ import annotations from contextvars import copy_context import typing as _t -import traceback import mimetypes import inspect import pkgutil import time import sys -import re +from typing import Any # Attempt top-level Quart imports; allow absence if user not using quart backend -from quart import ( - Quart, - Response, - jsonify, - request, - Blueprint, - g, -) - -if _t.TYPE_CHECKING: - from dash import Dash +try: + from quart import ( + Quart, + Response, + jsonify, + request, + Blueprint, + g, + ) +except ImportError: + Quart = None + Response = None + jsonify = None + request = None + Blueprint = None + g = None from dash.exceptions import PreventUpdate, InvalidResourceError from dash.fingerprint import check_fingerprint -from dash import _validate +from dash import _validate, Dash from .base_server import BaseDashServer -from typing import Any +from ._utils import format_traceback_html class QuartDashServer(BaseDashServer): @@ -68,113 +72,9 @@ def register_assets_blueprint( self.server.register_blueprint(bp) def _get_traceback(self, _secret, error: Exception): - tb = error.__traceback__ - errors = traceback.format_exception(type(error), error, tb) - pass_errs = [] - callback_handled = False - for err in errors: - if self.error_handling_mode == "prune": - if not callback_handled: - if "callback invoked" in str(err) and "_callback.py" in str(err): - callback_handled = True - continue - pass_errs.append(err) - formatted_tb = "".join(pass_errs) - error_type = type(error).__name__ - error_msg = str(error) - - # Parse traceback lines to group by file - file_cards = [] - pattern = re.compile(r' File "(.+)", line (\d+), in (\w+)') - lines = formatted_tb.split("\n") - current_file = None - card_lines = [] - - for line in lines[:-1]: # Skip the last line (error message) - match = pattern.match(line) - if match: - if current_file and card_lines: - file_cards.append((current_file, card_lines)) - current_file = ( - f"{match.group(1)} (line {match.group(2)}, in {match.group(3)})" - ) - card_lines = [line] - elif current_file: - card_lines.append(line) - if current_file and card_lines: - file_cards.append((current_file, card_lines)) - - cards_html = "" - for filename, card in file_cards: - cards_html += ( - f""" -
-
{filename}
-
"""
-                + "\n".join(card)
-                + """
-
- """ - ) - - html = f""" - - - - {error_type}: {error_msg} // Quart Debugger - - - -
-

{error_type}

-
-

{error_type}: {error_msg}

-
-

Traceback (most recent call last)

- {cards_html} -
{error_type}: {error_msg}
-
-

This is the Copy/Paste friendly version of the traceback.

- -
-
- The debugger caught an exception in your ASGI application. You can now - look at the traceback which led to the error. -
- -
- - - """ - return html + return format_traceback_html( + error, self.error_handling_mode, "Quart Debugger", "Quart" + ) def register_prune_error_handler(self, secret, prune_errors): if prune_errors: @@ -185,7 +85,9 @@ def register_prune_error_handler(self, secret, prune_errors): @self.server.errorhandler(Exception) async def _wrap_errors(error): if self.error_handling_mode == "ignore": - return Response("Internal server error.", status=500, content_type="text/plain") + return Response( + "Internal server error.", status=500, content_type="text/plain" + ) tb = self._get_traceback(secret, error) return Response(tb, status=500, content_type="text/html") @@ -337,14 +239,16 @@ async def _dispatch(): adapter = QuartRequestAdapter() body = await adapter.get_json() # pylint: disable=protected-access - g = dash_app._initialize_context(body) + cb_ctx = dash_app._initialize_context(body) # pylint: disable=protected-access - func = dash_app._prepare_callback(g, body) + func = dash_app._prepare_callback(cb_ctx, body) # pylint: disable=protected-access - args = dash_app._inputs_to_vals(g.inputs_list + g.states_list) + args = dash_app._inputs_to_vals(cb_ctx.inputs_list + cb_ctx.states_list) ctx = copy_context() # pylint: disable=protected-access - partial_func = dash_app._execute_callback(func, args, g.outputs_list, g) + partial_func = dash_app._execute_callback( + func, args, cb_ctx.outputs_list, cb_ctx + ) response_data = ctx.run(partial_func) if inspect.iscoroutine(response_data): # if user callback is async response_data = await response_data diff --git a/dash/backends/_utils.py b/dash/backends/_utils.py new file mode 100644 index 0000000000..0a5f4b0e76 --- /dev/null +++ b/dash/backends/_utils.py @@ -0,0 +1,108 @@ +import traceback +import re + + +def format_traceback_html(error, error_handling_mode, title, backend): + tb = error.__traceback__ + errors = traceback.format_exception(type(error), error, tb) + pass_errs = [] + callback_handled = False + for err in errors: + if error_handling_mode == "prune": + if not callback_handled: + if "callback invoked" in str(err) and "_callback.py" in str(err): + callback_handled = True + continue + pass_errs.append(err) + formatted_tb = "".join(pass_errs) + error_type = type(error).__name__ + error_msg = str(error) + # Parse traceback lines to group by file + file_cards = [] + pattern = re.compile(r' File "(.+)", line (\d+), in (\w+)') + lines = formatted_tb.split("\n") + current_file = None + card_lines = [] + for line in lines[:-1]: # Skip the last line (error message) + match = pattern.match(line) + if match: + if current_file and card_lines: + file_cards.append((current_file, card_lines)) + current_file = ( + f"{match.group(1)} (line {match.group(2)}, in {match.group(3)})" + ) + card_lines = [line] + elif current_file: + card_lines.append(line) + if current_file and card_lines: + file_cards.append((current_file, card_lines)) + cards_html = "" + for filename, card in file_cards: + cards_html += ( + f""" +
+
{filename}
+
"""
+            + "\n".join(card)
+            + """
+
+ """ + ) + html = f""" + + + + {error_type}: {error_msg} // {title} + + + +
+

{error_type}

+
+

{error_type}: {error_msg}

+
+

Traceback (most recent call last)

+ {cards_html} +
{error_type}: {error_msg}
+
+

This is the Copy/Paste friendly version of the traceback.

+ +
+
+ The debugger caught an exception in your ASGI application. You can now + look at the traceback which led to the error. +
+
+ Brought to you by DON'T PANIC, your + friendly {backend} powered traceback interpreter. +
+
+ + + """ + return html diff --git a/dash/testing/application_runners.py b/dash/testing/application_runners.py index 2956f1a4c0..6e6cc8b810 100644 --- a/dash/testing/application_runners.py +++ b/dash/testing/application_runners.py @@ -173,9 +173,9 @@ def run(): try: module = app.server.__class__.__module__ # FastAPI support - if not module.startswith("flask"): + if module.startswith("fastapi"): app.run(**options) - # Dash/Flask fallback + # Dash/Flask/Quart fallback else: app.run(threaded=True, **options) except SystemExit: @@ -237,9 +237,9 @@ def target(): try: module = app.server.__class__.__module__ # FastAPI support - if not module.startswith("flask"): + if module.startswith("fastapi"): app.run(**options) - # Dash/Flask fallback + # Dash/Flask/Quart fallback else: app.run(threaded=True, **options) except SystemExit: diff --git a/tests/backend_tests/test_custom_backend.py b/tests/backend_tests/test_custom_backend.py index aa590599b5..befff7734b 100644 --- a/tests/backend_tests/test_custom_backend.py +++ b/tests/backend_tests/test_custom_backend.py @@ -1,9 +1,12 @@ import pytest from dash import Dash, Input, Output, html, dcc -from fastapi import FastAPI import traceback import re -from dash.backends._fastapi import FastAPIDashServer + +try: + from dash.backends._fastapi import FastAPIDashServer +except ImportError: + FastAPIDashServer = None class CustomDashServer(FastAPIDashServer): From cd02cc5cbefefb7db331db625deee14897bf88b2 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 18 Sep 2025 14:05:28 -0400 Subject: [PATCH 072/297] adjustment for delayed config --- dash/dash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/dash.py b/dash/dash.py index 2d71766b4e..6b022108b6 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -579,7 +579,7 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches # tracks internally if a function already handled at least one request. self._got_first_request = {"pages": False, "setup_server": False} - if self.server is not None: + if server: self.init_app() self.logger.setLevel(logging.INFO) From 16b3c9e08743918b4e7af26cf43186955af1494f Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 18 Sep 2025 14:27:20 -0400 Subject: [PATCH 073/297] fix typing error --- dash/backends/base_server.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index cf2b62c2e7..2b11bc763b 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -1,11 +1,11 @@ from abc import ABC, abstractmethod -from typing import Any +from typing import Any, Dict class BaseDashServer(ABC): server_type: str server: Any - config: dict[str, Any] + config: Dict[str, Any] request_adapter: Any def __call__(self, *args, **kwargs) -> Any: From 493d1503630f3d87f5be95cd4a8dc641a84adad0 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Mon, 22 Sep 2025 08:30:16 -0400 Subject: [PATCH 074/297] fixes for pages --- dash/_pages.py | 13 +- dash/backends/_fastapi.py | 41 +++++-- dash/backends/_flask.py | 14 +++ dash/backends/_quart.py | 14 +++ dash/dash.py | 251 ++++++++++++++++++-------------------- 5 files changed, 181 insertions(+), 152 deletions(-) diff --git a/dash/_pages.py b/dash/_pages.py index 19a797bcf2..0a5f9d8c06 100644 --- a/dash/_pages.py +++ b/dash/_pages.py @@ -150,22 +150,13 @@ def _parse_path_variables(pathname, path_template): return dict(zip(var_names, variables)) -def _create_redirect_function(redirect_to): - def redirect(): - return flask.redirect(redirect_to, code=301) - - return redirect - - def _set_redirect(redirect_from, path): app = get_app() if redirect_from and len(redirect_from): for redirect in redirect_from: fullname = app.get_relative_path(redirect) - app.server.add_url_rule( - fullname, - fullname, - _create_redirect_function(app.get_relative_path(path)), + app.backend.add_redirect_rule( + app, fullname, app.get_relative_path(path) ) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index dc7805501b..61b2d65a8f 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -15,7 +15,7 @@ try: from fastapi import FastAPI, Request, Response, Body - from fastapi.responses import JSONResponse + from fastapi.responses import JSONResponse, RedirectResponse from fastapi.staticfiles import StaticFiles from starlette.responses import Response as StarletteResponse from starlette.datastructures import MutableHeaders @@ -27,6 +27,7 @@ Response = None Body = None JSONResponse = None + RedirectResponse = None StaticFiles = None StarletteResponse = None MutableHeaders = None @@ -115,6 +116,7 @@ def __init__(self, server: FastAPI): self.server: FastAPI = server self.error_handling_mode = "ignore" self.request_adapter = FastAPIRequestAdapter + self._before_request_funcs = [] super().__init__() def __call__(self, *args: Any, **kwargs: Any): @@ -213,9 +215,13 @@ def add_url_rule( ) def before_request(self, func: Callable[[], Any] | None): - # FastAPI does not have before_request, but we can use middleware - self.server.add_middleware(CurrentRequestMiddleware) - self.server.middleware("http")(self._make_before_middleware(func)) + if func is not None: + self._before_request_funcs.append(func) + # Only add the middleware once + if not hasattr(self, "_before_middleware_added"): + self.server.add_middleware(CurrentRequestMiddleware) + self.server.middleware("http")(self._make_before_middleware()) + self._before_middleware_added = True def after_request(self, func: Callable[[], Any] | None): # FastAPI does not have after_request, but we can use middleware @@ -262,18 +268,20 @@ def make_response( def jsonify(self, obj: Any): return JSONResponse(content=obj) - def _make_before_middleware(self, _func: Callable[[], Any] | None): + def _make_before_middleware(self): async def middleware(request, call_next): + for func in self._before_request_funcs: + if inspect.iscoroutinefunction(func): + await func() + else: + func() try: response = await call_next(request) return response except PreventUpdate: - # No content, nothing to update return Response(status_code=204) - except (Exception) as e: # pylint: disable=broad-except - # Handle exceptions based on error_handling_mode + except Exception as e: if self.error_handling_mode in ["raise", "prune"]: - # Prune the traceback to remove internal Dash calls tb = self._get_traceback(None, e) return Response(content=tb, media_type="text/html", status_code=500) return JSONResponse( @@ -338,6 +346,21 @@ async def serve(request: Request, package_name: str, fingerprinted_path: str): name = "_dash-component-suites/{package_name}/{fingerprinted_path:path}" dash_app._add_url(name, serve) # pylint: disable=protected-access + def _create_redirect_function(self, redirect_to): + def _redirect(): + return RedirectResponse(url=redirect_to, status_code=301) + + return _redirect + + def add_redirect_rule(self, app, fullname, path): + self.server.add_api_route( + fullname, + self._create_redirect_function(app.get_relative_path(path)), + methods=["GET"], + name=fullname, + include_in_schema=False, + ) + def dispatch(self, dash_app: Dash): async def _dispatch(request: Request): # pylint: disable=protected-access diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index d9abe9c7ed..2f7e08acf5 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -16,6 +16,7 @@ request, jsonify, g as flask_g, + redirect, ) from werkzeug.debug import tbtools @@ -194,6 +195,19 @@ def serve(package_name, fingerprinted_path): serve, ) + def _create_redirect_function(self, redirect_to): + def _redirect(): + return redirect(redirect_to, code=301) + + return _redirect + + def add_redirect_rule(self, app, fullname, path): + self.server.add_url_rule( + fullname, + fullname, + self._create_redirect_function(app.get_relative_path(path)), + ) + # pylint: disable=unused-argument def dispatch(self, dash_app: Dash): def _dispatch(): diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index f417bc0d2e..c08a165234 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -17,6 +17,7 @@ request, Blueprint, g, + redirect, ) except ImportError: Quart = None @@ -233,6 +234,19 @@ async def serve(package_name, fingerprinted_path): serve, ) + def _create_redirect_function(self, redirect_to): + def _redirect(): + return redirect(redirect_to, code=301) + + return _redirect + + def add_redirect_rule(self, app, fullname, path): + self.server.add_url_rule( + fullname, + fullname, + self._create_redirect_function(app.get_relative_path(path)), + ) + # pylint: disable=unused-argument def dispatch(self, dash_app: Dash): # type: ignore[name-defined] Quart always async async def _dispatch(): diff --git a/dash/dash.py b/dash/dash.py index 6b022108b6..53818cb5fb 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -2241,7 +2241,8 @@ def enable_pages(self) -> None: if self.pages_folder: _import_layouts_from_pages(self.config.pages_folder) - def router(): + # Async version + async def router_async(): if self._got_first_request["pages"]: return self._got_first_request["pages"] = True @@ -2250,157 +2251,143 @@ def router(): "pathname_": Input(_ID_LOCATION, "pathname"), "search_": Input(_ID_LOCATION, "search"), } - inputs.update(self.routing_callback_inputs) # type: ignore[reportCallIssue] + inputs.update(self.routing_callback_inputs) - if self._use_async: + @self.callback( + Output(_ID_CONTENT, "children"), + Output(_ID_STORE, "data"), + inputs=inputs, + prevent_initial_call=True, + ) + async def update(pathname_, search_, **states): + query_parameters = _parse_query_string(search_) + page, path_variables = _path_to_page(self.strip_relative_path(pathname_)) + if page == {}: + for module, page in _pages.PAGE_REGISTRY.items(): + if module.split(".")[-1] == "not_found_404": + layout = page["layout"] + title = page["title"] + break + else: + layout = html.H1("404 - Page not found") + title = self.title + else: + layout = page.get("layout", "") + title = page["title"] - @self.callback( - Output(_ID_CONTENT, "children"), - Output(_ID_STORE, "data"), - inputs=inputs, - prevent_initial_call=True, - ) - async def update(pathname_, search_, **states): - """ - Updates dash.page_container layout on page navigation. - Updates the stored page title which will trigger the clientside callback to update the app title - """ - - query_parameters = _parse_query_string(search_) - page, path_variables = _path_to_page( - self.strip_relative_path(pathname_) + if callable(layout): + layout = await execute_async_function( + layout, + **{**(path_variables or {}), **query_parameters, **states}, ) + if callable(title): + title = await execute_async_function( + title, **{**(path_variables or {})} + ) + return layout, {"title": title} - # get layout - if page == {}: - for module, page in _pages.PAGE_REGISTRY.items(): - if module.split(".")[-1] == "not_found_404": - layout = page["layout"] - title = page["title"] - break - else: - layout = html.H1("404 - Page not found") - title = self.title - else: - layout = page.get("layout", "") - title = page["title"] - - if callable(layout): - layout = await execute_async_function( - layout, - **{**(path_variables or {}), **query_parameters, **states}, - ) - if callable(title): - title = await execute_async_function( - title, **{**(path_variables or {})} - ) + _validate.check_for_duplicate_pathnames(_pages.PAGE_REGISTRY) + _validate.validate_registry(_pages.PAGE_REGISTRY) - return layout, {"title": title} + if not self.config.suppress_callback_exceptions: + async def get_layouts(): + return [ + await execute_async_function(page["layout"]) + if callable(page["layout"]) else page["layout"] + for page in _pages.PAGE_REGISTRY.values() + ] + layouts = await get_layouts() + layouts += [ + self.layout() if callable(self.layout) else self.layout + ] + self.validation_layout = html.Div(layouts) + if _ID_CONTENT not in self.validation_layout: + raise Exception("`dash.page_container` not found in the layout") - _validate.check_for_duplicate_pathnames(_pages.PAGE_REGISTRY) - _validate.validate_registry(_pages.PAGE_REGISTRY) + self.clientside_callback( + """ + function(data) { + document.title = data.title + } + """, + Output(_ID_DUMMY, "children"), + Input(_ID_STORE, "data"), + ) - # Set validation_layout - if not self.config.suppress_callback_exceptions: - self.validation_layout = html.Div( - [ - ( - asyncio.run(execute_async_function(page["layout"])) - if callable(page["layout"]) - else page["layout"] - ) - for page in _pages.PAGE_REGISTRY.values() - ] - + [ - # pylint: disable=not-callable - self.layout() - if callable(self.layout) - else self.layout - ] - ) - if _ID_CONTENT not in self.validation_layout: - raise Exception("`dash.page_container` not found in the layout") - else: + # Sync version + def router_sync(): + if self._got_first_request["pages"]: + return + self._got_first_request["pages"] = True - @self.callback( - Output(_ID_CONTENT, "children"), - Output(_ID_STORE, "data"), - inputs=inputs, - prevent_initial_call=True, - ) - def update(pathname_, search_, **states): - """ - Updates dash.page_container layout on page navigation. - Updates the stored page title which will trigger the clientside callback to update the app title - """ - - query_parameters = _parse_query_string(search_) - page, path_variables = _path_to_page( - self.strip_relative_path(pathname_) - ) + inputs = { + "pathname_": Input(_ID_LOCATION, "pathname"), + "search_": Input(_ID_LOCATION, "search"), + } + inputs.update(self.routing_callback_inputs) - # get layout - if page == {}: - for module, page in _pages.PAGE_REGISTRY.items(): - if module.split(".")[-1] == "not_found_404": - layout = page["layout"] - title = page["title"] - break - else: - layout = html.H1("404 - Page not found") - title = self.title + @self.callback( + Output(_ID_CONTENT, "children"), + Output(_ID_STORE, "data"), + inputs=inputs, + prevent_initial_call=True, + ) + def update(pathname_, search_, **states): + query_parameters = _parse_query_string(search_) + page, path_variables = _path_to_page(self.strip_relative_path(pathname_)) + if page == {}: + for module, page in _pages.PAGE_REGISTRY.items(): + if module.split(".")[-1] == "not_found_404": + layout = page["layout"] + title = page["title"] + break else: - layout = page.get("layout", "") - title = page["title"] + layout = html.H1("404 - Page not found") + title = self.title + else: + layout = page.get("layout", "") + title = page["title"] - if callable(layout): - layout = layout( - **{**(path_variables or {}), **query_parameters, **states} - ) - if callable(title): - title = title(**(path_variables or {})) - - return layout, {"title": title} - - _validate.check_for_duplicate_pathnames(_pages.PAGE_REGISTRY) - _validate.validate_registry(_pages.PAGE_REGISTRY) - - # Set validation_layout - if not self.config.suppress_callback_exceptions: - layout = self.layout - if not isinstance(layout, list): - layout = [ - # pylint: disable=not-callable - self.layout() - if callable(self.layout) - else self.layout - ] - self.validation_layout = html.Div( - [ - ( - page["layout"]() - if callable(page["layout"]) - else page["layout"] - ) - for page in _pages.PAGE_REGISTRY.values() - ] - + layout - ) - if _ID_CONTENT not in self.validation_layout: - raise Exception("`dash.page_container` not found in the layout") + if callable(layout): + layout = layout( + **{**(path_variables or {}), **query_parameters, **states} + ) + if callable(title): + title = title(**(path_variables or {})) + return layout, {"title": title} + + _validate.check_for_duplicate_pathnames(_pages.PAGE_REGISTRY) + _validate.validate_registry(_pages.PAGE_REGISTRY) + + if not self.config.suppress_callback_exceptions: + layout = self.layout + if not isinstance(layout, list): + layout = [ + self.layout() if callable(self.layout) else self.layout + ] + self.validation_layout = html.Div( + [ + page["layout"]() if callable(page["layout"]) else page["layout"] + for page in _pages.PAGE_REGISTRY.values() + ] + layout + ) + if _ID_CONTENT not in self.validation_layout: + raise Exception("`dash.page_container` not found in the layout") - # Update the page title on page navigation self.clientside_callback( """ - function(data) {{ + function(data) { document.title = data.title - }} + } """, Output(_ID_DUMMY, "children"), Input(_ID_STORE, "data"), ) - self.backend.before_request(router) + if self._use_async: + self.backend.before_request(router_async) + else: + self.backend.before_request(router_sync) def __call__(self, *args, **kwargs): return self.backend.__call__(*args, **kwargs) From a10f86b46e04e369b1fd859266b177f574333b4a Mon Sep 17 00:00:00 2001 From: chgiesse <83552131+chgiesse@users.noreply.github.com> Date: Wed, 12 Nov 2025 12:14:29 +0100 Subject: [PATCH 075/297] Decouple flask (#7) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ∙ Added has_request_context to base_server ∙ removed flask specific import in _validate and use backends.backend.has_request_context now * ∙ added context to request adapter ∙ callback context uses request adapter context now ∙ * added get_root_path to dash _utils removed flask.helpers.get_root_path usage * moved compress to server implementations flask fully decoupled from dash * fixed compress in quart and fastapi * Fixed server.config in fastapi to use config file * Update dash/backends/_fastapi.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * removed unused flask import in pages * Update dash/backends/_quart.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * removed flask specific return type to remove global dependency --------- Co-authored-by: Christian Giessel Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- dash/_callback_context.py | 11 +-- dash/_configs.py | 5 +- dash/_hooks.py | 3 +- dash/_pages.py | 10 +-- dash/_utils.py | 59 ++++++++++++++++ dash/_validate.py | 3 +- dash/backends/_fastapi.py | 24 +++++++ dash/backends/_flask.py | 31 +++++++++ dash/backends/_quart.py | 44 ++++++++++-- dash/backends/base_server.py | 131 +++++++++++++++++++---------------- dash/dash.py | 21 +----- 11 files changed, 241 insertions(+), 101 deletions(-) diff --git a/dash/_callback_context.py b/dash/_callback_context.py index 72b92e09e2..58c5c9bbd5 100644 --- a/dash/_callback_context.py +++ b/dash/_callback_context.py @@ -4,9 +4,8 @@ import contextvars import typing -import flask - from . import exceptions +from . import backends from ._utils import AttributeDict, stringify_id @@ -220,14 +219,15 @@ def record_timing(name, duration, description=None): :param description: A description of the resource. :type description: string or None """ - timing_information = getattr(flask.g, "timing_information", {}) + request = backends.backend.request_adapter() + timing_information = getattr(request.context, "timing_information", {}) if name in timing_information: raise KeyError(f'Duplicate resource name "{name}" found.') timing_information[name] = {"dur": round(duration * 1000), "desc": description} - setattr(flask.g, "timing_information", timing_information) + setattr(request.context, "timing_information", timing_information) @property @has_context @@ -250,7 +250,8 @@ def using_outputs_grouping(self): @property @has_context def timing_information(self): - return getattr(flask.g, "timing_information", {}) + request = backends.backend.request_adapter() + return getattr(request.context, "timing_information", {}) @has_context def set_props(self, component_id: typing.Union[str, dict], props: dict): diff --git a/dash/_configs.py b/dash/_configs.py index edbf7b50d1..c4ff8d59e6 100644 --- a/dash/_configs.py +++ b/dash/_configs.py @@ -1,6 +1,5 @@ +from ._utils import get_root_path import os -import flask - # noinspection PyCompatibility from . import exceptions from ._utils import AttributeDict @@ -127,7 +126,7 @@ def pages_folder_config(name, pages_folder, use_pages): if not pages_folder: return None is_custom_folder = str(pages_folder) != "pages" - pages_folder_path = os.path.join(flask.helpers.get_root_path(name), pages_folder) + pages_folder_path = os.path.join(get_root_path(name), pages_folder) if (use_pages or is_custom_folder) and not os.path.isdir(pages_folder_path): error_msg = f""" A folder called `{pages_folder}` does not exist. If a folder for pages is not diff --git a/dash/_hooks.py b/dash/_hooks.py index 98e5cf1ecd..4276c9f9f5 100644 --- a/dash/_hooks.py +++ b/dash/_hooks.py @@ -3,7 +3,6 @@ from importlib import metadata as _importlib_metadata import typing_extensions as _tx -import flask as _f from .exceptions import HookError from .resources import ResourceType @@ -125,7 +124,7 @@ def route( Add a route to the Dash server. """ - def wrap(func: _t.Callable[[], _f.Response]): + def wrap(func: _t.Callable[[], _t.Any]): _name = name or func.__name__ self.add_hook( "routes", diff --git a/dash/_pages.py b/dash/_pages.py index 0a5f9d8c06..be9d847309 100644 --- a/dash/_pages.py +++ b/dash/_pages.py @@ -9,13 +9,11 @@ from pathlib import Path from urllib.parse import parse_qs -import flask - from . import _validate from ._callback_context import context_value from ._get_app import get_app from ._get_paths import get_relative_path -from ._utils import AttributeDict +from ._utils import AttributeDict, get_root_path CONFIG = AttributeDict() PAGE_REGISTRY = collections.OrderedDict() @@ -98,7 +96,7 @@ def _path_to_module_name(path): def _infer_module_name(page_path): relative_path = page_path.split(CONFIG.pages_folder)[-1] module = _path_to_module_name(relative_path) - proj_root = flask.helpers.get_root_path(CONFIG.name) + proj_root = get_root_path(CONFIG.name) if CONFIG.pages_folder.startswith(proj_root): parent_path = CONFIG.pages_folder[len(proj_root) :] else: @@ -155,9 +153,7 @@ def _set_redirect(redirect_from, path): if redirect_from and len(redirect_from): for redirect in redirect_from: fullname = app.get_relative_path(redirect) - app.backend.add_redirect_rule( - app, fullname, app.get_relative_path(path) - ) + app.backend.add_redirect_rule(app, fullname, app.get_relative_path(path)) def register_page( diff --git a/dash/_utils.py b/dash/_utils.py index ef6c63c281..df090d252c 100644 --- a/dash/_utils.py +++ b/dash/_utils.py @@ -3,6 +3,7 @@ import sys import uuid import hashlib +import importlib from collections import abc import subprocess import logging @@ -12,6 +13,7 @@ import string import inspect import re +import os from html import escape from functools import wraps @@ -322,3 +324,60 @@ def pascal_case(name: Union[str, None]): return s[0].upper() + re.sub( r"[\-_\.]+([a-z])", lambda match: match.group(1).upper(), s[1:] ) + + +def get_root_path(import_name: str) -> str: + """Find the root path of a package, or the path that contains a + module. If it cannot be found, returns the current working + directory. + + Not to be confused with the value returned by :func:`find_package`. + + :meta private: + """ + # Module already imported and has a file attribute. Use that first. + mod = sys.modules.get(import_name) + + if mod is not None and hasattr(mod, "__file__") and mod.__file__ is not None: + return os.path.dirname(os.path.abspath(mod.__file__)) + + # Next attempt: check the loader. + try: + spec = importlib.util.find_spec(import_name) + + if spec is None: + raise ValueError + except (ImportError, ValueError): + loader = None + else: + loader = spec.loader + + # Loader does not exist or we're referring to an unloaded main + # module or a main module without path (interactive sessions), go + # with the current working directory. + if loader is None: + return os.getcwd() + + if hasattr(loader, "get_filename"): + filepath = loader.get_filename(import_name) # pyright: ignore + else: + # Fall back to imports. + __import__(import_name) + mod = sys.modules[import_name] + filepath = getattr(mod, "__file__", None) + + # If we don't have a file path it might be because it is a + # namespace package. In this case pick the root path from the + # first module that is contained in the package. + if filepath is None: + raise RuntimeError( + "No root path can be found for the provided module" + f" {import_name!r}. This can happen because the module" + " came from an import hook that does not provide file" + " name information or because it's a namespace package." + " In this case the root path needs to be explicitly" + " provided." + ) + + # filepath is import_name.py for a module, or __init__.py for a package. + return os.path.dirname(os.path.abspath(filepath)) # type: ignore[no-any-return] diff --git a/dash/_validate.py b/dash/_validate.py index d595cba0fc..8511b37150 100644 --- a/dash/_validate.py +++ b/dash/_validate.py @@ -3,7 +3,6 @@ import re from textwrap import dedent from keyword import iskeyword -import flask from ._grouping import grouping_len, map_grouping from ._no_update import NoUpdate @@ -511,7 +510,7 @@ def validate_use_pages(config): "`dash.register_page()` must be called after app instantiation" ) - if flask.has_request_context(): + if backends.backend.has_request_context(): raise exceptions.PageError( """ dash.register_page() can’t be called within a callback as it updates dash.page_registry, which is a global variable. diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 61b2d65a8f..3de76f7b42 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -227,6 +227,13 @@ def after_request(self, func: Callable[[], Any] | None): # FastAPI does not have after_request, but we can use middleware self.server.middleware("http")(self._make_after_middleware(func)) + def has_request_context(self) -> bool: + try: + get_current_request() + return True + except RuntimeError: + return False + def run(self, dash_app: Dash, host, port, debug, **kwargs): frame = inspect.stack()[2] dev_tools = dash_app._dev_tools # pylint: disable=protected-access @@ -456,6 +463,16 @@ async def view_func(_request: Request, body: dict = Body(...)): include_in_schema=True, ) + def enable_compression(self) -> None: + from fastapi.middleware.gzip import GZipMiddleware + + self.server.add_middleware(GZipMiddleware, minimum_size=500) + config = _load_config() + if "COMPRESS_ALGORITHM" not in config: + config["COMPRESS_ALGORITHM"] = ["gzip"] + + _save_config(config) + class FastAPIRequestAdapter(RequestAdapter): def __init__(self): @@ -466,6 +483,13 @@ def __call__(self): self._request = get_current_request() return self + @property + def context(self): + if self._request is None: + raise RuntimeError("No active request in context") + + return self._request.state + @property def root(self): return str(self._request.base_url) diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index 2f7e08acf5..75e16371f5 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -1,6 +1,7 @@ from __future__ import annotations from contextvars import copy_context +from importlib_metadata import version as _get_distribution_version from typing import TYPE_CHECKING, Any, Callable, Dict import asyncio import pkgutil @@ -16,6 +17,7 @@ request, jsonify, g as flask_g, + has_request_context, redirect, ) from werkzeug.debug import tbtools @@ -24,8 +26,10 @@ from dash import _validate from dash.exceptions import PreventUpdate, InvalidResourceError from dash._callback import _invoke_callback, _async_invoke_callback +from dash._utils import parse_version from .base_server import BaseDashServer, RequestAdapter + if TYPE_CHECKING: # pragma: no cover - typing only from dash import Dash @@ -128,6 +132,9 @@ def after_request(self, func: Callable[[Any], Any]): # Flask after_request expects a function(response) -> response self.server.after_request(func) + def has_request_context(self) -> bool: + return has_request_context() + def run(self, dash_app: Dash, host: str, port: int, debug: bool, **kwargs: Any): self.server.run(host=host, port=port, debug=debug, **kwargs) @@ -318,6 +325,24 @@ def _sync_view_func(*args, handler=handler, **kwargs): route, endpoint=endpoint, view_func=view_func, methods=methods ) + def enable_compression(self) -> None: + try: + import flask_compress # pylint: disable=import-outside-toplevel + + Compress = flask_compress.Compress + Compress(self.server) + _flask_compress_version = parse_version( + _get_distribution_version("flask_compress") + ) + if not hasattr( + self.server.config, "COMPRESS_ALGORITHM" + ) and _flask_compress_version >= parse_version("1.6.0"): + self.server.config["COMPRESS_ALGORITHM"] = ["gzip"] + except ImportError as error: + raise ImportError( + "To use the compress option, you need to install dash[compress]" + ) from error + class FlaskRequestAdapter(RequestAdapter): """Flask implementation using property-based accessors.""" @@ -330,6 +355,12 @@ def __init__(self) -> None: def __call__(self, *args: Any, **kwds: Any): return self + @property + def context(self): + if not has_request_context(): + raise RuntimeError("No active request in context") + return flask_g + @property def args(self): return self._request.args diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index c08a165234..11af4bc169 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -1,4 +1,5 @@ from __future__ import annotations +from importlib_metadata import version as _get_distribution_version from contextvars import copy_context import typing as _t import mimetypes @@ -16,7 +17,8 @@ jsonify, request, Blueprint, - g, + g as quart_g, + has_request_context, redirect, ) except ImportError: @@ -25,10 +27,11 @@ jsonify = None request = None Blueprint = None - g = None + quart_g = None from dash.exceptions import PreventUpdate, InvalidResourceError from dash.fingerprint import check_fingerprint +from dash._utils import parse_version from dash import _validate, Dash from .base_server import BaseDashServer from ._utils import format_traceback_html @@ -95,15 +98,17 @@ async def _wrap_errors(error): def register_timing_hooks(self, _first_run: bool): # type: ignore[name-defined] parity with Flask factory @self.server.before_request async def _before_request(): # pragma: no cover - timing infra - if g is not None: - g.timing_information = { # type: ignore[attr-defined] + if quart_g is not None: + quart_g.timing_information = { # type: ignore[attr-defined] "__dash_server": {"dur": time.time(), "desc": None} } @self.server.after_request async def _after_request(response): # pragma: no cover - timing infra timing_information = ( - getattr(g, "timing_information", None) if g is not None else None + getattr(quart_g, "timing_information", None) + if quart_g is not None + else None ) if timing_information is None: return response @@ -181,6 +186,11 @@ async def _after(response): await result return response + def has_request_context(self) -> bool: + if has_request_context is None: + raise RuntimeError("Quart not installed; cannot check request context") + return has_request_context() + def run(self, dash_app: Dash, host: str, port: int, debug: bool, **kwargs: _t.Any): self.config = {"debug": debug, **kwargs} if debug else kwargs self.server.run(host=host, port=port, debug=debug, **kwargs) @@ -318,6 +328,24 @@ def _serve_default_favicon(self): pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" ) + def enable_compression(self) -> None: + try: + import quart_compress # pylint: disable=import-outside-toplevel + + Compress = quart_compress.Compress + Compress(self.server) + _flask_compress_version = parse_version( + _get_distribution_version("quart_compress") + ) + if not hasattr( + self.server.config, "COMPRESS_ALGORITHM" + ) and _flask_compress_version >= parse_version("1.6.0"): + self.server.config["COMPRESS_ALGORITHM"] = ["gzip"] + except ImportError as error: + raise ImportError( + "To use the compress option, you need to install quart_compress." + ) from error + class QuartRequestAdapter: def __init__(self) -> None: @@ -325,6 +353,12 @@ def __init__(self) -> None: if self._request is None: raise RuntimeError("Quart not installed; cannot access request context") + @property + def context(self): + if not has_request_context(): + raise RuntimeError("No active request in context") + return quart_g + @property def request(self) -> _t.Any: return self._request diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index 2b11bc763b..f571669bee 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -2,68 +2,15 @@ from typing import Any, Dict -class BaseDashServer(ABC): - server_type: str - server: Any - config: Dict[str, Any] - request_adapter: Any - - def __call__(self, *args, **kwargs) -> Any: - # Default: WSGI - return self.server(*args, **kwargs) - - @staticmethod - @abstractmethod - def create_app( - name: str = "__main__", config=None - ) -> Any: # pragma: no cover - interface - pass - - @abstractmethod - def register_assets_blueprint( - self, blueprint_name: str, assets_url_path: str, assets_folder: str - ) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def register_error_handlers(self) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def add_url_rule( - self, rule: str, view_func, endpoint=None, methods=None - ) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def before_request(self, func) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def after_request(self, func) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def run( - self, dash_app, host: str, port: int, debug: bool, **kwargs - ) -> None: # pragma: no cover - interface - pass - - @abstractmethod - def make_response( - self, data, mimetype=None, content_type=None - ) -> Any: # pragma: no cover - interface - pass - - @abstractmethod - def jsonify(self, obj) -> Any: # pragma: no cover - interface - pass - - class RequestAdapter(ABC): - def __call__(self) -> Any: + def __call__(self) -> "RequestAdapter": return self + @property + @abstractmethod + def context(self) -> Any: # pragma: no cover - interface + raise NotImplementedError() + # Properties to be implemented in concrete adapters @property # pragma: no cover - interface @abstractmethod @@ -118,3 +65,69 @@ def origin(self): @abstractmethod def path(self) -> str: raise NotImplementedError() + + +class BaseDashServer(ABC): + server_type: str + server: Any + config: Dict[str, Any] + request_adapter: RequestAdapter + + def __call__(self, *args, **kwargs) -> Any: + # Default: WSGI + return self.server(*args, **kwargs) + + @staticmethod + @abstractmethod + def create_app( + name: str = "__main__", config=None + ) -> Any: # pragma: no cover - interface + pass + + @abstractmethod + def register_assets_blueprint( + self, blueprint_name: str, assets_url_path: str, assets_folder: str + ) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def register_error_handlers(self) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def add_url_rule( + self, rule: str, view_func, endpoint=None, methods=None + ) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def before_request(self, func) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def after_request(self, func) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def has_request_context(self) -> bool: # pragma: no cover - interface + pass + + @abstractmethod + def run( + self, dash_app, host: str, port: int, debug: bool, **kwargs + ) -> None: # pragma: no cover - interface + pass + + @abstractmethod + def make_response( + self, data, mimetype=None, content_type=None + ) -> Any: # pragma: no cover - interface + pass + + @abstractmethod + def jsonify(self, obj) -> Any: # pragma: no cover - interface + pass + + @abstractmethod + def enable_compression(self) -> None: # pragma: no cover - interface + pass diff --git a/dash/dash.py b/dash/dash.py index acb557b977..f662e75efb 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -18,7 +18,6 @@ from typing import Any, Callable, Dict, Optional, Union, Sequence, Literal, List import asyncio -import flask from importlib_metadata import version as _get_distribution_version @@ -55,6 +54,7 @@ hooks_to_js_object, parse_version, get_caller_name, + get_root_path, ) from . import _callback from . import _get_paths @@ -463,7 +463,7 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches self.config = AttributeDict( name=caller_name, assets_folder=os.path.join( - flask.helpers.get_root_path(caller_name), assets_folder + get_root_path(caller_name), assets_folder ), # type: ignore assets_url_path=assets_url_path, assets_ignore=assets_ignore, @@ -659,22 +659,7 @@ def init_app(self, app: Optional[Any] = None, **kwargs) -> None: self.config.assets_folder, ) if config.compress: - try: - import flask_compress # pylint: disable=import-outside-toplevel - - Compress = flask_compress.Compress - Compress(self.server) - _flask_compress_version = parse_version( - _get_distribution_version("flask_compress") - ) - if not hasattr( - self.server.config, "COMPRESS_ALGORITHM" - ) and _flask_compress_version >= parse_version("1.6.0"): - self.server.config["COMPRESS_ALGORITHM"] = ["gzip"] - except ImportError as error: - raise ImportError( - "To use the compress option, you need to install dash[compress]" - ) from error + self.backend.enable_compression() # type: ignore self.backend.register_error_handlers() self.backend.before_request(self._setup_server) From 358a0451285feb585f12f76735375bc3cec963f3 Mon Sep 17 00:00:00 2001 From: Corebit <123189979+corebit-nl@users.noreply.github.com> Date: Sat, 22 Nov 2025 11:22:59 +0100 Subject: [PATCH 076/297] Fallback on background callback function names if source cannot be found --- dash/background_callback/managers/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dash/background_callback/managers/__init__.py b/dash/background_callback/managers/__init__.py index 6bea3765d3..4145f27f63 100644 --- a/dash/background_callback/managers/__init__.py +++ b/dash/background_callback/managers/__init__.py @@ -56,7 +56,11 @@ def get_updated_props(self, key): raise NotImplementedError def build_cache_key(self, fn, args, cache_args_to_ignore, triggered): - fn_source = inspect.getsource(fn) + try: + fn_source = inspect.getsource(fn) + fn_str = fn_source + except OSError: # pylint: disable=too-broad-exception + fn_str = getattr(fn, "__name__", "") if not isinstance(cache_args_to_ignore, (list, tuple)): cache_args_to_ignore = [cache_args_to_ignore] @@ -69,7 +73,7 @@ def build_cache_key(self, fn, args, cache_args_to_ignore, triggered): arg for i, arg in enumerate(args) if i not in cache_args_to_ignore ] - hash_dict = dict(args=args, fn_source=fn_source, triggered=triggered) + hash_dict = dict(args=args, fn_source=fn_str, triggered=triggered) if self.cache_by is not None: # Caching enabled From 5932df4bbff199247545920bbce9f33baf10debf Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Mon, 12 Jan 2026 12:02:04 -0500 Subject: [PATCH 077/297] fixes issue where components wouldnt remount when passed as a children prop (cherry picked from commit cdd40ed1f23eaea4d84f717a206f3cfc1ab2f8fd) --- dash/dash-renderer/src/wrapper/DashWrapper.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dash/dash-renderer/src/wrapper/DashWrapper.tsx b/dash/dash-renderer/src/wrapper/DashWrapper.tsx index 57e152ebcc..40f5817f36 100644 --- a/dash/dash-renderer/src/wrapper/DashWrapper.tsx +++ b/dash/dash-renderer/src/wrapper/DashWrapper.tsx @@ -65,6 +65,7 @@ function DashWrapper({ const dispatch = useDispatch(); const memoizedKeys: MutableRefObject = useRef({}); const newRender = useRef(false); + const freshRenders = useRef(0); const renderedPath = useRef(componentPath); let renderComponent: any = null; let renderComponentProps: any = null; @@ -85,6 +86,7 @@ function DashWrapper({ if (_newRender) { newRender.current = true; renderH = 0; + freshRenders.current += 1; if (renderH in memoizedKeys.current) { delete memoizedKeys.current[renderH]; } @@ -498,6 +500,7 @@ function DashWrapper({ } error={_dashprivate_error} dispatch={dispatch} + key={freshRenders.current} > {React.isValidElement(hydrated) ? hydrated :
} From cb1f299b7909774eded40e1871f3aa1950ca7faf Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 20 Jan 2026 18:13:46 -0500 Subject: [PATCH 078/297] update to remove hashes of decendents upon `newRender` --- dash/dash-renderer/src/actions/constants.js | 3 ++- dash/dash-renderer/src/actions/index.js | 1 + dash/dash-renderer/src/reducers/reducer.js | 11 +++++++++++ dash/dash-renderer/src/wrapper/DashWrapper.tsx | 6 +++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/dash/dash-renderer/src/actions/constants.js b/dash/dash-renderer/src/actions/constants.js index 9c744f1655..47406b6627 100644 --- a/dash/dash-renderer/src/actions/constants.js +++ b/dash/dash-renderer/src/actions/constants.js @@ -10,7 +10,8 @@ const actionList = { ON_ERROR: 1, SET_HOOKS: 1, INSERT_COMPONENT: 1, - REMOVE_COMPONENT: 1 + REMOVE_COMPONENT: 1, + RESET_COMPONENT_STATE: 1 }; export const getAction = action => { diff --git a/dash/dash-renderer/src/actions/index.js b/dash/dash-renderer/src/actions/index.js index 5df75d708e..ee7f8fd9db 100644 --- a/dash/dash-renderer/src/actions/index.js +++ b/dash/dash-renderer/src/actions/index.js @@ -22,6 +22,7 @@ export const insertComponent = createAction(getAction('INSERT_COMPONENT')); export const removeComponent = createAction(getAction('REMOVE_COMPONENT')); export const onPropChange = createAction(getAction('ON_PROP_CHANGE')); +export const resetComponentState = createAction(getAction('RESET_COMPONENT_STATE')); export function updateProps(payload) { return (dispatch, getState) => { diff --git a/dash/dash-renderer/src/reducers/reducer.js b/dash/dash-renderer/src/reducers/reducer.js index 56d2c82ad2..b9704c96b7 100644 --- a/dash/dash-renderer/src/reducers/reducer.js +++ b/dash/dash-renderer/src/reducers/reducer.js @@ -49,6 +49,17 @@ const layoutHashes = (state = {}, action) => { }, state ); + } else if (action.type === 'RESET_COMPONENT_STATE') { + const { itempath } = action.payload; + if (itempath) { + const prefixStr = stringifyPath(itempath); + // Remove all hashes for keys starting with prefixStr + return Object.fromEntries( + Object.entries(state).filter( + ([key]) => !key.startsWith(prefixStr) + ) + ); + }; } return state; }; diff --git a/dash/dash-renderer/src/wrapper/DashWrapper.tsx b/dash/dash-renderer/src/wrapper/DashWrapper.tsx index 40f5817f36..43fccdb2c3 100644 --- a/dash/dash-renderer/src/wrapper/DashWrapper.tsx +++ b/dash/dash-renderer/src/wrapper/DashWrapper.tsx @@ -21,7 +21,7 @@ import {useSelector, useDispatch, batch} from 'react-redux'; import ComponentErrorBoundary from '../components/error/ComponentErrorBoundary.react'; import {DashLayoutPath, UpdatePropsPayload} from '../types/component'; import {DashConfig} from '../config'; -import {notifyObservers, onError, updateProps} from '../actions'; +import {notifyObservers, onError, updateProps, resetComponentState} from '../actions'; import {getWatchedKeys, stringifyId} from '../actions/dependencies'; import { createElement, @@ -90,6 +90,10 @@ function DashWrapper({ if (renderH in memoizedKeys.current) { delete memoizedKeys.current[renderH]; } + // Reset hashes and layout for this component and all descendants + dispatch(resetComponentState({ + itempath: componentPath, + })); } else { newRender.current = false; } From 8e960df105276a5cc657c0eb9a66ab8486258105 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 20 Jan 2026 20:46:44 -0500 Subject: [PATCH 079/297] fix for lint --- dash/dash-renderer/src/actions/index.js | 4 +++- dash/dash-renderer/src/wrapper/DashWrapper.tsx | 15 +++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/dash/dash-renderer/src/actions/index.js b/dash/dash-renderer/src/actions/index.js index ee7f8fd9db..7c92d17afc 100644 --- a/dash/dash-renderer/src/actions/index.js +++ b/dash/dash-renderer/src/actions/index.js @@ -22,7 +22,9 @@ export const insertComponent = createAction(getAction('INSERT_COMPONENT')); export const removeComponent = createAction(getAction('REMOVE_COMPONENT')); export const onPropChange = createAction(getAction('ON_PROP_CHANGE')); -export const resetComponentState = createAction(getAction('RESET_COMPONENT_STATE')); +export const resetComponentState = createAction( + getAction('RESET_COMPONENT_STATE') +); export function updateProps(payload) { return (dispatch, getState) => { diff --git a/dash/dash-renderer/src/wrapper/DashWrapper.tsx b/dash/dash-renderer/src/wrapper/DashWrapper.tsx index 43fccdb2c3..80f973ba91 100644 --- a/dash/dash-renderer/src/wrapper/DashWrapper.tsx +++ b/dash/dash-renderer/src/wrapper/DashWrapper.tsx @@ -21,7 +21,12 @@ import {useSelector, useDispatch, batch} from 'react-redux'; import ComponentErrorBoundary from '../components/error/ComponentErrorBoundary.react'; import {DashLayoutPath, UpdatePropsPayload} from '../types/component'; import {DashConfig} from '../config'; -import {notifyObservers, onError, updateProps, resetComponentState} from '../actions'; +import { + notifyObservers, + onError, + updateProps, + resetComponentState +} from '../actions'; import {getWatchedKeys, stringifyId} from '../actions/dependencies'; import { createElement, @@ -91,9 +96,11 @@ function DashWrapper({ delete memoizedKeys.current[renderH]; } // Reset hashes and layout for this component and all descendants - dispatch(resetComponentState({ - itempath: componentPath, - })); + dispatch( + resetComponentState({ + itempath: componentPath + }) + ); } else { newRender.current = false; } From fd25ea8484eb8c4ec8587b864fea9a472caa5053 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 20 Jan 2026 21:04:15 -0500 Subject: [PATCH 080/297] fixing issue with bad setState --- .../dash-renderer/src/wrapper/DashWrapper.tsx | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/dash/dash-renderer/src/wrapper/DashWrapper.tsx b/dash/dash-renderer/src/wrapper/DashWrapper.tsx index 80f973ba91..8a017ed09d 100644 --- a/dash/dash-renderer/src/wrapper/DashWrapper.tsx +++ b/dash/dash-renderer/src/wrapper/DashWrapper.tsx @@ -1,4 +1,10 @@ -import React, {useCallback, MutableRefObject, useRef, useMemo} from 'react'; +import React, { + useCallback, + MutableRefObject, + useRef, + useMemo, + useEffect +} from 'react'; import { path, concat, @@ -95,12 +101,6 @@ function DashWrapper({ if (renderH in memoizedKeys.current) { delete memoizedKeys.current[renderH]; } - // Reset hashes and layout for this component and all descendants - dispatch( - resetComponentState({ - itempath: componentPath - }) - ); } else { newRender.current = false; } @@ -445,6 +445,16 @@ function DashWrapper({ return props; }; + useEffect(() => { + if (_newRender) { + dispatch( + resetComponentState({ + itempath: componentPath + }) + ); + } + }, [_newRender]); + const hydrateFunc = () => { if (newRender.current) { renderComponent = _passedComponent; From dc2e3ad2693426326d8f58f7f0442502b3db4eb6 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 20 Jan 2026 21:04:47 -0500 Subject: [PATCH 081/297] fixing for lint --- dash/dash-renderer/src/reducers/reducer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/dash-renderer/src/reducers/reducer.js b/dash/dash-renderer/src/reducers/reducer.js index b9704c96b7..5952bab271 100644 --- a/dash/dash-renderer/src/reducers/reducer.js +++ b/dash/dash-renderer/src/reducers/reducer.js @@ -50,7 +50,7 @@ const layoutHashes = (state = {}, action) => { state ); } else if (action.type === 'RESET_COMPONENT_STATE') { - const { itempath } = action.payload; + const {itempath} = action.payload; if (itempath) { const prefixStr = stringifyPath(itempath); // Remove all hashes for keys starting with prefixStr From 316b9ac9b303cca21eb46200a910e21391783346 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 20 Jan 2026 21:28:30 -0500 Subject: [PATCH 082/297] fix for lint --- dash/dash-renderer/src/reducers/reducer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/dash-renderer/src/reducers/reducer.js b/dash/dash-renderer/src/reducers/reducer.js index 5952bab271..759c198989 100644 --- a/dash/dash-renderer/src/reducers/reducer.js +++ b/dash/dash-renderer/src/reducers/reducer.js @@ -59,7 +59,7 @@ const layoutHashes = (state = {}, action) => { ([key]) => !key.startsWith(prefixStr) ) ); - }; + } } return state; }; From 3e22e930cc55ceda6a26a1c2e8705b2f7a4d70f2 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sat, 24 Jan 2026 06:12:26 -0500 Subject: [PATCH 083/297] Update dash/backends/_utils.py Co-authored-by: Philippe Duval --- dash/backends/_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/backends/_utils.py b/dash/backends/_utils.py index 0a5f4b0e76..1191d21038 100644 --- a/dash/backends/_utils.py +++ b/dash/backends/_utils.py @@ -94,7 +94,7 @@ def format_traceback_html(error, error_handling_mode, title, backend):
- The debugger caught an exception in your ASGI application. You can now + The debugger caught an exception in your Dash application. You can now look at the traceback which led to the error.
From f5dfc07896fb359ab366a669b2164602433fd24e Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sat, 24 Jan 2026 06:25:26 -0500 Subject: [PATCH 084/297] updates for formatting --- dash/_callback.py | 3 +-- dash/_configs.py | 1 + dash/dash.py | 32 +++++++++++++++++++------------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/dash/_callback.py b/dash/_callback.py index 3f3904cf18..d203f72f5b 100644 --- a/dash/_callback.py +++ b/dash/_callback.py @@ -182,7 +182,6 @@ def callback( background_spec: Any = None - config_prevent_initial_callbacks = _kwargs.pop( "config_prevent_initial_callbacks", False ) @@ -694,7 +693,7 @@ def add_context(*args, **kwargs): args, kwargs, inputs_state_indices, has_output, insert_output ) - response: dict = {"multi": True} # type: ignore + response: dict = {"multi": True} # type: ignore jsonResponse: Optional[str] = None try: if background is not None: diff --git a/dash/_configs.py b/dash/_configs.py index c4ff8d59e6..225c604842 100644 --- a/dash/_configs.py +++ b/dash/_configs.py @@ -1,5 +1,6 @@ from ._utils import get_root_path import os + # noinspection PyCompatibility from . import exceptions from ._utils import AttributeDict diff --git a/dash/dash.py b/dash/dash.py index a65545f48d..7e1a972d09 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -211,6 +211,7 @@ def _do_skip(error): return "".join(traceback.format_exception(type(error), error, _do_skip(error))) + # Singleton signal to not update an output, alternative to PreventUpdate no_update = _callback.NoUpdate() # pylint: disable=protected-access @@ -723,7 +724,6 @@ def _handle_error(_): """Handle a halted callback and return an empty 204 response.""" return "", 204 - # To-Do add error handlers for these two scenarios # add handler for halted callbacks # self.backend.before_request(_handle_error) @@ -2395,10 +2395,13 @@ async def router_async(): Output(_ID_STORE, "data"), inputs=inputs, prevent_initial_call=True, - hidden=True,) + hidden=True, + ) async def update(pathname_, search_, **states): query_parameters = _parse_query_string(search_) - page, path_variables = _path_to_page(self.strip_relative_path(pathname_)) + page, path_variables = _path_to_page( + self.strip_relative_path(pathname_) + ) if page == {}: for module, page in _pages.PAGE_REGISTRY.items(): if module.split(".")[-1] == "not_found_404": @@ -2427,16 +2430,17 @@ async def update(pathname_, search_, **states): _validate.validate_registry(_pages.PAGE_REGISTRY) if not self.config.suppress_callback_exceptions: + async def get_layouts(): return [ await execute_async_function(page["layout"]) - if callable(page["layout"]) else page["layout"] + if callable(page["layout"]) + else page["layout"] for page in _pages.PAGE_REGISTRY.values() ] + layouts = await get_layouts() - layouts += [ - self.layout() if callable(self.layout) else self.layout - ] + layouts += [self.layout() if callable(self.layout) else self.layout] self.validation_layout = html.Div(layouts) if _ID_CONTENT not in self.validation_layout: raise Exception("`dash.page_container` not found in the layout") @@ -2468,10 +2472,13 @@ def router_sync(): Output(_ID_STORE, "data"), inputs=inputs, prevent_initial_call=True, - hidden=True,) + hidden=True, + ) def update(pathname_, search_, **states): query_parameters = _parse_query_string(search_) - page, path_variables = _path_to_page(self.strip_relative_path(pathname_)) + page, path_variables = _path_to_page( + self.strip_relative_path(pathname_) + ) if page == {}: for module, page in _pages.PAGE_REGISTRY.items(): if module.split(".")[-1] == "not_found_404": @@ -2499,14 +2506,13 @@ def update(pathname_, search_, **states): if not self.config.suppress_callback_exceptions: layout = self.layout if not isinstance(layout, list): - layout = [ - self.layout() if callable(self.layout) else self.layout - ] + layout = [self.layout() if callable(self.layout) else self.layout] self.validation_layout = html.Div( [ page["layout"]() if callable(page["layout"]) else page["layout"] for page in _pages.PAGE_REGISTRY.values() - ] + layout + ] + + layout ) if _ID_CONTENT not in self.validation_layout: raise Exception("`dash.page_container` not found in the layout") From 907aba294827cdd9851ad8ad8471e1d72c5900ac Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sat, 24 Jan 2026 06:34:11 -0500 Subject: [PATCH 085/297] adjusting favicon to be consistent between all and using `make_response` instead of splitting it out --- dash/backends/_fastapi.py | 5 ----- dash/backends/_flask.py | 5 ----- dash/backends/_quart.py | 7 ------- dash/dash.py | 7 ++++++- 4 files changed, 6 insertions(+), 18 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 3de76f7b42..1240772b2d 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -393,11 +393,6 @@ async def _dispatch(request: Request): return _dispatch - def _serve_default_favicon(self): - return Response( - content=pkgutil.get_data("dash", "favicon.ico"), media_type="image/x-icon" - ) - def register_timing_hooks(self, first_run: bool): if not first_run: return diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index 75e16371f5..d33819fd62 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -257,11 +257,6 @@ async def _dispatch_async(): return _dispatch_async return _dispatch - def _serve_default_favicon(self): - return Response( - pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" - ) - def register_timing_hooks(self, _first_run: bool): # Define timing hooks inside method scope and register them def _before_request() -> None: diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 11af4bc169..6d61ee741b 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -321,13 +321,6 @@ async def sync_view_func(*args, **kwargs): route, endpoint=endpoint, view_func=view_func, methods=methods ) - def _serve_default_favicon(self): - if Response is None: - raise RuntimeError("Quart not installed; cannot generate Response") - return Response( - pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" - ) - def enable_compression(self) -> None: try: import quart_compress # pylint: disable=import-outside-toplevel diff --git a/dash/dash.py b/dash/dash.py index 7e1a972d09..181bdd0030 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -747,6 +747,11 @@ def _add_url(self, name: str, view_func: RouteCallable, methods=("GET",)) -> Non ) self.routes.append(full_name) + def _serve_default_favicon(self): + return self.backend.make_response( + pkgutil.get_data("dash", "favicon.ico"), content_type="image/x-icon" + ) + def _setup_routes(self): self.backend.setup_component_suites(self) self._add_url("_dash-layout", self.serve_layout) @@ -759,7 +764,7 @@ def _setup_routes(self): self._add_url("_reload-hash", self.serve_reload_hash) self._add_url( "_favicon.ico", - self.backend._serve_default_favicon, # pylint: disable=protected-access + self._serve_default_favicon, # pylint: disable=protected-access ) if self.config.health_endpoint is not None: self._add_url(self.config.health_endpoint, self.serve_health) From 9852bf61fbbe40e35dee0d6bec933a9c3c8df474 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sat, 24 Jan 2026 06:38:34 -0500 Subject: [PATCH 086/297] renaming `dispatch` to `serve_callback` --- dash/backends/_fastapi.py | 2 +- dash/backends/_flask.py | 2 +- dash/backends/_quart.py | 2 +- dash/dash.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 1240772b2d..33705e85b9 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -368,7 +368,7 @@ def add_redirect_rule(self, app, fullname, path): include_in_schema=False, ) - def dispatch(self, dash_app: Dash): + def serve_callback(self, dash_app: Dash): async def _dispatch(request: Request): # pylint: disable=protected-access body = await request.json() diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index d33819fd62..396c020e6b 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -216,7 +216,7 @@ def add_redirect_rule(self, app, fullname, path): ) # pylint: disable=unused-argument - def dispatch(self, dash_app: Dash): + def serve_callback(self, dash_app: Dash): def _dispatch(): body = request.get_json() # pylint: disable=protected-access diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 6d61ee741b..72c0caeecc 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -258,7 +258,7 @@ def add_redirect_rule(self, app, fullname, path): ) # pylint: disable=unused-argument - def dispatch(self, dash_app: Dash): # type: ignore[name-defined] Quart always async + def serve_callback(self, dash_app: Dash): # type: ignore[name-defined] Quart always async async def _dispatch(): adapter = QuartRequestAdapter() body = await adapter.get_json() diff --git a/dash/dash.py b/dash/dash.py index 181bdd0030..676803c6e1 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -758,7 +758,7 @@ def _setup_routes(self): self._add_url("_dash-dependencies", self.dependencies) self._add_url( "_dash-update-component", - self.backend.dispatch(self), + self.backend.serve_callback(self), ["POST"], ) self._add_url("_reload-hash", self.serve_reload_hash) From d961899475f06d4cde3ba5d885e9cc91aa26bbc3 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sat, 24 Jan 2026 06:41:02 -0500 Subject: [PATCH 087/297] adding a config description for `debug=True` --- dash/backends/_fastapi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 33705e85b9..62b8db8f6a 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -84,6 +84,7 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: # # Internal config helpers (local to this file) +# This is used to persist dev tools config between reloads, since uvicorn runs a new process _CONFIG_PATH = os.path.join(os.path.dirname(__file__), "dash_config.json") From 8f038756d98c523246db1a14aaac738bce2e8b87 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sat, 24 Jan 2026 07:08:13 -0500 Subject: [PATCH 088/297] fastapi requires `server` to be defined --- dash/backends/_fastapi.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 62b8db8f6a..d88a54bed7 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -249,10 +249,10 @@ def run(self, dash_app: Dash, host, port, debug, **kwargs): if kwargs.get("reload"): # Dynamically determine the module name from the file path file_path = frame.filename - spec = spec_from_file_location("app", file_path) - module_name = spec.name if spec and getattr(spec, "name", None) else "app" + rel_path = os.path.relpath(file_path, os.getcwd()) + module_name = os.path.splitext(rel_path)[0].replace(os.sep, ".") uvicorn.run( - f"{module_name}:app.server", + f"{module_name}:server", host=host, port=port, **kwargs, From c87e1a767a47ffb14a13a0b947febc020410ab5a Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sat, 24 Jan 2026 07:21:35 -0500 Subject: [PATCH 089/297] changing import errors --- dash/backends/_fastapi.py | 17 +++-------------- dash/backends/_quart.py | 9 +++------ 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index d88a54bed7..aa5b75768e 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -22,20 +22,9 @@ from starlette.types import ASGIApp, Scope, Receive, Send import uvicorn except ImportError: - FastAPI = None - Request = None - Response = None - Body = None - JSONResponse = None - RedirectResponse = None - StaticFiles = None - StarletteResponse = None - MutableHeaders = None - ASGIApp = None - Scope = None - Receive = None - Send = None - uvicorn = None + raise ImportError( + "All dependencies not installed. Please install it with `dash[fastapi]` to use the FastAPI backend." + ) from None from dash.fingerprint import check_fingerprint from dash import _validate diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 72c0caeecc..911d228e21 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -22,12 +22,9 @@ redirect, ) except ImportError: - Quart = None - Response = None - jsonify = None - request = None - Blueprint = None - quart_g = None + raise ImportError( + "All dependencies not installed. Please install it with `dash[quart]` to use the Quart backend." + ) from None from dash.exceptions import PreventUpdate, InvalidResourceError from dash.fingerprint import check_fingerprint From cad3cbaab2c5ede4511e8e0ea300f1af562ce12c Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Sat, 24 Jan 2026 07:46:57 -0500 Subject: [PATCH 090/297] making the path name for the config file more dynamic in order to not replace --- dash/backends/_fastapi.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index aa5b75768e..eae11e8b16 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -71,31 +71,25 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: # finally: reset_current_request(token) - -# Internal config helpers (local to this file) -# This is used to persist dev tools config between reloads, since uvicorn runs a new process -_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "dash_config.json") - - -def _save_config(config): - with open(_CONFIG_PATH, "w", encoding="utf-8") as f: +def _save_config(config_path, config): + with open(config_path, "w", encoding="utf-8") as f: json.dump(config, f) -def _load_config(): +def _load_config(config_path): resp = {"debug": False} try: - if os.path.exists(_CONFIG_PATH): - with open(_CONFIG_PATH, "r", encoding="utf-8") as f: + if os.path.exists(config_path): + with open(config_path, "r", encoding="utf-8") as f: resp = json.load(f) except (json.JSONDecodeError, OSError): pass # ignore errors return resp -def _remove_config(): +def _remove_config(config_path): try: - os.remove(_CONFIG_PATH) + os.remove(config_path) except FileNotFoundError: pass @@ -107,6 +101,14 @@ def __init__(self, server: FastAPI): self.error_handling_mode = "ignore" self.request_adapter = FastAPIRequestAdapter self._before_request_funcs = [] + + fname = inspect.stack()[2] + file_path = fname.filename + rel_path = os.path.relpath(file_path, os.getcwd()) + module_name = os.path.splitext(rel_path)[0].replace(os.sep, ".") + # Internal config helpers (local to this file) + # This is used to persist dev tools config between reloads, since uvicorn runs a new process + self._CONFIG_PATH = os.path.join(os.path.dirname(file_path), f"_{module_name}_dash_config.json") super().__init__() def __call__(self, *args: Any, **kwargs: Any): @@ -169,12 +171,12 @@ async def index(_request: Request): def setup_catchall(self, dash_app: Dash): @self.server.on_event("shutdown") def cleanup_config(): - _remove_config() + _remove_config(self._CONFIG_PATH) @self.server.on_event("startup") def _setup_catchall(): dash_app.enable_dev_tools( - **_load_config(), first_run=False + **_load_config(self._CONFIG_PATH), first_run=False ) # do this to make sure dev tools are enabled async def catchall(_request: Request): @@ -231,7 +233,7 @@ def run(self, dash_app: Dash, host, port, debug, **kwargs): {"debug": debug} if debug else {"debug": False}, **{f"dev_tools_{k}": v for k, v in dev_tools.items()}, ) - _save_config(config) + _save_config(self._CONFIG_PATH, config) if debug: if kwargs.get("reload") is None: kwargs["reload"] = True From ee1e6116757ca1441be17946b557397f75e339b8 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Mon, 26 Jan 2026 10:11:41 -0500 Subject: [PATCH 091/297] Update dash/backends/_quart.py Co-authored-by: Philippe Duval --- dash/backends/_quart.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 911d228e21..5abda7e30e 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -21,10 +21,10 @@ has_request_context, redirect, ) -except ImportError: +except ImportError as _err: raise ImportError( "All dependencies not installed. Please install it with `dash[quart]` to use the Quart backend." - ) from None + ) from _err from dash.exceptions import PreventUpdate, InvalidResourceError from dash.fingerprint import check_fingerprint From 476d1dd4bb3562c22dbaf733fd0b4311b7743be5 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Mon, 26 Jan 2026 11:31:57 -0500 Subject: [PATCH 092/297] adjustments for fastapi to use a controllable subprocess vs running with uvicorn, this allows for unloading the config file properly --- dash/backends/_fastapi.py | 66 ++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index eae11e8b16..c21cf67473 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -12,6 +12,7 @@ from importlib.util import spec_from_file_location import json import os +import subprocess try: from fastapi import FastAPI, Request, Response, Body @@ -71,6 +72,7 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: # finally: reset_current_request(token) + def _save_config(config_path, config): with open(config_path, "w", encoding="utf-8") as f: json.dump(config, f) @@ -104,11 +106,16 @@ def __init__(self, server: FastAPI): fname = inspect.stack()[2] file_path = fname.filename - rel_path = os.path.relpath(file_path, os.getcwd()) - module_name = os.path.splitext(rel_path)[0].replace(os.sep, ".") - # Internal config helpers (local to this file) - # This is used to persist dev tools config between reloads, since uvicorn runs a new process - self._CONFIG_PATH = os.path.join(os.path.dirname(file_path), f"_{module_name}_dash_config.json") + + # Manually build the config directory path + home_dir = os.path.expanduser("~") + config_dir = os.path.join(home_dir, ".local", "share", "plotly-dash-configs") + os.makedirs(config_dir, exist_ok=True) + + # Hash the file path for a unique config filename + hash_digest = hashlib.sha256(file_path.encode("utf-8")).hexdigest() + config_filename = f"{hash_digest}.json" + self._CONFIG_PATH = os.path.join(config_dir, config_filename) super().__init__() def __call__(self, *args: Any, **kwargs: Any): @@ -117,6 +124,9 @@ def __call__(self, *args: Any, **kwargs: Any): return self.server(*args, **kwargs) raise TypeError("FastAPI app must be called with (scope, receive, send)") + def _cleanup_config(self): + _remove_config(self._CONFIG_PATH) + @staticmethod def create_app(name: str = "__main__", config: Dict[str, Any] | None = None): app = FastAPI() @@ -169,10 +179,6 @@ async def index(_request: Request): dash_app._add_url("", index, methods=["GET"]) def setup_catchall(self, dash_app: Dash): - @self.server.on_event("shutdown") - def cleanup_config(): - _remove_config(self._CONFIG_PATH) - @self.server.on_event("startup") def _setup_catchall(): dash_app.enable_dev_tools( @@ -228,28 +234,38 @@ def has_request_context(self) -> bool: def run(self, dash_app: Dash, host, port, debug, **kwargs): frame = inspect.stack()[2] - dev_tools = dash_app._dev_tools # pylint: disable=protected-access + dev_tools = dash_app._dev_tools config = dict( {"debug": debug} if debug else {"debug": False}, **{f"dev_tools_{k}": v for k, v in dev_tools.items()}, ) _save_config(self._CONFIG_PATH, config) - if debug: - if kwargs.get("reload") is None: - kwargs["reload"] = True + if debug and kwargs.get("reload") is None: + kwargs["reload"] = True + + file_path = frame.filename + rel_path = os.path.relpath(file_path, os.getcwd()) + module_name = os.path.splitext(rel_path)[0].replace(os.sep, ".") + uvicorn_args = [ + sys.executable, + "-m", + "uvicorn", + f"{module_name}:server", + "--host", + str(host), + "--port", + str(port), + ] if kwargs.get("reload"): - # Dynamically determine the module name from the file path - file_path = frame.filename - rel_path = os.path.relpath(file_path, os.getcwd()) - module_name = os.path.splitext(rel_path)[0].replace(os.sep, ".") - uvicorn.run( - f"{module_name}:server", - host=host, - port=port, - **kwargs, - ) - else: - uvicorn.run(self.server, host=host, port=port, **kwargs) + uvicorn_args.append("--reload") + + # Add any other kwargs as CLI args if needed + + try: + proc = subprocess.Popen(uvicorn_args, env=os.environ.copy()) + proc.wait() + finally: + self._cleanup_config() def make_response( self, From 1d26d72c75900ce615a464337d508b630fb6cb47 Mon Sep 17 00:00:00 2001 From: philippe Date: Mon, 26 Jan 2026 11:44:39 -0500 Subject: [PATCH 093/297] fix dcc build --- components/dash-core-components/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dash-core-components/package.json b/components/dash-core-components/package.json index 063fe6d661..fc4d8a967f 100644 --- a/components/dash-core-components/package.json +++ b/components/dash-core-components/package.json @@ -101,6 +101,6 @@ "react-dom": "16 - 19" }, "browserslist": [ - "last 9 years and not dead" + "last 10 years and not dead" ] } From b3a47bd58719887e09435ce841ae4b83f46f0b80 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 5 Feb 2026 11:14:56 -0500 Subject: [PATCH 094/297] fix request_adapter calls --- dash/_callback.py | 22 ++++++++-------------- dash/_validate.py | 4 ++-- dash/backends/__init__.py | 4 ++-- dash/dash.py | 9 ++++----- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/dash/_callback.py b/dash/_callback.py index 3684247110..6895623a74 100644 --- a/dash/_callback.py +++ b/dash/_callback.py @@ -1,15 +1,9 @@ -from typing import Callable, Optional, Any, List, Tuple, Union +from typing import Callable, Optional, Any, List, Tuple, Union, Dict from functools import wraps import collections import hashlib import inspect -from functools import wraps - -from typing import Callable, Optional, Any, List, Tuple, Union, Dict - -import asyncio - from .dependencies import ( handle_callback_args, handle_grouped_callback_args, @@ -363,7 +357,7 @@ def _initialize_context(args, kwargs, inputs_state_indices, has_output, insert_o def _get_callback_manager( kwargs: dict, background: dict -) -> Union[BaseBackgroundCallbackManager, None]: +) -> BaseBackgroundCallbackManager: """Set up the background callback and manage jobs.""" callback_manager = background.get( "manager", kwargs.get("background_callback_manager", None) @@ -379,7 +373,7 @@ def _get_callback_manager( " and store results on redis.\n" ) - adapter = backends.request_adapter() + adapter = backends.backend.request_adapter() old_job = adapter.args.getlist("oldJob") if hasattr(adapter.args, "getlist") else [] if old_job: @@ -439,7 +433,7 @@ def _setup_background_callback( def _progress_background_callback(response, callback_manager, background): progress_outputs = background.get("progress") - adapter = backends.request_adapter() + adapter = backends.backend.request_adapter() cache_key = adapter.args.get("cacheKey") if progress_outputs: @@ -457,7 +451,7 @@ def _update_background_callback( """Set up the background callback and manage jobs.""" callback_manager = _get_callback_manager(kwargs, background) - adapter = backends.request_adapter() + adapter = backends.backend.request_adapter() cache_key = adapter.args.get("cacheKey") if adapter else None job_id = adapter.args.get("job") if adapter else None @@ -479,7 +473,7 @@ def _handle_rest_background_callback( multi, has_update=False, ): - adapter = backends.request_adapter() + adapter = backends.backend.request_adapter() cache_key = adapter.args.get("cacheKey") if adapter else None job_id = adapter.args.get("job") if adapter else None # Must get job_running after get_result since get_results terminates it. @@ -697,7 +691,7 @@ def add_context(*args, **kwargs): jsonResponse: Optional[str] = None try: if background is not None: - adapter = backends.request_adapter() + adapter = backends.backend.request_adapter() if not (adapter and adapter.args.get("cacheKey")): return _setup_background_callback( kwargs, @@ -769,7 +763,7 @@ async def async_add_context(*args, **kwargs): try: if background is not None: - adapter = backends.request_adapter() + adapter = backends.backend.request_adapter() if not (adapter and adapter.args.get("cacheKey")): return _setup_background_callback( kwargs, diff --git a/dash/_validate.py b/dash/_validate.py index ceddb74030..bb76f896e1 100644 --- a/dash/_validate.py +++ b/dash/_validate.py @@ -590,14 +590,14 @@ def _valid(out): def check_async(use_async): if use_async is None: try: - import asgiref # pylint: disable=unused-import, import-outside-toplevel # noqa + import asgiref # type: ignore[import-not-found] # pylint: disable=unused-import, import-outside-toplevel # noqa use_async = True except ImportError: pass elif use_async: try: - import asgiref # pylint: disable=unused-import, import-outside-toplevel # noqa + import asgiref # type: ignore[import-not-found] # pylint: disable=unused-import, import-outside-toplevel # noqa except ImportError as exc: raise Exception( "You are trying to use dash[async] without having installed the requirements please install via: `pip install dash[async]`" diff --git a/dash/backends/__init__.py b/dash/backends/__init__.py index e8b007a50b..cde81b0fd4 100644 --- a/dash/backends/__init__.py +++ b/dash/backends/__init__.py @@ -43,7 +43,7 @@ def _is_flask_instance(obj): def _is_fastapi_instance(obj): try: # pylint: disable=import-outside-toplevel - from fastapi import FastAPI + from fastapi import FastAPI # type: ignore[import-not-found] return isinstance(obj, FastAPI) except ImportError: @@ -53,7 +53,7 @@ def _is_fastapi_instance(obj): def _is_quart_instance(obj): try: # pylint: disable=import-outside-toplevel - from quart import Quart + from quart import Quart # type: ignore[import-not-found] return isinstance(obj, Quart) except ImportError: diff --git a/dash/dash.py b/dash/dash.py index 7949540dfc..ce39a3f446 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -20,8 +20,6 @@ import traceback -from importlib_metadata import version as _get_distribution_version - from dash import dcc from dash import html from dash import dash_table @@ -53,7 +51,6 @@ convert_to_AttributeDict, gen_salt, hooks_to_js_object, - parse_version, get_caller_name, get_root_path, ) @@ -1182,7 +1179,7 @@ def index(self, *_args, **_kwargs): renderer = self._generate_renderer() title = self.title # Refactored: direct access to global request adapter - request = backends.request_adapter() + request = backends.backend.request_adapter() if self.use_pages and self.config.include_pages_meta and request: metas = _page_meta_tags(self, request) + metas @@ -1398,7 +1395,7 @@ def _inputs_to_vals(self, inputs): # pylint: disable=R0915 def _initialize_context(self, body): """Initialize the global context for the request.""" - adapter = backends.request_adapter() + adapter = backends.backend.request_adapter() g = AttributeDict({}) g.inputs_list = body.get("inputs", []) g.states_list = body.get("state", []) @@ -2445,6 +2442,7 @@ async def get_layouts(): ] layouts = await get_layouts() + # pylint: disable=not-callable layouts += [self.layout() if callable(self.layout) else self.layout] self.validation_layout = html.Div(layouts) if _ID_CONTENT not in self.validation_layout: @@ -2512,6 +2510,7 @@ def update(pathname_, search_, **states): if not self.config.suppress_callback_exceptions: layout = self.layout if not isinstance(layout, list): + # pylint: disable=not-callable layout = [self.layout() if callable(self.layout) else self.layout] self.validation_layout = html.Div( [ From ef9ff4fed3bee47e2cb203e60dc0b07034b04b43 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 5 Feb 2026 11:24:56 -0500 Subject: [PATCH 095/297] import/lint fixes --- dash/_configs.py | 3 ++- dash/backends/_fastapi.py | 8 +++----- dash/backends/_flask.py | 9 ++++++--- dash/backends/_quart.py | 7 +++++-- dash/backends/base_server.py | 4 ++-- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/dash/_configs.py b/dash/_configs.py index 225c604842..107b8308f5 100644 --- a/dash/_configs.py +++ b/dash/_configs.py @@ -1,6 +1,7 @@ -from ._utils import get_root_path import os +from ._utils import get_root_path + # noinspection PyCompatibility from . import exceptions from ._utils import AttributeDict diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index c21cf67473..8ebf38ed96 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -9,7 +9,6 @@ import inspect import pkgutil import time -from importlib.util import spec_from_file_location import json import os import subprocess @@ -21,11 +20,10 @@ from starlette.responses import Response as StarletteResponse from starlette.datastructures import MutableHeaders from starlette.types import ASGIApp, Scope, Receive, Send - import uvicorn -except ImportError: +except ImportError as _err: raise ImportError( "All dependencies not installed. Please install it with `dash[fastapi]` to use the FastAPI backend." - ) from None + ) from _err from dash.fingerprint import check_fingerprint from dash import _validate @@ -234,7 +232,7 @@ def has_request_context(self) -> bool: def run(self, dash_app: Dash, host, port, debug, **kwargs): frame = inspect.stack()[2] - dev_tools = dash_app._dev_tools + dev_tools = dash_app._dev_tools # pylint-disable=W0212 config = dict( {"debug": debug} if debug else {"debug": False}, **{f"dev_tools_{k}": v for k, v in dev_tools.items()}, diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index 396c020e6b..f1494a8335 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -1,8 +1,5 @@ from __future__ import annotations -from contextvars import copy_context -from importlib_metadata import version as _get_distribution_version -from typing import TYPE_CHECKING, Any, Callable, Dict import asyncio import pkgutil import sys @@ -10,6 +7,12 @@ import time import inspect import traceback + +from contextvars import copy_context +from typing import TYPE_CHECKING, Any, Callable, Dict + +from importlib_metadata import version as _get_distribution_version + from flask import ( Flask, Blueprint, diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 5abda7e30e..3a9df59578 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -1,14 +1,17 @@ from __future__ import annotations -from importlib_metadata import version as _get_distribution_version -from contextvars import copy_context + import typing as _t import mimetypes import inspect import pkgutil import time import sys + +from contextvars import copy_context from typing import Any +from importlib_metadata import version as _get_distribution_version + # Attempt top-level Quart imports; allow absence if user not using quart backend try: from quart import ( diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index f571669bee..fc149b3847 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Any, Dict +from typing import Any, Dict, Type class RequestAdapter(ABC): @@ -71,7 +71,7 @@ class BaseDashServer(ABC): server_type: str server: Any config: Dict[str, Any] - request_adapter: RequestAdapter + request_adapter: Type[RequestAdapter] def __call__(self, *args, **kwargs) -> Any: # Default: WSGI From 25e1f453ac4d798872262c88e125c69ba7f1f1a1 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 5 Feb 2026 13:29:34 -0500 Subject: [PATCH 096/297] fix linting --- dash/_callback.py | 2 +- dash/backends/__init__.py | 4 +++- dash/backends/_fastapi.py | 23 ++++++++++++++--------- dash/backends/_flask.py | 5 ++--- dash/backends/_quart.py | 12 ++++++------ dash/backends/base_server.py | 18 +++++++++++++++--- dash/dash.py | 1 + 7 files changed, 42 insertions(+), 23 deletions(-) diff --git a/dash/_callback.py b/dash/_callback.py index 6895623a74..0ce4ee59a4 100644 --- a/dash/_callback.py +++ b/dash/_callback.py @@ -276,7 +276,7 @@ def insert_callback( no_output=False, optional=False, hidden=None, -): +) -> str: if prevent_initial_call is None: prevent_initial_call = config_prevent_initial_callbacks diff --git a/dash/backends/__init__.py b/dash/backends/__init__.py index cde81b0fd4..3a12e7939a 100644 --- a/dash/backends/__init__.py +++ b/dash/backends/__init__.py @@ -1,4 +1,6 @@ import importlib +from typing import Type + from .base_server import BaseDashServer @@ -12,7 +14,7 @@ } -def get_backend(name: str) -> BaseDashServer: +def get_backend(name: str) -> Type[BaseDashServer]: module_name, server_class = _backend_imports[name.lower()] try: module = importlib.import_module(module_name) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 8ebf38ed96..dfeb26e13c 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -94,13 +94,14 @@ def _remove_config(config_path): pass -class FastAPIDashServer(BaseDashServer): +class FastAPIDashServer(BaseDashServer[FastAPI]): def __init__(self, server: FastAPI): + super().__init__(server) self.server_type = "fastapi" - self.server: FastAPI = server self.error_handling_mode = "ignore" self.request_adapter = FastAPIRequestAdapter self._before_request_funcs = [] + self._before_middleware_added = False fname = inspect.stack()[2] file_path = fname.filename @@ -114,7 +115,6 @@ def __init__(self, server: FastAPI): hash_digest = hashlib.sha256(file_path.encode("utf-8")).hexdigest() config_filename = f"{hash_digest}.json" self._CONFIG_PATH = os.path.join(config_dir, config_filename) - super().__init__() def __call__(self, *args: Any, **kwargs: Any): # ASGI: (scope, receive, send) @@ -232,7 +232,7 @@ def has_request_context(self) -> bool: def run(self, dash_app: Dash, host, port, debug, **kwargs): frame = inspect.stack()[2] - dev_tools = dash_app._dev_tools # pylint-disable=W0212 + dev_tools = dash_app._dev_tools # pylint: disable=W0212 config = dict( {"debug": debug} if debug else {"debug": False}, **{f"dev_tools_{k}": v for k, v in dev_tools.items()}, @@ -260,6 +260,7 @@ def run(self, dash_app: Dash, host, port, debug, **kwargs): # Add any other kwargs as CLI args if needed try: + # pylint: disable=R1732 proc = subprocess.Popen(uvicorn_args, env=os.environ.copy()) proc.wait() finally: @@ -293,7 +294,7 @@ async def middleware(request, call_next): return response except PreventUpdate: return Response(status_code=204) - except Exception as e: + except Exception as e: # pylint: disable=W0718 if self.error_handling_mode in ["raise", "prune"]: tb = self._get_traceback(None, e) return Response(content=tb, media_type="text/html", status_code=500) @@ -465,14 +466,18 @@ async def view_func(_request: Request, body: dict = Body(...)): ) def enable_compression(self) -> None: - from fastapi.middleware.gzip import GZipMiddleware + from fastapi.middleware.gzip import ( + GZipMiddleware, + ) # pylint: disable=import-outside-toplevel self.server.add_middleware(GZipMiddleware, minimum_size=500) - config = _load_config() + config = _load_config(self._CONFIG_PATH) if "COMPRESS_ALGORITHM" not in config: - config["COMPRESS_ALGORITHM"] = ["gzip"] + config["COMPRESS_ALGORITHM"] = [ + "gzip" + ] # pylint: disable=no-value-for-parameter - _save_config(config) + _save_config(self._CONFIG_PATH, config) class FastAPIRequestAdapter(RequestAdapter): diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index f1494a8335..ef31d81557 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -37,12 +37,11 @@ from dash import Dash -class FlaskDashServer(BaseDashServer): +class FlaskDashServer(BaseDashServer[Flask]): def __init__(self, server: Flask) -> None: - self.server: Flask = server + super().__init__(server) self.server_type = "flask" self.request_adapter = FlaskRequestAdapter - super().__init__() def __call__(self, *args: Any, **kwargs: Any): # Always WSGI diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 3a9df59578..2f7a07203d 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -33,18 +33,17 @@ from dash.fingerprint import check_fingerprint from dash._utils import parse_version from dash import _validate, Dash -from .base_server import BaseDashServer +from .base_server import BaseDashServer, RequestAdapter from ._utils import format_traceback_html -class QuartDashServer(BaseDashServer): +class QuartDashServer(BaseDashServer[Quart]): def __init__(self, server: Quart) -> None: + super().__init__(server) self.server_type = "quart" - self.server: Quart = server self.config = {} self.error_handling_mode = "ignore" self.request_adapter = QuartRequestAdapter - super().__init__() def __call__(self, *args: Any, **kwargs: Any): # type: ignore[name-defined] return self.server(*args, **kwargs) @@ -340,7 +339,7 @@ def enable_compression(self) -> None: ) from error -class QuartRequestAdapter: +class QuartRequestAdapter(RequestAdapter): def __init__(self) -> None: self._request = request # type: ignore[assignment] if self._request is None: @@ -396,5 +395,6 @@ def origin(self): def path(self): return self.request.path - async def get_json(self): + async def get_json(self): # pylint: disable=W0236 + # TODO consider using a sync wraper return await self.request.get_json() diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index fc149b3847..da0c920a37 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -1,5 +1,13 @@ from abc import ABC, abstractmethod -from typing import Any, Dict, Type +from typing import Any, Dict, Type, TypeVar, Generic, Protocol + + +class _ServerCallable(Protocol): # pylint: disable=too-few-public-methods + def __call__(self, *args: Any, **kwds: Any) -> Any: + raise NotImplementedError + + +ServerType = TypeVar("ServerType", bound=_ServerCallable) class RequestAdapter(ABC): @@ -67,12 +75,16 @@ def path(self) -> str: raise NotImplementedError() -class BaseDashServer(ABC): +class BaseDashServer(ABC, Generic[ServerType]): server_type: str - server: Any + server: ServerType config: Dict[str, Any] request_adapter: Type[RequestAdapter] + def __init__(self, server: ServerType) -> None: + super().__init__() + self.server = server + def __call__(self, *args, **kwargs) -> Any: # Default: WSGI return self.server(*args, **kwargs) diff --git a/dash/dash.py b/dash/dash.py index ce39a3f446..75cd57aa37 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -2301,6 +2301,7 @@ def run( host = host or "127.0.0.1" else: host = host or os.getenv("HOST", "127.0.0.1") + assert host port = port or os.getenv("PORT", "8050") proxy = proxy or os.getenv("DASH_PROXY") From 710c9d0c8c662565085a27dac1709f3aa4326d62 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 5 Feb 2026 13:56:54 -0500 Subject: [PATCH 097/297] add missing backend abstract method --- dash/backends/_fastapi.py | 3 ++- dash/backends/base_server.py | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index dfeb26e13c..4d8d5ed5f3 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -466,9 +466,10 @@ async def view_func(_request: Request, body: dict = Body(...)): ) def enable_compression(self) -> None: + # pylint: disable=import-outside-toplevel from fastapi.middleware.gzip import ( GZipMiddleware, - ) # pylint: disable=import-outside-toplevel + ) self.server.add_middleware(GZipMiddleware, minimum_size=500) config = _load_config(self._CONFIG_PATH) diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index da0c920a37..8a7b25ad08 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -143,3 +143,11 @@ def jsonify(self, obj) -> Any: # pragma: no cover - interface @abstractmethod def enable_compression(self) -> None: # pragma: no cover - interface pass + + @abstractmethod + def register_prune_error_handler(self, secret: str, prune_errors: bool) -> None: + pass + + @abstractmethod + def register_timing_hooks(self, first_run: bool) -> None: + pass From 86272974f5dbb45b246331eccdcdc409e69584ac Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 5 Feb 2026 15:28:37 -0500 Subject: [PATCH 098/297] lint fix --- dash/backends/_fastapi.py | 3 ++- dash/backends/_quart.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 4d8d5ed5f3..75247c760f 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -126,6 +126,7 @@ def _cleanup_config(self): _remove_config(self._CONFIG_PATH) @staticmethod + # pylint: disable=W0613 def create_app(name: str = "__main__", config: Dict[str, Any] | None = None): app = FastAPI() @@ -466,7 +467,7 @@ async def view_func(_request: Request, body: dict = Body(...)): ) def enable_compression(self) -> None: - # pylint: disable=import-outside-toplevel + # pylint: disable=import-outside-toplevel,import-error from fastapi.middleware.gzip import ( GZipMiddleware, ) diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 2f7a07203d..9bd927d80c 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -190,6 +190,7 @@ def has_request_context(self) -> bool: raise RuntimeError("Quart not installed; cannot check request context") return has_request_context() + # pylint: disable=W0613 def run(self, dash_app: Dash, host: str, port: int, debug: bool, **kwargs: _t.Any): self.config = {"debug": debug, **kwargs} if debug else kwargs self.server.run(host=host, port=port, debug=debug, **kwargs) From c74278b0f9b463283a1df5c1397dd92cb7e30209 Mon Sep 17 00:00:00 2001 From: philippe Date: Fri, 6 Feb 2026 10:14:46 -0500 Subject: [PATCH 099/297] fix fastapi request middleware --- dash/backends/_fastapi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 75247c760f..142a90bb0a 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -215,7 +215,7 @@ def before_request(self, func: Callable[[], Any] | None): if func is not None: self._before_request_funcs.append(func) # Only add the middleware once - if not hasattr(self, "_before_middleware_added"): + if not self._before_middleware_added: self.server.add_middleware(CurrentRequestMiddleware) self.server.middleware("http")(self._make_before_middleware()) self._before_middleware_added = True From e7f46668eabfb8b3d2ac3c9a26d0dfb1ee08387c Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 6 Feb 2026 11:49:15 -0500 Subject: [PATCH 100/297] adjustment for failing test --- tests/integration/renderer/test_redraw.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/integration/renderer/test_redraw.py b/tests/integration/renderer/test_redraw.py index 4f1dc814e0..99d1141985 100644 --- a/tests/integration/renderer/test_redraw.py +++ b/tests/integration/renderer/test_redraw.py @@ -29,6 +29,11 @@ def on_click(_): dash_duo.wait_for_text_to_equal("#counter", "1") dash_duo.find_element("#redraw").click() - dash_duo.wait_for_text_to_equal("#counter", "2") + # dash_duo.wait_for_text_to_equal("#counter", "2") + # time.sleep(1) + # dash_duo.wait_for_text_to_equal("#counter", "2") + + ## the above was changed due to a mechanism change that generates a new React component, thus resetting the counter + dash_duo.wait_for_text_to_equal("#counter", "1") time.sleep(1) - dash_duo.wait_for_text_to_equal("#counter", "2") + dash_duo.wait_for_text_to_equal("#counter", "1") From 62946094edc1572dce3d57ed35ad9d64643ae61f Mon Sep 17 00:00:00 2001 From: philippe Date: Mon, 16 Feb 2026 13:20:48 -0500 Subject: [PATCH 101/297] fix backend tests --- dash/backends/_fastapi.py | 84 ++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 23 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 142a90bb0a..ae5faf6cdd 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -12,6 +12,7 @@ import json import os import subprocess +import threading try: from fastapi import FastAPI, Request, Response, Body @@ -20,6 +21,7 @@ from starlette.responses import Response as StarletteResponse from starlette.datastructures import MutableHeaders from starlette.types import ASGIApp, Scope, Receive, Send + import uvicorn except ImportError as _err: raise ImportError( "All dependencies not installed. Please install it with `dash[fastapi]` to use the FastAPI backend." @@ -242,30 +244,66 @@ def run(self, dash_app: Dash, host, port, debug, **kwargs): if debug and kwargs.get("reload") is None: kwargs["reload"] = True - file_path = frame.filename - rel_path = os.path.relpath(file_path, os.getcwd()) - module_name = os.path.splitext(rel_path)[0].replace(os.sep, ".") - uvicorn_args = [ - sys.executable, - "-m", - "uvicorn", - f"{module_name}:server", - "--host", - str(host), - "--port", - str(port), - ] - if kwargs.get("reload"): - uvicorn_args.append("--reload") - - # Add any other kwargs as CLI args if needed + # Check if we're running in a thread (e.g., from testing framework) + # If so, run uvicorn directly instead of spawning a subprocess + is_threaded = threading.current_thread() != threading.main_thread() - try: - # pylint: disable=R1732 - proc = subprocess.Popen(uvicorn_args, env=os.environ.copy()) - proc.wait() - finally: - self._cleanup_config() + if is_threaded: + # Running in a thread (testing context) - use uvicorn.run directly + # This allows the testing framework to control the server lifecycle + if kwargs.get("reload"): + kwargs["reload"] = True + try: + uvicorn.run(self.server, host=host, port=port, **kwargs) + finally: + self._cleanup_config() + else: + # Running in main thread (normal context) - use subprocess + file_path = frame.filename + rel_path = os.path.relpath(file_path, os.getcwd()) + + # Check if the file is outside the current working directory + if rel_path.startswith(".."): + # File is outside cwd, try to find the module name from sys.modules + module_name = None + for mod_name, mod in sys.modules.items(): + if hasattr(mod, "__file__") and mod.__file__: + if os.path.abspath(mod.__file__) == os.path.abspath(file_path): + module_name = mod_name + break + + # If we still can't find it, raise an error + if not module_name: + raise RuntimeError( + f"Cannot determine module name for {file_path}. " + "The file is outside the current working directory and not found in sys.modules. " + "Please ensure the FastAPI app is being run from a file within the current working directory." + ) + else: + # File is within cwd, use relative path + module_name = os.path.splitext(rel_path)[0].replace(os.sep, ".") + + uvicorn_args = [ + sys.executable, + "-m", + "uvicorn", + f"{module_name}:server", + "--host", + str(host), + "--port", + str(port), + ] + if kwargs.get("reload"): + uvicorn_args.append("--reload") + + # Add any other kwargs as CLI args if needed + + try: + # pylint: disable=R1732 + proc = subprocess.Popen(uvicorn_args, env=os.environ.copy()) + proc.wait() + finally: + self._cleanup_config() def make_response( self, From 58ad02fc6ebc3130011fa59228639ca681aff59d Mon Sep 17 00:00:00 2001 From: philippe Date: Tue, 17 Feb 2026 09:24:05 -0500 Subject: [PATCH 102/297] fix status code make_response --- dash/backends/_fastapi.py | 3 ++- dash/backends/_flask.py | 5 ++++- dash/backends/_quart.py | 5 ++++- dash/backends/base_server.py | 6 +++++- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index ae5faf6cdd..a27b338da4 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -310,13 +310,14 @@ def make_response( data: str | bytes | bytearray, mimetype: str | None = None, content_type: str | None = None, + status: int | None = None, ): headers = {} if mimetype: headers["content-type"] = mimetype if content_type: headers["content-type"] = content_type - return Response(content=data, headers=headers) + return Response(content=data, headers=headers, status_code=status or 200) def jsonify(self, obj: Any): return JSONResponse(content=obj) diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index ef31d81557..af18961b55 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -145,8 +145,11 @@ def make_response( data: str | bytes | bytearray, mimetype: str | None = None, content_type: str | None = None, + status: int | None = None, ): - return Response(data, mimetype=mimetype, content_type=content_type) + return Response( + data, mimetype=mimetype, content_type=content_type, status=status + ) def jsonify(self, obj: Any): return jsonify(obj) diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 9bd927d80c..0bc0afcce5 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -200,10 +200,13 @@ def make_response( data: str | bytes | bytearray, mimetype: str | None = None, content_type: str | None = None, + status=None, ): if Response is None: raise RuntimeError("Quart not installed; cannot generate Response") - return Response(data, mimetype=mimetype, content_type=content_type) + return Response( + data, mimetype=mimetype, content_type=content_type, status=status + ) def jsonify(self, obj): return jsonify(obj) diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index 8a7b25ad08..49c8596ce7 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -132,7 +132,11 @@ def run( @abstractmethod def make_response( - self, data, mimetype=None, content_type=None + self, + data, + mimetype=None, + content_type=None, + status=None, ) -> Any: # pragma: no cover - interface pass From 11166eed0d1241f6c254622ac87aab3b3b78a725 Mon Sep 17 00:00:00 2001 From: philippe Date: Tue, 17 Feb 2026 10:52:14 -0500 Subject: [PATCH 103/297] fix test number input --- .../tests/integration/input/test_number_input.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dash-core-components/tests/integration/input/test_number_input.py b/components/dash-core-components/tests/integration/input/test_number_input.py index 01deb79287..f16eb2c7b5 100644 --- a/components/dash-core-components/tests/integration/input/test_number_input.py +++ b/components/dash-core-components/tests/integration/input/test_number_input.py @@ -245,7 +245,7 @@ def test_inni010_valid_numbers(dash_dcc, ninput_app): (str(sys.float_info.max), float), (str(sys.float_info.min), float), ): - elem = dash_dcc.find_element("#input_false") + elem = dash_dcc.wait_for_element("#input_false") elem.send_keys(num) assert dash_dcc.wait_for_text_to_equal( "#div_false", str(op(num)) From 6d56c395376c028866b1b9f1db6e90c9fbb5e17e Mon Sep 17 00:00:00 2001 From: philippe Date: Tue, 17 Feb 2026 13:59:11 -0500 Subject: [PATCH 104/297] wait for input false first --- .../tests/integration/input/test_number_input.py | 1 + 1 file changed, 1 insertion(+) diff --git a/components/dash-core-components/tests/integration/input/test_number_input.py b/components/dash-core-components/tests/integration/input/test_number_input.py index f16eb2c7b5..e2ec647c69 100644 --- a/components/dash-core-components/tests/integration/input/test_number_input.py +++ b/components/dash-core-components/tests/integration/input/test_number_input.py @@ -238,6 +238,7 @@ def update_output(val): def test_inni010_valid_numbers(dash_dcc, ninput_app): dash_dcc.start_server(ninput_app) + elem = dash_dcc.wait_for_element("#input_false") for num, op in ( ("1.0", lambda x: int(float(x))), # limitation of js/json ("10e10", lambda x: int(float(x))), From 3209a63ef8e3986e0e49c4182672a38df220839d Mon Sep 17 00:00:00 2001 From: philippe Date: Tue, 17 Feb 2026 15:34:31 -0500 Subject: [PATCH 105/297] fix fastapi run to auto resolve instance --- dash/backends/_fastapi.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index a27b338da4..00c351cb38 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -119,10 +119,8 @@ def __init__(self, server: FastAPI): self._CONFIG_PATH = os.path.join(config_dir, config_filename) def __call__(self, *args: Any, **kwargs: Any): - # ASGI: (scope, receive, send) - if len(args) == 3 and isinstance(args[0], dict) and "type" in args[0]: - return self.server(*args, **kwargs) - raise TypeError("FastAPI app must be called with (scope, receive, send)") + # ASGI: pass through to FastAPI + return self.server(*args, **kwargs) def _cleanup_config(self): _remove_config(self._CONFIG_PATH) @@ -283,11 +281,33 @@ def run(self, dash_app: Dash, host, port, debug, **kwargs): # File is within cwd, use relative path module_name = os.path.splitext(rel_path)[0].replace(os.sep, ".") + # Find the Dash app variable name by inspecting the calling frame + dash_var_name = None + calling_frame = frame.frame + for var_name, var_value in calling_frame.f_locals.items(): + if var_value is dash_app: + dash_var_name = var_name + break + + # If not found in locals, check globals + if not dash_var_name: + for var_name, var_value in calling_frame.f_globals.items(): + if var_value is dash_app: + dash_var_name = var_name + break + + # Construct the app path - use .server to access the FastAPI instance + if dash_var_name: + app_path = f"{module_name}:{dash_var_name}.server" + else: + # Fallback to looking for 'server' variable (old behavior) + app_path = f"{module_name}:server" + uvicorn_args = [ sys.executable, "-m", "uvicorn", - f"{module_name}:server", + app_path, "--host", str(host), "--port", From 2e17d1132d243c1f89a23e68c70544eec3ba49cc Mon Sep 17 00:00:00 2001 From: philippe Date: Tue, 17 Feb 2026 15:53:47 -0500 Subject: [PATCH 106/297] Disable route logging for quart & fastapi --- dash/backends/_quart.py | 13 +++++++++ dash/dash.py | 27 ++++++++++++++----- .../backend_tests/test_preconfig_backends.py | 25 +++++++++++++++++ 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 0bc0afcce5..56f3253bac 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -7,6 +7,7 @@ import time import sys +from logging.config import dictConfig from contextvars import copy_context from typing import Any @@ -193,6 +194,18 @@ def has_request_context(self) -> bool: # pylint: disable=W0613 def run(self, dash_app: Dash, host: str, port: int, debug: bool, **kwargs: _t.Any): self.config = {"debug": debug, **kwargs} if debug else kwargs + if dash_app._dev_tools.silence_routes_logging: + dictConfig( + { + "version": 1, + "loggers": { + "quart.app": { + "level": "ERROR", + }, + }, + } + ) + self.server.run(host=host, port=port, debug=debug, **kwargs) def make_response( diff --git a/dash/dash.py b/dash/dash.py index 75cd57aa37..96ccf4dde6 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -1944,9 +1944,10 @@ def enable_dev_tools( # pylint: disable=too-many-branches env: ``DASH_HOT_RELOAD_MAX_RETRY`` :type dev_tools_hot_reload_max_retry: int - :param dev_tools_silence_routes_logging: Silence the `werkzeug` logger, - will remove all routes logging. Enabled with debugging by default - because hot reload hash checks generate a lot of requests. + :param dev_tools_silence_routes_logging: Silence the route logging for the + web server (werkzeug for Flask, hypercorn for Quart, uvicorn for FastAPI). + Enabled with debugging by default because hot reload hash checks generate + a lot of requests. env: ``DASH_SILENCE_ROUTES_LOGGING`` :type dev_tools_silence_routes_logging: bool @@ -1981,7 +1982,18 @@ def enable_dev_tools( # pylint: disable=too-many-branches ) if dev_tools.silence_routes_logging: - logging.getLogger("werkzeug").setLevel(logging.ERROR) + # Silence route logging based on backend type + backend_type = getattr(self.backend, "server_type", "flask") + if backend_type == "flask": + logging.getLogger("werkzeug").setLevel(logging.ERROR) + elif backend_type == "quart": + # Quart uses hypercorn as its ASGI server + logging.getLogger("hypercorn.access").setLevel(logging.ERROR) + logging.getLogger("hypercorn.error").setLevel(logging.ERROR) + elif backend_type == "fastapi": + # FastAPI uses uvicorn as its ASGI server + logging.getLogger("uvicorn.access").setLevel(logging.ERROR) + logging.getLogger("uvicorn.error").setLevel(logging.ERROR) if dev_tools.hot_reload: _reload = self._hot_reload @@ -2236,9 +2248,10 @@ def run( env: ``DASH_HOT_RELOAD_MAX_RETRY`` :type dev_tools_hot_reload_max_retry: int - :param dev_tools_silence_routes_logging: Silence the `werkzeug` logger, - will remove all routes logging. Enabled with debugging by default - because hot reload hash checks generate a lot of requests. + :param dev_tools_silence_routes_logging: Silence the route logging for the + web server (werkzeug for Flask, hypercorn for Quart, uvicorn for FastAPI). + Enabled with debugging by default because hot reload hash checks generate + a lot of requests. env: ``DASH_SILENCE_ROUTES_LOGGING`` :type dev_tools_silence_routes_logging: bool diff --git a/tests/backend_tests/test_preconfig_backends.py b/tests/backend_tests/test_preconfig_backends.py index 4c4ccc7083..3193305ee2 100644 --- a/tests/backend_tests/test_preconfig_backends.py +++ b/tests/backend_tests/test_preconfig_backends.py @@ -1,3 +1,4 @@ +import logging import pytest from dash import Dash, Input, Output, html, dcc @@ -215,3 +216,27 @@ def update_output_bg(value): "#output", f"Background typed: {backend.title()} BG Test" ) assert dash_duo.get_logs() == [] + + +@pytest.mark.parametrize( + "backend,expected_loggers", + [ + ("flask", ["werkzeug"]), + ("quart", ["hypercorn.access", "hypercorn.error"]), + ("fastapi", ["uvicorn.access", "uvicorn.error"]), + ], +) +def test_silence_routes_logging(backend, expected_loggers): + """Test that route logging is silenced for all backends when dev_tools_silence_routes_logging is enabled.""" + app = Dash(__name__, backend=backend) + app.layout = html.Div([html.Div(id="output", children="Test")]) + + # Enable dev tools with silence_routes_logging + app.enable_dev_tools(debug=True, dev_tools_silence_routes_logging=True) + + # Check that the expected loggers have been set to ERROR level + for logger_name in expected_loggers: + logger = logging.getLogger(logger_name) + assert ( + logger.level == logging.ERROR + ), f"Logger {logger_name} should be set to ERROR level for {backend} backend" From 2a2f45c6323cbd85e2ef9bc862b1b7954f799385 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 18 Feb 2026 09:02:22 -0500 Subject: [PATCH 107/297] fix test ini --- .../tests/integration/input/conftest.py | 8 ++++---- dash/backends/_fastapi.py | 2 +- dash/backends/_quart.py | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/components/dash-core-components/tests/integration/input/conftest.py b/components/dash-core-components/tests/integration/input/conftest.py index c03087db1a..f612cfe462 100644 --- a/components/dash-core-components/tests/integration/input/conftest.py +++ b/components/dash-core-components/tests/integration/input/conftest.py @@ -2,7 +2,7 @@ from dash import Dash, Input, Output, dcc, html -@pytest.fixture(scope="module") +@pytest.fixture def ninput_app(): app = Dash(__name__) app.layout = html.Div( @@ -35,7 +35,7 @@ def render(fval, tval): yield app -@pytest.fixture(scope="module") +@pytest.fixture def input_range_app(): app = Dash(__name__) app.layout = html.Div( @@ -59,7 +59,7 @@ def range_out(val): yield app -@pytest.fixture(scope="module") +@pytest.fixture def debounce_text_app(): app = Dash(__name__) app.layout = html.Div( @@ -89,7 +89,7 @@ def render(slow_val, fast_val): yield app -@pytest.fixture(scope="module") +@pytest.fixture def debounce_number_app(): app = Dash(__name__) app.layout = html.Div( diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 00c351cb38..f19e628a73 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -231,7 +231,7 @@ def has_request_context(self) -> bool: except RuntimeError: return False - def run(self, dash_app: Dash, host, port, debug, **kwargs): + def run(self, dash_app: Dash, host, port, debug, **kwargs): # pylint: disable=R0912 frame = inspect.stack()[2] dev_tools = dash_app._dev_tools # pylint: disable=W0212 config = dict( diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 56f3253bac..92f67c2205 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -194,6 +194,7 @@ def has_request_context(self) -> bool: # pylint: disable=W0613 def run(self, dash_app: Dash, host: str, port: int, debug: bool, **kwargs: _t.Any): self.config = {"debug": debug, **kwargs} if debug else kwargs + # pylint: disable=protected-access if dash_app._dev_tools.silence_routes_logging: dictConfig( { From 31493def7e3db283f38d0591eb815b56503721da Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 19 Feb 2026 10:29:58 -0500 Subject: [PATCH 108/297] fastapi config from env, refactor middlewares --- dash/backends/_fastapi.py | 302 ++++++++++++++++++----------------- dash/backends/base_server.py | 29 +++- dash/dash.py | 1 + 3 files changed, 184 insertions(+), 148 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index f19e628a73..f781300bdf 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -2,6 +2,7 @@ import asyncio from contextvars import copy_context, ContextVar +import json from typing import TYPE_CHECKING, Any, Callable, Dict import sys import mimetypes @@ -9,7 +10,6 @@ import inspect import pkgutil import time -import json import os import subprocess import threading @@ -55,45 +55,122 @@ def get_current_request() -> Request: return req -class CurrentRequestMiddleware: # pylint: disable=too-few-public-methods - def __init__(self, app: ASGIApp) -> None: # type: ignore[name-defined] +_ENV_CONFIG = "_DASH_FASTAPI_CONFIG" + + +class DashMiddleware: # pylint: disable=too-few-public-methods + """Consolidated middleware for all Dash/FastAPI integration needs.""" + + def __init__( + self, + app: ASGIApp, + dash_app: Dash, + before_request_funcs: list, + after_request_func: Callable | None = None, + enable_timing: bool = False, + error_handling_mode: str = "ignore", + get_traceback_func: Callable | None = None, + ) -> None: self.app = app + self.dash_app = dash_app + self.before_request_funcs = before_request_funcs + self.after_request_func = after_request_func + self.enable_timing = enable_timing + self.error_handling_mode = error_handling_mode + self.get_traceback_func = get_traceback_func + self._dev_tools_initialized = False + + async def _initialize_dev_tools(self) -> None: + """Initialize dev tools from environment config on first run.""" + if not self._dev_tools_initialized: + config = json.loads(os.getenv(_ENV_CONFIG, "{}")) + if config: + self.dash_app.enable_dev_tools(**config, first_run=False) + self._dev_tools_initialized = True + + def _setup_timing(self, request: Request) -> None: + """Set up timing information for the request.""" + if self.enable_timing: + request.state.timing_information = { + "__dash_server": {"dur": time.time(), "desc": None} + } - async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: # type: ignore[name-defined] - # non-http/ws scopes pass through (lifespan etc.) + async def _run_before_hooks(self) -> None: + """Run all before-request hooks.""" + for func in self.before_request_funcs: + if inspect.iscoroutinefunction(func): + await func() + else: + func() + + async def _run_after_hooks(self) -> None: + """Run after-request hook if configured.""" + if self.after_request_func is not None: + if inspect.iscoroutinefunction(self.after_request_func): + await self.after_request_func() + else: + self.after_request_func() + + def _finalize_timing(self, request: Request) -> dict | None: + """Calculate final timing information and return headers to add.""" + if not self.enable_timing or not hasattr(request.state, "timing_information"): + return None + + timing_information = request.state.timing_information + dash_total = timing_information.get("__dash_server", None) + if dash_total is not None: + dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) + + return timing_information + + async def _handle_error( + self, error: Exception, scope: Scope, receive: Receive, send: Send + ) -> None: + """Handle exceptions during request processing.""" + if isinstance(error, PreventUpdate): + response = Response(status_code=204) + elif self.error_handling_mode in ["raise", "prune"] and self.get_traceback_func: + tb = self.get_traceback_func(None, error) + response = Response(content=tb, media_type="text/html", status_code=500) + else: + response = JSONResponse( + status_code=500, + content={ + "error": "InternalServerError", + "message": "An internal server error occurred.", + }, + ) + await response(scope, receive, send) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + # Handle lifespan events (startup/shutdown) + if scope["type"] == "lifespan": + await self._initialize_dev_tools() + await self.app(scope, receive, send) + return + + # Non-HTTP/WebSocket scopes pass through if scope["type"] not in ("http", "websocket"): await self.app(scope, receive, send) return + # HTTP/WebSocket request handling request = Request(scope, receive=receive) token = set_current_request(request) - try: - await self.app(scope, receive, send) - finally: - reset_current_request(token) - - -def _save_config(config_path, config): - with open(config_path, "w", encoding="utf-8") as f: - json.dump(config, f) + try: + self._setup_timing(request) + await self._run_before_hooks() -def _load_config(config_path): - resp = {"debug": False} - try: - if os.path.exists(config_path): - with open(config_path, "r", encoding="utf-8") as f: - resp = json.load(f) - except (json.JSONDecodeError, OSError): - pass # ignore errors - return resp + await self.app(scope, receive, send) + await self._run_after_hooks() + self._finalize_timing(request) -def _remove_config(config_path): - try: - os.remove(config_path) - except FileNotFoundError: - pass + except Exception as e: # pylint: disable=W0718 + await self._handle_error(e, scope, receive, send) + finally: + reset_current_request(token) class FastAPIDashServer(BaseDashServer[FastAPI]): @@ -103,28 +180,13 @@ def __init__(self, server: FastAPI): self.error_handling_mode = "ignore" self.request_adapter = FastAPIRequestAdapter self._before_request_funcs = [] - self._before_middleware_added = False - - fname = inspect.stack()[2] - file_path = fname.filename - - # Manually build the config directory path - home_dir = os.path.expanduser("~") - config_dir = os.path.join(home_dir, ".local", "share", "plotly-dash-configs") - os.makedirs(config_dir, exist_ok=True) - - # Hash the file path for a unique config filename - hash_digest = hashlib.sha256(file_path.encode("utf-8")).hexdigest() - config_filename = f"{hash_digest}.json" - self._CONFIG_PATH = os.path.join(config_dir, config_filename) + self._after_request_func = None + self._enable_timing = False def __call__(self, *args: Any, **kwargs: Any): # ASGI: pass through to FastAPI return self.server(*args, **kwargs) - def _cleanup_config(self): - _remove_config(self._CONFIG_PATH) - @staticmethod # pylint: disable=W0613 def create_app(name: str = "__main__", config: Dict[str, Any] | None = None): @@ -178,17 +240,11 @@ async def index(_request: Request): dash_app._add_url("", index, methods=["GET"]) def setup_catchall(self, dash_app: Dash): - @self.server.on_event("startup") - def _setup_catchall(): - dash_app.enable_dev_tools( - **_load_config(self._CONFIG_PATH), first_run=False - ) # do this to make sure dev tools are enabled - - async def catchall(_request: Request): - return Response(content=dash_app.index(), media_type="text/html") + async def catchall(_request: Request): + return Response(content=dash_app.index(), media_type="text/html") - # pylint: disable=protected-access - dash_app._add_url("{path:path}", catchall, methods=["GET"]) + # pylint: disable=protected-access + dash_app._add_url("{path:path}", catchall, methods=["GET"]) def add_url_rule( self, @@ -214,15 +270,9 @@ def add_url_rule( def before_request(self, func: Callable[[], Any] | None): if func is not None: self._before_request_funcs.append(func) - # Only add the middleware once - if not self._before_middleware_added: - self.server.add_middleware(CurrentRequestMiddleware) - self.server.middleware("http")(self._make_before_middleware()) - self._before_middleware_added = True def after_request(self, func: Callable[[], Any] | None): - # FastAPI does not have after_request, but we can use middleware - self.server.middleware("http")(self._make_after_middleware(func)) + self._after_request_func = func def has_request_context(self) -> bool: try: @@ -233,12 +283,6 @@ def has_request_context(self) -> bool: def run(self, dash_app: Dash, host, port, debug, **kwargs): # pylint: disable=R0912 frame = inspect.stack()[2] - dev_tools = dash_app._dev_tools # pylint: disable=W0212 - config = dict( - {"debug": debug} if debug else {"debug": False}, - **{f"dev_tools_{k}": v for k, v in dev_tools.items()}, - ) - _save_config(self._CONFIG_PATH, config) if debug and kwargs.get("reload") is None: kwargs["reload"] = True @@ -251,10 +295,7 @@ def run(self, dash_app: Dash, host, port, debug, **kwargs): # pylint: disable=R # This allows the testing framework to control the server lifecycle if kwargs.get("reload"): kwargs["reload"] = True - try: - uvicorn.run(self.server, host=host, port=port, **kwargs) - finally: - self._cleanup_config() + uvicorn.run(self.server, host=host, port=port, **kwargs) else: # Running in main thread (normal context) - use subprocess file_path = frame.filename @@ -316,14 +357,19 @@ def run(self, dash_app: Dash, host, port, debug, **kwargs): # pylint: disable=R if kwargs.get("reload"): uvicorn_args.append("--reload") + dev_tools = dash_app._dev_tools # pylint: disable=W0212 + config = dict( + {"debug": debug} if debug else {"debug": False}, + **{f"dev_tools_{k}": v for k, v in dev_tools.items()}, + ) + env = os.environ.copy() + env[_ENV_CONFIG] = json.dumps(config) + # Add any other kwargs as CLI args if needed - try: - # pylint: disable=R1732 - proc = subprocess.Popen(uvicorn_args, env=os.environ.copy()) - proc.wait() - finally: - self._cleanup_config() + # pylint: disable=R1732 + proc = subprocess.Popen(uvicorn_args, env=env) + proc.wait() def make_response( self, @@ -342,44 +388,6 @@ def make_response( def jsonify(self, obj: Any): return JSONResponse(content=obj) - def _make_before_middleware(self): - async def middleware(request, call_next): - for func in self._before_request_funcs: - if inspect.iscoroutinefunction(func): - await func() - else: - func() - try: - response = await call_next(request) - return response - except PreventUpdate: - return Response(status_code=204) - except Exception as e: # pylint: disable=W0718 - if self.error_handling_mode in ["raise", "prune"]: - tb = self._get_traceback(None, e) - return Response(content=tb, media_type="text/html", status_code=500) - return JSONResponse( - status_code=500, - content={ - "error": "InternalServerError", - "message": "An internal server error occurred.", - }, - ) - - return middleware - - def _make_after_middleware(self, func: Callable[[], Any] | None): - async def middleware(request, call_next): - response = await call_next(request) - if func is not None: - if inspect.iscoroutinefunction(func): - await func() - else: - func() - return response - - return middleware - def serve_component_suites( self, dash_app: Dash, @@ -461,31 +469,8 @@ async def _dispatch(request: Request): return _dispatch def register_timing_hooks(self, first_run: bool): - if not first_run: - return - - @self.server.middleware("http") - async def timing_middleware(request: Request, call_next): - # Before request - request.state.timing_information = { - "__dash_server": {"dur": time.time(), "desc": None} - } - response = await call_next(request) - # After request - timing_information = getattr(request.state, "timing_information", None) - if timing_information is not None: - dash_total = timing_information.get("__dash_server", None) - if dash_total is not None: - dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) - headers = MutableHeaders(response.headers) - for name, info in timing_information.items(): - value = name - if info.get("desc") is not None: - value += f';desc="{info["desc"]}"' - if info.get("dur") is not None: - value += f";dur={info['dur']}" - headers.append("Server-Timing", value) - return response + if first_run: + self._enable_timing = True def register_callback_api_routes( self, callback_api_paths: Dict[str, Callable[..., Any]] @@ -532,13 +517,36 @@ def enable_compression(self) -> None: ) self.server.add_middleware(GZipMiddleware, minimum_size=500) - config = _load_config(self._CONFIG_PATH) - if "COMPRESS_ALGORITHM" not in config: - config["COMPRESS_ALGORITHM"] = [ - "gzip" - ] # pylint: disable=no-value-for-parameter - _save_config(self._CONFIG_PATH, config) + def setup_backend(self, dash_app: Dash): + # Add consolidated middleware for all Dash functionality + self.server.add_middleware( + DashMiddleware, + dash_app=dash_app, + before_request_funcs=self._before_request_funcs, + after_request_func=self._after_request_func, + enable_timing=self._enable_timing, + error_handling_mode=self.error_handling_mode, + get_traceback_func=self._get_traceback, + ) + + # Add timing middleware separately if enabled (needs to modify response headers) + if self._enable_timing: + + @self.server.middleware("http") + async def timing_headers_middleware(request: Request, call_next): + response = await call_next(request) + timing_information = getattr(request.state, "timing_information", None) + if timing_information is not None: + headers = MutableHeaders(response.headers) + for name, info in timing_information.items(): + value = name + if info.get("desc") is not None: + value += f';desc="{info["desc"]}"' + if info.get("dur") is not None: + value += f";dur={info['dur']}" + headers.append("Server-Timing", value) + return response class FastAPIRequestAdapter(RequestAdapter): diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index 49c8596ce7..9f12791afa 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -1,5 +1,9 @@ from abc import ABC, abstractmethod -from typing import Any, Dict, Type, TypeVar, Generic, Protocol +from typing import Any, Dict, Type, TypeVar, Generic, Protocol, TYPE_CHECKING + + +if TYPE_CHECKING: + import dash class _ServerCallable(Protocol): # pylint: disable=too-few-public-methods @@ -155,3 +159,26 @@ def register_prune_error_handler(self, secret: str, prune_errors: bool) -> None: @abstractmethod def register_timing_hooks(self, first_run: bool) -> None: pass + + @abstractmethod + def register_callback_api_routes(self, callback_api_paths): + pass + + @abstractmethod + def setup_component_suites(self, dash_app: "dash.Dash") -> str: + pass + + @abstractmethod + def serve_callback(self, dash_app: "dash.Dash"): + pass + + @abstractmethod + def setup_index(self, dash_app: "dash.Dash"): + pass + + @abstractmethod + def setup_catchall(self, dash_app: "dash.Dash"): + pass + + def setup_backend(self, dash_app: "dash.Dash"): + """Override to provide any other required setup""" diff --git a/dash/dash.py b/dash/dash.py index 96ccf4dde6..036ca3bd3b 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -729,6 +729,7 @@ def _handle_error(_): self.backend.register_error_handlers() self.backend.before_request(self._setup_server) + self.backend.setup_backend(self) self._setup_routes() _get_app.APP = self self.enable_pages() From f8c89836a53332ccb00f748d230201f51dfaa796 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 19 Feb 2026 10:49:48 -0500 Subject: [PATCH 109/297] add docstring to base server --- dash/backends/base_server.py | 167 ++++++++++++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 1 deletion(-) diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index 9f12791afa..d88d8422f7 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -1,3 +1,8 @@ +"""Base server abstractions for Dash backend implementations. + +This module provides abstract base classes and protocols that define the interface +for different web server backends (Flask, Quart, FastAPI, etc.) to integrate with Dash. +""" from abc import ABC, abstractmethod from typing import Any, Dict, Type, TypeVar, Generic, Protocol, TYPE_CHECKING @@ -7,6 +12,10 @@ class _ServerCallable(Protocol): # pylint: disable=too-few-public-methods + """Protocol for callable server instances. + + Defines the interface for server objects that can be called as WSGI/ASGI applications. + """ def __call__(self, *args: Any, **kwds: Any) -> Any: raise NotImplementedError @@ -15,81 +24,123 @@ def __call__(self, *args: Any, **kwds: Any) -> Any: class RequestAdapter(ABC): + """Abstract adapter for normalizing HTTP request objects across different server backends. + + This adapter provides a unified interface for accessing request data regardless of + the underlying web framework (Flask, Quart, FastAPI, etc.). Concrete implementations + wrap framework-specific request objects and expose their data through these properties. + """ def __call__(self) -> "RequestAdapter": return self @property @abstractmethod def context(self) -> Any: # pragma: no cover - interface + """Get the framework-specific request context object.""" raise NotImplementedError() # Properties to be implemented in concrete adapters @property # pragma: no cover - interface @abstractmethod def root(self) -> str: + """Get the application root path.""" raise NotImplementedError() @property # pragma: no cover - interface @abstractmethod def args(self): + """Get the request query string arguments.""" raise NotImplementedError() @abstractmethod # kept as method (may be sync or async) def get_json(self): # pragma: no cover - interface + """Get the parsed JSON body of the request. + + May be synchronous or asynchronous depending on the backend. + """ raise NotImplementedError() @property # pragma: no cover - interface @abstractmethod def is_json(self) -> bool: + """Check if the request has a JSON content type.""" raise NotImplementedError() @property # pragma: no cover - interface @abstractmethod def cookies(self): + """Get the request cookies.""" raise NotImplementedError() @property # pragma: no cover - interface @abstractmethod def headers(self): + """Get the request headers.""" raise NotImplementedError() @property # pragma: no cover - interface @abstractmethod def full_path(self) -> str: + """Get the full request path including query string.""" raise NotImplementedError() @property # pragma: no cover - interface @abstractmethod def url(self) -> str: + """Get the full request URL.""" raise NotImplementedError() @property # pragma: no cover - interface @abstractmethod def remote_addr(self): + """Get the remote client IP address.""" raise NotImplementedError() @property # pragma: no cover - interface @abstractmethod def origin(self): + """Get the Origin header value.""" raise NotImplementedError() @property # pragma: no cover - interface @abstractmethod def path(self) -> str: + """Get the request path without query string.""" raise NotImplementedError() class BaseDashServer(ABC, Generic[ServerType]): + """Abstract base class for Dash server backend implementations. + + This class defines the interface that all server backends must implement to + work with Dash. Concrete implementations exist for Flask, Quart, FastAPI, and + other web frameworks. + + Attributes: + server_type: String identifier for the server backend (e.g., 'flask', 'quart') + server: The underlying server instance + config: Configuration dictionary for the server + request_adapter: RequestAdapter class for normalizing requests + """ server_type: str server: ServerType config: Dict[str, Any] request_adapter: Type[RequestAdapter] def __init__(self, server: ServerType) -> None: + """Initialize the server wrapper. + + Args: + server: The underlying server instance to wrap + """ super().__init__() self.server = server def __call__(self, *args, **kwargs) -> Any: + """Make the server wrapper callable as a WSGI/ASGI application. + + Delegates to the underlying server instance. + """ # Default: WSGI return self.server(*args, **kwargs) @@ -98,40 +149,89 @@ def __call__(self, *args, **kwargs) -> Any: def create_app( name: str = "__main__", config=None ) -> Any: # pragma: no cover - interface + """Create a new server application instance. + + Args: + name: Application name, defaults to '__main__' + config: Configuration dictionary or object + + Returns: + The server application instance + """ pass @abstractmethod def register_assets_blueprint( self, blueprint_name: str, assets_url_path: str, assets_folder: str ) -> None: # pragma: no cover - interface + """Register a blueprint/router for serving static assets. + + Args: + blueprint_name: Name for the assets blueprint + assets_url_path: URL path prefix for assets + assets_folder: Filesystem path to the assets folder + """ pass @abstractmethod def register_error_handlers(self) -> None: # pragma: no cover - interface + """Register error handlers for common HTTP errors.""" pass @abstractmethod def add_url_rule( self, rule: str, view_func, endpoint=None, methods=None ) -> None: # pragma: no cover - interface + """Add a URL routing rule. + + Args: + rule: URL pattern/route + view_func: View function to handle the route + endpoint: Optional endpoint name + methods: Optional list of HTTP methods (e.g., ['GET', 'POST']) + """ pass @abstractmethod def before_request(self, func) -> None: # pragma: no cover - interface + """Register a function to run before each request. + + Args: + func: Function to execute before request handling + """ pass @abstractmethod def after_request(self, func) -> None: # pragma: no cover - interface + """Register a function to run after each request. + + Args: + func: Function to execute after request handling + """ pass @abstractmethod def has_request_context(self) -> bool: # pragma: no cover - interface + """Check if currently executing within a request context. + + Returns: + True if in request context, False otherwise + """ pass @abstractmethod def run( self, dash_app, host: str, port: int, debug: bool, **kwargs ) -> None: # pragma: no cover - interface + """Start the development server. + + Args: + dash_app: The Dash application instance + host: Hostname to bind to + port: Port number to bind to + debug: Enable debug mode + **kwargs: Additional server-specific arguments + """ pass @abstractmethod @@ -142,43 +242,108 @@ def make_response( content_type=None, status=None, ) -> Any: # pragma: no cover - interface + """Create an HTTP response object. + + Args: + data: Response body data + mimetype: MIME type of the response + content_type: Content-Type header value + status: HTTP status code + + Returns: + Server-specific response object + """ pass @abstractmethod def jsonify(self, obj) -> Any: # pragma: no cover - interface + """Convert an object to a JSON response. + + Args: + obj: Object to serialize to JSON + + Returns: + JSON response object + """ pass @abstractmethod def enable_compression(self) -> None: # pragma: no cover - interface + """Enable HTTP compression for responses.""" pass @abstractmethod def register_prune_error_handler(self, secret: str, prune_errors: bool) -> None: + """Register handler for pruning error stack traces. + + Args: + secret: Secret key for error handling + prune_errors: Whether to prune stack traces in errors + """ pass @abstractmethod def register_timing_hooks(self, first_run: bool) -> None: + """Register hooks for timing request/response cycles. + + Args: + first_run: Whether this is the first run of the application + """ pass @abstractmethod def register_callback_api_routes(self, callback_api_paths): + """Register routes for Dash callback API endpoints. + + Args: + callback_api_paths: Paths for callback API endpoints + """ pass @abstractmethod def setup_component_suites(self, dash_app: "dash.Dash") -> str: + """Set up routes for serving component JavaScript bundles. + + Args: + dash_app: The Dash application instance + + Returns: + Base path for component suites + """ pass @abstractmethod def serve_callback(self, dash_app: "dash.Dash"): + """Set up the callback handling endpoint. + + Args: + dash_app: The Dash application instance + """ pass @abstractmethod def setup_index(self, dash_app: "dash.Dash"): + """Set up the index/root route for serving the main application. + + Args: + dash_app: The Dash application instance + """ pass @abstractmethod def setup_catchall(self, dash_app: "dash.Dash"): + """Set up the catchall route for client-side routing. + + Args: + dash_app: The Dash application instance + """ pass def setup_backend(self, dash_app: "dash.Dash"): - """Override to provide any other required setup""" + """Perform any additional backend-specific setup. + + Override this method in concrete implementations to provide custom setup logic. + + Args: + dash_app: The Dash application instance + """ From 6e616f5a102bcc661931278d195957021c84875c Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 19 Feb 2026 11:17:37 -0500 Subject: [PATCH 110/297] fix fastapi traceback debugger --- dash/backends/_fastapi.py | 13 +++++-------- dash/backends/base_server.py | 21 +++------------------ 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index f781300bdf..6476ca7a00 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -65,19 +65,17 @@ def __init__( self, app: ASGIApp, dash_app: Dash, + dash_server: FastAPIDashServer, before_request_funcs: list, after_request_func: Callable | None = None, enable_timing: bool = False, - error_handling_mode: str = "ignore", - get_traceback_func: Callable | None = None, ) -> None: self.app = app self.dash_app = dash_app + self.dash_server = dash_server self.before_request_funcs = before_request_funcs self.after_request_func = after_request_func self.enable_timing = enable_timing - self.error_handling_mode = error_handling_mode - self.get_traceback_func = get_traceback_func self._dev_tools_initialized = False async def _initialize_dev_tools(self) -> None: @@ -129,8 +127,8 @@ async def _handle_error( """Handle exceptions during request processing.""" if isinstance(error, PreventUpdate): response = Response(status_code=204) - elif self.error_handling_mode in ["raise", "prune"] and self.get_traceback_func: - tb = self.get_traceback_func(None, error) + elif self.dash_server.error_handling_mode in ["raise", "prune"]: + tb = self.dash_server._get_traceback(None, error) # pylint: disable=W0212 response = Response(content=tb, media_type="text/html", status_code=500) else: response = JSONResponse( @@ -523,11 +521,10 @@ def setup_backend(self, dash_app: Dash): self.server.add_middleware( DashMiddleware, dash_app=dash_app, + dash_server=self, before_request_funcs=self._before_request_funcs, after_request_func=self._after_request_func, enable_timing=self._enable_timing, - error_handling_mode=self.error_handling_mode, - get_traceback_func=self._get_traceback, ) # Add timing middleware separately if enabled (needs to modify response headers) diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index d88d8422f7..5606da8824 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -16,6 +16,7 @@ class _ServerCallable(Protocol): # pylint: disable=too-few-public-methods Defines the interface for server objects that can be called as WSGI/ASGI applications. """ + def __call__(self, *args: Any, **kwds: Any) -> Any: raise NotImplementedError @@ -30,6 +31,7 @@ class RequestAdapter(ABC): the underlying web framework (Flask, Quart, FastAPI, etc.). Concrete implementations wrap framework-specific request objects and expose their data through these properties. """ + def __call__(self) -> "RequestAdapter": return self @@ -122,6 +124,7 @@ class BaseDashServer(ABC, Generic[ServerType]): config: Configuration dictionary for the server request_adapter: RequestAdapter class for normalizing requests """ + server_type: str server: ServerType config: Dict[str, Any] @@ -158,7 +161,6 @@ def create_app( Returns: The server application instance """ - pass @abstractmethod def register_assets_blueprint( @@ -171,12 +173,10 @@ def register_assets_blueprint( assets_url_path: URL path prefix for assets assets_folder: Filesystem path to the assets folder """ - pass @abstractmethod def register_error_handlers(self) -> None: # pragma: no cover - interface """Register error handlers for common HTTP errors.""" - pass @abstractmethod def add_url_rule( @@ -190,7 +190,6 @@ def add_url_rule( endpoint: Optional endpoint name methods: Optional list of HTTP methods (e.g., ['GET', 'POST']) """ - pass @abstractmethod def before_request(self, func) -> None: # pragma: no cover - interface @@ -199,7 +198,6 @@ def before_request(self, func) -> None: # pragma: no cover - interface Args: func: Function to execute before request handling """ - pass @abstractmethod def after_request(self, func) -> None: # pragma: no cover - interface @@ -208,7 +206,6 @@ def after_request(self, func) -> None: # pragma: no cover - interface Args: func: Function to execute after request handling """ - pass @abstractmethod def has_request_context(self) -> bool: # pragma: no cover - interface @@ -217,7 +214,6 @@ def has_request_context(self) -> bool: # pragma: no cover - interface Returns: True if in request context, False otherwise """ - pass @abstractmethod def run( @@ -232,7 +228,6 @@ def run( debug: Enable debug mode **kwargs: Additional server-specific arguments """ - pass @abstractmethod def make_response( @@ -253,7 +248,6 @@ def make_response( Returns: Server-specific response object """ - pass @abstractmethod def jsonify(self, obj) -> Any: # pragma: no cover - interface @@ -265,12 +259,10 @@ def jsonify(self, obj) -> Any: # pragma: no cover - interface Returns: JSON response object """ - pass @abstractmethod def enable_compression(self) -> None: # pragma: no cover - interface """Enable HTTP compression for responses.""" - pass @abstractmethod def register_prune_error_handler(self, secret: str, prune_errors: bool) -> None: @@ -280,7 +272,6 @@ def register_prune_error_handler(self, secret: str, prune_errors: bool) -> None: secret: Secret key for error handling prune_errors: Whether to prune stack traces in errors """ - pass @abstractmethod def register_timing_hooks(self, first_run: bool) -> None: @@ -289,7 +280,6 @@ def register_timing_hooks(self, first_run: bool) -> None: Args: first_run: Whether this is the first run of the application """ - pass @abstractmethod def register_callback_api_routes(self, callback_api_paths): @@ -298,7 +288,6 @@ def register_callback_api_routes(self, callback_api_paths): Args: callback_api_paths: Paths for callback API endpoints """ - pass @abstractmethod def setup_component_suites(self, dash_app: "dash.Dash") -> str: @@ -310,7 +299,6 @@ def setup_component_suites(self, dash_app: "dash.Dash") -> str: Returns: Base path for component suites """ - pass @abstractmethod def serve_callback(self, dash_app: "dash.Dash"): @@ -319,7 +307,6 @@ def serve_callback(self, dash_app: "dash.Dash"): Args: dash_app: The Dash application instance """ - pass @abstractmethod def setup_index(self, dash_app: "dash.Dash"): @@ -328,7 +315,6 @@ def setup_index(self, dash_app: "dash.Dash"): Args: dash_app: The Dash application instance """ - pass @abstractmethod def setup_catchall(self, dash_app: "dash.Dash"): @@ -337,7 +323,6 @@ def setup_catchall(self, dash_app: "dash.Dash"): Args: dash_app: The Dash application instance """ - pass def setup_backend(self, dash_app: "dash.Dash"): """Perform any additional backend-specific setup. From a263af2b90fd58658461b9becf774a870d43ba8f Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 19 Feb 2026 14:32:11 -0500 Subject: [PATCH 111/297] allowing a common method for cookies and headers on a new response_adapter --- dash/backends/_fastapi.py | 26 ++++++++++++++++++++--- dash/backends/_flask.py | 33 ++++++++++++++++++++++++----- dash/backends/_quart.py | 27 ++++++++++++++++++++++-- dash/backends/base_server.py | 41 ++++++++++++++++++++++++++++++++++++ dash/dash.py | 4 +--- 5 files changed, 118 insertions(+), 13 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 6476ca7a00..ed652cab0f 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -30,13 +30,33 @@ from dash.fingerprint import check_fingerprint from dash import _validate from dash.exceptions import PreventUpdate -from .base_server import BaseDashServer, RequestAdapter +from .base_server import BaseDashServer, RequestAdapter, ResponseAdapter from ._utils import format_traceback_html if TYPE_CHECKING: # pragma: no cover - typing only from dash import Dash +class FastAPIResponseAdapter(ResponseAdapter): + """ + A custom Response class that wraps FastAPI's JSONResponse + and provides a set_response() method for compatibility with Dash's callback system. + """ + + def set_response(self, **kwargs): + """ + Set the response data. This method provides compatibility with Flask's Response.set_data(). + """ + data = kwargs.get("data") + if isinstance(data, (str, bytes, bytearray)): + resp = Response(content=data, headers=self._headers) + else: + resp = JSONResponse(content=data, headers=self._headers) + if self._cookies: + for key, (value, cookie_kwargs) in self._cookies.items(): + resp.set_cookie(key, value, **cookie_kwargs) + return resp + _current_request_var = ContextVar("dash_current_request", default=None) @@ -177,6 +197,7 @@ def __init__(self, server: FastAPI): self.server_type = "fastapi" self.error_handling_mode = "ignore" self.request_adapter = FastAPIRequestAdapter + self.response_adapter = FastAPIResponseAdapter self._before_request_funcs = [] self._after_request_func = None self._enable_timing = False @@ -461,8 +482,7 @@ async def _dispatch(request: Request): response_data = ctx.run(partial_func) if inspect.iscoroutine(response_data): response_data = await response_data - # Instead of set_data, return a new Response - return Response(content=response_data, media_type="application/json") + return cb_ctx.dash_response.set_response(data=response_data) return _dispatch diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index af18961b55..b9630c02fe 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -30,18 +30,43 @@ from dash.exceptions import PreventUpdate, InvalidResourceError from dash._callback import _invoke_callback, _async_invoke_callback from dash._utils import parse_version -from .base_server import BaseDashServer, RequestAdapter +from .base_server import BaseDashServer, RequestAdapter, ResponseAdapter if TYPE_CHECKING: # pragma: no cover - typing only from dash import Dash +class FlaskResponseAdapter(ResponseAdapter): + """ + A custom Response class that wraps Flask's Response + and provides a set_response() method for compatibility with Dash's callback system. + """ + + def __init__(self): + self._flask_response = Response(content_type='application/json') + super().__init__() + + @property + def callback_response(self) -> Response: + return self._flask_response + + def set_cookie(self, key, value='', **kwargs): + self._flask_response.set_cookie(key, value, **kwargs) + + def set_header(self, key, value): + self._flask_response.headers.add(key, value) + + def set_response(self, **kwargs): + self._flask_response.set_data(kwargs.get('data','')) + return self._flask_response + class FlaskDashServer(BaseDashServer[Flask]): def __init__(self, server: Flask) -> None: super().__init__(server) self.server_type = "flask" self.request_adapter = FlaskRequestAdapter + self.response_adapter = FlaskResponseAdapter def __call__(self, *args: Any, **kwargs: Any): # Always WSGI @@ -239,8 +264,7 @@ def _dispatch(): "Please install the dependencies via `pip install dash[async]` and ensure " "that `use_async=False` is not being passed to the app." ) - cb_ctx.dash_response.set_data(response_data) - return cb_ctx.dash_response + return cb_ctx.dash_response.set_response(data=response_data) async def _dispatch_async(): body = request.get_json() @@ -255,8 +279,7 @@ async def _dispatch_async(): response_data = ctx.run(partial_func) if asyncio.iscoroutine(response_data): response_data = await response_data - cb_ctx.dash_response.set_data(response_data) - return cb_ctx.dash_response + return cb_ctx.dash_response.set_response(data=response_data) if dash_app._use_async: # pylint: disable=protected-access return _dispatch_async diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 92f67c2205..d793e19574 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -34,9 +34,31 @@ from dash.fingerprint import check_fingerprint from dash._utils import parse_version from dash import _validate, Dash -from .base_server import BaseDashServer, RequestAdapter +from .base_server import BaseDashServer, RequestAdapter, ResponseAdapter from ._utils import format_traceback_html +class QuartResponseAdapter(ResponseAdapter): + """ + A custom Response class that wraps Quart's Response + and provides a set_response() method for compatibility with Dash's callback system. + """ + def __init__(self): + self._quart_response = Response(content_type='application/json') + super().__init__() + + @property + def callback_response(self) -> Response: + return self._quart_response + + def set_cookie(self, key, value='', **kwargs): + self._quart_response.set_cookie(key, value, **kwargs) + + def set_header(self, key, value): + self._quart_response.headers.add(key, value) + + def set_response(self, **kwargs): + self._quart_response.set_data(kwargs.get('data','')) + return self._quart_response class QuartDashServer(BaseDashServer[Quart]): def __init__(self, server: Quart) -> None: @@ -45,6 +67,7 @@ def __init__(self, server: Quart) -> None: self.config = {} self.error_handling_mode = "ignore" self.request_adapter = QuartRequestAdapter + self.response_adapter = QuartResponseAdapter def __call__(self, *args: Any, **kwargs: Any): # type: ignore[name-defined] return self.server(*args, **kwargs) @@ -293,7 +316,7 @@ async def _dispatch(): response_data = ctx.run(partial_func) if inspect.iscoroutine(response_data): # if user callback is async response_data = await response_data - return Response(response_data, content_type="application/json") # type: ignore[arg-type] + return cb_ctx.dash_response.set_response(data=response_data) # type: ignore[arg-type] return _dispatch diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index 5606da8824..82e62299b4 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -110,6 +110,46 @@ def path(self) -> str: """Get the request path without query string.""" raise NotImplementedError() +class ResponseAdapter: + """Adapter for server response objects to allow setting data.""" + + def __init__(self): + # Accept a pre-made response object + self._headers = {} + self._cookies = {} + + @property + def callback_response(self): + """Get the response object to be returned from a callback.""" + # This method should be overridden in concrete implementations to return the appropriate response object + raise NotImplementedError() + + def set_cookie(self, key, value='', **kwargs): + """Set a cookie in the response (like Flask's set_cookie).""" + # Store as a tuple: (value, kwargs) + self._cookies[key] = (value, kwargs) + + def set_header(self, key, value): + """Add a header to the response (like Flask's headers.add).""" + # Allow multiple values per header key + if key in self._headers: + if isinstance(self._headers[key], list): + self._headers[key].append(value) + else: + self._headers[key] = [self._headers[key], value] + else: + self._headers[key] = value + + def set_response(self, **kwargs): + """Set the response data if supported by the response object.""" + raise NotImplementedError() + + + @property + def response(self): + """Get the underlying response object.""" + return self._response + class BaseDashServer(ABC, Generic[ServerType]): """Abstract base class for Dash server backend implementations. @@ -129,6 +169,7 @@ class BaseDashServer(ABC, Generic[ServerType]): server: ServerType config: Dict[str, Any] request_adapter: Type[RequestAdapter] + response_adapter: Type[ResponseAdapter] def __init__(self, server: ServerType) -> None: """Initialize the server wrapper. diff --git a/dash/dash.py b/dash/dash.py index 036ca3bd3b..71f7f33cb4 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -1407,9 +1407,7 @@ def _initialize_context(self, body): {"prop_id": x, "value": g.input_values.get(x)} for x in body.get("changedPropIds", []) ] - g.dash_response = self.backend.make_response( - mimetype="application/json", data=None - ) + g.dash_response = self.backend.response_adapter() g.cookies = dict(adapter.cookies) g.headers = dict(adapter.headers) g.args = adapter.args From b78853a9ad25b5f9a36f8991a4456eb9329e6fd1 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 19 Feb 2026 14:53:06 -0500 Subject: [PATCH 112/297] fix for lint --- dash/backends/_fastapi.py | 1 + dash/backends/_flask.py | 7 ++++--- dash/backends/_quart.py | 11 +++++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index ed652cab0f..cca9a11d8e 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -57,6 +57,7 @@ def set_response(self, **kwargs): resp.set_cookie(key, value, **cookie_kwargs) return resp + _current_request_var = ContextVar("dash_current_request", default=None) diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index b9630c02fe..930b7a3a4f 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -36,6 +36,7 @@ if TYPE_CHECKING: # pragma: no cover - typing only from dash import Dash + class FlaskResponseAdapter(ResponseAdapter): """ A custom Response class that wraps Flask's Response @@ -43,21 +44,21 @@ class FlaskResponseAdapter(ResponseAdapter): """ def __init__(self): - self._flask_response = Response(content_type='application/json') + self._flask_response = Response(content_type="application/json") super().__init__() @property def callback_response(self) -> Response: return self._flask_response - def set_cookie(self, key, value='', **kwargs): + def set_cookie(self, key, value="", **kwargs): self._flask_response.set_cookie(key, value, **kwargs) def set_header(self, key, value): self._flask_response.headers.add(key, value) def set_response(self, **kwargs): - self._flask_response.set_data(kwargs.get('data','')) + self._flask_response.set_data(kwargs.get("data", "")) return self._flask_response diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index d793e19574..cf197e2d60 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -37,29 +37,32 @@ from .base_server import BaseDashServer, RequestAdapter, ResponseAdapter from ._utils import format_traceback_html + class QuartResponseAdapter(ResponseAdapter): """ A custom Response class that wraps Quart's Response and provides a set_response() method for compatibility with Dash's callback system. """ + def __init__(self): - self._quart_response = Response(content_type='application/json') + self._quart_response = Response(content_type="application/json") super().__init__() @property def callback_response(self) -> Response: return self._quart_response - def set_cookie(self, key, value='', **kwargs): + def set_cookie(self, key, value="", **kwargs): self._quart_response.set_cookie(key, value, **kwargs) def set_header(self, key, value): self._quart_response.headers.add(key, value) def set_response(self, **kwargs): - self._quart_response.set_data(kwargs.get('data','')) + self._quart_response.set_data(kwargs.get("data", "")) return self._quart_response + class QuartDashServer(BaseDashServer[Quart]): def __init__(self, server: Quart) -> None: super().__init__(server) @@ -316,7 +319,7 @@ async def _dispatch(): response_data = ctx.run(partial_func) if inspect.iscoroutine(response_data): # if user callback is async response_data = await response_data - return cb_ctx.dash_response.set_response(data=response_data) # type: ignore[arg-type] + return cb_ctx.dash_response.set_response(data=response_data) # type: ignore[arg-type] return _dispatch From 7d7321c244e880dc37dbfa6a0baa9606dd8af97d Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 19 Feb 2026 15:43:48 -0500 Subject: [PATCH 113/297] fix for lint --- dash/backends/base_server.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index 82e62299b4..09367f285d 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -110,6 +110,7 @@ def path(self) -> str: """Get the request path without query string.""" raise NotImplementedError() + class ResponseAdapter: """Adapter for server response objects to allow setting data.""" @@ -124,7 +125,7 @@ def callback_response(self): # This method should be overridden in concrete implementations to return the appropriate response object raise NotImplementedError() - def set_cookie(self, key, value='', **kwargs): + def set_cookie(self, key, value="", **kwargs): """Set a cookie in the response (like Flask's set_cookie).""" # Store as a tuple: (value, kwargs) self._cookies[key] = (value, kwargs) @@ -144,7 +145,6 @@ def set_response(self, **kwargs): """Set the response data if supported by the response object.""" raise NotImplementedError() - @property def response(self): """Get the underlying response object.""" From dd0d8e21577504f7fc94a9c0c2f38b38327da6e2 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 19 Feb 2026 16:23:20 -0500 Subject: [PATCH 114/297] fix for lint --- dash/backends/base_server.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index 09367f285d..32c708a55a 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -145,11 +145,6 @@ def set_response(self, **kwargs): """Set the response data if supported by the response object.""" raise NotImplementedError() - @property - def response(self): - """Get the underlying response object.""" - return self._response - class BaseDashServer(ABC, Generic[ServerType]): """Abstract base class for Dash server backend implementations. From 2bd80f497882a0aaf0ee1302fb5256a53a3f8fdf Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 19 Feb 2026 16:45:25 -0500 Subject: [PATCH 115/297] fix for lint --- dash/backends/_fastapi.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index cca9a11d8e..782ebab7d4 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -43,6 +43,14 @@ class FastAPIResponseAdapter(ResponseAdapter): and provides a set_response() method for compatibility with Dash's callback system. """ + @property + def callback_response(self): + """Get the response object to be returned from a callback.""" + print( + "Cannot access callback_response directly on FastAPIResponseAdapter. Use set_response() to create a response with data." + ) + raise NotImplementedError() + def set_response(self, **kwargs): """ Set the response data. This method provides compatibility with Flask's Response.set_data(). From 20fb94f5bf118bfb4e8d5853f8a4f074f2d459f1 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Thu, 19 Feb 2026 17:37:17 -0500 Subject: [PATCH 116/297] adding tests for cookies and headers --- .../backend_tests/test_preconfig_backends.py | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/backend_tests/test_preconfig_backends.py b/tests/backend_tests/test_preconfig_backends.py index 3193305ee2..e1c0dac0d2 100644 --- a/tests/backend_tests/test_preconfig_backends.py +++ b/tests/backend_tests/test_preconfig_backends.py @@ -1,6 +1,35 @@ import logging import pytest -from dash import Dash, Input, Output, html, dcc +from dash import Dash, Input, Output, html, dcc, ctx + + +@pytest.mark.parametrize( + "backend,fixture", + [ + ("flask", "dash_duo"), + ("fastapi", "dash_duo"), + ("quart", "dash_duo_mp"), + ], +) +def test_set_cookie_and_header(request, backend, fixture): + dash_duo = request.getfixturevalue(fixture) + app = Dash(__name__, backend=backend) + app.layout = html.Div([html.Button("Set", id="btn"), html.Div(id="output")]) + + @app.callback(Output("output", "children"), Input("btn", "n_clicks")) + def set_cookie_and_header(n): + if ctx.response: + ctx.response.set_cookie("mycookie", "cookieval") + ctx.response.set_header("X-My-Header", "HeaderVal") + return f"Clicked {n}" if n else "Not clicked" + + dash_duo.start_server(app) + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal("#output", "Clicked 1") + + # Check cookie + cookies = dash_duo.driver.get_cookies() + assert any(c["name"] == "mycookie" and c["value"] == "cookieval" for c in cookies) @pytest.mark.parametrize( From 7f220aa07edd4e0629a90398fd9bc62ede838059 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 20 Feb 2026 05:36:52 -0500 Subject: [PATCH 117/297] allowing for header test --- tests/backend_tests/test_preconfig_backends.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/backend_tests/test_preconfig_backends.py b/tests/backend_tests/test_preconfig_backends.py index e1c0dac0d2..0bcd65cfe1 100644 --- a/tests/backend_tests/test_preconfig_backends.py +++ b/tests/backend_tests/test_preconfig_backends.py @@ -24,6 +24,21 @@ def set_cookie_and_header(n): return f"Clicked {n}" if n else "Not clicked" dash_duo.start_server(app) + dash_duo.driver.execute_script( + """ + window._lastResponseHeaders = null; + const origFetch = window.fetch; + window.fetch = async function() { + const response = await origFetch.apply(this, arguments); + response.clone().headers.forEach((v, k) => { + if (!window._lastResponseHeaders) window._lastResponseHeaders = {}; + window._lastResponseHeaders[k] = v; + }); + return response; + }; + """ + ) + dash_duo.find_element("#btn").click() dash_duo.wait_for_text_to_equal("#output", "Clicked 1") @@ -31,6 +46,9 @@ def set_cookie_and_header(n): cookies = dash_duo.driver.get_cookies() assert any(c["name"] == "mycookie" and c["value"] == "cookieval" for c in cookies) + headers = dash_duo.driver.execute_script("return window._lastResponseHeaders;") + assert headers and headers["x-my-header"] == "HeaderVal" + @pytest.mark.parametrize( "backend,fixture,input_value", From a9d55c1c3f2222404760c288114e03c371aab69a Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Fri, 20 Feb 2026 10:08:44 -0500 Subject: [PATCH 118/297] adjustments for append and set methods of headers, and adjusting the test --- dash/backends/_fastapi.py | 11 +++++++++-- dash/backends/_flask.py | 5 ++++- dash/backends/_quart.py | 5 ++++- dash/backends/base_server.py | 6 +++++- tests/backend_tests/test_preconfig_backends.py | 6 +++++- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 782ebab7d4..0b27f43692 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -57,9 +57,16 @@ def set_response(self, **kwargs): """ data = kwargs.get("data") if isinstance(data, (str, bytes, bytearray)): - resp = Response(content=data, headers=self._headers) + resp = Response(content=data) else: - resp = JSONResponse(content=data, headers=self._headers) + resp = JSONResponse(content=data) + if self._headers: + for key, value in self._headers.items(): + if isinstance(value, list): + for v in value: + resp.headers.append(key, v) + else: + resp.headers[key] = value if self._cookies: for key, (value, cookie_kwargs) in self._cookies.items(): resp.set_cookie(key, value, **cookie_kwargs) diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index 930b7a3a4f..00c8730d8a 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -54,9 +54,12 @@ def callback_response(self) -> Response: def set_cookie(self, key, value="", **kwargs): self._flask_response.set_cookie(key, value, **kwargs) - def set_header(self, key, value): + def append_header(self, key, value): self._flask_response.headers.add(key, value) + def set_header(self, key, value): + self._flask_response.headers.set(key, value) + def set_response(self, **kwargs): self._flask_response.set_data(kwargs.get("data", "")) return self._flask_response diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index cf197e2d60..ddf31ff2f4 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -55,9 +55,12 @@ def callback_response(self) -> Response: def set_cookie(self, key, value="", **kwargs): self._quart_response.set_cookie(key, value, **kwargs) - def set_header(self, key, value): + def append_header(self, key, value): self._quart_response.headers.add(key, value) + def set_header(self, key, value): + self._quart_response.headers.set(key, value) + def set_response(self, **kwargs): self._quart_response.set_data(kwargs.get("data", "")) return self._quart_response diff --git a/dash/backends/base_server.py b/dash/backends/base_server.py index 32c708a55a..f7211f44a6 100644 --- a/dash/backends/base_server.py +++ b/dash/backends/base_server.py @@ -130,7 +130,7 @@ def set_cookie(self, key, value="", **kwargs): # Store as a tuple: (value, kwargs) self._cookies[key] = (value, kwargs) - def set_header(self, key, value): + def append_header(self, key, value): """Add a header to the response (like Flask's headers.add).""" # Allow multiple values per header key if key in self._headers: @@ -141,6 +141,10 @@ def set_header(self, key, value): else: self._headers[key] = value + def set_header(self, key, value): + """Set a header to the response.""" + self._headers[key] = [value] + def set_response(self, **kwargs): """Set the response data if supported by the response object.""" raise NotImplementedError() diff --git a/tests/backend_tests/test_preconfig_backends.py b/tests/backend_tests/test_preconfig_backends.py index 0bcd65cfe1..eec832070a 100644 --- a/tests/backend_tests/test_preconfig_backends.py +++ b/tests/backend_tests/test_preconfig_backends.py @@ -21,6 +21,9 @@ def set_cookie_and_header(n): if ctx.response: ctx.response.set_cookie("mycookie", "cookieval") ctx.response.set_header("X-My-Header", "HeaderVal") + ctx.response.append_header("X-My-Header", "HeaderVal2") + ctx.response.append_header("X-My-Header2", "HeaderVal3") + ctx.response.set_header("X-My-Header2", "HeaderVal4") return f"Clicked {n}" if n else "Not clicked" dash_duo.start_server(app) @@ -47,7 +50,8 @@ def set_cookie_and_header(n): assert any(c["name"] == "mycookie" and c["value"] == "cookieval" for c in cookies) headers = dash_duo.driver.execute_script("return window._lastResponseHeaders;") - assert headers and headers["x-my-header"] == "HeaderVal" + assert headers and headers["x-my-header"] == "HeaderVal, HeaderVal2" + assert headers and headers["x-my-header2"] == "HeaderVal4" @pytest.mark.parametrize( From c820fee6a87cbb7ac7dd4009c6024ea07a198784 Mon Sep 17 00:00:00 2001 From: philippe Date: Mon, 23 Feb 2026 12:27:59 -0500 Subject: [PATCH 119/297] version 4.1.0rc0 --- CHANGELOG.md | 10 ++++++++++ dash/version.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cb22d4d02..5209f0dd11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ All notable changes to `dash` will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). +# [4.1.0rc0] - 2026-02-23 + +## Added + +- Add support for multiple backend implementation beside flask such as fastapi and quart (both included). + - Add `app = Dash(backend="flask" | "fastapi" | "quart" | CustomBackendImpl)` parameter to automatically setup + - An existing `Fastapi`, `Quart` or `Flask` instance can also be given as `app = Dash(server=Fastapi())` to automatically setup a dash app on the server. + - Install fastapi dependencies with `pip install dash[fastapi]` or quart with `pip install dash[quart]`, flask is still included by default. + - Custom backend implementation can be added as a subclass of `dash.backends.base_server.BaseDashServer` and response/request adapters. + ## [4.0.0] - 2026-02-03 ## Added diff --git a/dash/version.py b/dash/version.py index ce1305bf4e..498a21e35c 100644 --- a/dash/version.py +++ b/dash/version.py @@ -1 +1 @@ -__version__ = "4.0.0" +__version__ = "4.1.0rc0" From e3939d8402ecb6534a87b490faa21f0c8c86eb35 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 23 Feb 2026 13:01:01 -0500 Subject: [PATCH 120/297] Update dash.py --- dash/dash.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index 71f7f33cb4..e543bda31c 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -237,12 +237,11 @@ class Dash(ObsoleteChecker): best value to use. Default ``'__main__'``, env: ``DASH_APP_NAME`` :type name: string - :param server: Sets the Flask server for your app. There are three options: - ``True`` (default): Dash will create a new server + :param server: Sets the server for your app. There are three options: + ``True`` (default): Dash will create a new server using the specified backend ``False``: The server will be added later via ``app.init_app(server)`` - where ``server`` is a ``flask.Flask`` instance. - ``flask.Flask``: use this pre-existing Flask server. - :type server: boolean or flask.Flask + A server instance: Use a pre-existing server (Flask, Quart, or FastAPI) + :type server: boolean or server instance :param backend: The backend to use for the Dash app. Can be a string (name of the backend) or a backend class. Default is None, which From 5481f09e3987bb01ea5c248ee85a037ed16417d7 Mon Sep 17 00:00:00 2001 From: philippe Date: Tue, 24 Feb 2026 11:46:54 -0500 Subject: [PATCH 121/297] remove global backends.backend --- dash/_callback.py | 15 +++++++-------- dash/_callback_context.py | 6 +++--- dash/_get_app.py | 4 +++- dash/_validate.py | 19 ++++++++++++------- dash/backends/__init__.py | 4 ---- dash/dash.py | 11 ++++------- dash/exceptions.py | 4 ++++ 7 files changed, 33 insertions(+), 30 deletions(-) diff --git a/dash/_callback.py b/dash/_callback.py index 0ce4ee59a4..37a53d7ec5 100644 --- a/dash/_callback.py +++ b/dash/_callback.py @@ -20,7 +20,7 @@ BackgroundCallbackError, ImportedInsideCallbackError, ) - +from ._get_app import get_app from ._grouping import ( flatten_grouping, make_grouping_by_index, @@ -39,7 +39,6 @@ from ._callback_context import context_value from ._no_update import NoUpdate from . import _validate -from . import backends async def _async_invoke_callback( @@ -373,7 +372,7 @@ def _get_callback_manager( " and store results on redis.\n" ) - adapter = backends.backend.request_adapter() + adapter = get_app().backend.request_adapter() old_job = adapter.args.getlist("oldJob") if hasattr(adapter.args, "getlist") else [] if old_job: @@ -433,7 +432,7 @@ def _setup_background_callback( def _progress_background_callback(response, callback_manager, background): progress_outputs = background.get("progress") - adapter = backends.backend.request_adapter() + adapter = get_app().backend.request_adapter() cache_key = adapter.args.get("cacheKey") if progress_outputs: @@ -451,7 +450,7 @@ def _update_background_callback( """Set up the background callback and manage jobs.""" callback_manager = _get_callback_manager(kwargs, background) - adapter = backends.backend.request_adapter() + adapter = get_app().backend.request_adapter() cache_key = adapter.args.get("cacheKey") if adapter else None job_id = adapter.args.get("job") if adapter else None @@ -473,7 +472,7 @@ def _handle_rest_background_callback( multi, has_update=False, ): - adapter = backends.backend.request_adapter() + adapter = get_app().backend.request_adapter() cache_key = adapter.args.get("cacheKey") if adapter else None job_id = adapter.args.get("job") if adapter else None # Must get job_running after get_result since get_results terminates it. @@ -691,7 +690,7 @@ def add_context(*args, **kwargs): jsonResponse: Optional[str] = None try: if background is not None: - adapter = backends.backend.request_adapter() + adapter = get_app().backend.request_adapter() if not (adapter and adapter.args.get("cacheKey")): return _setup_background_callback( kwargs, @@ -763,7 +762,7 @@ async def async_add_context(*args, **kwargs): try: if background is not None: - adapter = backends.backend.request_adapter() + adapter = get_app().backend.request_adapter() if not (adapter and adapter.args.get("cacheKey")): return _setup_background_callback( kwargs, diff --git a/dash/_callback_context.py b/dash/_callback_context.py index 10cfb20055..646db990ab 100644 --- a/dash/_callback_context.py +++ b/dash/_callback_context.py @@ -5,7 +5,7 @@ import typing from . import exceptions -from . import backends +from ._get_app import get_app from ._utils import AttributeDict, stringify_id @@ -221,7 +221,7 @@ def record_timing(name, duration, description=None): :param description: A description of the resource. :type description: string or None """ - request = backends.backend.request_adapter() + request = get_app().backend.request_adapter() timing_information = getattr(request.context, "timing_information", {}) if name in timing_information: @@ -252,7 +252,7 @@ def using_outputs_grouping(self): @property @has_context def timing_information(self): - request = backends.backend.request_adapter() + request = get_app().backend.request_adapter() return getattr(request.context, "timing_information", {}) @has_context diff --git a/dash/_get_app.py b/dash/_get_app.py index a64a7450cc..ab0b897f81 100644 --- a/dash/_get_app.py +++ b/dash/_get_app.py @@ -4,6 +4,8 @@ from textwrap import dedent from typing import Any, Optional +from dash.exceptions import AppNotFoundError + APP: Optional[Any] = None app_context: ContextVar[Any] = ContextVar("dash_app_context") @@ -55,7 +57,7 @@ def get_app(): pass if APP is None: - raise Exception( + raise AppNotFoundError( dedent( """ App object is not yet defined. `app = dash.Dash()` needs to be run diff --git a/dash/_validate.py b/dash/_validate.py index bb76f896e1..fb5689f850 100644 --- a/dash/_validate.py +++ b/dash/_validate.py @@ -9,6 +9,7 @@ from .development.base_component import Component from . import backends from . import exceptions +from ._get_app import get_app from ._utils import ( patch_collections_abc, stringify_id, @@ -510,13 +511,17 @@ def validate_use_pages(config): "`dash.register_page()` must be called after app instantiation" ) - if backends.backend.has_request_context(): - raise exceptions.PageError( - """ - dash.register_page() can’t be called within a callback as it updates dash.page_registry, which is a global variable. - For more details, see https://dash.plotly.com/sharing-data-between-callbacks#why-global-variables-will-break-your-app - """ - ) + try: + if get_app().backend.has_request_context(): + raise exceptions.PageError( + """ + dash.register_page() can’t be called within a callback as it updates dash.page_registry, which is a global variable. + For more details, see https://dash.plotly.com/sharing-data-between-callbacks#why-global-variables-will-break-your-app + """ + ) + except exceptions.AppNotFoundError: + # If the app is not found we can add pages since before instantiation. + pass def validate_module_name(module): diff --git a/dash/backends/__init__.py b/dash/backends/__init__.py index 3a12e7939a..585d34a65c 100644 --- a/dash/backends/__init__.py +++ b/dash/backends/__init__.py @@ -4,9 +4,6 @@ from .base_server import BaseDashServer -backend: BaseDashServer - - _backend_imports = { "flask": ("dash.backends._flask", "FlaskDashServer"), "fastapi": ("dash.backends._fastapi", "FastAPIDashServer"), @@ -74,6 +71,5 @@ def get_server_type(server): __all__ = [ "get_backend", - "backend", "get_server_type", ] diff --git a/dash/dash.py b/dash/dash.py index 71f7f33cb4..a46f3af99a 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -502,14 +502,10 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches self.backend = backend_cls(server) self.server = server - backends.backend = self.backend # type: ignore - backends.request_adapter = self.backend.request_adapter # type: ignore else: # No server instance provided, create backend and let backend create server self.server = backend_cls.create_app(caller_name) # type: ignore self.backend = backend_cls(self.server) - backends.backend = self.backend - backends.request_adapter = self.backend.request_adapter # type: ignore base_prefix, routes_prefix, requests_prefix = pathname_configs( url_base_pathname, routes_pathname_prefix, requests_pathname_prefix @@ -642,6 +638,7 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches self._got_first_request = {"pages": False, "setup_server": False} if server: + print(f"init app from server {server}") self.init_app() self.logger.setLevel(logging.INFO) @@ -1180,7 +1177,7 @@ def index(self, *_args, **_kwargs): renderer = self._generate_renderer() title = self.title # Refactored: direct access to global request adapter - request = backends.backend.request_adapter() + request = self.backend.request_adapter() if self.use_pages and self.config.include_pages_meta and request: metas = _page_meta_tags(self, request) + metas @@ -1396,7 +1393,7 @@ def _inputs_to_vals(self, inputs): # pylint: disable=R0915 def _initialize_context(self, body): """Initialize the global context for the request.""" - adapter = backends.backend.request_adapter() + adapter = self.backend.request_adapter() g = AttributeDict({}) g.inputs_list = body.get("inputs", []) g.states_list = body.get("state", []) @@ -2383,7 +2380,7 @@ def verify_url_part(served_part, url_part, part_name): server_url=jupyter_server_url, ) else: - backends.backend.run( + self.backend.run( dash_app=self, host=host, port=port, debug=debug, **flask_run_options ) diff --git a/dash/exceptions.py b/dash/exceptions.py index 00bd2c1553..019f0d2726 100644 --- a/dash/exceptions.py +++ b/dash/exceptions.py @@ -109,3 +109,7 @@ class ImportedInsideCallbackError(DashException): class HookError(DashException): pass + + +class AppNotFoundError(DashException): + pass From 6de4b8d39e942957fdb482e395056e0c16fd0f2c Mon Sep 17 00:00:00 2001 From: Ian MacDougall Murray Date: Wed, 4 Mar 2026 17:35:06 +0000 Subject: [PATCH 122/297] fix: flatten outputs before building loadingOutputs Fixes #3619 --- dash/dash-renderer/src/actions/callbacks.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/dash-renderer/src/actions/callbacks.ts b/dash/dash-renderer/src/actions/callbacks.ts index ee3a251378..37aab3f194 100644 --- a/dash/dash-renderer/src/actions/callbacks.ts +++ b/dash/dash-renderer/src/actions/callbacks.ts @@ -791,7 +791,7 @@ export function executeCallback( } const __execute = async (): Promise => { - const loadingOutputs = outputs.map(out => ({ + const loadingOutputs = flatten(outputs).map(out => ({ path: getPath(paths, out.id), property: out.property?.split('@')[0], id: stringifyId(out.id) From d95ddc3e36e0ccac83cb64b30c433e4848745bdb Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 17 Mar 2026 11:16:23 -0400 Subject: [PATCH 123/297] fixing issue where FastAPI would not allow new paths to be added --- dash/backends/_fastapi.py | 51 ++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 0b27f43692..867e9a25b0 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -28,10 +28,11 @@ ) from _err from dash.fingerprint import check_fingerprint -from dash import _validate +from dash import _validate, get_app from dash.exceptions import PreventUpdate from .base_server import BaseDashServer, RequestAdapter, ResponseAdapter from ._utils import format_traceback_html +import traceback if TYPE_CHECKING: # pragma: no cover - typing only from dash import Dash @@ -122,8 +123,12 @@ async def _initialize_dev_tools(self) -> None: self.dash_app.enable_dev_tools(**config, first_run=False) self._dev_tools_initialized = True - def _setup_timing(self, request: Request) -> None: + async def _setup_timing(self, request: Request) -> None: """Set up timing information for the request.""" + try: + request.state.json_body = await request.json() if request.headers.get("content-type", "").startswith("application/json") else None + except: + request.state.json_body = None if self.enable_timing: request.state.timing_information = { "__dash_server": {"dur": time.time(), "desc": None} @@ -179,6 +184,12 @@ async def _handle_error( async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: # Handle lifespan events (startup/shutdown) if scope["type"] == "lifespan": + try: + dash_app = get_app() + dash_app.backend._setup_catchall() + except: + print("Error during catch-all setup:") + print(traceback.format_exc()) await self._initialize_dev_tools() await self.app(scope, receive, send) return @@ -193,7 +204,7 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: token = set_current_request(request) try: - self._setup_timing(request) + await self._setup_timing(request) await self._run_before_hooks() await self.app(scope, receive, send) @@ -275,11 +286,24 @@ async def index(_request: Request): dash_app._add_url("", index, methods=["GET"]) def setup_catchall(self, dash_app: Dash): - async def catchall(_request: Request): - return Response(content=dash_app.index(), media_type="text/html") + '''This is needed to ensure that all routes are handled by FastAPI + and passed through the middleware, which is necessary for features like authentication + and timing to work correctly on all routes. FastAPI will match this catch-all route + for any path that isn't matched by a more specific route, allowing the middleware to + process the request and then return the appropriate response (e.g., 404 if no Dash route matches).''' - # pylint: disable=protected-access - dash_app._add_url("{path:path}", catchall, methods=["GET"]) + + def _setup_catchall(self): + try: + print("Setting up catch-all route for unmatched paths") + dash_app = get_app() + async def catchall(_request: Request): + return Response(content=dash_app.index(), media_type="text/html") + + # pylint: disable=protected-access + self.add_url_rule("{path:path}", catchall, methods=["GET"]) + except: + print(traceback.format_exc()) def add_url_rule( self, @@ -289,6 +313,7 @@ def add_url_rule( methods: list[str] | None = None, include_in_schema: bool = False, ): + print(f"Adding URL rule: {rule} -> {view_func} (endpoint: {endpoint}, methods: {methods})") if rule == "": rule = "/" if isinstance(view_func, str): @@ -481,7 +506,7 @@ def add_redirect_rule(self, app, fullname, path): def serve_callback(self, dash_app: Dash): async def _dispatch(request: Request): # pylint: disable=protected-access - body = await request.json() + body = self.request_adapter().get_json() cb_ctx = dash_app._initialize_context( body ) # pylint: disable=protected-access @@ -641,5 +666,13 @@ def origin(self): def path(self): return self._request.url.path + async def _get_json(self, request: Request=None): + req = self._request + if not hasattr(req.state, "json_body"): + req.state.json_body = await request.json() + return req.state.json_body + def get_json(self): - return asyncio.run(self._request.json()) + if not hasattr(self, "_request") or self._request is None: + self._request = get_current_request() + return self._request.state.json_body From bebfe63f0a10b69db011708ee1d060b1b19189ec Mon Sep 17 00:00:00 2001 From: Ian MacDougall Murray Date: Tue, 17 Mar 2026 21:11:16 +0000 Subject: [PATCH 124/297] test: add test for loading spinner with ALL wildcard pattern matching Add test_ldcp019_loading_component_pattern_matching to verify that dcc.Loading spinner triggers correctly when callback Output uses the ALL wildcard with pattern-matching IDs. --- .../loading/test_loading_component.py | 53 ++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/components/dash-core-components/tests/integration/loading/test_loading_component.py b/components/dash-core-components/tests/integration/loading/test_loading_component.py index 35507dfe8a..261094965a 100644 --- a/components/dash-core-components/tests/integration/loading/test_loading_component.py +++ b/components/dash-core-components/tests/integration/loading/test_loading_component.py @@ -1,5 +1,5 @@ from multiprocessing import Lock -from dash import Dash, Input, Output, dcc, html +from dash import Dash, Input, Output, dcc, html, MATCH, ALL from dash.dependencies import stringify_id from dash.testing import wait import time @@ -839,3 +839,54 @@ def update_btn1_children(n_clicks): assert spinners == [] assert dash_dcc.get_logs() == [] + + +# loading spinner triggers when callback Output uses ALL wildcard +def test_ldcp019_loading_component_pattern_matching(dash_dcc): + lock = Lock() + + app = Dash(__name__) + + app.layout = html.Div( + [ + dcc.Loading( + [ + html.Div( + id={"type": "div-1", "index": 1, "name": "test"}, + className="div-1", + ) + ], + className="loading", + ) + ], + id={"type": "root", "index": 1, "name": "test"}, + className="root", + ) + + @app.callback( + Output( + {"type": "div-1", "index": ALL, "name": MATCH}, "children" + ), + Input( + {"type": "root", "index": ALL, "name": MATCH}, "n_clicks" + ), + ) + def updateDiv(n_clicks): + if n_clicks == [1]: + time.sleep(0.1) + return ["changed"] + return ["content"] + + with lock: + dash_dcc.start_server(app) + dash_dcc.wait_for_text_to_equal(".div-1", "content") + + dash_dcc.find_element(".root").click() + + dash_dcc.find_element(".loading .dash-spinner") + # mounted but hidden, so looks like no text + dash_dcc.wait_for_text_to_equal(".div-1", "") + + dash_dcc.wait_for_text_to_equal(".div-1", "changed") + + assert dash_dcc.get_logs() == [] From 50b300354600d34bceca643879b43d3a1638e09d Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Mon, 23 Mar 2026 12:34:23 -0600 Subject: [PATCH 125/297] add missing changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f1816c5d7..e632dbfe6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). - [#3656][(](https://github.com/plotly/dash/pull/3656)) Improved dropdown performance for large collections of options - [#3643][(](https://github.com/plotly/dash/pull/3643)) Fix multiselect dropdown with components as labels - [#3609][(](https://github.com/plotly/dash/pull/3609)) Add backward compat alias for _Wildcard +- [#3672][(](https://github.com/plotly/dash/pull/3672)) Improve browser performance when app contains a large number of clientside callbacks ## [4.0.0] - 2026-02-03 From ada7f354a63b25d2a0a7220d7eb4df72be6eb301 Mon Sep 17 00:00:00 2001 From: Ian MacDougall Murray Date: Tue, 24 Mar 2026 07:38:31 +0000 Subject: [PATCH 126/297] style: apply black formatting and fix duplicate test name --- .../integration/loading/test_loading_component.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/components/dash-core-components/tests/integration/loading/test_loading_component.py b/components/dash-core-components/tests/integration/loading/test_loading_component.py index 261094965a..165ecbc524 100644 --- a/components/dash-core-components/tests/integration/loading/test_loading_component.py +++ b/components/dash-core-components/tests/integration/loading/test_loading_component.py @@ -417,7 +417,7 @@ def updateDiv(n_clicks): # update multiple props of same component, only targeted id/prop triggers spinner # test that target_components id can be a dict id -def test_ldcp011_loading_component_target_components(dash_dcc): +def test_ldcp010_loading_component_target_components(dash_dcc): lock = Lock() app = Dash(__name__) @@ -864,12 +864,8 @@ def test_ldcp019_loading_component_pattern_matching(dash_dcc): ) @app.callback( - Output( - {"type": "div-1", "index": ALL, "name": MATCH}, "children" - ), - Input( - {"type": "root", "index": ALL, "name": MATCH}, "n_clicks" - ), + Output({"type": "div-1", "index": ALL, "name": MATCH}, "children"), + Input({"type": "root", "index": ALL, "name": MATCH}, "n_clicks"), ) def updateDiv(n_clicks): if n_clicks == [1]: From 9b9057a9a6e0b89592b31810a8e2363cc3cb83f5 Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Mon, 23 Mar 2026 12:34:23 -0600 Subject: [PATCH 127/297] add missing changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e632dbfe6a..a5e7e9f9bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). - [#3656][(](https://github.com/plotly/dash/pull/3656)) Improved dropdown performance for large collections of options - [#3643][(](https://github.com/plotly/dash/pull/3643)) Fix multiselect dropdown with components as labels - [#3609][(](https://github.com/plotly/dash/pull/3609)) Add backward compat alias for _Wildcard -- [#3672][(](https://github.com/plotly/dash/pull/3672)) Improve browser performance when app contains a large number of clientside callbacks +- [#3672][(](https://github.com/plotly/dash/pull/3672)) Improve browser performance when app contains a large number of pattern matching callback callbacks. Exposes an api endpoint to fetch the latest computeGraph call. ## [4.0.0] - 2026-02-03 From cc103433ee713d9b391b48048601e02b22ace3c4 Mon Sep 17 00:00:00 2001 From: AnnMarueW Date: Tue, 24 Mar 2026 14:50:53 -0700 Subject: [PATCH 128/297] Fix input when min or max is None --- .../src/components/Input.tsx | 4 +-- .../integration/input/test_number_input.py | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/components/dash-core-components/src/components/Input.tsx b/components/dash-core-components/src/components/Input.tsx index e099b2ee36..bcc08d3ca8 100644 --- a/components/dash-core-components/src/components/Input.tsx +++ b/components/dash-core-components/src/components/Input.tsx @@ -188,13 +188,13 @@ function Input({ // Apply min/max constraints let constrainedValue = newValue; - if (props.min !== undefined) { + if (props.min !== null && props.min !== undefined) { constrainedValue = Math.max( constrainedValue, parseFloat(props.min as string) ); } - if (props.max !== undefined) { + if (props.max !== null && props.min !== undefined) { constrainedValue = Math.min( constrainedValue, parseFloat(props.max as string) diff --git a/components/dash-core-components/tests/integration/input/test_number_input.py b/components/dash-core-components/tests/integration/input/test_number_input.py index 01deb79287..299cbecf93 100644 --- a/components/dash-core-components/tests/integration/input/test_number_input.py +++ b/components/dash-core-components/tests/integration/input/test_number_input.py @@ -253,3 +253,29 @@ def test_inni010_valid_numbers(dash_dcc, ninput_app): dash_dcc.clear_input(elem) assert dash_dcc.get_logs() == [] + + +def test_inni011_min_max_bug(dash_dcc): + """Test that decrement increment button works correctly with min/max set to None.""" + + app = Dash(__name__) + app.layout = html.Div( + [ + dcc.Input(id="number", value=17, type="number", min=None, max=None), + html.Div(id="output"), + ] + ) + + @app.callback(Output("output", "children"), [Input("number", "value")]) + def update_output(val): + return val + + dash_dcc.start_server(app) + + decrement_btn = dash_dcc.find_element(".dash-stepper-decrement") + + # Initial value is 17, should be able to decrement to 16 + decrement_btn.click() + dash_dcc.wait_for_text_to_equal("#output", "16") + + assert dash_dcc.get_logs() == [] From bc52e55b99fddcc7312134e5b102c44f783dbac9 Mon Sep 17 00:00:00 2001 From: AnnMarueW Date: Tue, 24 Mar 2026 17:46:33 -0700 Subject: [PATCH 129/297] changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5e7e9f9bc..ad846b4a46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to `dash` will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). +## [UNRELEASED] + +## Fixed +- [#3690](https://github.com/plotly/dash/pull/3690) Fixes Input when min or max is set to None + ## [4.1.0] - 2026-03-23 ## Added From 3c3a3becad2633571f48a7e5348da6420cb32fae Mon Sep 17 00:00:00 2001 From: Mike Baker Date: Wed, 25 Mar 2026 11:18:18 +0900 Subject: [PATCH 130/297] added `typed_callback` --- dash/__init__.py | 3 +- dash/_callback.py | 153 ++++++++++- .../compliance/test_typed_callback_typing.py | 255 +++++++++++++++++ .../callbacks/test_typed_callback.py | 260 ++++++++++++++++++ tests/unit/test_typed_callback_unit.py | 111 ++++++++ 5 files changed, 776 insertions(+), 6 deletions(-) create mode 100644 tests/compliance/test_typed_callback_typing.py create mode 100644 tests/integration/callbacks/test_typed_callback.py create mode 100644 tests/unit/test_typed_callback_unit.py diff --git a/dash/__init__.py b/dash/__init__.py index 6f16a068aa..e67fe4671d 100644 --- a/dash/__init__.py +++ b/dash/__init__.py @@ -19,7 +19,7 @@ from . import dash_table # noqa: F401,E402 from .version import __version__ # noqa: F401,E402 from ._callback_context import callback_context, set_props # noqa: F401,E402 -from ._callback import callback, clientside_callback # noqa: F401,E402 +from ._callback import callback, clientside_callback, typed_callback # noqa: F401,E402 from ._get_app import get_app # noqa: F401,E402 from ._get_paths import ( # noqa: F401,E402 get_asset_url, @@ -77,6 +77,7 @@ def _jupyter_nbextension_paths(): "callback_context", "set_props", "callback", + "typed_callback", "get_app", "get_asset_url", "get_relative_path", diff --git a/dash/_callback.py b/dash/_callback.py index 0b63f17740..68ced8fe21 100644 --- a/dash/_callback.py +++ b/dash/_callback.py @@ -3,7 +3,13 @@ import inspect from functools import wraps -from typing import Callable, Optional, Any, List, Tuple, Union, Dict +import sys +from typing import Callable, Optional, Any, List, Tuple, Union, Dict, TypeVar, cast + +if sys.version_info >= (3, 10): + from typing import ParamSpec +else: + from typing_extensions import ParamSpec import flask @@ -234,15 +240,152 @@ def callback( ) +Params = ParamSpec("Params") +ReturnVar = TypeVar("ReturnVar") + + +# pylint: disable=too-many-arguments +def typed_callback( + *_args, + background: bool = False, + interval: int = 1000, + progress: Optional[Union[List[Output], Output]] = None, + progress_default: Any = None, + running: Optional[List[Tuple[Output, Any, Any]]] = None, + cancel: Optional[Union[List[Input], Input]] = None, + manager: Optional[BaseBackgroundCallbackManager] = None, + cache_args_to_ignore: Optional[list] = None, + cache_ignore_triggered=True, + on_error: Optional[Callable[[Exception], Any]] = None, + api_endpoint: Optional[str] = None, + optional: Optional[bool] = False, + hidden: Optional[bool] = None, + **_kwargs, +) -> Callable[[Callable[Params, ReturnVar]], Callable[Params, ReturnVar]]: + """Decorator factory for Dash callbacks with full type preservation. + + Centralizes the typing gap in Dash's untyped decorator, satisfying + disallow_untyped_decorators while preserving callback function signatures. + + This is a type-safe wrapper around `dash.callback` that preserves the + exact signature of the decorated function. Use this when working with + strict Mypy settings like `disallow_untyped_decorators`. + + :Usage: + ```python + @dash.typed_callback( + Output('output-id', 'children'), + Input('input-id', 'value') + ) + def my_callback(value: str) -> str: + return f"You entered: {value}" + ``` + + :Keyword Arguments: + :param background: + Mark the callback as a background callback to execute in a manager for + callbacks that take a long time without locking up the Dash app + or timing out. + :param manager: + A background callback manager instance. Currently, an instance of one of + `DiskcacheManager` or `CeleryManager`. + Defaults to the `background_callback_manager` instance provided to the + `dash.Dash` constructor. + - A diskcache manager (`DiskcacheManager`) that runs callback + logic in a separate process and stores the results to disk using the + diskcache library. This is the easiest backend to use for local + development. + - A Celery manager (`CeleryManager`) that runs callback logic + in a celery worker and returns results to the Dash app through a Celery + broker like RabbitMQ or Redis. + :param running: + A list of 3-element tuples. The first element of each tuple should be + an `Output` dependency object referencing a property of a component in + the app layout. The second element is the value that the property + should be set to while the callback is running, and the third element + is the value the property should be set to when the callback completes. + :param cancel: + A list of `Input` dependency objects that reference a property of a + component in the app's layout. When the value of this property changes + while a callback is running, the callback is canceled. + Note that the value of the property is not significant, any change in + value will result in the cancellation of the running job (if any). + This parameter only applies to background callbacks (`background=True`). + :param progress: + An `Output` dependency grouping that references properties of + components in the app's layout. When provided, the decorated function + will be called with an extra argument as the first argument to the + function. This argument, is a function handle that the decorated + function should call in order to provide updates to the app on its + current progress. This function accepts a single argument, which + correspond to the grouping of properties specified in the provided + `Output` dependency grouping. This parameter only applies to background + callbacks (`background=True`). + :param progress_default: + A grouping of values that should be assigned to the components + specified by the `progress` argument when the callback is not in + progress. If `progress_default` is not provided, all the dependency + properties specified in `progress` will be set to `None` when the + callback is not running. This parameter only applies to background + callbacks (`background=True`). + :param cache_args_to_ignore: + Arguments to ignore when caching is enabled. If callback is configured + with keyword arguments (Input/State provided in a dict), + this should be a list of argument names as strings. Otherwise, + this should be a list of argument indices as integers. + This parameter only applies to background callbacks (`background=True`). + :param cache_ignore_triggered: + Whether to ignore which inputs triggered the callback when creating + the cache. This parameter only applies to background callbacks + (`background=True`). + :param interval: + Time to wait between the background callback update requests. + :param on_error: + Function to call when the callback raises an exception. Receives the + exception object as first argument. The callback_context can be used + to access the original callback inputs, states and output. + :param optional: + Mark all dependencies as not required on the initial layout checks. + :param hidden: + Hide the callback from the devtools callbacks tab. + :param api_endpoint: + If provided, the callback will be available at the given API endpoint. + This allows you to call the callback directly through HTTP requests + instead of through the Dash front-end. The endpoint should be a string + that starts with a forward slash (e.g. `/my_callback`). + The endpoint is relative to the Dash app's base URL. + Note that the endpoint will not appear in the list of registered + callbacks in the Dash devtools. + """ + raw = callback( + *_args, + background=background, + interval=interval, + progress=progress, + progress_default=progress_default, + running=running, + cancel=cancel, + manager=manager, + cache_args_to_ignore=cache_args_to_ignore, + cache_ignore_triggered=cache_ignore_triggered, + on_error=on_error, + api_endpoint=api_endpoint, + optional=optional, + hidden=hidden, + **_kwargs, + ) # type: ignore[no-untyped-call] + return cast( + Callable[[Callable[Params, ReturnVar]], Callable[Params, ReturnVar]], raw + ) + + def validate_background_inputs(deps): for dep in deps: if dep.has_wildcard(): - raise WildcardInLongCallback( - f""" + raise WildcardInLongCallback(f""" background callbacks does not support dependencies with pattern-matching ids - Received: {repr(dep)}\n""" - ) + Received: {repr(dep)}\n""") ClientsideFuncType = Union[str, ClientsideFunction] diff --git a/tests/compliance/test_typed_callback_typing.py b/tests/compliance/test_typed_callback_typing.py new file mode 100644 index 0000000000..b5a85dc461 --- /dev/null +++ b/tests/compliance/test_typed_callback_typing.py @@ -0,0 +1,255 @@ +"""Type compliance tests for typed_callback with strict mypy/pyright settings.""" +import os +import sys +import pytest + +# Import the testing utilities from the main test_typing.py +from .test_typing import run_module, format_template_and_save + + +# Template for testing typed_callback with strict type checking +typed_callback_template = """ +from dash import Dash, html, dcc, typed_callback, Input, Output, State + +app = Dash() + +app.layout = html.Div([ + dcc.Input(id='input1', value=''), + dcc.Input(id='input2', value=''), + html.Button('Click', id='btn'), + html.Div(id='output1'), + html.Div(id='output2'), +]) + +{0} +""" + +# Template for testing with strict mypy settings +strict_mypy_template = """# mypy: disallow-untyped-defs +# mypy: disallow-untyped-calls +# mypy: disallow-untyped-decorators +from dash import Dash, html, dcc, typed_callback, Input, Output, State + +app = Dash(__name__) + +app.layout = html.Div([ + dcc.Input(id='input', value=''), + html.Div(id='output'), +]) + +{0} +""" + + +valid_typed_callback_single = """ +@typed_callback(Output('output1', 'children'), Input('input1', 'value')) +def update_output(value: str) -> str: + return f"You typed: {value}" +""" + +valid_typed_callback_multi_input = """ +@typed_callback( + Output('output1', 'children'), + Input('input1', 'value'), + Input('input2', 'value') +) +def update_output(val1: str, val2: str) -> str: + return f"{val1} and {val2}" +""" + +valid_typed_callback_with_state = """ +@typed_callback( + Output('output1', 'children'), + Input('btn', 'n_clicks'), + State('input1', 'value') +) +def update_output(n_clicks: int | None, state_value: str) -> str: + if n_clicks is None: + return "Not clicked" + return f"Clicked {n_clicks} times with {state_value}" +""" + +valid_typed_callback_multi_output = """ +@typed_callback( + Output('output1', 'children'), + Output('output2', 'children'), + Input('input1', 'value') +) +def update_outputs(value: str) -> tuple[str, str]: + return f"First: {value}", f"Second: {value}" +""" + +# This should pass with typed_callback but fail with regular callback in strict mode +strict_mode_typed_callback = """ +@typed_callback(Output('output', 'children'), Input('input', 'value')) +def my_callback(value: str) -> str: + '''Fully typed callback function.''' + return f"Result: {value}" +""" + +# Regular callback would fail in strict mode (for comparison) +strict_mode_regular_callback = """ +@app.callback(Output('output', 'children'), Input('input', 'value')) +def my_callback(value: str) -> str: + '''This should fail with disallow-untyped-decorators.''' + return f"Result: {value}" +""" + +# Test with complex return types +complex_return_types = """ +from typing import Union + +@typed_callback( + Output('output1', 'children'), + Output('output2', 'children'), + Input('input1', 'value') +) +def complex_callback(value: str) -> tuple[Union[str, int], list[str]]: + return len(value), [value, value.upper()] +""" + + +typing_modules = ["pyright"] +if sys.version_info.minor >= 10: + typing_modules.append("mypy") + + +@pytest.mark.parametrize("typing_module", typing_modules) +@pytest.mark.parametrize( + "callback_code, expected_status", + [ + (valid_typed_callback_single, 0), + (valid_typed_callback_multi_input, 0), + (valid_typed_callback_with_state, 0), + (valid_typed_callback_multi_output, 0), + (complex_return_types, 0), + ], +) +def test_typi_typed_callback_basic( + typing_module, callback_code, expected_status, tmp_path +): + """Test that typed_callback passes type checking in normal mode.""" + codefile = os.path.join(tmp_path, "code.py") + code = format_template_and_save( + typed_callback_template, codefile, callback_code + ) + + output, error, status = run_module(codefile, typing_module) + assert ( + status == expected_status + ), f"Status: {status}\nOutput: {output}\nError: {error}\nCode: {code}\nModule: {typing_module}" + + +@pytest.mark.parametrize("typing_module", typing_modules) +def test_typi_typed_callback_strict_mode(typing_module, tmp_path): + """Test that typed_callback works with strict mypy/pyright settings. + + This is the main purpose of typed_callback - to satisfy + disallow_untyped_decorators and similar strict settings. + """ + codefile = os.path.join(tmp_path, "code.py") + code = format_template_and_save( + strict_mypy_template, codefile, strict_mode_typed_callback + ) + + output, error, status = run_module(codefile, typing_module) + assert status == 0, ( + f"typed_callback should pass strict type checking.\n" + f"Status: {status}\nOutput: {output}\nError: {error}\n" + f"Code: {code}\nModule: {typing_module}" + ) + + +@pytest.mark.parametrize("typing_module", typing_modules) +def test_typi_regular_callback_strict_mode_fails(typing_module, tmp_path): + """Verify that regular callback fails in strict mode (comparison test). + + This demonstrates why typed_callback is needed. + """ + codefile = os.path.join(tmp_path, "code.py") + code = format_template_and_save( + strict_mypy_template, codefile, strict_mode_regular_callback + ) + + output, error, status = run_module(codefile, typing_module) + + # Regular callback should fail in strict mode + # (This test validates that our strict mode setup is actually strict) + if typing_module == "mypy": + # Mypy should report untyped decorator error + assert status != 0 or "Untyped decorator" in output or "untyped" in error.lower(), ( + f"Regular callback should fail with disallow-untyped-decorators.\n" + f"Status: {status}\nOutput: {output}\nError: {error}\n" + f"Module: {typing_module}" + ) + elif typing_module == "pyright": + # Pyright might or might not catch this depending on strict settings + # The important thing is that typed_callback passes when regular might not + pass + + +@pytest.mark.parametrize("typing_module", typing_modules) +def test_typi_typed_callback_preserves_signature(typing_module, tmp_path): + """Test that typed_callback preserves function signatures for type inference.""" + code = """ +from typing import reveal_type # type: ignore +from dash import typed_callback, Input, Output, html, Dash + +app = Dash(__name__) +app.layout = html.Div([html.Div(id='in'), html.Div(id='out')]) + +@typed_callback(Output('out', 'children'), Input('in', 'children')) +def my_func(value: str) -> int: + return len(value) + +# The decorated function should still have its original signature +result = my_func("test") # Should return int +""" + + codefile = os.path.join(tmp_path, "code.py") + with open(codefile, "w") as f: + f.write(code) + + output, error, status = run_module(codefile, typing_module) + + # Should pass type checking - the function signature is preserved + assert status == 0, ( + f"typed_callback should preserve function signature.\n" + f"Status: {status}\nOutput: {output}\nError: {error}\n" + f"Module: {typing_module}" + ) + + +@pytest.mark.parametrize("typing_module", typing_modules) +def test_typi_typed_callback_with_none_values(typing_module, tmp_path): + """Test typed_callback with Optional types.""" + code = """ +from dash import Dash, html, dcc, typed_callback, Input, Output + +app = Dash(__name__) +app.layout = html.Div([ + dcc.Input(id='input', value=''), + html.Button('Click', id='btn'), + html.Div(id='output'), +]) + +@typed_callback( + Output('output', 'children'), + Input('btn', 'n_clicks') +) +def handle_optional(n_clicks: int | None) -> str: + if n_clicks is None: + return "Not clicked yet" + return f"Clicked {n_clicks} times" +""" + + codefile = os.path.join(tmp_path, "code.py") + with open(codefile, "w") as f: + f.write(code) + + output, error, status = run_module(codefile, typing_module) + assert status == 0, ( + f"typed_callback should handle Optional types.\n" + f"Status: {status}\nOutput: {output}\nError: {error}\n" + f"Module: {typing_module}" + ) diff --git a/tests/integration/callbacks/test_typed_callback.py b/tests/integration/callbacks/test_typed_callback.py new file mode 100644 index 0000000000..e3f096f99d --- /dev/null +++ b/tests/integration/callbacks/test_typed_callback.py @@ -0,0 +1,260 @@ +"""Integration tests for typed_callback functionality.""" +import dash +from dash import Input, Output, State, dcc, html, typed_callback + + +def test_tcb001_basic_typed_callback(dash_duo): + """Test that typed_callback works identically to callback for basic usage.""" + app = dash.Dash(__name__) + + app.layout = html.Div( + [ + dcc.Input(id="input", value="initial"), + html.Div(id="output-typed"), + html.Div(id="output-regular"), + ] + ) + + @typed_callback(Output("output-typed", "children"), Input("input", "value")) + def update_typed(value): + return f"Typed: {value}" + + @dash.callback(Output("output-regular", "children"), Input("input", "value")) + def update_regular(value): + return f"Regular: {value}" + + dash_duo.start_server(app) + dash_duo.wait_for_text_to_equal("#output-typed", "Typed: initial") + dash_duo.wait_for_text_to_equal("#output-regular", "Regular: initial") + + input_element = dash_duo.find_element("#input") + dash_duo.clear_input(input_element) + input_element.send_keys("test") + + dash_duo.wait_for_text_to_equal("#output-typed", "Typed: test") + dash_duo.wait_for_text_to_equal("#output-regular", "Regular: test") + + assert not dash_duo.get_logs() + + +def test_tcb002_typed_callback_multi_input(dash_duo): + """Test typed_callback with multiple inputs.""" + app = dash.Dash(__name__) + + app.layout = html.Div( + [ + dcc.Input(id="input1", value="Hello"), + dcc.Input(id="input2", value="World"), + html.Div(id="output"), + ] + ) + + @typed_callback( + Output("output", "children"), + Input("input1", "value"), + Input("input2", "value"), + ) + def combine_inputs(val1, val2): + return f"{val1} {val2}" + + dash_duo.start_server(app) + dash_duo.wait_for_text_to_equal("#output", "Hello World") + + input1 = dash_duo.find_element("#input1") + dash_duo.clear_input(input1) + input1.send_keys("Goodbye") + + dash_duo.wait_for_text_to_equal("#output", "Goodbye World") + + assert not dash_duo.get_logs() + + +def test_tcb003_typed_callback_with_state(dash_duo): + """Test typed_callback with State dependencies.""" + app = dash.Dash(__name__) + + app.layout = html.Div( + [ + dcc.Input(id="input1", value="stored"), + dcc.Input(id="input2", value="trigger"), + html.Button("Submit", id="button"), + html.Div(id="output"), + ] + ) + + @typed_callback( + Output("output", "children"), + Input("button", "n_clicks"), + State("input1", "value"), + State("input2", "value"), + ) + def update_with_state(n_clicks, state1, state2): + if n_clicks is None: + return "Not clicked" + return f"Click {n_clicks}: {state1} + {state2}" + + dash_duo.start_server(app) + dash_duo.wait_for_text_to_equal("#output", "Not clicked") + + dash_duo.find_element("#button").click() + dash_duo.wait_for_text_to_equal("#output", "Click 1: stored + trigger") + + dash_duo.find_element("#button").click() + dash_duo.wait_for_text_to_equal("#output", "Click 2: stored + trigger") + + assert not dash_duo.get_logs() + + +def test_tcb004_typed_callback_multi_output(dash_duo): + """Test typed_callback with multiple outputs.""" + app = dash.Dash(__name__) + + app.layout = html.Div( + [ + dcc.Input(id="input", value="test"), + html.Div(id="output1"), + html.Div(id="output2"), + html.Div(id="output3"), + ] + ) + + @typed_callback( + Output("output1", "children"), + Output("output2", "children"), + Output("output3", "children"), + Input("input", "value"), + ) + def update_multiple(value): + return f"First: {value}", f"Second: {value}", f"Third: {value}" + + dash_duo.start_server(app) + dash_duo.wait_for_text_to_equal("#output1", "First: test") + dash_duo.wait_for_text_to_equal("#output2", "Second: test") + dash_duo.wait_for_text_to_equal("#output3", "Third: test") + + input_element = dash_duo.find_element("#input") + dash_duo.clear_input(input_element) + input_element.send_keys("changed") + + dash_duo.wait_for_text_to_equal("#output1", "First: changed") + dash_duo.wait_for_text_to_equal("#output2", "Second: changed") + dash_duo.wait_for_text_to_equal("#output3", "Third: changed") + + assert not dash_duo.get_logs() + + +def test_tcb005_typed_callback_prevent_initial_call(dash_duo): + """Test typed_callback with prevent_initial_call parameter.""" + app = dash.Dash(__name__) + + app.layout = html.Div( + [ + dcc.Input(id="input", value="initial"), + html.Div(id="output", children="default"), + ] + ) + + @typed_callback( + Output("output", "children"), + Input("input", "value"), + prevent_initial_call=True, + ) + def update_no_initial(value): + return f"Updated: {value}" + + dash_duo.start_server(app) + # Should remain "default" because prevent_initial_call=True + dash_duo.wait_for_text_to_equal("#output", "default") + + input_element = dash_duo.find_element("#input") + input_element.send_keys("x") + + dash_duo.wait_for_text_to_equal("#output", "Updated: initialx") + + assert not dash_duo.get_logs() + + +def test_tcb006_typed_callback_mixed_with_regular(dash_duo): + """Test that typed_callback and regular callback can coexist.""" + app = dash.Dash(__name__) + + app.layout = html.Div( + [ + dcc.Input(id="input"), + html.Div(id="output1"), + html.Div(id="output2"), + html.Div(id="output3"), + html.Div(id="output4"), + ] + ) + + # Using typed_callback (global style) + @typed_callback(Output("output1", "children"), Input("input", "value")) + def update_1(value): + return f"Typed global: {value}" + + # Using dash.callback (global style) + @dash.callback(Output("output2", "children"), Input("input", "value")) + def update_2(value): + return f"Regular global: {value}" + + # Using app.callback (app instance style) + @app.callback(Output("output3", "children"), Input("input", "value")) + def update_3(value): + return f"App callback: {value}" + + # Another typed_callback + @typed_callback(Output("output4", "children"), Input("input", "value")) + def update_4(value): + return f"Typed global 2: {value}" + + dash_duo.start_server(app) + + input_element = dash_duo.find_element("#input") + input_element.send_keys("test") + + dash_duo.wait_for_text_to_equal("#output1", "Typed global: test") + dash_duo.wait_for_text_to_equal("#output2", "Regular global: test") + dash_duo.wait_for_text_to_equal("#output3", "App callback: test") + dash_duo.wait_for_text_to_equal("#output4", "Typed global 2: test") + + assert not dash_duo.get_logs() + + +def test_tcb007_typed_callback_with_no_update(dash_duo): + """Test typed_callback with no_update.""" + app = dash.Dash(__name__) + + app.layout = html.Div( + [ + dcc.Input(id="input", value="0"), + html.Div(id="output1"), + html.Div(id="output2"), + ] + ) + + @typed_callback( + Output("output1", "children"), + Output("output2", "children"), + Input("input", "value"), + ) + def selective_update(value): + num = int(value) if value and value.isdigit() else 0 + if num % 2 == 0: + return f"Even: {num}", dash.no_update + else: + return dash.no_update, f"Odd: {num}" + + dash_duo.start_server(app) + dash_duo.wait_for_text_to_equal("#output1", "Even: 0") + + input_element = dash_duo.find_element("#input") + dash_duo.clear_input(input_element) + input_element.send_keys("1") + dash_duo.wait_for_text_to_equal("#output2", "Odd: 1") + + dash_duo.clear_input(input_element) + input_element.send_keys("2") + dash_duo.wait_for_text_to_equal("#output1", "Even: 2") + + assert not dash_duo.get_logs() diff --git a/tests/unit/test_typed_callback_unit.py b/tests/unit/test_typed_callback_unit.py new file mode 100644 index 0000000000..2e5210b084 --- /dev/null +++ b/tests/unit/test_typed_callback_unit.py @@ -0,0 +1,111 @@ +"""Unit tests for typed_callback - no browser required.""" +import dash +from dash import Input, Output, State, typed_callback, callback + + +def test_typed_callback_returns_callable(): + """Test that typed_callback returns a callable decorator.""" + decorator = typed_callback(Output("output", "children"), Input("input", "value")) + assert callable(decorator) + + +def test_typed_callback_decorates_function(): + """Test that typed_callback can decorate a function.""" + @typed_callback(Output("output", "children"), Input("input", "value")) + def my_callback(value): + return f"Value: {value}" + + assert callable(my_callback) + assert my_callback.__name__ == "my_callback" + + +def test_typed_callback_signature_matches_callback(): + """Test that typed_callback has the same signature as callback.""" + import inspect + + typed_sig = inspect.signature(typed_callback) + callback_sig = inspect.signature(callback) + + # Both should have the same parameters + assert typed_sig.parameters.keys() == callback_sig.parameters.keys() + + +def test_typed_callback_with_multiple_inputs(): + """Test typed_callback with multiple inputs.""" + @typed_callback( + Output("output", "children"), + Input("input1", "value"), + Input("input2", "value"), + ) + def multi_input_callback(val1, val2): + return f"{val1} + {val2}" + + assert callable(multi_input_callback) + + +def test_typed_callback_with_state(): + """Test typed_callback with State.""" + @typed_callback( + Output("output", "children"), + Input("input", "value"), + State("state", "value"), + ) + def callback_with_state(input_val, state_val): + return f"{input_val} - {state_val}" + + assert callable(callback_with_state) + + +def test_typed_callback_with_multiple_outputs(): + """Test typed_callback with multiple outputs.""" + @typed_callback( + Output("output1", "children"), + Output("output2", "children"), + Input("input", "value"), + ) + def multi_output_callback(value): + return value, f"Copy: {value}" + + assert callable(multi_output_callback) + + +def test_typed_callback_preserves_docstring(): + """Test that typed_callback preserves the wrapped function's docstring.""" + @typed_callback(Output("output", "children"), Input("input", "value")) + def documented_callback(value): + """This is a documented callback.""" + return value + + assert documented_callback.__doc__ == "This is a documented callback." + + +def test_typed_callback_with_prevent_initial_call(): + """Test typed_callback with prevent_initial_call parameter.""" + @typed_callback( + Output("output", "children"), + Input("input", "value"), + prevent_initial_call=True, + ) + def callback_no_initial(value): + return value + + assert callable(callback_no_initial) + + +def test_typed_callback_with_background_params(): + """Test that typed_callback accepts background callback parameters.""" + # Just test that the decorator accepts these parameters + # Full background callback testing requires integration tests + decorator = typed_callback( + Output("output", "children"), + Input("input", "value"), + background=False, + interval=1000, + ) + assert callable(decorator) + + +def test_typed_callback_module_export(): + """Test that typed_callback is properly exported from dash module.""" + assert hasattr(dash, "typed_callback") + assert dash.typed_callback is typed_callback From ea1af0167624c0c2be775c87aebdbd9e830c7554 Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Thu, 26 Mar 2026 13:04:22 -0600 Subject: [PATCH 131/297] Add changelog entry (and fix some markdown) --- CHANGELOG.md | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad846b4a46..c3dc4e9284 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,23 +4,26 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## [UNRELEASED] +## Added +- [#3523](https://github.com/plotly/dash/pull/3523) Fall back to background callback function names if source cannot be found + ## Fixed -- [#3690](https://github.com/plotly/dash/pull/3690) Fixes Input when min or max is set to None +- [#3690](https://github.com/plotly/dash/pull/3690) Fixes Input when min or max is set to None ## [4.1.0] - 2026-03-23 ## Added -- [#3637](https://github.com/plotly/dash/pull/3637) Added `debounce` prop to `Dropdown`. +- [#3637](https://github.com/plotly/dash/pull/3637) Added `debounce` prop to `Dropdown`. ## Fixed - [#3629](https://github.com/plotly/dash/pull/3629) Fix date pickers not showing date when initially rendered in a hidden container. -- [#3660][(](https://github.com/plotly/dash/pull/3660)) Allow same date to be selected for both start and end in DatePickerRange components -- [#3600][(](https://github.com/plotly/dash/pull/3600)) DatePicker support for the Moment.js `Y` year token -- [#3627][(](https://github.com/plotly/dash/pull/3627)) Make dropdowns searchable wheen focused, without requiring to open them first -- [#3656][(](https://github.com/plotly/dash/pull/3656)) Improved dropdown performance for large collections of options -- [#3643][(](https://github.com/plotly/dash/pull/3643)) Fix multiselect dropdown with components as labels -- [#3609][(](https://github.com/plotly/dash/pull/3609)) Add backward compat alias for _Wildcard -- [#3672][(](https://github.com/plotly/dash/pull/3672)) Improve browser performance when app contains a large number of pattern matching callback callbacks. Exposes an api endpoint to fetch the latest computeGraph call. +- [#3660](https://github.com/plotly/dash/pull/3660) Allow same date to be selected for both start and end in DatePickerRange components +- [#3600](https://github.com/plotly/dash/pull/3600) DatePicker support for the Moment.js `Y` year token +- [#3627](https://github.com/plotly/dash/pull/3627) Make dropdowns searchable wheen focused, without requiring to open them first +- [#3656](https://github.com/plotly/dash/pull/3656) Improved dropdown performance for large collections of options +- [#3643](https://github.com/plotly/dash/pull/3643) Fix multiselect dropdown with components as labels +- [#3609](https://github.com/plotly/dash/pull/3609) Add backward compat alias for _Wildcard +- [#3672](https://github.com/plotly/dash/pull/3672) Improve browser performance when app contains a large number of pattern matching callback callbacks. Exposes an api endpoint to fetch the latest computeGraph call. ## [4.0.0] - 2026-02-03 @@ -93,8 +96,8 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## Added -- [#3568]((https://github.com/plotly/dash/pull/3568) Added `children` and `copied_children` props to `dcc.Clipboard` to customize the button contents before and after copying. -- [#3534]((https://github.com/plotly/dash/pull/3534) Adds `playsInline` prop to `html.Video`. Based on [#2338]((https://github.com/plotly/dash/pull/2338) +- [#3568](https://github.com/plotly/dash/pull/3568) Added `children` and `copied_children` props to `dcc.Clipboard` to customize the button contents before and after copying. +- [#3534](https://github.com/plotly/dash/pull/3534) Adds `playsInline` prop to `html.Video`. Based on [#2338](https://github.com/plotly/dash/pull/2338) - [#3541](https://github.com/plotly/dash/pull/3541) Add `attributes` dictionary to be be formatted on script/link (_js_dist/_css_dist) tags of the index, allows for `type="module"` or `type="importmap"`. [#3538](https://github.com/plotly/dash/issues/3538) - [#3542](https://github.com/plotly/dash/pull/3542) Add hidden=True to dash pages callback. - [#3564](https://github.com/plotly/dash/pull/3564) Add new parameter `hide_all_callbacks` to `run()`. Closes [#3493](https://github.com/plotly/dash/issues/3493) @@ -151,7 +154,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). # [3.1.1] - 2025-06-29 ## Fixed -[#3351](https://github.com/plotly/dash/pull/3351) Fix multi-page app with `suppress_callback_exceptions=True` +- [#3351](https://github.com/plotly/dash/pull/3351) Fix multi-page app with `suppress_callback_exceptions=True` ## [3.1.0] - 2025-06-27 From 8da44c161ae62c429a31623b456e5ea894cbdb25 Mon Sep 17 00:00:00 2001 From: Ian MacDougall Murray Date: Sat, 28 Mar 2026 15:49:04 +0000 Subject: [PATCH 132/297] fix: use attribute selector for dict id in loading test The test_ldcp010_loading_component_target_components test used an ID selector built from stringify_id(...), but this contains special characters that are not safe in a CSS #id selector. Now switched to an attribute selector form so Selenium can find the element. This surfaced after duplicate test names were resolved in a previous commit, which allowed this test to run and expose the selector issue. --- .../tests/integration/loading/test_loading_component.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dash-core-components/tests/integration/loading/test_loading_component.py b/components/dash-core-components/tests/integration/loading/test_loading_component.py index 165ecbc524..dd7946e7e8 100644 --- a/components/dash-core-components/tests/integration/loading/test_loading_component.py +++ b/components/dash-core-components/tests/integration/loading/test_loading_component.py @@ -461,7 +461,7 @@ def updateDiv2(n_clicks): dash_dcc.start_server(app) - btn1id = "#" + stringify_id({"type": "button", "index": "one"}) + btn1id = "[id='" + stringify_id({"type": "button", "index": "one"}) + "']" dash_dcc.wait_for_text_to_equal(btn1id, "content 1") From b18fdfd33149ee7cc11867b9222bbc5525a4f246 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 1 Apr 2026 09:14:46 -0400 Subject: [PATCH 133/297] put 14 days minimum release age for dependabot --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ad62dcef38..4dc5b57ddd 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,6 +10,7 @@ updates: npm-dependencies: patterns: - "*" + minimum-release-age: 14 ignore: # Ignore @plotly packages - dependency-name: "@plotly/*" @@ -24,6 +25,7 @@ updates: npm-dependencies: patterns: - "*" + minimum-release-age: 14 # Components - dash-core-components - package-ecosystem: "npm" @@ -35,6 +37,7 @@ updates: npm-dependencies: patterns: - "*" + minimum-release-age: 14 # Components - dash-html-components - package-ecosystem: "npm" @@ -46,6 +49,7 @@ updates: npm-dependencies: patterns: - "*" + minimum-release-age: 14 # Components - dash-table - package-ecosystem: "npm" @@ -57,6 +61,7 @@ updates: npm-dependencies: patterns: - "*" + minimum-release-age: 14 # Python dependencies - package-ecosystem: "pip" @@ -68,3 +73,4 @@ updates: pip-dependencies: patterns: - "*" + minimum-release-age: 14 From ee1fb3fd585255ac9b144a4f6bddbc70986bb933 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 1 Apr 2026 09:17:04 -0400 Subject: [PATCH 134/297] group up dependabot security updates --- .github/dependabot.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4dc5b57ddd..26309972a1 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,9 +8,14 @@ updates: day: "monday" groups: npm-dependencies: + applies-to: version-updates patterns: - "*" minimum-release-age: 14 + npm-dependencies-security: + applies-to: security-updates + patterns: + - "*" ignore: # Ignore @plotly packages - dependency-name: "@plotly/*" @@ -23,9 +28,14 @@ updates: day: "monday" groups: npm-dependencies: + applies-to: version-updates patterns: - "*" minimum-release-age: 14 + npm-dependencies-security: + applies-to: security-updates + patterns: + - "*" # Components - dash-core-components - package-ecosystem: "npm" @@ -35,9 +45,14 @@ updates: day: "monday" groups: npm-dependencies: + applies-to: version-updates patterns: - "*" minimum-release-age: 14 + npm-dependencies-security: + applies-to: security-updates + patterns: + - "*" # Components - dash-html-components - package-ecosystem: "npm" @@ -47,9 +62,14 @@ updates: day: "monday" groups: npm-dependencies: + applies-to: version-updates patterns: - "*" minimum-release-age: 14 + npm-dependencies-security: + applies-to: security-updates + patterns: + - "*" # Components - dash-table - package-ecosystem: "npm" @@ -59,9 +79,14 @@ updates: day: "monday" groups: npm-dependencies: + applies-to: version-updates patterns: - "*" minimum-release-age: 14 + npm-dependencies-security: + applies-to: security-updates + patterns: + - "*" # Python dependencies - package-ecosystem: "pip" @@ -71,6 +96,11 @@ updates: day: "monday" groups: pip-dependencies: + applies-to: version-updates patterns: - "*" minimum-release-age: 14 + pip-dependencies-security: + applies-to: security-updates + patterns: + - "*" From 7fa111ff4defdcaaad0054e813191c1b777a1c55 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 1 Apr 2026 09:24:22 -0400 Subject: [PATCH 135/297] only allow safe to update dcc dependabot --- .github/dependabot.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 26309972a1..0ee31aba24 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -53,6 +53,18 @@ updates: applies-to: security-updates patterns: - "*" + # Only auto-update these packages for version updates + allow: + - dependency-name: "date-fns" + - dependency-name: "file-saver" + - dependency-name: "ramda" + - dependency-name: "react-window" + - dependency-name: "@radix-ui/*" + - dependency-name: "@types/*" + - dependency-name: "@babel/*" + - dependency-name: "eslint*" + - dependency-name: "webpack*" + - dependency-name: "typescript" # Components - dash-html-components - package-ecosystem: "npm" From 2ee42bbe733c897f97767e916a7e1ad25a71bd08 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 1 Apr 2026 09:36:29 -0400 Subject: [PATCH 136/297] narrow other dependencies --- .github/dependabot.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0ee31aba24..8b96450063 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -36,6 +36,16 @@ updates: applies-to: security-updates patterns: - "*" + allow: + - dependency-name: "@types/*" + - dependency-name: "@babel/*" + - dependency-name: "babel-loader" + - dependency-name: "ts-loader" + - dependency-name: "cookie" + - dependency-name: "eslint*" + - dependency-name: "prettier" + - dependency-name: "webpack*" + - dependency-name: "typescript" # Components - dash-core-components - package-ecosystem: "npm" @@ -62,7 +72,9 @@ updates: - dependency-name: "@radix-ui/*" - dependency-name: "@types/*" - dependency-name: "@babel/*" + - dependency-name: "babel-loader" - dependency-name: "eslint*" + - dependency-name: "prettier" - dependency-name: "webpack*" - dependency-name: "typescript" @@ -82,6 +94,13 @@ updates: applies-to: security-updates patterns: - "*" + allow: + - dependency-name: "@types/*" + - dependency-name: "@babel/*" + - dependency-name: "babel-loader" + - dependency-name: "eslint*" + - dependency-name: "webpack*" + - dependency-name: "typescript" # Components - dash-table - package-ecosystem: "npm" @@ -99,6 +118,18 @@ updates: applies-to: security-updates patterns: - "*" + allow: + - dependency-name: "@types/*" + - dependency-name: "@babel/*" + - dependency-name: "babel-loader" + - dependency-name: "ts-loader" + - dependency-name: "css-loader" + - dependency-name: "less" + - dependency-name: "less-loader" + - dependency-name: "eslint*" + - dependency-name: "prettier" + - dependency-name: "webpack*" + - dependency-name: "typescript" # Python dependencies - package-ecosystem: "pip" From 7c8c47dacf8630a2f4f43063ec474594274d01fa Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 1 Apr 2026 09:50:59 -0400 Subject: [PATCH 137/297] exclude plotly directory --- .github/dependabot.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8b96450063..ad6e195987 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -2,7 +2,9 @@ version: 2 updates: # Root package dependencies - package-ecosystem: "npm" - directory: "/" + directories: + - "/" + - "!/@plotly/*" schedule: interval: "weekly" day: "monday" @@ -16,9 +18,6 @@ updates: applies-to: security-updates patterns: - "*" - ignore: - # Ignore @plotly packages - - dependency-name: "@plotly/*" # Dash renderer - package-ecosystem: "npm" From 26c6752134fc53e3788c940cc0702007122a8468 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 1 Apr 2026 12:02:31 -0400 Subject: [PATCH 138/297] minimum-release-age -> cooldown --- .github/dependabot.yml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ad6e195987..e243cae08d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,12 +8,13 @@ updates: schedule: interval: "weekly" day: "monday" + cooldown: + default-days: 14 groups: npm-dependencies: applies-to: version-updates patterns: - "*" - minimum-release-age: 14 npm-dependencies-security: applies-to: security-updates patterns: @@ -25,12 +26,13 @@ updates: schedule: interval: "weekly" day: "monday" + cooldown: + default-days: 14 groups: npm-dependencies: applies-to: version-updates patterns: - "*" - minimum-release-age: 14 npm-dependencies-security: applies-to: security-updates patterns: @@ -52,12 +54,13 @@ updates: schedule: interval: "weekly" day: "monday" + cooldown: + default-days: 14 groups: npm-dependencies: applies-to: version-updates patterns: - "*" - minimum-release-age: 14 npm-dependencies-security: applies-to: security-updates patterns: @@ -83,12 +86,13 @@ updates: schedule: interval: "weekly" day: "monday" + cooldown: + default-days: 14 groups: npm-dependencies: applies-to: version-updates patterns: - "*" - minimum-release-age: 14 npm-dependencies-security: applies-to: security-updates patterns: @@ -107,12 +111,13 @@ updates: schedule: interval: "weekly" day: "monday" + cooldown: + default-days: 14 groups: npm-dependencies: applies-to: version-updates patterns: - "*" - minimum-release-age: 14 npm-dependencies-security: applies-to: security-updates patterns: @@ -136,12 +141,13 @@ updates: schedule: interval: "weekly" day: "monday" + cooldown: + default-days: 14 groups: pip-dependencies: applies-to: version-updates patterns: - "*" - minimum-release-age: 14 pip-dependencies-security: applies-to: security-updates patterns: From cb126710d3891ddf97972f59b1c86769365fbc88 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 2 Apr 2026 09:12:56 -0400 Subject: [PATCH 139/297] fix dcc build --- .../dash-core-components/package-lock.json | 110 ++++-------------- components/dash-core-components/package.json | 2 +- .../dash-core-components/webpack.config.js | 2 +- 3 files changed, 23 insertions(+), 91 deletions(-) diff --git a/components/dash-core-components/package-lock.json b/components/dash-core-components/package-lock.json index 6496a64287..e88eb0b229 100644 --- a/components/dash-core-components/package-lock.json +++ b/components/dash-core-components/package-lock.json @@ -3757,7 +3757,6 @@ "version": "0.3.11", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -4785,7 +4784,6 @@ "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -4795,7 +4793,6 @@ "version": "3.7.7", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -4805,7 +4802,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, "license": "MIT" }, "node_modules/@types/fast-isnumeric": { @@ -4883,8 +4879,7 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "node_modules/@types/json5": { "version": "0.0.29", @@ -4896,7 +4891,6 @@ "version": "22.13.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", - "dev": true, "dependencies": { "undici-types": "~6.20.0" } @@ -4905,7 +4899,7 @@ "version": "15.7.15", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@types/ramda": { @@ -4922,7 +4916,7 @@ "version": "16.14.68", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.68.tgz", "integrity": "sha512-GEe60JEJg7wIvnUzXBX/A++ieyum98WXF/q2oFr1RVar8OK8JxU/uEYBXgv7jF87SoaDdxtAq3KUaJFlu02ziw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -4934,7 +4928,7 @@ "version": "16.9.25", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.25.tgz", "integrity": "sha512-ZK//eAPhwft9Ul2/Zj+6O11YR6L4JX0J2sVeBC9Ft7x7HFN7xk7yUV/zDxqV6rjvqgl6r8Dq7oQImxtyf/Mzcw==", - "dev": true, + "devOptional": true, "license": "MIT", "peerDependencies": { "@types/react": "^16.0.0" @@ -4964,7 +4958,7 @@ "version": "0.16.8", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@types/semver": { @@ -5287,7 +5281,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" @@ -5296,26 +5289,22 @@ "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", @@ -5325,14 +5314,12 @@ "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -5344,7 +5331,6 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -5353,7 +5339,6 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -5361,14 +5346,12 @@ "node_modules/@webassemblyjs/utf8": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -5384,7 +5367,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", @@ -5397,7 +5379,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -5409,7 +5390,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", @@ -5423,7 +5403,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" @@ -5476,14 +5455,12 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "node_modules/abort-controller": { "version": "3.0.0", @@ -5547,7 +5524,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, "dependencies": { "ajv": "^8.0.0" }, @@ -5564,7 +5540,6 @@ "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -5579,8 +5554,7 @@ "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/ansi-escapes": { "version": "4.3.2", @@ -6400,8 +6374,7 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/buffer-xor": { "version": "1.0.3", @@ -6619,7 +6592,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, "engines": { "node": ">=6.0" } @@ -7114,7 +7086,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/d3-format": { @@ -7483,7 +7455,6 @@ "version": "5.18.2", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", - "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -7695,7 +7666,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", - "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { @@ -8200,7 +8170,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -8212,7 +8181,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -8321,8 +8289,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.3.2", @@ -8735,7 +8702,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/globalthis": { @@ -8799,8 +8765,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/graphemer": { "version": "1.4.0", @@ -12134,7 +12099,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", @@ -12149,7 +12113,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -12159,7 +12122,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -12261,8 +12223,7 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -12394,7 +12355,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.11.5" @@ -12587,8 +12547,7 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/merge2": { "version": "1.4.1", @@ -12634,7 +12593,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -12643,7 +12601,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -13915,7 +13872,6 @@ "version": "16.14.0", "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", - "dev": true, "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -13965,7 +13921,6 @@ "version": "16.14.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "dev": true, "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -14368,7 +14323,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -14661,7 +14615,6 @@ "version": "0.19.1", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "dev": true, "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -14671,7 +14624,6 @@ "version": "4.3.3", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", @@ -14691,7 +14643,6 @@ "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -14707,7 +14658,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -14718,8 +14668,7 @@ "node_modules/schema-utils/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/semver": { "version": "6.3.1", @@ -14733,7 +14682,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" @@ -14939,7 +14887,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -14958,7 +14905,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", @@ -15378,7 +15324,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -15392,7 +15337,6 @@ "version": "5.46.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -15411,7 +15355,6 @@ "version": "5.3.16", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", @@ -15446,7 +15389,6 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -15459,7 +15401,6 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, "license": "MIT" }, "node_modules/test-exclude": { @@ -15964,8 +15905,7 @@ "node_modules/undici-types": { "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "dev": true + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" }, "node_modules/unherit": { "version": "1.1.3", @@ -16128,7 +16068,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -16290,7 +16229,6 @@ "version": "2.4.4", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", - "dev": true, "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", @@ -16314,7 +16252,6 @@ "version": "5.104.1", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", - "dev": true, "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", @@ -16431,7 +16368,6 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" @@ -16441,7 +16377,6 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -16454,7 +16389,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" @@ -16467,7 +16401,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -16480,7 +16413,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "engines": { "node": ">=4.0" } diff --git a/components/dash-core-components/package.json b/components/dash-core-components/package.json index ac9d88c80c..ffe7de1d2f 100644 --- a/components/dash-core-components/package.json +++ b/components/dash-core-components/package.json @@ -126,6 +126,6 @@ "react-dom": "16 - 19" }, "browserslist": [ - "last 9 years and not dead" + "last 10 years and not dead" ] } diff --git a/components/dash-core-components/webpack.config.js b/components/dash-core-components/webpack.config.js index bcdc1d3489..c2ac1a36ad 100644 --- a/components/dash-core-components/webpack.config.js +++ b/components/dash-core-components/webpack.config.js @@ -98,7 +98,7 @@ module.exports = (env, argv) => { presets: [ ['@babel/preset-env', { targets: { - browsers: ['last 9 years and not dead'] + browsers: ['last 10 years and not dead'] }, modules: false }] From b97a99faeba7cdb6533ac12d8178335c2b8cd855 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 2 Apr 2026 09:27:44 -0400 Subject: [PATCH 140/297] bump browserlist dash-table --- components/dash-table/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dash-table/package.json b/components/dash-table/package.json index b5d65499e9..295517a4c9 100644 --- a/components/dash-table/package.json +++ b/components/dash-table/package.json @@ -119,6 +119,6 @@ "npm": ">=6.1.0" }, "browserslist": [ - "last 9 years and not dead" + "last 10 years and not dead" ] } From e97d6d6ebdf58cc0af5ae453638576b11f1e78e4 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 2 Apr 2026 09:31:43 -0400 Subject: [PATCH 141/297] npm audit fix --- .../dash-core-components/package-lock.json | 574 +++--- .../dash-html-components/package-lock.json | 391 ++-- components/dash-table/package-lock.json | 553 +++--- dash/dash-renderer/package-lock.json | 1710 +++++++++-------- 4 files changed, 1705 insertions(+), 1523 deletions(-) diff --git a/components/dash-core-components/package-lock.json b/components/dash-core-components/package-lock.json index e88eb0b229..aa57e966ce 100644 --- a/components/dash-core-components/package-lock.json +++ b/components/dash-core-components/package-lock.json @@ -2439,9 +2439,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "engines": { "node": ">=12" @@ -2451,9 +2451,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "engines": { "node": ">=12" @@ -2486,12 +2486,12 @@ } }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" @@ -3131,11 +3131,10 @@ } }, "node_modules/@jest/environment-jsdom-abstract/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -5505,9 +5504,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -5537,14 +5536,14 @@ } }, "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -5779,20 +5778,19 @@ } }, "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" + "minimalistic-assert": "^1.0.0" } }, "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" }, "node_modules/assert": { "version": "2.1.0", @@ -6177,15 +6175,14 @@ } }, "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", + "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==" }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "license": "MIT", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6244,46 +6241,74 @@ } }, "node_modules/browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", "dependencies": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/browserify-sign": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", - "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", + "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", "dependencies": { - "bn.js": "^5.2.1", - "browserify-rsa": "^4.1.0", + "bn.js": "^5.2.2", + "browserify-rsa": "^4.1.1", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.4", + "elliptic": "^6.6.1", "inherits": "^2.0.4", - "parse-asn1": "^5.1.6", - "readable-stream": "^3.6.2", + "parse-asn1": "^5.1.9", + "readable-stream": "^2.3.8", "safe-buffer": "^5.2.1" }, "engines": { - "node": ">= 4" + "node": ">= 0.10" } }, + "node_modules/browserify-sign/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/browserify-sign/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/browserify-sign/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" } }, + "node_modules/browserify-sign/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/browserify-zlib": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", @@ -6613,12 +6638,16 @@ } }, "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/cjs-module-lexer": { @@ -6816,8 +6845,7 @@ "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "node_modules/create-ecdh": { "version": "4.0.4", @@ -6829,9 +6857,9 @@ } }, "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" }, "node_modules/create-hash": { "version": "1.2.0", @@ -6970,24 +6998,40 @@ } }, "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", + "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" + "browserify-cipher": "^1.0.1", + "browserify-sign": "^4.2.3", + "create-ecdh": "^4.0.4", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "diffie-hellman": "^5.0.3", + "hash-base": "~3.0.4", + "inherits": "^2.0.4", + "pbkdf2": "^3.1.2", + "public-encrypt": "^4.0.3", + "randombytes": "^2.1.0", + "randomfill": "^1.0.4" }, "engines": { - "node": "*" + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/crypto-browserify/node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/css-loader": { @@ -7275,9 +7319,9 @@ } }, "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" }, "node_modules/dir-glob": { "version": "3.0.1", @@ -7423,9 +7467,9 @@ } }, "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" }, "node_modules/emittery": { "version": "0.13.1", @@ -8327,6 +8371,21 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -8469,9 +8528,9 @@ } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true }, "node_modules/fn.name": { @@ -8774,11 +8833,10 @@ "dev": true }, "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", "dev": true, - "license": "MIT", "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", @@ -8871,31 +8929,56 @@ } }, "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", "dependencies": { "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" }, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, + "node_modules/hash-base/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/hash-base/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hash-base/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/hash-base/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" } }, + "node_modules/hash-base/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", @@ -9920,16 +10003,13 @@ } }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -10852,11 +10932,10 @@ } }, "node_modules/jest-environment-jsdom/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -12145,9 +12224,9 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "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.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "dependencies": { "argparse": "^2.0.1" @@ -12585,9 +12664,9 @@ } }, "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" }, "node_modules/mime-db": { "version": "1.52.0", @@ -12637,9 +12716,9 @@ "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" }, "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==", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -12657,9 +12736,9 @@ } }, "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -13189,6 +13268,12 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -13207,15 +13292,18 @@ } }, "node_modules/parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", + "integrity": "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==", + "dependencies": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "pbkdf2": "^3.1.5", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/parse-entities": { @@ -13306,29 +13394,26 @@ "dev": true }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/path-type": { "version": "3.0.0", @@ -13352,51 +13437,19 @@ } }, "node_modules/pbkdf2": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.3.tgz", - "integrity": "sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==", - "license": "MIT", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", "dependencies": { - "create-hash": "~1.1.3", + "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "ripemd160": "=2.0.1", + "ripemd160": "^2.0.3", "safe-buffer": "^5.2.1", - "sha.js": "^2.4.11", - "to-buffer": "^1.2.0" + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" }, "engines": { - "node": ">=0.12" - } - }, - "node_modules/pbkdf2/node_modules/create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==", - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "sha.js": "^2.4.0" - } - }, - "node_modules/pbkdf2/node_modules/hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1" - } - }, - "node_modules/pbkdf2/node_modules/ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==", - "license": "MIT", - "dependencies": { - "hash-base": "^2.0.0", - "inherits": "^2.0.1" + "node": ">= 0.10" } }, "node_modules/picocolors": { @@ -13405,9 +13458,9 @@ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "engines": { "node": ">=8.6" @@ -13729,8 +13782,7 @@ "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "node_modules/prompts": { "version": "2.4.2", @@ -13770,9 +13822,9 @@ } }, "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" }, "node_modules/punycode": { "version": "2.3.1", @@ -13800,11 +13852,11 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -14417,11 +14469,10 @@ } }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -14443,34 +14494,33 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -14492,12 +14542,15 @@ } }, "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" } }, "node_modules/rrweb-cssom": { @@ -14596,7 +14649,8 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "node_modules/saxes": { "version": "6.0.0", @@ -14640,14 +14694,14 @@ } }, "node_modules/schema-utils/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -14678,15 +14732,6 @@ "semver": "bin/semver.js" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -14724,15 +14769,22 @@ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" }, "bin": { "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/shallow-clone": { @@ -15352,15 +15404,13 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", - "license": "MIT", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", + "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "engines": { @@ -15513,10 +15563,9 @@ "license": "BSD-3-Clause" }, "node_modules/to-buffer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", - "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", - "license": "MIT", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", "dependencies": { "isarray": "^2.0.5", "safe-buffer": "^5.2.1", @@ -16068,6 +16117,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } diff --git a/components/dash-html-components/package-lock.json b/components/dash-html-components/package-lock.json index ae1e59cf2e..22e9d65461 100644 --- a/components/dash-html-components/package-lock.json +++ b/components/dash-html-components/package-lock.json @@ -1889,9 +1889,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "engines": { "node": ">=12" @@ -1901,9 +1901,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "engines": { "node": ">=12" @@ -1936,12 +1936,12 @@ } }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" @@ -2410,9 +2410,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -2443,15 +2443,15 @@ } }, "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -2763,11 +2763,10 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3997,6 +3996,22 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -4117,9 +4132,9 @@ } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true }, "node_modules/fn.name": { @@ -5116,16 +5131,13 @@ } }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -5180,9 +5192,9 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "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.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "dependencies": { "argparse": "^2.0.1" @@ -5559,9 +5571,9 @@ } }, "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, "dependencies": { "brace-expansion": "^1.1.7" @@ -5580,9 +5592,9 @@ } }, "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -5968,6 +5980,12 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6027,29 +6045,26 @@ "dev": true }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/path-type": { "version": "3.0.0", @@ -6079,9 +6094,9 @@ "dev": true }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "engines": { "node": ">=8.6" @@ -6266,16 +6281,6 @@ "url": "https://opencollective.com/ramda" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/react": { "version": "16.14.0", "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", @@ -6593,11 +6598,10 @@ } }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -6619,34 +6623,33 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -6785,15 +6788,15 @@ } }, "node_modules/schema-utils/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -6827,16 +6830,6 @@ "semver": "bin/semver.js" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/set-function-length": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", @@ -7257,16 +7250,14 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", + "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "engines": { @@ -8440,7 +8431,8 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true + "dev": true, + "requires": {} }, "@babel/plugin-syntax-import-assertions": { "version": "7.28.6", @@ -9283,15 +9275,15 @@ }, "dependencies": { "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true }, "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true }, "emoji-regex": { @@ -9312,12 +9304,12 @@ } }, "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "requires": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^6.2.2" } }, "wrap-ansi": { @@ -9673,19 +9665,22 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true + "dev": true, + "requires": {} }, "@webpack-cli/info": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true + "dev": true, + "requires": {} }, "@webpack-cli/serve": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true + "dev": true, + "requires": {} }, "@xtuc/ieee754": { "version": "1.2.0", @@ -9709,12 +9704,13 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "dev": true, + "requires": {} }, "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -9733,15 +9729,15 @@ }, "dependencies": { "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" } }, "json-schema-traverse": { @@ -9968,9 +9964,9 @@ "dev": true }, "brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -10918,6 +10914,12 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true + }, "fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -11006,9 +11008,9 @@ } }, "flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true }, "fn.name": { @@ -11714,9 +11716,9 @@ } }, "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "requires": { "@isaacs/cliui": "^8.0.2", @@ -11757,9 +11759,9 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "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.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "requires": { "argparse": "^2.0.1" @@ -12062,9 +12064,9 @@ "dev": true }, "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, "requires": { "brace-expansion": "^1.1.7" @@ -12077,9 +12079,9 @@ "dev": true }, "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true }, "mkdirp": { @@ -12374,6 +12376,12 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -12418,19 +12426,19 @@ "dev": true }, "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "dependencies": { "lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true } } @@ -12459,9 +12467,9 @@ "dev": true }, "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true }, "pidtree": { @@ -12569,15 +12577,6 @@ "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.30.1.tgz", "integrity": "sha512-tEF5I22zJnuclswcZMc8bDIrwRHRzf+NqVEmqg50ShAZMP7MWeR/RGDthfM/p+BlqvF2fXAzpn8i+SJcYD3alw==" }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, "react": { "version": "16.14.0", "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", @@ -12810,9 +12809,9 @@ }, "dependencies": { "brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, "requires": { "balanced-match": "^1.0.0" @@ -12829,25 +12828,26 @@ } }, "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "requires": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" } }, "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "requires": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" } }, "signal-exit": { @@ -12925,15 +12925,15 @@ }, "dependencies": { "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" } }, "ajv-keywords": { @@ -12959,15 +12959,6 @@ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true }, - "serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, "set-function-length": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", @@ -13301,15 +13292,14 @@ } }, "terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", + "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", "terser": "^5.31.1" } }, @@ -13587,7 +13577,8 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "dev": true + "dev": true, + "requires": {} }, "eslint-scope": { "version": "5.1.1", diff --git a/components/dash-table/package-lock.json b/components/dash-table/package-lock.json index 4555879632..77d8f45f39 100644 --- a/components/dash-table/package-lock.json +++ b/components/dash-table/package-lock.json @@ -3245,11 +3245,10 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3280,11 +3279,10 @@ } }, "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -3452,11 +3450,10 @@ } }, "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", - "dev": true, - "license": "MIT" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "dev": true }, "node_modules/assert": { "version": "2.1.0", @@ -3677,31 +3674,29 @@ } }, "node_modules/bn.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", - "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", - "dev": true, - "license": "MIT" + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", + "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", + "dev": true }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "dev": true, - "license": "MIT", "dependencies": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8", @@ -3718,6 +3713,26 @@ "ms": "2.0.0" } }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -3725,6 +3740,15 @@ "dev": true, "license": "MIT" }, + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/bonjour-service": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", @@ -3737,11 +3761,10 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3840,25 +3863,23 @@ } }, "node_modules/browserify-sign": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz", - "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", + "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", "dev": true, - "license": "ISC", "dependencies": { - "bn.js": "^5.2.1", - "browserify-rsa": "^4.1.0", + "bn.js": "^5.2.2", + "browserify-rsa": "^4.1.1", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.5", - "hash-base": "~3.0", + "elliptic": "^6.6.1", "inherits": "^2.0.4", - "parse-asn1": "^5.1.7", + "parse-asn1": "^5.1.9", "readable-stream": "^2.3.8", "safe-buffer": "^5.2.1" }, "engines": { - "node": ">= 0.12" + "node": ">= 0.10" } }, "node_modules/browserify-sign/node_modules/isarray": { @@ -4726,11 +4747,10 @@ } }, "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", - "dev": true, - "license": "MIT" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "dev": true }, "node_modules/create-hash": { "version": "1.2.0", @@ -5150,11 +5170,10 @@ "license": "MIT" }, "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -5172,11 +5191,10 @@ } }, "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", - "dev": true, - "license": "MIT" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "dev": true }, "node_modules/dir-glob": { "version": "3.0.1", @@ -5296,11 +5314,10 @@ } }, "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", - "dev": true, - "license": "MIT" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "dev": true }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -5940,40 +5957,39 @@ } }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "dev": true, - "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", + "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.13.0", + "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", + "send": "~0.19.0", + "serve-static": "~1.16.2", "setprototypeof": "1.2.0", - "statuses": "2.0.1", + "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -5986,16 +6002,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/express/node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -6356,11 +6362,10 @@ } }, "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==", - "dev": true, - "license": "ISC" + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true }, "node_modules/fn.name": { "version": "1.1.0", @@ -7083,7 +7088,6 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, - "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -8118,15 +8122,13 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "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.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -8386,23 +8388,21 @@ } }, "node_modules/karma-webpack/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/karma-webpack/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, - "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -8611,11 +8611,10 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, - "license": "MIT" + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true }, "node_modules/lodash.debounce": { "version": "4.0.8", @@ -8704,7 +8703,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -8884,11 +8882,10 @@ } }, "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", - "dev": true, - "license": "MIT" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "dev": true }, "node_modules/mime": { "version": "2.6.0", @@ -8951,11 +8948,10 @@ "license": "MIT" }, "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": { "brace-expansion": "^1.1.7" }, @@ -9033,21 +9029,19 @@ } }, "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/mocha/node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -9074,11 +9068,10 @@ } }, "node_modules/mocha/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -9210,11 +9203,10 @@ } }, "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", + "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", "dev": true, - "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" } @@ -9440,7 +9432,6 @@ "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" @@ -9730,17 +9721,15 @@ } }, "node_modules/parse-asn1": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", - "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", + "integrity": "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==", "dev": true, - "license": "ISC", "dependencies": { "asn1.js": "^4.10.1", "browserify-aes": "^1.2.0", "evp_bytestokey": "^1.0.3", - "hash-base": "~3.0", - "pbkdf2": "^3.1.2", + "pbkdf2": "^3.1.5", "safe-buffer": "^5.2.1" }, "engines": { @@ -9850,11 +9839,10 @@ "license": "ISC" }, "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "dev": true, - "license": "MIT" + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "dev": true }, "node_modules/path-type": { "version": "4.0.0", @@ -9877,55 +9865,20 @@ } }, "node_modules/pbkdf2": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.3.tgz", - "integrity": "sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", "dev": true, - "license": "MIT", "dependencies": { - "create-hash": "~1.1.3", + "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "ripemd160": "=2.0.1", + "ripemd160": "^2.0.3", "safe-buffer": "^5.2.1", - "sha.js": "^2.4.11", - "to-buffer": "^1.2.0" + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" }, "engines": { - "node": ">=0.12" - } - }, - "node_modules/pbkdf2/node_modules/create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "sha.js": "^2.4.0" - } - }, - "node_modules/pbkdf2/node_modules/hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1" - } - }, - "node_modules/pbkdf2/node_modules/ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==", - "dev": true, - "license": "MIT", - "dependencies": { - "hash-base": "^2.0.0", - "inherits": "^2.0.1" + "node": ">= 0.10" } }, "node_modules/picocolors": { @@ -9936,11 +9889,10 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.6" }, @@ -10258,7 +10210,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -10314,11 +10265,10 @@ } }, "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", - "dev": true, - "license": "MIT" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "dev": true }, "node_modules/punycode": { "version": "1.4.1", @@ -10338,13 +10288,12 @@ } }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -10426,17 +10375,45 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "dev": true, - "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/raw-body/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -10561,7 +10538,6 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, "license": "MIT" }, "node_modules/react-select": { @@ -10921,11 +10897,10 @@ } }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -10948,11 +10923,11 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, - "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -10969,13 +10944,12 @@ } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, - "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -10998,16 +10972,75 @@ } }, "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", "dev": true, - "license": "MIT", "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/hash-base": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/ripemd160/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/ripemd160/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ripemd160/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" } }, + "node_modules/ripemd160/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, "node_modules/run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -11178,11 +11211,10 @@ } }, "node_modules/schema-utils/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -11721,37 +11753,18 @@ } }, "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", "dev": true, - "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" + "debug": "~4.4.1" }, "engines": { "node": ">=10.0.0" } }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/socket.io/node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -12236,16 +12249,14 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", + "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "engines": { diff --git a/dash/dash-renderer/package-lock.json b/dash/dash-renderer/package-lock.json index 231ec4a4b7..1c767f031c 100644 --- a/dash/dash-renderer/package-lock.json +++ b/dash/dash-renderer/package-lock.json @@ -1,12 +1,12 @@ { "name": "dash-renderer", - "version": "3.0.0", + "version": "3.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "dash-renderer", - "version": "3.0.0", + "version": "3.1.0", "license": "MIT", "dependencies": { "@babel/polyfill": "^7.12.1", @@ -2046,9 +2046,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "engines": { "node": ">=12" @@ -2058,9 +2058,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "engines": { "node": ">=12" @@ -2093,12 +2093,12 @@ } }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" @@ -2128,7 +2128,6 @@ "version": "0.3.12", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -2150,7 +2149,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -2159,7 +2157,6 @@ "version": "0.3.11", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -2170,14 +2167,12 @@ "version": "1.5.4", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.29", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2510,15 +2505,6 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/@types/base16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/base16/-/base16-1.0.2.tgz", @@ -2551,7 +2537,6 @@ "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -2561,7 +2546,6 @@ "version": "3.7.7", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -2571,7 +2555,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, "license": "MIT" }, "node_modules/@types/hoist-non-react-statics": { @@ -2587,7 +2570,6 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, "license": "MIT" }, "node_modules/@types/json5": { @@ -2610,8 +2592,7 @@ "node_modules/@types/node": { "version": "20.2.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.3.tgz", - "integrity": "sha512-pg9d0yC4rVNWQzX8U7xb4olIOFuuVL9za3bzMT2pu2SU0SNEi66i2qrvhE2qt0HvkhuCaWJu7pLNOt/Pj8BIrw==", - "dev": true + "integrity": "sha512-pg9d0yC4rVNWQzX8U7xb4olIOFuuVL9za3bzMT2pu2SU0SNEi66i2qrvhE2qt0HvkhuCaWJu7pLNOt/Pj8BIrw==" }, "node_modules/@types/prop-types": { "version": "15.7.5", @@ -2962,7 +2943,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" @@ -2971,26 +2951,22 @@ "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", @@ -3000,14 +2976,12 @@ "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -3019,7 +2993,6 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -3028,7 +3001,6 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -3036,14 +3008,12 @@ "node_modules/@webassemblyjs/utf8": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -3059,7 +3029,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", @@ -3072,7 +3041,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -3084,7 +3052,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", @@ -3098,7 +3065,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" @@ -3151,14 +3117,12 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "node_modules/abort-controller": { "version": "3.0.0", @@ -3207,9 +3171,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -3226,7 +3190,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, "dependencies": { "ajv": "^8.0.0" }, @@ -3240,15 +3203,14 @@ } }, "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -3258,8 +3220,7 @@ "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/ansi-colors": { "version": "4.1.3", @@ -3401,20 +3362,19 @@ } }, "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" + "minimalistic-assert": "^1.0.0" } }, "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" }, "node_modules/assert": { "version": "2.0.0", @@ -3561,7 +3521,6 @@ "version": "2.9.18", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.18.tgz", "integrity": "sha512-e23vBV1ZLfjb9apvfPk4rHVu2ry6RIr2Wfs+O324okSidrX7pTAnEJPCh/O5BtRlr7QtZI7ktOP3vsqr7Z5XoA==", - "dev": true, "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.js" @@ -3577,29 +3536,28 @@ } }, "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", + "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==" }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "dev": true, - "license": "MIT", "dependencies": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8", @@ -3628,11 +3586,10 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3697,46 +3654,74 @@ } }, "node_modules/browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", "dependencies": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/browserify-sign": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", - "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", + "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", "dependencies": { - "bn.js": "^5.2.1", - "browserify-rsa": "^4.1.0", + "bn.js": "^5.2.2", + "browserify-rsa": "^4.1.1", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.4", + "elliptic": "^6.6.1", "inherits": "^2.0.4", - "parse-asn1": "^5.1.6", - "readable-stream": "^3.6.2", + "parse-asn1": "^5.1.9", + "readable-stream": "^2.3.8", "safe-buffer": "^5.2.1" }, "engines": { - "node": ">= 4" + "node": ">= 0.10" } }, + "node_modules/browserify-sign/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/browserify-sign/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/browserify-sign/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" } }, + "node_modules/browserify-sign/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/browserify-zlib": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", @@ -3749,7 +3734,6 @@ "version": "4.28.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3806,7 +3790,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, "license": "MIT" }, "node_modules/buffer-xor": { @@ -3900,7 +3883,6 @@ "version": "1.0.30001766", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz", "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3992,7 +3974,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, "engines": { "node": ">=6.0" } @@ -4194,6 +4175,11 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -4252,9 +4238,9 @@ } }, "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" }, "node_modules/create-hash": { "version": "1.2.0", @@ -4296,24 +4282,40 @@ } }, "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", + "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" + "browserify-cipher": "^1.0.1", + "browserify-sign": "^4.2.3", + "create-ecdh": "^4.0.4", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "diffie-hellman": "^5.0.3", + "hash-base": "~3.0.4", + "inherits": "^2.0.4", + "pbkdf2": "^3.1.2", + "public-encrypt": "^4.0.3", + "randombytes": "^2.1.0", + "randomfill": "^1.0.4" }, "engines": { - "node": "*" + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/crypto-browserify/node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/css-loader": { @@ -4651,9 +4653,9 @@ "dev": true }, "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true, "engines": { "node": ">=0.3.1" @@ -4670,9 +4672,9 @@ } }, "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" }, "node_modules/dir-glob": { "version": "3.0.1", @@ -4816,7 +4818,6 @@ "version": "1.5.279", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.279.tgz", "integrity": "sha512-0bblUU5UNdOt5G7XqGiJtpZMONma6WAfq9vsFmtn9x1+joAObr6x1chfqyxFSDCAFwFhCQDrqeAr6MYdpwJ9Hg==", - "dev": true, "license": "ISC" }, "node_modules/elliptic": { @@ -4834,9 +4835,9 @@ } }, "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -4905,7 +4906,6 @@ "version": "5.18.2", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", - "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -5076,7 +5076,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", - "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { @@ -5140,7 +5139,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -5387,7 +5385,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -5400,7 +5397,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "engines": { "node": ">=4.0" } @@ -5587,7 +5583,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -5599,7 +5594,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -5653,8 +5647,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.2.12", @@ -5692,6 +5685,21 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -5961,9 +5969,9 @@ } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true }, "node_modules/fn.name": { @@ -6216,7 +6224,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/globalthis": { @@ -6278,8 +6285,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/grapheme-splitter": { "version": "1.0.4", @@ -6383,31 +6389,56 @@ } }, "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", "dependencies": { "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" }, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, + "node_modules/hash-base/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/hash-base/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hash-base/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/hash-base/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" } }, + "node_modules/hash-base/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", @@ -6463,25 +6494,29 @@ "dev": true }, "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==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "dev": true, "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, "engines": { "node": ">= 0.8" @@ -7039,16 +7074,13 @@ } }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -7060,7 +7092,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", @@ -7075,7 +7106,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -7085,7 +7115,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -7103,9 +7132,9 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "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.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "dependencies": { "argparse": "^2.0.1" @@ -7136,8 +7165,7 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -7370,7 +7398,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.11.5" @@ -7396,9 +7423,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==" }, "node_modules/lodash.curry": { "version": "4.1.1", @@ -7641,7 +7668,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, "license": "MIT" }, "node_modules/merge2": { @@ -7680,9 +7706,9 @@ } }, "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" }, "node_modules/mime": { "version": "2.6.0", @@ -7700,7 +7726,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -7709,7 +7734,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -7728,9 +7752,9 @@ "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" }, "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, "dependencies": { "brace-expansion": "^1.1.7" @@ -7749,9 +7773,9 @@ } }, "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -7805,11 +7829,10 @@ } }, "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -7872,9 +7895,9 @@ } }, "node_modules/mocha/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -7953,8 +7976,7 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node_modules/nice-try": { "version": "1.0.5", @@ -8014,7 +8036,6 @@ "version": "2.0.27", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "dev": true, "license": "MIT" }, "node_modules/normalize-package-data": { @@ -8160,11 +8181,10 @@ } }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "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" }, @@ -8365,6 +8385,12 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -8383,15 +8409,18 @@ } }, "node_modules/parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", + "integrity": "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==", + "dependencies": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "pbkdf2": "^3.1.5", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/parse-json": { @@ -8460,29 +8489,26 @@ "dev": true }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/path-type": { "version": "4.0.0", @@ -8503,63 +8529,30 @@ } }, "node_modules/pbkdf2": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.3.tgz", - "integrity": "sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==", - "license": "MIT", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", "dependencies": { - "create-hash": "~1.1.3", + "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "ripemd160": "=2.0.1", + "ripemd160": "^2.0.3", "safe-buffer": "^5.2.1", - "sha.js": "^2.4.11", - "to-buffer": "^1.2.0" + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" }, "engines": { - "node": ">=0.12" - } - }, - "node_modules/pbkdf2/node_modules/create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==", - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "sha.js": "^2.4.0" - } - }, - "node_modules/pbkdf2/node_modules/hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1" - } - }, - "node_modules/pbkdf2/node_modules/ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==", - "license": "MIT", - "dependencies": { - "hash-base": "^2.0.0", - "inherits": "^2.0.1" + "node": ">= 0.10" } }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "engines": { "node": ">=8.6" @@ -8800,6 +8793,11 @@ "node": ">= 0.6.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -8824,9 +8822,9 @@ } }, "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" }, "node_modules/punycode": { "version": "2.3.0", @@ -8846,13 +8844,12 @@ } }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -8934,15 +8931,15 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "dev": true, "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" @@ -9260,7 +9257,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -9357,44 +9353,42 @@ } }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/rimraf/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -9404,12 +9398,15 @@ } }, "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" } }, "node_modules/run-parallel": { @@ -9480,7 +9477,17 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "dev": true, + "engines": { + "node": ">=11.0.0" + } }, "node_modules/scheduler": { "version": "0.23.2", @@ -9494,7 +9501,6 @@ "version": "4.3.3", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", @@ -9511,15 +9517,14 @@ } }, "node_modules/schema-utils/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -9530,7 +9535,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -9541,8 +9545,7 @@ "node_modules/schema-utils/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/semver": { "version": "6.3.1", @@ -9652,16 +9655,69 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "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": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "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, + "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, + "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, + "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" @@ -9745,23 +9801,45 @@ } }, "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", "dev": true, "dependencies": { "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" + "debug": "~4.4.1" }, "engines": { "node": ">=10.0.0" } }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -9779,7 +9857,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", @@ -10107,18 +10184,18 @@ "dev": true }, "node_modules/svgo": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.4.tgz", - "integrity": "sha512-T+Xul3JwuJ6VGXKo/p2ndqx1ibxNKnLTvRc1ZTWKCfyKS/GgNjRZcYsK84fxTsy/izr91g/Rwx6fGnVgaFSI5g==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.3.tgz", + "integrity": "sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng==", "dev": true, "dependencies": { - "@trysound/sax": "0.2.0", "commander": "^7.2.0", "css-select": "^5.1.0", - "css-tree": "^2.2.1", + "css-tree": "^2.3.1", "css-what": "^6.1.0", - "csso": "5.0.5", - "picocolors": "^1.0.0" + "csso": "^5.0.5", + "picocolors": "^1.0.0", + "sax": "^1.5.0" }, "bin": { "svgo": "bin/svgo" @@ -10144,7 +10221,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -10158,7 +10234,6 @@ "version": "5.46.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -10174,16 +10249,13 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", - "dev": true, - "license": "MIT", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", + "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "engines": { @@ -10212,7 +10284,6 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -10225,7 +10296,6 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, "license": "MIT" }, "node_modules/text-hex": { @@ -10712,7 +10782,6 @@ "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": [ { "type": "opencollective", @@ -10834,7 +10903,6 @@ "version": "2.4.4", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", - "dev": true, "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", @@ -10848,7 +10916,6 @@ "version": "5.104.1", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", - "dev": true, "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", @@ -10973,7 +11040,6 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" @@ -10983,7 +11049,6 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -10996,7 +11061,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" @@ -11718,7 +11782,8 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true + "dev": true, + "requires": {} }, "@babel/plugin-syntax-import-assertions": { "version": "7.28.6", @@ -12620,15 +12685,15 @@ }, "dependencies": { "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true }, "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true }, "emoji-regex": { @@ -12649,12 +12714,12 @@ } }, "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "requires": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^6.2.2" } }, "wrap-ansi": { @@ -12674,7 +12739,6 @@ "version": "0.3.12", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", - "dev": true, "requires": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" @@ -12693,14 +12757,12 @@ "@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" }, "@jridgewell/source-map": { "version": "0.3.11", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -12709,14 +12771,12 @@ "@jridgewell/sourcemap-codec": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", - "dev": true + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==" }, "@jridgewell/trace-mapping": { "version": "0.3.29", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", - "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -12783,49 +12843,57 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-remove-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-remove-jsx-empty-expression": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-replace-jsx-attribute-value": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-svg-dynamic-title": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-svg-em-dimensions": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-transform-react-native-svg": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-transform-svg-component": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-preset": { "version": "8.1.0", @@ -12905,12 +12973,6 @@ "@svgr/plugin-svgo": "8.1.0" } }, - "@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true - }, "@types/base16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/base16/-/base16-1.0.2.tgz", @@ -12941,7 +13003,6 @@ "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, "requires": { "@types/estree": "*", "@types/json-schema": "*" @@ -12951,7 +13012,6 @@ "version": "3.7.7", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, "requires": { "@types/eslint": "*", "@types/estree": "*" @@ -12960,8 +13020,7 @@ "@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" }, "@types/hoist-non-react-statics": { "version": "3.3.1", @@ -12975,8 +13034,7 @@ "@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "@types/json5": { "version": "0.0.29", @@ -12998,8 +13056,7 @@ "@types/node": { "version": "20.2.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.3.tgz", - "integrity": "sha512-pg9d0yC4rVNWQzX8U7xb4olIOFuuVL9za3bzMT2pu2SU0SNEi66i2qrvhE2qt0HvkhuCaWJu7pLNOt/Pj8BIrw==", - "dev": true + "integrity": "sha512-pg9d0yC4rVNWQzX8U7xb4olIOFuuVL9za3bzMT2pu2SU0SNEi66i2qrvhE2qt0HvkhuCaWJu7pLNOt/Pj8BIrw==" }, "@types/prop-types": { "version": "15.7.5", @@ -13240,7 +13297,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, "requires": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" @@ -13249,26 +13305,22 @@ "@webassemblyjs/floating-point-hex-parser": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==" }, "@webassemblyjs/helper-api-error": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==" }, "@webassemblyjs/helper-buffer": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==" }, "@webassemblyjs/helper-numbers": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, "requires": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", @@ -13278,14 +13330,12 @@ "@webassemblyjs/helper-wasm-bytecode": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==" }, "@webassemblyjs/helper-wasm-section": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, "requires": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -13297,7 +13347,6 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" } @@ -13306,7 +13355,6 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, "requires": { "@xtuc/long": "4.2.2" } @@ -13314,14 +13362,12 @@ "@webassemblyjs/utf8": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==" }, "@webassemblyjs/wasm-edit": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, "requires": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -13337,7 +13383,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, "requires": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", @@ -13350,7 +13395,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, "requires": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -13362,7 +13406,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, "requires": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", @@ -13376,7 +13419,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, "requires": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" @@ -13386,31 +13428,32 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true + "dev": true, + "requires": {} }, "@webpack-cli/info": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true + "dev": true, + "requires": {} }, "@webpack-cli/serve": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true + "dev": true, + "requires": {} }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "abort-controller": { "version": "3.0.0", @@ -13440,12 +13483,13 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "dev": true, + "requires": {} }, "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -13458,28 +13502,25 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, "requires": { "ajv": "^8.0.0" }, "dependencies": { "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "requires": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" } }, "json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" } } }, @@ -13587,20 +13628,19 @@ } }, "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" + "minimalistic-assert": "^1.0.0" }, "dependencies": { "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" } } }, @@ -13700,8 +13740,7 @@ "baseline-browser-mapping": { "version": "2.9.18", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.18.tgz", - "integrity": "sha512-e23vBV1ZLfjb9apvfPk4rHVu2ry6RIr2Wfs+O324okSidrX7pTAnEJPCh/O5BtRlr7QtZI7ktOP3vsqr7Z5XoA==", - "dev": true + "integrity": "sha512-e23vBV1ZLfjb9apvfPk4rHVu2ry6RIr2Wfs+O324okSidrX7pTAnEJPCh/O5BtRlr7QtZI7ktOP3vsqr7Z5XoA==" }, "binary-extensions": { "version": "2.2.0", @@ -13710,28 +13749,28 @@ "dev": true }, "bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", + "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==" }, "body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "dev": true, "requires": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "dependencies": { "debug": { @@ -13758,9 +13797,9 @@ "dev": true }, "brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -13822,38 +13861,70 @@ } }, "browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", "requires": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" } }, "browserify-sign": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", - "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", + "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", "requires": { - "bn.js": "^5.2.1", - "browserify-rsa": "^4.1.0", + "bn.js": "^5.2.2", + "browserify-rsa": "^4.1.1", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.4", + "elliptic": "^6.6.1", "inherits": "^2.0.4", - "parse-asn1": "^5.1.6", - "readable-stream": "^3.6.2", + "parse-asn1": "^5.1.9", + "readable-stream": "^2.3.8", "safe-buffer": "^5.2.1" }, "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } } } } @@ -13870,7 +13941,6 @@ "version": "4.28.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "dev": true, "requires": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -13891,8 +13961,7 @@ "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "buffer-xor": { "version": "1.0.3", @@ -13954,8 +14023,7 @@ "caniuse-lite": { "version": "1.0.30001766", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz", - "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==", - "dev": true + "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==" }, "chai": { "version": "4.3.10", @@ -14011,8 +14079,7 @@ "chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" }, "cipher-base": { "version": "1.0.7", @@ -14181,6 +14248,11 @@ "browserslist": "^4.26.3" } }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -14221,9 +14293,9 @@ }, "dependencies": { "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" } } }, @@ -14264,21 +14336,33 @@ } }, "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", + "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" + "browserify-cipher": "^1.0.1", + "browserify-sign": "^4.2.3", + "create-ecdh": "^4.0.4", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "diffie-hellman": "^5.0.3", + "hash-base": "~3.0.4", + "inherits": "^2.0.4", + "pbkdf2": "^3.1.2", + "public-encrypt": "^4.0.3", + "randombytes": "^2.1.0", + "randomfill": "^1.0.4" + }, + "dependencies": { + "hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "requires": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + } + } } }, "css-loader": { @@ -14520,9 +14604,9 @@ "dev": true }, "diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true }, "diffie-hellman": { @@ -14536,9 +14620,9 @@ }, "dependencies": { "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" } } }, @@ -14649,8 +14733,7 @@ "electron-to-chromium": { "version": "1.5.279", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.279.tgz", - "integrity": "sha512-0bblUU5UNdOt5G7XqGiJtpZMONma6WAfq9vsFmtn9x1+joAObr6x1chfqyxFSDCAFwFhCQDrqeAr6MYdpwJ9Hg==", - "dev": true + "integrity": "sha512-0bblUU5UNdOt5G7XqGiJtpZMONma6WAfq9vsFmtn9x1+joAObr6x1chfqyxFSDCAFwFhCQDrqeAr6MYdpwJ9Hg==" }, "elliptic": { "version": "6.6.1", @@ -14667,9 +14750,9 @@ }, "dependencies": { "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" } } }, @@ -14727,7 +14810,6 @@ "version": "5.18.2", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", - "dev": true, "requires": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -14851,8 +14933,7 @@ "es-module-lexer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", - "dev": true + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==" }, "es-object-atoms": { "version": "1.1.1", @@ -14901,8 +14982,7 @@ "escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" }, "escape-html": { "version": "1.0.3", @@ -15058,7 +15138,8 @@ "version": "8.8.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", - "dev": true + "dev": true, + "requires": {} }, "eslint-import-resolver-node": { "version": "0.3.7", @@ -15194,7 +15275,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "requires": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -15203,8 +15283,7 @@ "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" } } }, @@ -15238,7 +15317,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "requires": { "estraverse": "^5.2.0" } @@ -15246,8 +15324,7 @@ "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" }, "esutils": { "version": "2.0.3", @@ -15289,8 +15366,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { "version": "3.2.12", @@ -15325,6 +15401,11 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==" + }, "fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -15518,9 +15599,9 @@ } }, "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true }, "fn.name": { @@ -15686,8 +15767,7 @@ "glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "globalthis": { "version": "1.0.3", @@ -15728,8 +15808,7 @@ "graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "grapheme-splitter": { "version": "1.0.4", @@ -15800,23 +15879,55 @@ } }, "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", "requires": { "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" }, "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } } } } @@ -15869,22 +15980,22 @@ "dev": true }, "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==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "dev": true, "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "dependencies": { "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true } } @@ -15918,7 +16029,8 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true + "dev": true, + "requires": {} }, "ieee754": { "version": "1.2.1", @@ -16249,9 +16361,9 @@ "dev": true }, "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "requires": { "@isaacs/cliui": "^8.0.2", @@ -16262,7 +16374,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "requires": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -16272,14 +16383,12 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -16292,9 +16401,9 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "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.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "requires": { "argparse": "^2.0.1" @@ -16315,8 +16424,7 @@ "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "json-schema-traverse": { "version": "0.4.1", @@ -16509,8 +16617,7 @@ "loader-runner": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", - "dev": true + "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==" }, "locate-path": { "version": "6.0.0", @@ -16522,9 +16629,9 @@ } }, "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==" }, "lodash.curry": { "version": "4.1.1", @@ -16720,8 +16827,7 @@ "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "merge2": { "version": "1.4.1", @@ -16749,9 +16855,9 @@ }, "dependencies": { "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" } } }, @@ -16764,14 +16870,12 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "requires": { "mime-db": "1.52.0" } @@ -16787,9 +16891,9 @@ "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" }, "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, "requires": { "brace-expansion": "^1.1.7" @@ -16802,9 +16906,9 @@ "dev": true }, "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true }, "mkdirp": { @@ -16845,9 +16949,9 @@ }, "dependencies": { "brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, "requires": { "balanced-match": "^1.0.0" @@ -16888,9 +16992,9 @@ "dev": true }, "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -16946,8 +17050,7 @@ "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "nice-try": { "version": "1.0.5", @@ -17000,8 +17103,7 @@ "node-releases": { "version": "2.0.27", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "dev": true + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==" }, "normalize-package-data": { "version": "2.5.0", @@ -17112,9 +17214,9 @@ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true }, "object-is": { @@ -17256,6 +17358,12 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -17271,15 +17379,15 @@ } }, "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", + "integrity": "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==", + "requires": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "pbkdf2": "^3.1.5", + "safe-buffer": "^5.2.1" } }, "parse-json": { @@ -17330,19 +17438,19 @@ "dev": true }, "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "dependencies": { "lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true } } @@ -17360,58 +17468,27 @@ "dev": true }, "pbkdf2": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.3.tgz", - "integrity": "sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", "requires": { - "create-hash": "~1.1.3", + "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "ripemd160": "=2.0.1", + "ripemd160": "^2.0.3", "safe-buffer": "^5.2.1", - "sha.js": "^2.4.11", - "to-buffer": "^1.2.0" - }, - "dependencies": { - "create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==", - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "sha.js": "^2.4.0" - } - }, - "hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==", - "requires": { - "inherits": "^2.0.1" - } - }, - "ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==", - "requires": { - "hash-base": "^2.0.0", - "inherits": "^2.0.1" - } - } + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" } }, "picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true }, "pidtree": { @@ -17494,7 +17571,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-modules-local-by-default": { "version": "4.0.3", @@ -17558,6 +17636,11 @@ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -17582,9 +17665,9 @@ }, "dependencies": { "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" } } }, @@ -17600,12 +17683,12 @@ "dev": true }, "qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "dev": true, "requires": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" } }, "querystring": { @@ -17653,15 +17736,15 @@ "dev": true }, "raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "dev": true, "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" } }, "react": { @@ -17825,7 +17908,8 @@ "redux-thunk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", - "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==" + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "requires": {} }, "regenerate": { "version": "1.4.2", @@ -17896,8 +17980,7 @@ "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" }, "requires-port": { "version": "1.0.0", @@ -17961,45 +18044,46 @@ }, "dependencies": { "brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, "requires": { "balanced-match": "^1.0.0" } }, "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "requires": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" } }, "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "requires": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" } } } }, "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "hash-base": "^3.1.2", + "inherits": "^2.0.4" } }, "run-parallel": { @@ -18036,7 +18120,14 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "dev": true }, "scheduler": { "version": "0.23.2", @@ -18050,7 +18141,6 @@ "version": "4.3.3", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, "requires": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -18059,22 +18149,20 @@ }, "dependencies": { "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "requires": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" } }, "ajv-keywords": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "requires": { "fast-deep-equal": "^3.1.3" } @@ -18082,8 +18170,7 @@ "json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" } } }, @@ -18167,15 +18254,51 @@ "dev": true }, "side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "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, "requires": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + } + }, + "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, + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + } + }, + "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, + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + } + }, + "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, + "requires": { + "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" } }, "signal-exit": { @@ -18241,20 +18364,36 @@ } }, "socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", "dev": true, "requires": { "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" + "debug": "~4.4.1" + }, + "dependencies": { + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } } }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-js": { "version": "1.0.2", @@ -18266,7 +18405,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -18495,7 +18633,8 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==", - "dev": true + "dev": true, + "requires": {} }, "supports-color": { "version": "5.5.0", @@ -18519,18 +18658,18 @@ "dev": true }, "svgo": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.4.tgz", - "integrity": "sha512-T+Xul3JwuJ6VGXKo/p2ndqx1ibxNKnLTvRc1ZTWKCfyKS/GgNjRZcYsK84fxTsy/izr91g/Rwx6fGnVgaFSI5g==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.3.tgz", + "integrity": "sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng==", "dev": true, "requires": { - "@trysound/sax": "0.2.0", "commander": "^7.2.0", "css-select": "^5.1.0", - "css-tree": "^2.2.1", + "css-tree": "^2.3.1", "css-what": "^6.1.0", - "csso": "5.0.5", - "picocolors": "^1.0.0" + "csso": "^5.0.5", + "picocolors": "^1.0.0", + "sax": "^1.5.0" }, "dependencies": { "commander": { @@ -18544,14 +18683,12 @@ "tapable": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "dev": true + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==" }, "terser": { "version": "5.46.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", - "dev": true, "requires": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", @@ -18562,27 +18699,23 @@ "acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==" }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" } } }, "terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", - "dev": true, + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", + "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", "requires": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", "terser": "^5.31.1" } }, @@ -18943,7 +19076,6 @@ "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, "requires": { "escalade": "^3.2.0", "picocolors": "^1.1.1" @@ -18977,7 +19109,8 @@ "use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==" + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "requires": {} }, "util": { "version": "0.12.5", @@ -19033,7 +19166,6 @@ "version": "2.4.4", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", - "dev": true, "requires": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -19043,7 +19175,6 @@ "version": "5.104.1", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", - "dev": true, "requires": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -19075,14 +19206,13 @@ "acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==" }, "acorn-import-phases": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "dev": true + "requires": {} } } }, @@ -19137,8 +19267,7 @@ "webpack-sources": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", - "dev": true + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==" }, "whatwg-fetch": { "version": "3.6.20", @@ -19340,7 +19469,8 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "dev": true + "dev": true, + "requires": {} }, "xtend": { "version": "4.0.2", From 608aa7b057161b1a767f662fea25206e9833ca29 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 2 Apr 2026 10:41:40 -0400 Subject: [PATCH 142/297] fix linting --- .flake8 | 1 + .pylintrc | 3 ++- package.json | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.flake8 b/.flake8 index 163d5bd88a..7222e3624e 100644 --- a/.flake8 +++ b/.flake8 @@ -1,6 +1,7 @@ [flake8] ignore = C901, E203, E266, E501, E731, W503 select = B,C,E,F,W,T4 +exclude = node_modules,metadata_test.py per-file-ignores = tests/*: E722, F811 dash/html/I.py: E742 diff --git a/.pylintrc b/.pylintrc index a1314bf820..7ffb5576b7 100644 --- a/.pylintrc +++ b/.pylintrc @@ -17,7 +17,8 @@ ignore-patterns= # The regex matches against paths. ignore-paths=^dash/dcc/.*$, ^dash/html/.*$, - ^dash/dash_table/.*$ + ^dash/dash_table/.*$, + ^.*/node_modules/.*$ # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). diff --git a/package.json b/package.json index fa4888dee7..cd50964c9a 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "private::build.renderer": "cd dash/dash-renderer && rimraf build/dash_renderer.min.js && renderer build && sh renderer-test.sh", "private::build.jupyterlab": "cd @plotly/dash-jupyterlab && jlpm install && jlpm build:pack", "private::lint.black": "black dash tests --exclude metadata_test.py --check", - "private::lint.flake8": "flake8 --exclude=metadata_test.py dash tests", + "private::lint.flake8": "flake8 dash tests", "private::lint.pylint-dash": "pylint dash setup.py --rcfile=.pylintrc", "private::lint.pylint-tests": "pylint tests/unit tests/integration -d all -e C0410,C0413,W0109 --rcfile=.pylintrc", "private::lint.renderer": "cd dash/dash-renderer && npm run lint", From f0fabb986fd8bd86ec9607ab21b0c3d19202ac37 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 2 Apr 2026 12:03:19 -0400 Subject: [PATCH 143/297] fix black --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index cd50964c9a..0d20651dbf 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "private": true, "license": "UNLICENSED", "scripts": { - "private::format.black": "black dash tests --exclude metadata_test.py", + "private::format.black": "black dash tests --exclude 'metadata_test.py|node_modules'", "private::format.renderer": "cd dash/dash-renderer && npm run format", "private::format.dcc": "cd components/dash-core-components && npm run format", "private::format.table": "cd components/dash-table && npm run format", @@ -12,7 +12,7 @@ "private::cibuild.renderer": "cd dash/dash-renderer && rimraf build/dash_renderer.min.js && renderer build && sh renderer-test.sh", "private::build.renderer": "cd dash/dash-renderer && rimraf build/dash_renderer.min.js && renderer build && sh renderer-test.sh", "private::build.jupyterlab": "cd @plotly/dash-jupyterlab && jlpm install && jlpm build:pack", - "private::lint.black": "black dash tests --exclude metadata_test.py --check", + "private::lint.black": "black dash tests --exclude 'metadata_test.py|node_modules' --check", "private::lint.flake8": "flake8 dash tests", "private::lint.pylint-dash": "pylint dash setup.py --rcfile=.pylintrc", "private::lint.pylint-tests": "pylint tests/unit tests/integration -d all -e C0410,C0413,W0109 --rcfile=.pylintrc", From b494ad398bc48fde005cf5f6cdea50a6bc307011 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 2 Apr 2026 12:57:00 -0400 Subject: [PATCH 144/297] wait for table after sort --- components/dash-table/tests/selenium/conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/components/dash-table/tests/selenium/conftest.py b/components/dash-table/tests/selenium/conftest.py index 6ee1bba60d..29ac66ef91 100644 --- a/components/dash-table/tests/selenium/conftest.py +++ b/components/dash-table/tests/selenium/conftest.py @@ -341,6 +341,7 @@ def select(self, row=0): @preconditions(_validate_row) def sort(self, row=0): self.find_inside(row, ".column-header--sort").click() + self.mixin._wait_for_table(self.id) def filter(self): return ( From 78f760e019d285689e9e86f0f4da66d7665d40d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 19:26:01 +0000 Subject: [PATCH 145/297] Bump the npm-dependencies-security group across 1 directory with 5 updates Bumps the npm-dependencies-security group with 5 updates in the / directory: | Package | From | To | | --- | --- | --- | | [glob](https://github.com/isaacs/node-glob) | `10.4.5` | `10.5.0` | | [brace-expansion](https://github.com/juliangruber/brace-expansion) | `1.1.12` | `1.1.13` | | [brace-expansion](https://github.com/juliangruber/brace-expansion) | `2.0.2` | `2.0.3` | | [brace-expansion](https://github.com/juliangruber/brace-expansion) | `5.0.2` | `5.0.5` | | [handlebars](https://github.com/handlebars-lang/handlebars.js) | `4.7.8` | `4.7.9` | | [picomatch](https://github.com/micromatch/picomatch) | `2.3.1` | `2.3.2` | | [picomatch](https://github.com/micromatch/picomatch) | `4.0.3` | `4.0.4` | | [tar](https://github.com/isaacs/node-tar) | `7.5.7` | `7.5.11` | Updates `glob` from 10.4.5 to 10.5.0 - [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md) - [Commits](https://github.com/isaacs/node-glob/compare/v10.4.5...v10.5.0) Updates `brace-expansion` from 1.1.12 to 1.1.13 - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/v1.1.12...v1.1.13) Updates `brace-expansion` from 2.0.2 to 2.0.3 - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/v1.1.12...v1.1.13) Updates `brace-expansion` from 5.0.2 to 5.0.5 - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/v1.1.12...v1.1.13) Updates `handlebars` from 4.7.8 to 4.7.9 - [Release notes](https://github.com/handlebars-lang/handlebars.js/releases) - [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/v4.7.9/release-notes.md) - [Commits](https://github.com/handlebars-lang/handlebars.js/compare/v4.7.8...v4.7.9) Updates `picomatch` from 2.3.1 to 2.3.2 - [Release notes](https://github.com/micromatch/picomatch/releases) - [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2) Updates `picomatch` from 4.0.3 to 4.0.4 - [Release notes](https://github.com/micromatch/picomatch/releases) - [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2) Updates `tar` from 7.5.7 to 7.5.11 - [Release notes](https://github.com/isaacs/node-tar/releases) - [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/isaacs/node-tar/compare/v7.5.7...v7.5.11) --- updated-dependencies: - dependency-name: glob dependency-version: 10.5.0 dependency-type: indirect dependency-group: npm-dependencies-security - dependency-name: brace-expansion dependency-version: 1.1.13 dependency-type: indirect dependency-group: npm-dependencies-security - dependency-name: brace-expansion dependency-version: 2.0.3 dependency-type: indirect dependency-group: npm-dependencies-security - dependency-name: brace-expansion dependency-version: 5.0.5 dependency-type: indirect dependency-group: npm-dependencies-security - dependency-name: handlebars dependency-version: 4.7.9 dependency-type: indirect dependency-group: npm-dependencies-security - dependency-name: picomatch dependency-version: 2.3.2 dependency-type: indirect dependency-group: npm-dependencies-security - dependency-name: picomatch dependency-version: 4.0.4 dependency-type: indirect dependency-group: npm-dependencies-security - dependency-name: tar dependency-version: 7.5.11 dependency-type: indirect dependency-group: npm-dependencies-security ... Signed-off-by: dependabot[bot] --- package-lock.json | 2096 +++++++++++++-------------------------------- 1 file changed, 613 insertions(+), 1483 deletions(-) diff --git a/package-lock.json b/package-lock.json index 589f7c4f34..7341387472 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,33 +40,42 @@ } }, "node_modules/@emnapi/core": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", - "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", "dev": true, "dependencies": { - "@emnapi/wasi-threads": "1.1.0", + "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", - "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", "dev": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", "dev": true, "dependencies": { "tslib": "^2.4.0" } }, + "node_modules/@gar/promise-retry": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz", + "integrity": "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==", + "dev": true, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", @@ -422,27 +431,6 @@ } } }, - "node_modules/@isaacs/balanced-match": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", - "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", - "dev": true, - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@isaacs/brace-expansion": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz", - "integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==", - "dev": true, - "dependencies": { - "@isaacs/balanced-match": "^4.0.1" - }, - "engines": { - "node": "20 || >=22" - } - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "license": "ISC", @@ -649,267 +637,6 @@ "node": "^14.15.0 || >=16.0.0" } }, - "node_modules/@lerna/create": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@lerna/create/-/create-9.0.4.tgz", - "integrity": "sha512-WxedGD98G8/a6HztCXNWquaM0x17oSvfvuqDsLxNNX1qXGyrzmMUmd1mQikF/47uy80X6qyWdaRtaAHlwkvEUA==", - "dev": true, - "dependencies": { - "@npmcli/arborist": "9.1.6", - "@npmcli/package-json": "7.0.2", - "@npmcli/run-script": "10.0.3", - "@nx/devkit": ">=21.5.2 < 23.0.0", - "@octokit/plugin-enterprise-rest": "6.0.1", - "@octokit/rest": "20.1.2", - "aproba": "2.0.0", - "byte-size": "8.1.1", - "chalk": "4.1.0", - "cmd-shim": "6.0.3", - "color-support": "1.1.3", - "columnify": "1.6.0", - "console-control-strings": "^1.1.0", - "conventional-changelog-core": "5.0.1", - "conventional-recommended-bump": "7.0.1", - "cosmiconfig": "9.0.0", - "dedent": "1.5.3", - "execa": "5.0.0", - "fs-extra": "^11.2.0", - "get-stream": "6.0.0", - "git-url-parse": "14.0.0", - "glob-parent": "6.0.2", - "has-unicode": "2.0.1", - "ini": "^1.3.8", - "init-package-json": "8.2.2", - "inquirer": "12.9.6", - "is-ci": "3.0.1", - "is-stream": "2.0.0", - "js-yaml": "4.1.1", - "libnpmpublish": "11.1.2", - "load-json-file": "6.2.0", - "make-dir": "4.0.0", - "make-fetch-happen": "15.0.2", - "minimatch": "3.0.5", - "multimatch": "5.0.0", - "npm-package-arg": "13.0.1", - "npm-packlist": "10.0.3", - "npm-registry-fetch": "19.1.0", - "nx": ">=21.5.3 < 23.0.0", - "p-map": "4.0.0", - "p-map-series": "2.1.0", - "p-queue": "6.6.2", - "p-reduce": "^2.1.0", - "pacote": "21.0.1", - "pify": "5.0.0", - "read-cmd-shim": "4.0.0", - "resolve-from": "5.0.0", - "rimraf": "^6.1.2", - "semver": "7.7.2", - "set-blocking": "^2.0.0", - "signal-exit": "3.0.7", - "slash": "^3.0.0", - "ssri": "12.0.0", - "string-width": "^4.2.3", - "tar": "7.5.7", - "temp-dir": "1.0.0", - "through": "2.3.8", - "tinyglobby": "0.2.12", - "upath": "2.0.1", - "uuid": "^11.1.0", - "validate-npm-package-license": "3.0.4", - "validate-npm-package-name": "6.0.2", - "wide-align": "1.1.5", - "write-file-atomic": "5.0.1", - "write-pkg": "4.0.0", - "yargs": "17.7.2", - "yargs-parser": "21.1.1" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - } - }, - "node_modules/@lerna/create/node_modules/balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", - "dev": true, - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@lerna/create/node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@lerna/create/node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "dev": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/@lerna/create/node_modules/execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/@lerna/create/node_modules/get-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", - "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna/create/node_modules/glob": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", - "dev": true, - "dependencies": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@lerna/create/node_modules/glob/node_modules/brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", - "dev": true, - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@lerna/create/node_modules/glob/node_modules/minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", - "dev": true, - "dependencies": { - "brace-expansion": "^5.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@lerna/create/node_modules/is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@lerna/create/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", - "dev": true, - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@lerna/create/node_modules/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@lerna/create/node_modules/path-scurry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", - "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", - "dev": true, - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@lerna/create/node_modules/rimraf": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", - "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", - "dev": true, - "dependencies": { - "glob": "^13.0.3", - "package-json-from-dist": "^1.0.1" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@lerna/describe-ref": { "version": "6.4.1", "dev": true, @@ -960,6 +687,12 @@ "node": "^14.15.0 || >=16.0.0" } }, + "node_modules/@ltd/j-toml": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/@ltd/j-toml/-/j-toml-1.38.0.tgz", + "integrity": "sha512-lYtBcmvHustHQtg4X7TXUu1Xa/tbLC3p2wLvgQI+fWVySguVZJF60Snxijw5EiohumxZbR10kWYFFebh1zotiw==", + "dev": true + }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", @@ -1044,42 +777,42 @@ } }, "node_modules/@npmcli/arborist/node_modules/balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/@npmcli/arborist/node_modules/brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/@npmcli/arborist/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "engines": { "node": "20 || >=22" } }, "node_modules/@npmcli/arborist/node_modules/minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "dependencies": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" }, "engines": { "node": "18 || 20 || >=22" @@ -1110,11 +843,12 @@ } }, "node_modules/@npmcli/arborist/node_modules/pacote": { - "version": "21.3.1", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.3.1.tgz", - "integrity": "sha512-O0EDXi85LF4AzdjG74GUwEArhdvawi/YOHcsW6IijKNj7wm8IvEWNF5GnfuxNpQ/ZpO3L37+v8hqdVh8GgWYhg==", + "version": "21.5.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.5.0.tgz", + "integrity": "sha512-VtZ0SB8mb5Tzw3dXDfVAIjhyVKUHZkS/ZH9/5mpKenwC9sFOXNI0JI7kEF7IMkwOnsWMFrvAZHzx1T5fmrp9FQ==", "dev": true, "dependencies": { + "@gar/promise-retry": "^1.0.0", "@npmcli/git": "^7.0.0", "@npmcli/installed-package-contents": "^4.0.0", "@npmcli/package-json": "^7.0.0", @@ -1128,7 +862,6 @@ "npm-pick-manifest": "^11.0.1", "npm-registry-fetch": "^19.0.0", "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", "sigstore": "^4.0.0", "ssri": "^13.0.0", "tar": "^7.4.3" @@ -1190,17 +923,17 @@ } }, "node_modules/@npmcli/git": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-7.0.1.tgz", - "integrity": "sha512-+XTFxK2jJF/EJJ5SoAzXk3qwIDfvFc5/g+bD274LZ7uY7LE8sTfG6Z8rOanPl2ZEvZWqNvmEdtXC25cE54VcoA==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-7.0.2.tgz", + "integrity": "sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg==", "dev": true, "dependencies": { + "@gar/promise-retry": "^1.0.0", "@npmcli/promise-spawn": "^9.0.0", "ini": "^6.0.0", "lru-cache": "^11.2.1", "npm-pick-manifest": "^11.0.1", "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", "semver": "^7.3.5", "which": "^6.0.0" }, @@ -1227,9 +960,9 @@ } }, "node_modules/@npmcli/git/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "engines": { "node": "20 || >=22" @@ -1300,24 +1033,24 @@ } }, "node_modules/@npmcli/map-workspaces/node_modules/balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/@npmcli/map-workspaces/node_modules/brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/@npmcli/map-workspaces/node_modules/glob": { @@ -1338,21 +1071,21 @@ } }, "node_modules/@npmcli/map-workspaces/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "engines": { "node": "20 || >=22" } }, "node_modules/@npmcli/map-workspaces/node_modules/minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "dependencies": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" }, "engines": { "node": "18 || 20 || >=22" @@ -1448,24 +1181,24 @@ } }, "node_modules/@npmcli/package-json/node_modules/balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/@npmcli/package-json/node_modules/brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/@npmcli/package-json/node_modules/glob": { @@ -1508,21 +1241,21 @@ } }, "node_modules/@npmcli/package-json/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "engines": { "node": "20 || >=22" } }, "node_modules/@npmcli/package-json/node_modules/minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "dependencies": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" }, "engines": { "node": "18 || 20 || >=22" @@ -1673,15 +1406,15 @@ } }, "node_modules/@nx/devkit": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-22.5.1.tgz", - "integrity": "sha512-1ZJ8pCB+6EWC8X6q8tfBweg92WzFAwliBhtBkOPP8Li8GQq71ulPWRdY4lDd5pH3Ea1zKqhOtBKWdOlyDPOKYA==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-22.6.4.tgz", + "integrity": "sha512-4VRND4Hl+zWSPvs68cJn0PUoxi1ADS1iqXy3VJNtUlVqjE7Y5LtZxKUC05w5OKP+2jMfU3viPTZIGwHnHuIaYA==", "dev": true, "dependencies": { "@zkochan/js-yaml": "0.0.7", "ejs": "^3.1.7", "enquirer": "~2.3.6", - "minimatch": "10.1.1", + "minimatch": "10.2.4", "semver": "^7.6.3", "tslib": "^2.3.0", "yargs-parser": "21.1.1" @@ -1690,25 +1423,46 @@ "nx": ">= 21 <= 23 || ^22.0.0-0" } }, + "node_modules/@nx/devkit/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@nx/devkit/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/@nx/devkit/node_modules/minimatch": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", - "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "brace-expansion": "^5.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@nx/nx-darwin-arm64": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-22.5.1.tgz", - "integrity": "sha512-DuvOwhXPO6l9W7/zM4/BaAbGTIXFyHVcbbCD1c7HfgZ3VfJPmcE7H4+TuQH0cigHHtpg/eGqV100NQbd7N4zwg==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-22.6.4.tgz", + "integrity": "sha512-KuUQ9t8pxIO+Px1kbjA0XDLOU6XoAsijl0ssIMRYN1w5ly+0k/KglWt7qgwDockkaLRHkQ3YSR8I2LJXJE+Vig==", "cpu": [ "arm64" ], @@ -1719,9 +1473,9 @@ ] }, "node_modules/@nx/nx-darwin-x64": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-22.5.1.tgz", - "integrity": "sha512-81Lb7+rp3Qltpgy33Kc1qxk+8IWqZLhqvdLdRFSVV1FN1pPSJDFKyPjCn9oMpRryNPSJ8DgZDpfIaVVyP85rUw==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-22.6.4.tgz", + "integrity": "sha512-FB2XL2+ixbRI1fddz4oW+9MhoJASoTD8Ai4q5+B1OUPftgarIPLxaqI8TWba30Bos2AiYDofMJPf9uhBmLDH5Q==", "cpu": [ "x64" ], @@ -1732,9 +1486,9 @@ ] }, "node_modules/@nx/nx-freebsd-x64": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-22.5.1.tgz", - "integrity": "sha512-Ig8yQN3lSz9R+Zf3NQWcvEnIzwDX4NSeaFtEliPnC3OHlQXGNXbOUfkExa0U0UUgyxa4rgnCgefmwuc12H9q2Q==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-22.6.4.tgz", + "integrity": "sha512-qNsXhlflc77afjcRKCn7bqI8l/HPEjKhQRFs8wfKbAfNw3XEASc0EZtBV/TStLGV6PEZQldVBaId5FBMp8GW6Q==", "cpu": [ "x64" ], @@ -1745,9 +1499,9 @@ ] }, "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-22.5.1.tgz", - "integrity": "sha512-C7tGoLnR9MjKLJsLMF2VsKcDChPiygAsw6dSVgU4B650H7sBWmkEHM/QjvyRvkcZuoQBDamS/eVs/UaJu9wNhA==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-22.6.4.tgz", + "integrity": "sha512-rjfnii0xGe8SQqsO/DDHeJSjbqp2H5fOEgZlaYXDGOwQeLZ1TQplEdx8hyI/ErAUwVO3YHnzoMtmachBQOlspw==", "cpu": [ "arm" ], @@ -1758,9 +1512,9 @@ ] }, "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-22.5.1.tgz", - "integrity": "sha512-GNxei+lwhzhrO9m+nNkibgxLhbkYKyFXPSRpOKLwv9VavNzJn5UmLfKJyhjNQPBOSYuNhiVPbU1Ja/qOBcozYw==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-22.6.4.tgz", + "integrity": "sha512-x6Zim1STewCXuHBCgoy2TO0586UlwH4RNCobn0mTiPd1jt7nU+fNqo3SpY8RzY1KmBfgcO48BBrfykPE9YWMpg==", "cpu": [ "arm64" ], @@ -1771,9 +1525,9 @@ ] }, "node_modules/@nx/nx-linux-arm64-musl": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-22.5.1.tgz", - "integrity": "sha512-VDJtdJP2nCgS8ommbfWFAKjoZCE51VH7tZyIfh8RFI5fxwoB3Pk6d6f6cmNHI/1t98YI3V7Onuf3Y9KBkYtyfQ==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-22.6.4.tgz", + "integrity": "sha512-vYOqdgXIhtHFWdtnonp/jFfmfkyNPTu1JEdXuJpSxwUQdV2dWqS/l3HVPVWHXDrVKofPafK3M72jMvoWoaOQ6g==", "cpu": [ "arm64" ], @@ -1784,9 +1538,9 @@ ] }, "node_modules/@nx/nx-linux-x64-gnu": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-22.5.1.tgz", - "integrity": "sha512-BZ/i+KTplEJmE8ZHKgPGD513Zl86DuSGyRAvbDZ7Qf19Tei7Of6vxW+ypvVDIwmDbyXfe13u54M5gDt8iiqFGQ==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-22.6.4.tgz", + "integrity": "sha512-UfWUDlOzlvQNVa1mnqOFxzvUwoGfM2o9ruhwYRoFm3XJbVYnjINyQsdcHwwDJItJP04LZzLPxA1+O8sU+Oqg6A==", "cpu": [ "x64" ], @@ -1797,9 +1551,9 @@ ] }, "node_modules/@nx/nx-linux-x64-musl": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-22.5.1.tgz", - "integrity": "sha512-e0VdiV6fe88Dbhill2gUjYAD9jMhHjYsafGOPR+/uaGMAYPoI1jKur6uPGY+ik6fvwvDFFl0VT2+HACKVn7RoA==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-22.6.4.tgz", + "integrity": "sha512-dwXpcyin4ScD5gH9FdhiNnOqFXclXLFBDTyRCEOlRUbOPayF9YEcH0PPIf9uWmwP3tshhAdr5sg9DLN+r7M3xg==", "cpu": [ "x64" ], @@ -1810,9 +1564,9 @@ ] }, "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-22.5.1.tgz", - "integrity": "sha512-3vWZO9y7uHKeyepcU55pE8VQTKGome3mLdicvx1TCoKKl0cA3bTR341Jdo2Zl4Waa2ENk7pGQbLWRQ3ZkaA92A==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-22.6.4.tgz", + "integrity": "sha512-KqjJbFWhKJaKjET3Ep8hltXPizO0EstF4yfmp3oepWVn11poagc2MT1pf/tnRf6cdD88wd0bmw/83Ng6WUQ3Uw==", "cpu": [ "arm64" ], @@ -1823,9 +1577,9 @@ ] }, "node_modules/@nx/nx-win32-x64-msvc": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-22.5.1.tgz", - "integrity": "sha512-4e5LduuhpBx96JgD1J3fHUGCwC+/lL+tvXp3UVtjh/AOdINGsyI+scinT3uaI9vcB5GKBcybTxbBZzwcH50w9g==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-22.6.4.tgz", + "integrity": "sha512-CIL9m6uilGGr/eU+41/+aVWUnEcq+j1EDynUX2A4InLTbAN0ylte4Af+72mvipNiqJgDkjKaNzOCQDnp8QBjEQ==", "cpu": [ "x64" ], @@ -2017,9 +1771,9 @@ } }, "node_modules/@sigstore/core": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.1.0.tgz", - "integrity": "sha512-o5cw1QYhNQ9IroioJxpzexmPjfCe7gzafd2RY3qnMpxr4ZEja+Jad/U8sgFpaue6bOaF+z7RVkyKVV44FN+N8A==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.2.0.tgz", + "integrity": "sha512-kxHrDQ9YgfrWUSXU0cjsQGv8JykOFZQ9ErNKbFPWzk3Hgpwu8x2hHrQ9IdA8yl+j9RTLTC3sAF3Tdq1IQCP4oA==", "dev": true, "engines": { "node": "^20.17.0 || >=22.9.0" @@ -2035,29 +1789,40 @@ } }, "node_modules/@sigstore/sign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.0.tgz", - "integrity": "sha512-Vx1RmLxLGnSUqx/o5/VsCjkuN5L7y+vxEEwawvc7u+6WtX2W4GNa7b9HEjmcRWohw/d6BpATXmvOwc78m+Swdg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.1.tgz", + "integrity": "sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ==", "dev": true, "dependencies": { + "@gar/promise-retry": "^1.0.2", "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", + "@sigstore/core": "^3.2.0", "@sigstore/protobuf-specs": "^0.5.0", - "make-fetch-happen": "^15.0.3", - "proc-log": "^6.1.0", - "promise-retry": "^2.0.1" + "make-fetch-happen": "^15.0.4", + "proc-log": "^6.1.0" }, "engines": { "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/@sigstore/sign/node_modules/@npmcli/redact": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-4.0.0.tgz", + "integrity": "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q==", + "dev": true, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/@sigstore/sign/node_modules/make-fetch-happen": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.3.tgz", - "integrity": "sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw==", + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.5.tgz", + "integrity": "sha512-uCbIa8jWWmQZt4dSnEStkVC6gdakiinAm4PiGsywIkguF0eWMdcjDz0ECYhUolFU3pFLOev9VNPCEygydXnddg==", "dev": true, "dependencies": { + "@gar/promise-retry": "^1.0.0", "@npmcli/agent": "^4.0.0", + "@npmcli/redact": "^4.0.0", "cacache": "^20.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", @@ -2066,7 +1831,6 @@ "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", "ssri": "^13.0.0" }, "engines": { @@ -2074,9 +1838,9 @@ } }, "node_modules/@sigstore/sign/node_modules/minipass-fetch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-5.0.1.tgz", - "integrity": "sha512-yHK8pb0iCGat0lDrs/D6RZmCdaBT64tULXjdxjSMAqoDi18Q3qKEUTHypHQZQd9+FYpIS+lkvpq6C/R6SbUeRw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-5.0.2.tgz", + "integrity": "sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ==", "dev": true, "dependencies": { "minipass": "^7.0.3", @@ -2087,7 +1851,7 @@ "node": "^20.17.0 || >=22.9.0" }, "optionalDependencies": { - "encoding": "^0.1.13" + "iconv-lite": "^0.7.2" } }, "node_modules/@sigstore/sign/node_modules/minipass-sized": { @@ -2124,9 +1888,9 @@ } }, "node_modules/@sigstore/tuf": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.1.tgz", - "integrity": "sha512-OPZBg8y5Vc9yZjmWCHrlWPMBqW5yd8+wFNl+thMdtcWz3vjVSoJQutF8YkrzI0SLGnkuFof4HSsWUhXrf219Lw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.2.tgz", + "integrity": "sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ==", "dev": true, "dependencies": { "@sigstore/protobuf-specs": "^0.5.0", @@ -2179,33 +1943,33 @@ } }, "node_modules/@tufjs/models/node_modules/balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/@tufjs/models/node_modules/brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/@tufjs/models/node_modules/minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "dependencies": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" }, "engines": { "node": "18 || 20 || >=22" @@ -2518,13 +2282,13 @@ } }, "node_modules/axios": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", - "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.0.tgz", + "integrity": "sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.11", - "form-data": "^4.0.5", + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, @@ -2629,8 +2393,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.12", - "license": "MIT", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2730,15 +2495,15 @@ } }, "node_modules/cacache/node_modules/brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/cacache/node_modules/glob": { @@ -2910,9 +2675,9 @@ } }, "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", "dev": true, "funding": [ { @@ -3475,15 +3240,6 @@ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true }, - "node_modules/detect-indent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", - "integrity": "sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/dot-prop": { "version": "5.3.0", "dev": true, @@ -3846,27 +3602,27 @@ } }, "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", "dev": true, "dependencies": { "minimatch": "^5.0.1" } }, "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -4013,9 +3769,9 @@ "dev": true }, "node_modules/fs-extra": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", - "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", + "version": "11.3.4", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", + "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", "dev": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -4231,17 +3987,6 @@ "node": ">=10" } }, - "node_modules/get-port": { - "version": "5.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-proto": { "version": "1.0.1", "license": "MIT", @@ -4282,6 +4027,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-3.0.0.tgz", "integrity": "sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==", + "deprecated": "This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead.", "dev": true, "dependencies": { "dargs": "^7.0.0", @@ -4308,19 +4054,11 @@ "node": ">=4" } }, - "node_modules/git-remote-origin-url/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/git-semver-tags": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-5.0.1.tgz", "integrity": "sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==", + "deprecated": "This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead.", "dev": true, "dependencies": { "meow": "^8.1.2", @@ -4362,8 +4100,10 @@ } }, "node_modules/glob": { - "version": "10.4.5", - "license": "ISC", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -4392,8 +4132,9 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.2", - "license": "MIT", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dependencies": { "balanced-match": "^1.0.0" } @@ -4439,9 +4180,9 @@ "license": "ISC" }, "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", "dev": true, "dependencies": { "minimist": "^1.2.5", @@ -4684,33 +4425,33 @@ } }, "node_modules/ignore-walk/node_modules/balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/ignore-walk/node_modules/brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/ignore-walk/node_modules/minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "dependencies": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" }, "engines": { "node": "18 || 20 || >=22" @@ -4918,6 +4659,21 @@ "is-ci": "bin.js" } }, + "node_modules/is-ci/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, "node_modules/is-core-module": { "version": "2.12.1", "license": "MIT", @@ -5309,28 +5065,11 @@ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-util/node_modules/ci-info": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", - "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/jest-util/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -5460,12 +5199,11 @@ } }, "node_modules/lerna": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/lerna/-/lerna-9.0.4.tgz", - "integrity": "sha512-wKy9TOkkdCWPWET0R5o7mh7J0KuNNjxE0g+qTruNAt5ffWwy54wfWiJtWyDSMOrcGDt6gtisDBTKniOqK/sJvw==", + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/lerna/-/lerna-9.0.7.tgz", + "integrity": "sha512-PMjbSWYfwL1yZ5c1D2PZuFyzmtYhLdn0f76uG8L25g6eYy34j+2jPb4Q6USx1UJvxVtxkdVEeAAWS/WxgJ8VZA==", "dev": true, "dependencies": { - "@lerna/create": "9.0.4", "@npmcli/arborist": "9.1.6", "@npmcli/package-json": "7.0.2", "@npmcli/run-script": "10.0.3", @@ -5475,6 +5213,7 @@ "aproba": "2.0.0", "byte-size": "8.1.1", "chalk": "4.1.0", + "ci-info": "4.3.1", "cmd-shim": "6.0.3", "color-support": "1.1.3", "columnify": "1.6.0", @@ -5487,7 +5226,6 @@ "envinfo": "7.13.0", "execa": "5.0.0", "fs-extra": "^11.2.0", - "get-port": "5.1.1", "get-stream": "6.0.0", "git-url-parse": "14.0.0", "glob-parent": "6.0.2", @@ -5497,16 +5235,13 @@ "init-package-json": "8.2.2", "inquirer": "12.9.6", "is-ci": "3.0.1", - "is-stream": "2.0.0", "jest-diff": ">=30.0.0 < 31", "js-yaml": "4.1.1", "libnpmaccess": "10.0.3", "libnpmpublish": "11.1.2", "load-json-file": "6.2.0", - "make-dir": "4.0.0", "make-fetch-happen": "15.0.2", - "minimatch": "3.0.5", - "multimatch": "5.0.0", + "minimatch": "3.1.4", "npm-package-arg": "13.0.1", "npm-packlist": "10.0.3", "npm-registry-fetch": "19.1.0", @@ -5518,28 +5253,21 @@ "p-reduce": "2.1.0", "p-waterfall": "2.1.1", "pacote": "21.0.1", - "pify": "5.0.0", "read-cmd-shim": "4.0.0", - "resolve-from": "5.0.0", - "rimraf": "^6.1.2", "semver": "7.7.2", - "set-blocking": "^2.0.0", "signal-exit": "3.0.7", "slash": "3.0.0", "ssri": "12.0.0", "string-width": "^4.2.3", - "tar": "7.5.7", - "temp-dir": "1.0.0", + "tar": "7.5.11", "through": "2.3.8", "tinyglobby": "0.2.12", "typescript": ">=3 < 6", "upath": "2.0.1", - "uuid": "^11.1.0", "validate-npm-package-license": "3.0.4", "validate-npm-package-name": "6.0.2", "wide-align": "1.1.5", "write-file-atomic": "5.0.1", - "write-pkg": "4.0.0", "yargs": "17.7.2", "yargs-parser": "21.1.1" }, @@ -5550,15 +5278,6 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/lerna/node_modules/balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", - "dev": true, - "engines": { - "node": "20 || >=22" - } - }, "node_modules/lerna/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -5624,72 +5343,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lerna/node_modules/glob": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", - "dev": true, - "dependencies": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/lerna/node_modules/glob/node_modules/brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", - "dev": true, - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/lerna/node_modules/glob/node_modules/minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", - "dev": true, - "dependencies": { - "brace-expansion": "^5.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/lerna/node_modules/is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/lerna/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", - "dev": true, - "engines": { - "node": "20 || >=22" - } - }, "node_modules/lerna/node_modules/minimatch": { - "version": "3.0.5", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.4.tgz", + "integrity": "sha512-twmL+S8+7yIsE9wsqgzU3E8/LumN3M3QELrBZ20OdmQ9jB2JvW5oZtBEmft84k/Gs5CG9mqtWc6Y9vW+JEzGxw==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -5697,41 +5355,6 @@ "node": "*" } }, - "node_modules/lerna/node_modules/path-scurry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", - "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", - "dev": true, - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/lerna/node_modules/rimraf": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", - "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", - "dev": true, - "dependencies": { - "glob": "^13.0.3", - "package-json-from-dist": "^1.0.1" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/libnpmaccess": { "version": "10.0.3", "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-10.0.3.tgz", @@ -5764,21 +5387,6 @@ "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/libnpmpublish/node_modules/ci-info": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", - "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, "node_modules/lilconfig": { "version": "3.1.3", "dev": true, @@ -6192,21 +5800,6 @@ "version": "10.4.3", "license": "ISC" }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/make-fetch-happen": { "version": "15.0.2", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.2.tgz", @@ -6826,12 +6419,6 @@ "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/node-machine-id": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", - "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", - "dev": true - }, "node_modules/nopt": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", @@ -7171,17 +6758,18 @@ } }, "node_modules/nx": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/nx/-/nx-22.5.1.tgz", - "integrity": "sha512-KIQqOSdoshkav9JuoH/+Vp42niA5MTRtACupe+q8CaB7bHiLsWr5nctQVC7ul3NauAmsoqNWH7t5CIi8KgrPIQ==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/nx/-/nx-22.6.4.tgz", + "integrity": "sha512-WEaCnLKeO9RhQAOBMfXgYO/Lx5wL4ARCtRGiYCjJtAJIZ5kcVn4uPKL2Xz1xekpF7ef/+YNrUQSrblx47Ms9Rg==", "dev": true, "hasInstallScript": true, "dependencies": { + "@ltd/j-toml": "^1.38.0", "@napi-rs/wasm-runtime": "0.2.4", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "3.0.2", "@zkochan/js-yaml": "0.0.7", - "axios": "^1.12.0", + "axios": "1.12.0", "cli-cursor": "3.1.0", "cli-spinners": "2.6.1", "cliui": "^8.0.1", @@ -7196,8 +6784,7 @@ "jest-diff": "^30.0.2", "jsonc-parser": "3.2.0", "lines-and-columns": "2.0.3", - "minimatch": "10.1.1", - "node-machine-id": "1.1.12", + "minimatch": "10.2.4", "npm-run-path": "^4.0.1", "open": "^8.4.0", "ora": "5.3.0", @@ -7219,20 +6806,20 @@ "nx-cloud": "bin/nx-cloud.js" }, "optionalDependencies": { - "@nx/nx-darwin-arm64": "22.5.1", - "@nx/nx-darwin-x64": "22.5.1", - "@nx/nx-freebsd-x64": "22.5.1", - "@nx/nx-linux-arm-gnueabihf": "22.5.1", - "@nx/nx-linux-arm64-gnu": "22.5.1", - "@nx/nx-linux-arm64-musl": "22.5.1", - "@nx/nx-linux-x64-gnu": "22.5.1", - "@nx/nx-linux-x64-musl": "22.5.1", - "@nx/nx-win32-arm64-msvc": "22.5.1", - "@nx/nx-win32-x64-msvc": "22.5.1" + "@nx/nx-darwin-arm64": "22.6.4", + "@nx/nx-darwin-x64": "22.6.4", + "@nx/nx-freebsd-x64": "22.6.4", + "@nx/nx-linux-arm-gnueabihf": "22.6.4", + "@nx/nx-linux-arm64-gnu": "22.6.4", + "@nx/nx-linux-arm64-musl": "22.6.4", + "@nx/nx-linux-x64-gnu": "22.6.4", + "@nx/nx-linux-x64-musl": "22.6.4", + "@nx/nx-win32-arm64-msvc": "22.6.4", + "@nx/nx-win32-x64-msvc": "22.6.4" }, "peerDependencies": { - "@swc-node/register": "1.11.1", - "@swc/core": "1.15.8" + "@swc-node/register": "^1.11.1", + "@swc/core": "^1.15.8" }, "peerDependenciesMeta": { "@swc-node/register": { @@ -7243,16 +6830,37 @@ } } }, + "node_modules/nx/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/nx/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/nx/node_modules/minimatch": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", - "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "brace-expansion": "^5.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -7749,9 +7357,10 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.6" }, @@ -7770,15 +7379,12 @@ } }, "node_modules/pify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, "node_modules/pkg-dir": { @@ -8430,22 +8036,10 @@ "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", - "dev": true, - "dependencies": { - "is-plain-obj": "^1.0.0" + "socks": "^2.8.3" }, "engines": { - "node": ">=4" + "node": ">= 14" } }, "node_modules/source-map": { @@ -8726,10 +8320,9 @@ } }, "node_modules/tar": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", - "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", - "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.11.tgz", + "integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==", "dev": true, "dependencies": { "@isaacs/fs-minipass": "^4.0.0", @@ -8758,15 +8351,6 @@ "node": ">=6" } }, - "node_modules/temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/text-extensions": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", @@ -8855,9 +8439,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "engines": { "node": ">=12" @@ -9083,19 +8667,6 @@ "dev": true, "license": "MIT" }, - "node_modules/uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/esm/bin/uuid" - } - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "license": "Apache-2.0", @@ -9251,88 +8822,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/write-json-file": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", - "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", - "dev": true, - "dependencies": { - "detect-indent": "^5.0.0", - "graceful-fs": "^4.1.15", - "make-dir": "^2.1.0", - "pify": "^4.0.1", - "sort-keys": "^2.0.0", - "write-file-atomic": "^2.4.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/write-json-file/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/write-json-file/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/write-json-file/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/write-json-file/node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "node_modules/write-pkg": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz", - "integrity": "sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==", - "dev": true, - "dependencies": { - "sort-keys": "^2.0.0", - "type-fest": "^0.4.1", - "write-json-file": "^3.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/write-pkg/node_modules/type-fest": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", - "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -9426,33 +8915,39 @@ "dev": true }, "@emnapi/core": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", - "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", "dev": true, "requires": { - "@emnapi/wasi-threads": "1.1.0", + "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "@emnapi/runtime": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", - "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", "dev": true, "requires": { "tslib": "^2.4.0" } }, "@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", "dev": true, "requires": { "tslib": "^2.4.0" } }, + "@gar/promise-retry": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz", + "integrity": "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==", + "dev": true + }, "@hutson/parse-repository-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", @@ -9642,21 +9137,6 @@ "dev": true, "requires": {} }, - "@isaacs/balanced-match": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", - "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", - "dev": true - }, - "@isaacs/brace-expansion": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz", - "integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==", - "dev": true, - "requires": { - "@isaacs/balanced-match": "^4.0.1" - } - }, "@isaacs/cliui": { "version": "8.0.2", "requires": { @@ -9772,218 +9252,23 @@ } }, "@lerna/child-process": { - "version": "6.4.1", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "execa": "^5.0.0", - "strong-log-transformer": "^2.1.0" - } - }, - "@lerna/collect-updates": { - "version": "6.4.1", - "dev": true, - "requires": { - "@lerna/child-process": "6.4.1", - "@lerna/describe-ref": "6.4.1", - "minimatch": "^3.0.4", - "npmlog": "^6.0.2", - "slash": "^3.0.0" - } - }, - "@lerna/create": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@lerna/create/-/create-9.0.4.tgz", - "integrity": "sha512-WxedGD98G8/a6HztCXNWquaM0x17oSvfvuqDsLxNNX1qXGyrzmMUmd1mQikF/47uy80X6qyWdaRtaAHlwkvEUA==", - "dev": true, - "requires": { - "@npmcli/arborist": "9.1.6", - "@npmcli/package-json": "7.0.2", - "@npmcli/run-script": "10.0.3", - "@nx/devkit": ">=21.5.2 < 23.0.0", - "@octokit/plugin-enterprise-rest": "6.0.1", - "@octokit/rest": "20.1.2", - "aproba": "2.0.0", - "byte-size": "8.1.1", - "chalk": "4.1.0", - "cmd-shim": "6.0.3", - "color-support": "1.1.3", - "columnify": "1.6.0", - "console-control-strings": "^1.1.0", - "conventional-changelog-core": "5.0.1", - "conventional-recommended-bump": "7.0.1", - "cosmiconfig": "9.0.0", - "dedent": "1.5.3", - "execa": "5.0.0", - "fs-extra": "^11.2.0", - "get-stream": "6.0.0", - "git-url-parse": "14.0.0", - "glob-parent": "6.0.2", - "has-unicode": "2.0.1", - "ini": "^1.3.8", - "init-package-json": "8.2.2", - "inquirer": "12.9.6", - "is-ci": "3.0.1", - "is-stream": "2.0.0", - "js-yaml": "4.1.1", - "libnpmpublish": "11.1.2", - "load-json-file": "6.2.0", - "make-dir": "4.0.0", - "make-fetch-happen": "15.0.2", - "minimatch": "3.0.5", - "multimatch": "5.0.0", - "npm-package-arg": "13.0.1", - "npm-packlist": "10.0.3", - "npm-registry-fetch": "19.1.0", - "nx": ">=21.5.3 < 23.0.0", - "p-map": "4.0.0", - "p-map-series": "2.1.0", - "p-queue": "6.6.2", - "p-reduce": "^2.1.0", - "pacote": "21.0.1", - "pify": "5.0.0", - "read-cmd-shim": "4.0.0", - "resolve-from": "5.0.0", - "rimraf": "^6.1.2", - "semver": "7.7.2", - "set-blocking": "^2.0.0", - "signal-exit": "3.0.7", - "slash": "^3.0.0", - "ssri": "12.0.0", - "string-width": "^4.2.3", - "tar": "7.5.7", - "temp-dir": "1.0.0", - "through": "2.3.8", - "tinyglobby": "0.2.12", - "upath": "2.0.1", - "uuid": "^11.1.0", - "validate-npm-package-license": "3.0.4", - "validate-npm-package-name": "6.0.2", - "wide-align": "1.1.5", - "write-file-atomic": "5.0.1", - "write-pkg": "4.0.0", - "yargs": "17.7.2", - "yargs-parser": "21.1.1" - }, - "dependencies": { - "balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", - "dev": true - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "dev": true, - "requires": {} - }, - "execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", - "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", - "dev": true - }, - "glob": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", - "dev": true, - "requires": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" - }, - "dependencies": { - "brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", - "dev": true, - "requires": { - "balanced-match": "^4.0.2" - } - }, - "minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", - "dev": true, - "requires": { - "brace-expansion": "^5.0.2" - } - } - } - }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - }, - "lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", - "dev": true - }, - "minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "path-scurry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", - "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", - "dev": true, - "requires": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - } - }, - "rimraf": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", - "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", - "dev": true, - "requires": { - "glob": "^13.0.3", - "package-json-from-dist": "^1.0.1" - } - } + "version": "6.4.1", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "execa": "^5.0.0", + "strong-log-transformer": "^2.1.0" + } + }, + "@lerna/collect-updates": { + "version": "6.4.1", + "dev": true, + "requires": { + "@lerna/child-process": "6.4.1", + "@lerna/describe-ref": "6.4.1", + "minimatch": "^3.0.4", + "npmlog": "^6.0.2", + "slash": "^3.0.0" } }, "@lerna/describe-ref": { @@ -10020,6 +9305,12 @@ "npmlog": "^6.0.2" } }, + "@ltd/j-toml": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/@ltd/j-toml/-/j-toml-1.38.0.tgz", + "integrity": "sha512-lYtBcmvHustHQtg4X7TXUu1Xa/tbLC3p2wLvgQI+fWVySguVZJF60Snxijw5EiohumxZbR10kWYFFebh1zotiw==", + "dev": true + }, "@napi-rs/wasm-runtime": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", @@ -10094,33 +9385,33 @@ }, "dependencies": { "balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true }, "brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "requires": { "balanced-match": "^4.0.2" } }, "lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true }, "minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "requires": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" } }, "npm-bundled": { @@ -10139,11 +9430,12 @@ "dev": true }, "pacote": { - "version": "21.3.1", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.3.1.tgz", - "integrity": "sha512-O0EDXi85LF4AzdjG74GUwEArhdvawi/YOHcsW6IijKNj7wm8IvEWNF5GnfuxNpQ/ZpO3L37+v8hqdVh8GgWYhg==", + "version": "21.5.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.5.0.tgz", + "integrity": "sha512-VtZ0SB8mb5Tzw3dXDfVAIjhyVKUHZkS/ZH9/5mpKenwC9sFOXNI0JI7kEF7IMkwOnsWMFrvAZHzx1T5fmrp9FQ==", "dev": true, "requires": { + "@gar/promise-retry": "^1.0.0", "@npmcli/git": "^7.0.0", "@npmcli/installed-package-contents": "^4.0.0", "@npmcli/package-json": "^7.0.0", @@ -10157,7 +9449,6 @@ "npm-pick-manifest": "^11.0.1", "npm-registry-fetch": "^19.0.0", "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", "sigstore": "^4.0.0", "ssri": "^13.0.0", "tar": "^7.4.3" @@ -10202,17 +9493,17 @@ } }, "@npmcli/git": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-7.0.1.tgz", - "integrity": "sha512-+XTFxK2jJF/EJJ5SoAzXk3qwIDfvFc5/g+bD274LZ7uY7LE8sTfG6Z8rOanPl2ZEvZWqNvmEdtXC25cE54VcoA==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-7.0.2.tgz", + "integrity": "sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg==", "dev": true, "requires": { + "@gar/promise-retry": "^1.0.0", "@npmcli/promise-spawn": "^9.0.0", "ini": "^6.0.0", "lru-cache": "^11.2.1", "npm-pick-manifest": "^11.0.1", "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", "semver": "^7.3.5", "which": "^6.0.0" }, @@ -10230,9 +9521,9 @@ "dev": true }, "lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true }, "proc-log": { @@ -10281,15 +9572,15 @@ "dev": true }, "balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true }, "brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "requires": { "balanced-match": "^4.0.2" @@ -10307,18 +9598,18 @@ } }, "lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true }, "minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "requires": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" } }, "path-scurry": { @@ -10388,15 +9679,15 @@ "dev": true }, "balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true }, "brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "requires": { "balanced-match": "^4.0.2" @@ -10426,18 +9717,18 @@ } }, "lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true }, "minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "requires": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" } }, "path-scurry": { @@ -10543,98 +9834,113 @@ } }, "@nx/devkit": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-22.5.1.tgz", - "integrity": "sha512-1ZJ8pCB+6EWC8X6q8tfBweg92WzFAwliBhtBkOPP8Li8GQq71ulPWRdY4lDd5pH3Ea1zKqhOtBKWdOlyDPOKYA==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-22.6.4.tgz", + "integrity": "sha512-4VRND4Hl+zWSPvs68cJn0PUoxi1ADS1iqXy3VJNtUlVqjE7Y5LtZxKUC05w5OKP+2jMfU3viPTZIGwHnHuIaYA==", "dev": true, "requires": { "@zkochan/js-yaml": "0.0.7", "ejs": "^3.1.7", "enquirer": "~2.3.6", - "minimatch": "10.1.1", + "minimatch": "10.2.4", "semver": "^7.6.3", "tslib": "^2.3.0", "yargs-parser": "21.1.1" }, "dependencies": { + "balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true + }, + "brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "requires": { + "balanced-match": "^4.0.2" + } + }, "minimatch": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", - "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, "requires": { - "@isaacs/brace-expansion": "^5.0.0" + "brace-expansion": "^5.0.2" } } } }, "@nx/nx-darwin-arm64": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-22.5.1.tgz", - "integrity": "sha512-DuvOwhXPO6l9W7/zM4/BaAbGTIXFyHVcbbCD1c7HfgZ3VfJPmcE7H4+TuQH0cigHHtpg/eGqV100NQbd7N4zwg==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-22.6.4.tgz", + "integrity": "sha512-KuUQ9t8pxIO+Px1kbjA0XDLOU6XoAsijl0ssIMRYN1w5ly+0k/KglWt7qgwDockkaLRHkQ3YSR8I2LJXJE+Vig==", "dev": true, "optional": true }, "@nx/nx-darwin-x64": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-22.5.1.tgz", - "integrity": "sha512-81Lb7+rp3Qltpgy33Kc1qxk+8IWqZLhqvdLdRFSVV1FN1pPSJDFKyPjCn9oMpRryNPSJ8DgZDpfIaVVyP85rUw==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-22.6.4.tgz", + "integrity": "sha512-FB2XL2+ixbRI1fddz4oW+9MhoJASoTD8Ai4q5+B1OUPftgarIPLxaqI8TWba30Bos2AiYDofMJPf9uhBmLDH5Q==", "dev": true, "optional": true }, "@nx/nx-freebsd-x64": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-22.5.1.tgz", - "integrity": "sha512-Ig8yQN3lSz9R+Zf3NQWcvEnIzwDX4NSeaFtEliPnC3OHlQXGNXbOUfkExa0U0UUgyxa4rgnCgefmwuc12H9q2Q==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-22.6.4.tgz", + "integrity": "sha512-qNsXhlflc77afjcRKCn7bqI8l/HPEjKhQRFs8wfKbAfNw3XEASc0EZtBV/TStLGV6PEZQldVBaId5FBMp8GW6Q==", "dev": true, "optional": true }, "@nx/nx-linux-arm-gnueabihf": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-22.5.1.tgz", - "integrity": "sha512-C7tGoLnR9MjKLJsLMF2VsKcDChPiygAsw6dSVgU4B650H7sBWmkEHM/QjvyRvkcZuoQBDamS/eVs/UaJu9wNhA==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-22.6.4.tgz", + "integrity": "sha512-rjfnii0xGe8SQqsO/DDHeJSjbqp2H5fOEgZlaYXDGOwQeLZ1TQplEdx8hyI/ErAUwVO3YHnzoMtmachBQOlspw==", "dev": true, "optional": true }, "@nx/nx-linux-arm64-gnu": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-22.5.1.tgz", - "integrity": "sha512-GNxei+lwhzhrO9m+nNkibgxLhbkYKyFXPSRpOKLwv9VavNzJn5UmLfKJyhjNQPBOSYuNhiVPbU1Ja/qOBcozYw==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-22.6.4.tgz", + "integrity": "sha512-x6Zim1STewCXuHBCgoy2TO0586UlwH4RNCobn0mTiPd1jt7nU+fNqo3SpY8RzY1KmBfgcO48BBrfykPE9YWMpg==", "dev": true, "optional": true }, "@nx/nx-linux-arm64-musl": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-22.5.1.tgz", - "integrity": "sha512-VDJtdJP2nCgS8ommbfWFAKjoZCE51VH7tZyIfh8RFI5fxwoB3Pk6d6f6cmNHI/1t98YI3V7Onuf3Y9KBkYtyfQ==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-22.6.4.tgz", + "integrity": "sha512-vYOqdgXIhtHFWdtnonp/jFfmfkyNPTu1JEdXuJpSxwUQdV2dWqS/l3HVPVWHXDrVKofPafK3M72jMvoWoaOQ6g==", "dev": true, "optional": true }, "@nx/nx-linux-x64-gnu": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-22.5.1.tgz", - "integrity": "sha512-BZ/i+KTplEJmE8ZHKgPGD513Zl86DuSGyRAvbDZ7Qf19Tei7Of6vxW+ypvVDIwmDbyXfe13u54M5gDt8iiqFGQ==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-22.6.4.tgz", + "integrity": "sha512-UfWUDlOzlvQNVa1mnqOFxzvUwoGfM2o9ruhwYRoFm3XJbVYnjINyQsdcHwwDJItJP04LZzLPxA1+O8sU+Oqg6A==", "dev": true, "optional": true }, "@nx/nx-linux-x64-musl": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-22.5.1.tgz", - "integrity": "sha512-e0VdiV6fe88Dbhill2gUjYAD9jMhHjYsafGOPR+/uaGMAYPoI1jKur6uPGY+ik6fvwvDFFl0VT2+HACKVn7RoA==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-22.6.4.tgz", + "integrity": "sha512-dwXpcyin4ScD5gH9FdhiNnOqFXclXLFBDTyRCEOlRUbOPayF9YEcH0PPIf9uWmwP3tshhAdr5sg9DLN+r7M3xg==", "dev": true, "optional": true }, "@nx/nx-win32-arm64-msvc": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-22.5.1.tgz", - "integrity": "sha512-3vWZO9y7uHKeyepcU55pE8VQTKGome3mLdicvx1TCoKKl0cA3bTR341Jdo2Zl4Waa2ENk7pGQbLWRQ3ZkaA92A==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-22.6.4.tgz", + "integrity": "sha512-KqjJbFWhKJaKjET3Ep8hltXPizO0EstF4yfmp3oepWVn11poagc2MT1pf/tnRf6cdD88wd0bmw/83Ng6WUQ3Uw==", "dev": true, "optional": true }, "@nx/nx-win32-x64-msvc": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-22.5.1.tgz", - "integrity": "sha512-4e5LduuhpBx96JgD1J3fHUGCwC+/lL+tvXp3UVtjh/AOdINGsyI+scinT3uaI9vcB5GKBcybTxbBZzwcH50w9g==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-22.6.4.tgz", + "integrity": "sha512-CIL9m6uilGGr/eU+41/+aVWUnEcq+j1EDynUX2A4InLTbAN0ylte4Af+72mvipNiqJgDkjKaNzOCQDnp8QBjEQ==", "dev": true, "optional": true }, @@ -10775,9 +10081,9 @@ } }, "@sigstore/core": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.1.0.tgz", - "integrity": "sha512-o5cw1QYhNQ9IroioJxpzexmPjfCe7gzafd2RY3qnMpxr4ZEja+Jad/U8sgFpaue6bOaF+z7RVkyKVV44FN+N8A==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.2.0.tgz", + "integrity": "sha512-kxHrDQ9YgfrWUSXU0cjsQGv8JykOFZQ9ErNKbFPWzk3Hgpwu8x2hHrQ9IdA8yl+j9RTLTC3sAF3Tdq1IQCP4oA==", "dev": true }, "@sigstore/protobuf-specs": { @@ -10787,26 +10093,34 @@ "dev": true }, "@sigstore/sign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.0.tgz", - "integrity": "sha512-Vx1RmLxLGnSUqx/o5/VsCjkuN5L7y+vxEEwawvc7u+6WtX2W4GNa7b9HEjmcRWohw/d6BpATXmvOwc78m+Swdg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.1.tgz", + "integrity": "sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ==", "dev": true, "requires": { + "@gar/promise-retry": "^1.0.2", "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", + "@sigstore/core": "^3.2.0", "@sigstore/protobuf-specs": "^0.5.0", - "make-fetch-happen": "^15.0.3", - "proc-log": "^6.1.0", - "promise-retry": "^2.0.1" + "make-fetch-happen": "^15.0.4", + "proc-log": "^6.1.0" }, "dependencies": { + "@npmcli/redact": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-4.0.0.tgz", + "integrity": "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q==", + "dev": true + }, "make-fetch-happen": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.3.tgz", - "integrity": "sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw==", + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.5.tgz", + "integrity": "sha512-uCbIa8jWWmQZt4dSnEStkVC6gdakiinAm4PiGsywIkguF0eWMdcjDz0ECYhUolFU3pFLOev9VNPCEygydXnddg==", "dev": true, "requires": { + "@gar/promise-retry": "^1.0.0", "@npmcli/agent": "^4.0.0", + "@npmcli/redact": "^4.0.0", "cacache": "^20.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", @@ -10815,17 +10129,16 @@ "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", "ssri": "^13.0.0" } }, "minipass-fetch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-5.0.1.tgz", - "integrity": "sha512-yHK8pb0iCGat0lDrs/D6RZmCdaBT64tULXjdxjSMAqoDi18Q3qKEUTHypHQZQd9+FYpIS+lkvpq6C/R6SbUeRw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-5.0.2.tgz", + "integrity": "sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ==", "dev": true, "requires": { - "encoding": "^0.1.13", + "iconv-lite": "^0.7.2", "minipass": "^7.0.3", "minipass-sized": "^2.0.0", "minizlib": "^3.0.1" @@ -10858,9 +10171,9 @@ } }, "@sigstore/tuf": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.1.tgz", - "integrity": "sha512-OPZBg8y5Vc9yZjmWCHrlWPMBqW5yd8+wFNl+thMdtcWz3vjVSoJQutF8YkrzI0SLGnkuFof4HSsWUhXrf219Lw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.2.tgz", + "integrity": "sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ==", "dev": true, "requires": { "@sigstore/protobuf-specs": "^0.5.0", @@ -10901,27 +10214,27 @@ }, "dependencies": { "balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true }, "brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "requires": { "balanced-match": "^4.0.2" } }, "minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "requires": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" } } } @@ -11163,13 +10476,13 @@ "version": "1.0.5" }, "axios": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", - "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.0.tgz", + "integrity": "sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==", "dev": true, "requires": { - "follow-redirects": "^1.15.11", - "form-data": "^4.0.5", + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, @@ -11243,7 +10556,9 @@ } }, "brace-expansion": { - "version": "1.1.12", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -11313,9 +10628,9 @@ "dev": true }, "brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "requires": { "balanced-match": "^4.0.2" @@ -11432,9 +10747,9 @@ "dev": true }, "ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", "dev": true }, "clean-stack": { @@ -11810,12 +11125,6 @@ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true }, - "detect-indent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", - "integrity": "sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==", - "dev": true - }, "dot-prop": { "version": "5.3.0", "dev": true, @@ -12067,27 +11376,27 @@ } }, "filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", "dev": true, "requires": { "minimatch": "^5.0.1" }, "dependencies": { "brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, "requires": { "balanced-match": "^1.0.0" } }, "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -12193,9 +11502,9 @@ "dev": true }, "fs-extra": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", - "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", + "version": "11.3.4", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", + "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", "dev": true, "requires": { "graceful-fs": "^4.2.0", @@ -12347,10 +11656,6 @@ } } }, - "get-port": { - "version": "5.1.1", - "dev": true - }, "get-proto": { "version": "1.0.1", "requires": { @@ -12388,14 +11693,6 @@ "requires": { "gitconfiglocal": "^1.0.0", "pify": "^2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true - } } }, "git-semver-tags": { @@ -12437,7 +11734,9 @@ } }, "glob": { - "version": "10.4.5", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "requires": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -12448,7 +11747,9 @@ }, "dependencies": { "brace-expansion": { - "version": "2.0.2", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "requires": { "balanced-match": "^1.0.0" } @@ -12483,9 +11784,9 @@ "version": "4.2.11" }, "handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", "dev": true, "requires": { "minimist": "^1.2.5", @@ -12624,27 +11925,27 @@ }, "dependencies": { "balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true }, "brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "requires": { "balanced-match": "^4.0.2" } }, "minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "requires": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" } } } @@ -12775,6 +12076,14 @@ "dev": true, "requires": { "ci-info": "^3.2.0" + }, + "dependencies": { + "ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true + } } }, "is-core-module": { @@ -13019,16 +12328,10 @@ "picomatch": "^4.0.2" }, "dependencies": { - "ci-info": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", - "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", - "dev": true - }, "picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true } } @@ -13124,12 +12427,11 @@ "dev": true }, "lerna": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/lerna/-/lerna-9.0.4.tgz", - "integrity": "sha512-wKy9TOkkdCWPWET0R5o7mh7J0KuNNjxE0g+qTruNAt5ffWwy54wfWiJtWyDSMOrcGDt6gtisDBTKniOqK/sJvw==", + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/lerna/-/lerna-9.0.7.tgz", + "integrity": "sha512-PMjbSWYfwL1yZ5c1D2PZuFyzmtYhLdn0f76uG8L25g6eYy34j+2jPb4Q6USx1UJvxVtxkdVEeAAWS/WxgJ8VZA==", "dev": true, "requires": { - "@lerna/create": "9.0.4", "@npmcli/arborist": "9.1.6", "@npmcli/package-json": "7.0.2", "@npmcli/run-script": "10.0.3", @@ -13139,6 +12441,7 @@ "aproba": "2.0.0", "byte-size": "8.1.1", "chalk": "4.1.0", + "ci-info": "4.3.1", "cmd-shim": "6.0.3", "color-support": "1.1.3", "columnify": "1.6.0", @@ -13151,7 +12454,6 @@ "envinfo": "7.13.0", "execa": "5.0.0", "fs-extra": "^11.2.0", - "get-port": "5.1.1", "get-stream": "6.0.0", "git-url-parse": "14.0.0", "glob-parent": "6.0.2", @@ -13161,16 +12463,13 @@ "init-package-json": "8.2.2", "inquirer": "12.9.6", "is-ci": "3.0.1", - "is-stream": "2.0.0", "jest-diff": ">=30.0.0 < 31", "js-yaml": "4.1.1", "libnpmaccess": "10.0.3", "libnpmpublish": "11.1.2", "load-json-file": "6.2.0", - "make-dir": "4.0.0", "make-fetch-happen": "15.0.2", - "minimatch": "3.0.5", - "multimatch": "5.0.0", + "minimatch": "3.1.4", "npm-package-arg": "13.0.1", "npm-packlist": "10.0.3", "npm-registry-fetch": "19.1.0", @@ -13182,38 +12481,25 @@ "p-reduce": "2.1.0", "p-waterfall": "2.1.1", "pacote": "21.0.1", - "pify": "5.0.0", "read-cmd-shim": "4.0.0", - "resolve-from": "5.0.0", - "rimraf": "^6.1.2", "semver": "7.7.2", - "set-blocking": "^2.0.0", "signal-exit": "3.0.7", "slash": "3.0.0", "ssri": "12.0.0", "string-width": "^4.2.3", - "tar": "7.5.7", - "temp-dir": "1.0.0", + "tar": "7.5.11", "through": "2.3.8", "tinyglobby": "0.2.12", "typescript": ">=3 < 6", "upath": "2.0.1", - "uuid": "^11.1.0", "validate-npm-package-license": "3.0.4", "validate-npm-package-name": "6.0.2", "wide-align": "1.1.5", "write-file-atomic": "5.0.1", - "write-pkg": "4.0.0", "yargs": "17.7.2", "yargs-parser": "21.1.1" }, "dependencies": { - "balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", - "dev": true - }, "chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -13254,75 +12540,14 @@ "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", "dev": true }, - "glob": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", - "dev": true, - "requires": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" - }, - "dependencies": { - "brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", - "dev": true, - "requires": { - "balanced-match": "^4.0.2" - } - }, - "minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", - "dev": true, - "requires": { - "brace-expansion": "^5.0.2" - } - } - } - }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - }, - "lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", - "dev": true - }, "minimatch": { - "version": "3.0.5", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.4.tgz", + "integrity": "sha512-twmL+S8+7yIsE9wsqgzU3E8/LumN3M3QELrBZ20OdmQ9jB2JvW5oZtBEmft84k/Gs5CG9mqtWc6Y9vW+JEzGxw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } - }, - "path-scurry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", - "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", - "dev": true, - "requires": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - } - }, - "rimraf": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", - "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", - "dev": true, - "requires": { - "glob": "^13.0.3", - "package-json-from-dist": "^1.0.1" - } } } }, @@ -13350,14 +12575,6 @@ "semver": "^7.3.7", "sigstore": "^4.0.0", "ssri": "^12.0.0" - }, - "dependencies": { - "ci-info": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", - "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", - "dev": true - } } }, "lilconfig": { @@ -13598,15 +12815,6 @@ "lru-cache": { "version": "10.4.3" }, - "make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "requires": { - "semver": "^7.5.3" - } - }, "make-fetch-happen": { "version": "15.0.2", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.2.tgz", @@ -14054,12 +13262,6 @@ } } }, - "node-machine-id": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", - "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", - "dev": true - }, "nopt": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", @@ -14303,26 +13505,27 @@ } }, "nx": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/nx/-/nx-22.5.1.tgz", - "integrity": "sha512-KIQqOSdoshkav9JuoH/+Vp42niA5MTRtACupe+q8CaB7bHiLsWr5nctQVC7ul3NauAmsoqNWH7t5CIi8KgrPIQ==", + "version": "22.6.4", + "resolved": "https://registry.npmjs.org/nx/-/nx-22.6.4.tgz", + "integrity": "sha512-WEaCnLKeO9RhQAOBMfXgYO/Lx5wL4ARCtRGiYCjJtAJIZ5kcVn4uPKL2Xz1xekpF7ef/+YNrUQSrblx47Ms9Rg==", "dev": true, "requires": { + "@ltd/j-toml": "^1.38.0", "@napi-rs/wasm-runtime": "0.2.4", - "@nx/nx-darwin-arm64": "22.5.1", - "@nx/nx-darwin-x64": "22.5.1", - "@nx/nx-freebsd-x64": "22.5.1", - "@nx/nx-linux-arm-gnueabihf": "22.5.1", - "@nx/nx-linux-arm64-gnu": "22.5.1", - "@nx/nx-linux-arm64-musl": "22.5.1", - "@nx/nx-linux-x64-gnu": "22.5.1", - "@nx/nx-linux-x64-musl": "22.5.1", - "@nx/nx-win32-arm64-msvc": "22.5.1", - "@nx/nx-win32-x64-msvc": "22.5.1", + "@nx/nx-darwin-arm64": "22.6.4", + "@nx/nx-darwin-x64": "22.6.4", + "@nx/nx-freebsd-x64": "22.6.4", + "@nx/nx-linux-arm-gnueabihf": "22.6.4", + "@nx/nx-linux-arm64-gnu": "22.6.4", + "@nx/nx-linux-arm64-musl": "22.6.4", + "@nx/nx-linux-x64-gnu": "22.6.4", + "@nx/nx-linux-x64-musl": "22.6.4", + "@nx/nx-win32-arm64-msvc": "22.6.4", + "@nx/nx-win32-x64-msvc": "22.6.4", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "3.0.2", "@zkochan/js-yaml": "0.0.7", - "axios": "^1.12.0", + "axios": "1.12.0", "cli-cursor": "3.1.0", "cli-spinners": "2.6.1", "cliui": "^8.0.1", @@ -14337,8 +13540,7 @@ "jest-diff": "^30.0.2", "jsonc-parser": "3.2.0", "lines-and-columns": "2.0.3", - "minimatch": "10.1.1", - "node-machine-id": "1.1.12", + "minimatch": "10.2.4", "npm-run-path": "^4.0.1", "open": "^8.4.0", "ora": "5.3.0", @@ -14356,13 +13558,28 @@ "yargs-parser": "21.1.1" }, "dependencies": { + "balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true + }, + "brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "requires": { + "balanced-match": "^4.0.2" + } + }, "minimatch": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", - "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, "requires": { - "@isaacs/brace-expansion": "^5.0.0" + "brace-expansion": "^5.0.2" } } } @@ -14717,16 +13934,18 @@ "dev": true }, "picomatch": { - "version": "2.3.1", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true }, "pidtree": { "version": "0.3.1" }, "pify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true }, "pkg-dir": { @@ -15159,15 +14378,6 @@ "socks": "^2.8.3" } }, - "sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -15354,9 +14564,9 @@ "version": "1.0.0" }, "tar": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", - "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.11.tgz", + "integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==", "dev": true, "requires": { "@isaacs/fs-minipass": "^4.0.0", @@ -15379,12 +14589,6 @@ "readable-stream": "^3.1.1" } }, - "temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==", - "dev": true - }, "text-extensions": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", @@ -15455,9 +14659,9 @@ "requires": {} }, "picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true } } @@ -15617,12 +14821,6 @@ "version": "1.0.2", "dev": true }, - "uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", - "dev": true - }, "validate-npm-package-license": { "version": "3.0.4", "requires": { @@ -15734,74 +14932,6 @@ } } }, - "write-json-file": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", - "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", - "dev": true, - "requires": { - "detect-indent": "^5.0.0", - "graceful-fs": "^4.1.15", - "make-dir": "^2.1.0", - "pify": "^4.0.1", - "sort-keys": "^2.0.0", - "write-file-atomic": "^2.4.2" - }, - "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, - "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - } - } - }, - "write-pkg": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz", - "integrity": "sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==", - "dev": true, - "requires": { - "sort-keys": "^2.0.0", - "type-fest": "^0.4.1", - "write-json-file": "^3.2.0" - }, - "dependencies": { - "type-fest": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", - "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", - "dev": true - } - } - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", From 3dc4abbd3ba8c2285f8f9f2270bf999e18ebf555 Mon Sep 17 00:00:00 2001 From: terminalchai Date: Fri, 3 Apr 2026 02:02:22 +0530 Subject: [PATCH 146/297] fix: align slider marks with empty labels --- .../src/components/css/sliders.css | 1 + .../tests/integration/sliders/test_sliders.py | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/components/dash-core-components/src/components/css/sliders.css b/components/dash-core-components/src/components/css/sliders.css index 95ebe582d3..cb6d4e41cd 100644 --- a/components/dash-core-components/src/components/css/sliders.css +++ b/components/dash-core-components/src/components/css/sliders.css @@ -92,6 +92,7 @@ .dash-slider-mark { position: absolute; font-size: 12px; + height: 12px; line-height: 12px; color: var(--Dash-Text-Strong); white-space: nowrap; diff --git a/components/dash-core-components/tests/integration/sliders/test_sliders.py b/components/dash-core-components/tests/integration/sliders/test_sliders.py index fed33c30d8..1364a6ef01 100644 --- a/components/dash-core-components/tests/integration/sliders/test_sliders.py +++ b/components/dash-core-components/tests/integration/sliders/test_sliders.py @@ -734,3 +734,30 @@ def update_rangeslider(value): dash_dcc.wait_for_text_to_equal("#rangeslider-output", "RangeSlider: 10-75") assert dash_dcc.get_logs() == [] + + +def test_slsl020_empty_mark_labels_keep_tick_alignment(dash_dcc): + app = Dash(__name__) + marks = {val: (str(val) if val % 10 == 0 else "") for val in range(0, 151, 5)} + + app.layout = dcc.Slider( + id="slider-empty-mark-labels", + min=0, + max=150, + step=None, + value=0, + marks=marks, + ) + + dash_dcc.start_server(app) + dash_dcc.wait_for_element("#slider-empty-mark-labels") + + rendered_marks = dash_dcc.find_elements( + "#slider-empty-mark-labels .dash-slider-mark" + ) + labeled_mark = next(mark for mark in rendered_marks if mark.text) + empty_mark = next(mark for mark in rendered_marks if not mark.text) + + assert labeled_mark.size["height"] == 12 + assert empty_mark.size["height"] == labeled_mark.size["height"] + assert dash_dcc.get_logs() == [] From fc7fe59d2d98310dfaf4fe0047a13b195c52e3f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 20:57:51 +0000 Subject: [PATCH 147/297] Bump the npm-dependencies-security group across 1 directory with 1 update Bumps the npm-dependencies-security group with 1 update in the / directory: [minimatch](https://github.com/isaacs/minimatch). Updates `minimatch` from 3.1.2 to 3.1.5 - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5) Updates `minimatch` from 9.0.5 to 9.0.9 - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5) Updates `minimatch` from 10.2.2 to 10.2.5 - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5) --- updated-dependencies: - dependency-name: minimatch dependency-version: 3.1.5 dependency-type: indirect dependency-group: npm-dependencies-security - dependency-name: minimatch dependency-version: 9.0.9 dependency-type: indirect dependency-group: npm-dependencies-security - dependency-name: minimatch dependency-version: 10.2.5 dependency-type: indirect dependency-group: npm-dependencies-security ... Signed-off-by: dependabot[bot] --- package-lock.json | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7341387472..810b726d69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2533,12 +2533,12 @@ } }, "node_modules/cacache/node_modules/minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "dependencies": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" }, "engines": { "node": "18 || 20 || >=22" @@ -4140,10 +4140,11 @@ } }, "node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "license": "ISC", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -6089,8 +6090,9 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "license": "ISC", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -10654,12 +10656,12 @@ "dev": true }, "minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "requires": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" } }, "p-map": { @@ -11755,9 +11757,11 @@ } }, "minimatch": { - "version": "9.0.5", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "requires": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" } } } @@ -13021,7 +13025,9 @@ "dev": true }, "minimatch": { - "version": "3.1.2", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "requires": { "brace-expansion": "^1.1.7" } From 54cd2822959cd7a61a9d786af6ca7888a38b0952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?In=C3=AAs=20Martins?= Date: Sun, 22 Mar 2026 15:38:07 +0000 Subject: [PATCH 148/297] Fix #2989: Preserve option order during dcc.Dropdown search When searching in dcc.Dropdown, results should maintain the original option order instead of being reordered by js-search. By creating a Set of search results and filtering the original options array, we preserve order while maintaining performance. --- .../src/utils/dropdownSearch.ts | 7 +- .../dropdown/test_dropdown_search_order.py | 160 ++++++++++++++++++ 2 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 components/dash-core-components/tests/integration/dropdown/test_dropdown_search_order.py diff --git a/components/dash-core-components/src/utils/dropdownSearch.ts b/components/dash-core-components/src/utils/dropdownSearch.ts index 41ad649bd3..c1a36a1c2b 100644 --- a/components/dash-core-components/src/utils/dropdownSearch.ts +++ b/components/dash-core-components/src/utils/dropdownSearch.ts @@ -79,5 +79,10 @@ export function filterOptions( search.addDocuments(options.options); } - return (search.search(searchValue) as DetailedOption[]) || []; + const searchResults = + (search.search(searchValue) as DetailedOption[]) || []; + + const resultSet = new Set(searchResults); + + return options.options.filter(option => resultSet.has(option)); } diff --git a/components/dash-core-components/tests/integration/dropdown/test_dropdown_search_order.py b/components/dash-core-components/tests/integration/dropdown/test_dropdown_search_order.py new file mode 100644 index 0000000000..2821169931 --- /dev/null +++ b/components/dash-core-components/tests/integration/dropdown/test_dropdown_search_order.py @@ -0,0 +1,160 @@ +from dash import Dash, html, dcc, Input, Output +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.common.action_chains import ActionChains +from time import sleep + + +def test_ddso001_search_preserves_custom_order(dash_duo): + app = Dash(__name__) + + app.layout = html.Div( + [ + dcc.Dropdown( + id="dropdown", + options=["11 Text", "12", "23", "112", "111", "110", "22"], + searchable=True, + ), + html.Div(id="output"), + ] + ) + + dash_duo.start_server(app) + + dropdown = dash_duo.find_element("#dropdown") + dropdown.click() + dash_duo.wait_for_element(".dash-dropdown-options") + + # Search for '11' + search_input = dash_duo.find_element(".dash-dropdown-search") + search_input.send_keys("11") + sleep(0.2) + + # Presents matching options in original order + options = dash_duo.find_elements(".dash-dropdown-option") + assert len(options) == 4 + assert [opt.text for opt in options] == ["11 Text", "112", "111", "110"] + + assert dash_duo.get_logs() == [] + + +def test_ddso002_multi_search_preserves_custom_order(dash_duo): + def send_keys(key): + ActionChains(dash_duo.driver).send_keys(key).perform() + + app = Dash(__name__) + app.layout = html.Div( + [ + dcc.Dropdown( + id="dropdown", + options=["11 Text", "12", "112", "111", "110"], + multi=True, + searchable=True, + ), + html.Div(id="output"), + ] + ) + + @app.callback(Output("output", "children"), Input("dropdown", "value")) + def update_output(value): + return f"Selected: {value}" + + dash_duo.start_server(app) + + dropdown = dash_duo.find_element("#dropdown") + dropdown.click() + dash_duo.wait_for_element(".dash-dropdown-options") + + # Select '12' (second option) + send_keys(Keys.ARROW_DOWN) + sleep(0.2) + send_keys(Keys.ARROW_DOWN) + sleep(0.2) + send_keys(Keys.SPACE) + dash_duo.wait_for_text_to_equal("#output", "Selected: ['12']") + sleep(0.2) + + # Select '111' (fourth option) + send_keys(Keys.ARROW_DOWN) + sleep(0.2) + send_keys(Keys.ARROW_DOWN) + sleep(0.2) + send_keys(Keys.SPACE) + dash_duo.wait_for_text_to_equal("#output", "Selected: ['12', '111']") + sleep(0.2) + + # Search for '1' + send_keys(Keys.HOME) + sleep(0.2) + send_keys("1") + sleep(0.2) + + # Presents selected options first and rest in original order + options = dash_duo.find_elements(".dash-dropdown-option") + assert len(options) == 5 + assert [opt.text for opt in options] == ["12", "111", "11 Text", "112", "110"] + + assert dash_duo.get_logs() == [] + + +def test_ddso003_search_preserves_custom_order_full_list(dash_duo): + app = Dash(__name__) + + app.layout = html.Div( + [ + dcc.Dropdown( + id="dropdown", + options=["A", "Zebra", "Apply", "Apple"], + searchable=True, + ), + html.Div(id="output"), + ] + ) + dash_duo.start_server(app) + + dropdown = dash_duo.find_element("#dropdown") + dropdown.click() + + search_input = dash_duo.find_element(".dash-dropdown-search") + + # Search for 'A', returns all options + search_input.send_keys("A") + sleep(0.2) + + # Presents all options in original order + options = dash_duo.find_elements(".dash-dropdown-option") + assert len(options) == 4 + assert [opt.text for opt in options] == ["A", "Zebra", "Apply", "Apple"] + + assert dash_duo.get_logs() == [] + + +def test_ddso004_search_no_match(dash_duo): + app = Dash(__name__) + + app = Dash(__name__) + app.layout = html.Div( + [ + dcc.Dropdown( + id="dropdown", + options=["11 Text", "12", "110", "111", "112"], + searchable=True, + ), + html.Div(id="output"), + ] + ) + dash_duo.start_server(app) + + dropdown = dash_duo.find_element("#dropdown") + dropdown.click() + + search_input = dash_duo.find_element(".dash-dropdown-search") + + # Search for 'A', returns no options + search_input.send_keys("A") + sleep(0.2) + + options = dash_duo.find_elements(".dash-dropdown-option") + + assert len(options) == 1 + assert [opt.text for opt in options] == ["No options found"] + assert dash_duo.get_logs() == [] From 57f41259d71e4d5bfdfee0454fbd845158318702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?In=C3=AAs=20Martins?= Date: Fri, 3 Apr 2026 12:48:17 +0100 Subject: [PATCH 149/297] Fix #2989, #2667: Add search_order prop to control dropdown result ordering - Adds new search_order prop with 'index' (default) and 'original' options ordering - Changed 4 integration tests to include new prop --- .../dash-core-components/src/fragments/Dropdown.tsx | 5 +++-- components/dash-core-components/src/types.ts | 7 +++++++ .../dash-core-components/src/utils/dropdownSearch.ts | 10 +++++++--- .../integration/dropdown/test_dropdown_search_order.py | 4 ++++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/components/dash-core-components/src/fragments/Dropdown.tsx b/components/dash-core-components/src/fragments/Dropdown.tsx index 3fedfc473a..6a838fb1df 100644 --- a/components/dash-core-components/src/fragments/Dropdown.tsx +++ b/components/dash-core-components/src/fragments/Dropdown.tsx @@ -41,6 +41,7 @@ const Dropdown = (props: DropdownProps) => { setProps, searchable, search_value, + search_order, style, value, } = props; @@ -81,9 +82,9 @@ const Dropdown = (props: DropdownProps) => { const filteredOptions = useMemo( () => searchable - ? filterOptions(sanitized, search_value) + ? filterOptions(sanitized, search_value, search_order) : sanitizedOptions, - [sanitized, searchable, search_value] + [sanitized, searchable, search_value, search_order] ); const sanitizedValues: OptionValue[] = useMemo(() => { diff --git a/components/dash-core-components/src/types.ts b/components/dash-core-components/src/types.ts index 8311259f3c..f4bc430141 100644 --- a/components/dash-core-components/src/types.ts +++ b/components/dash-core-components/src/types.ts @@ -746,6 +746,13 @@ export interface DropdownProps extends BaseDccProps { * Use with `closeOnSelect=False` */ debounce?: boolean; + + /** + * The order in which to search results appear. 'index' (the default) means that + * options are presented based on search relevance, while 'original' keeps the + * order of options as they were originally provided. + */ + search_order?: 'index' | 'original'; } export interface ChecklistProps extends BaseDccProps { diff --git a/components/dash-core-components/src/utils/dropdownSearch.ts b/components/dash-core-components/src/utils/dropdownSearch.ts index c1a36a1c2b..7b88014a4f 100644 --- a/components/dash-core-components/src/utils/dropdownSearch.ts +++ b/components/dash-core-components/src/utils/dropdownSearch.ts @@ -60,7 +60,8 @@ export function sanitizeDropdownOptions( export function filterOptions( options: SanitizedOptions, - searchValue?: string + searchValue?: string, + search_order?: 'index' | 'original' ): DetailedOption[] { if (!searchValue) { return options.options; @@ -82,7 +83,10 @@ export function filterOptions( const searchResults = (search.search(searchValue) as DetailedOption[]) || []; - const resultSet = new Set(searchResults); + if (search_order === 'original') { + const resultSet = new Set(searchResults); + return options.options.filter(option => resultSet.has(option)); + } - return options.options.filter(option => resultSet.has(option)); + return searchResults; } diff --git a/components/dash-core-components/tests/integration/dropdown/test_dropdown_search_order.py b/components/dash-core-components/tests/integration/dropdown/test_dropdown_search_order.py index 2821169931..04f09f960f 100644 --- a/components/dash-core-components/tests/integration/dropdown/test_dropdown_search_order.py +++ b/components/dash-core-components/tests/integration/dropdown/test_dropdown_search_order.py @@ -13,6 +13,7 @@ def test_ddso001_search_preserves_custom_order(dash_duo): id="dropdown", options=["11 Text", "12", "23", "112", "111", "110", "22"], searchable=True, + search_order="original", ), html.Div(id="output"), ] @@ -49,6 +50,7 @@ def send_keys(key): options=["11 Text", "12", "112", "111", "110"], multi=True, searchable=True, + search_order="original", ), html.Div(id="output"), ] @@ -105,6 +107,7 @@ def test_ddso003_search_preserves_custom_order_full_list(dash_duo): id="dropdown", options=["A", "Zebra", "Apply", "Apple"], searchable=True, + search_order="original", ), html.Div(id="output"), ] @@ -138,6 +141,7 @@ def test_ddso004_search_no_match(dash_duo): id="dropdown", options=["11 Text", "12", "110", "111", "112"], searchable=True, + search_order="original", ), html.Div(id="output"), ] From 286c212b45a3e8cbe3543349ad6906b2e84f635e Mon Sep 17 00:00:00 2001 From: Francisco Cruz Date: Tue, 17 Mar 2026 09:53:21 +0000 Subject: [PATCH 150/297] Fix #3030: Selection for DataTable cleared with custom action settings In derivedPropsHelper.ts, selected rows may be invalidated when sorting, filtering or changing pages, while using custom action settings. Invalidation happens when sorting, filtering or pagination actions are set to custom and their values change. The code does not check wether the same callback also provides a new selected_rows value. Because invalidation runs inside a setTimeout(..., 0), when a callback updates both selection and sorting, filtering or pagination, the selection briefly appears and clears, causing a visible "flicker". To fix this, before invalidating the selection, we simply have to check wether selected_rows actually changed in the current callback. The selection is only cleared if it did not change, preventing the invalidation of the sent selection. --- .../components/Table/derivedPropsHelper.ts | 20 ++-- .../selenium/test_selected_rows_custom.py | 107 ++++++++++++++++++ 2 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 components/dash-table/tests/selenium/test_selected_rows_custom.py diff --git a/components/dash-table/src/dash-table/components/Table/derivedPropsHelper.ts b/components/dash-table/src/dash-table/components/Table/derivedPropsHelper.ts index 1107942987..a381f3f1cf 100644 --- a/components/dash-table/src/dash-table/components/Table/derivedPropsHelper.ts +++ b/components/dash-table/src/dash-table/components/Table/derivedPropsHelper.ts @@ -18,6 +18,9 @@ export default () => { page_current, page_size ]); + const selectedRowsCache = memoizeOneWithFlag( + selected_rows => selected_rows + ); const sortCache = memoizeOneWithFlag(sort => sort); const viewportCache = memoizeOneWithFlag(viewport => viewport); const viewportSelectedColumnsCache = memoizeOneWithFlag( @@ -37,6 +40,7 @@ export default () => { page_action, page_current, page_size, + selected_rows, sort_action, sort_by, viewport, @@ -64,17 +68,19 @@ export default () => { const invalidatedFilter = filterCache(filter_query); const invalidatedPagination = paginationCache(page_current, page_size); const invalidatedSort = sortCache(sort_by); + const invalidatedSelectedRows = selectedRowsCache(selected_rows); const invalidateSelection = - (!invalidatedFilter.cached && + invalidatedSelectedRows.cached && + ((!invalidatedFilter.cached && !invalidatedFilter.first && filter_action.type === TableAction.Custom) || - (!invalidatedPagination.cached && - !invalidatedPagination.first && - page_action === TableAction.Custom) || - (!invalidatedSort.cached && - !invalidatedSort.first && - sort_action === TableAction.Custom); + (!invalidatedPagination.cached && + !invalidatedPagination.first && + page_action === TableAction.Custom) || + (!invalidatedSort.cached && + !invalidatedSort.first && + sort_action === TableAction.Custom)); const newProps: Partial = {}; diff --git a/components/dash-table/tests/selenium/test_selected_rows_custom.py b/components/dash-table/tests/selenium/test_selected_rows_custom.py new file mode 100644 index 0000000000..ab54f146da --- /dev/null +++ b/components/dash-table/tests/selenium/test_selected_rows_custom.py @@ -0,0 +1,107 @@ +import dash +from dash.dependencies import Input, Output +from dash import html +from dash.dash_table import DataTable + +import json +import time +import pandas as pd + +url = "https://github.com/plotly/datasets/raw/master/" "26k-consumer-complaints.csv" +rawDf = pd.read_csv(url, nrows=100) +rawDf["id"] = rawDf.index + 3000 +df = rawDf.to_dict("records") + + +def get_app(): + app = dash.Dash(__name__) + + app.layout = html.Div( + [ + DataTable( + id="table", + columns=[{"name": i, "id": i} for i in rawDf.columns], + data=df, + row_selectable=True, + selected_rows=[], + filter_action="custom", + filter_query="", + sort_action="custom", + sort_by=[], + page_action="custom", + page_current=0, + page_size=10, + style_cell=dict(width=100, min_width=100, max_width=100), + ), + html.Button("Set selected + sort_by", id="sort"), + html.Button("Set selected + filter", id="filter"), + html.Button("Set selected + page", id="page"), + html.Div(id="selected_rows_output"), + ] + ) + + @app.callback( + Output("selected_rows_output", "children"), + Input("table", "selected_rows"), + ) + def show_selected_rows(selected_rows): + return json.dumps(selected_rows) if selected_rows is not None else "None" + + @app.callback( + Output("table", "selected_rows"), + Output("table", "sort_by"), + Input("sort", "n_clicks"), + prevent_initial_call=True, + ) + def set_selected_and_sort(_): + return [0, 1, 2], [{"column_id": rawDf.columns[0], "direction": "asc"}] + + @app.callback( + Output("table", "selected_rows", allow_duplicate=True), + Output("table", "filter_query"), + Input("filter", "n_clicks"), + prevent_initial_call=True, + ) + def set_selected_and_filter(_): + return [0, 1, 2], "{} > 1".format(rawDf.columns[0]) + + @app.callback( + Output("table", "selected_rows", allow_duplicate=True), + Output("table", "page_current"), + Input("page", "n_clicks"), + prevent_initial_call=True, + ) + def set_selected_and_page(_): + return [0, 1, 2], 1 + + return app + + +def test_tsrc001_selected_rows_persists_with_sort_by(test): + test.start_server(get_app()) + + test.find_element("#sort").click() + time.sleep(1) + + assert test.find_element("#selected_rows_output").text == json.dumps([0, 1, 2]) + assert test.get_log_errors() == [] + + +def test_tsrc002_selected_rows_persists_with_filter_query(test): + test.start_server(get_app()) + + test.find_element("#filter").click() + time.sleep(1) + + assert test.find_element("#selected_rows_output").text == json.dumps([0, 1, 2]) + assert test.get_log_errors() == [] + + +def test_tsrc003_selected_rows_persists_with_page_current(test): + test.start_server(get_app()) + + test.find_element("#page").click() + time.sleep(1) + + assert test.find_element("#selected_rows_output").text == json.dumps([0, 1, 2]) + assert test.get_log_errors() == [] From b6fcc4a048d1c68c5fb3e4d5240a9691147cc03f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?In=C3=AAs=20Martins?= Date: Mon, 6 Apr 2026 21:02:07 +0100 Subject: [PATCH 151/297] Add changelog entry --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3dc4e9284..f8c5d00179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## [UNRELEASED] +## Added +- [#3680](https://github.com/plotly/dash/pull/3680) Added `search_order` prop to `Dropdown` to allow users to preserve original option order during search + ## Added - [#3523](https://github.com/plotly/dash/pull/3523) Fall back to background callback function names if source cannot be found From 519526c15116853f8e6831c7faf87d5526faf58c Mon Sep 17 00:00:00 2001 From: Francisco Cruz Date: Mon, 6 Apr 2026 17:40:16 +0100 Subject: [PATCH 152/297] Fix plotly#3030: Apply suggestion from @AnnMarieW Co-authored-by: Ann Marie Ward <72614349+AnnMarieW@users.noreply.github.com> --- .../dash-table/tests/selenium/test_selected_rows_custom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dash-table/tests/selenium/test_selected_rows_custom.py b/components/dash-table/tests/selenium/test_selected_rows_custom.py index ab54f146da..49d17a4c19 100644 --- a/components/dash-table/tests/selenium/test_selected_rows_custom.py +++ b/components/dash-table/tests/selenium/test_selected_rows_custom.py @@ -22,7 +22,7 @@ def get_app(): id="table", columns=[{"name": i, "id": i} for i in rawDf.columns], data=df, - row_selectable=True, + row_selectable="multi", selected_rows=[], filter_action="custom", filter_query="", From 7a23cf8e7a97a0ffeafa6f2189423e90c8c8d2df Mon Sep 17 00:00:00 2001 From: Francisco Cruz Date: Tue, 7 Apr 2026 13:39:01 +0100 Subject: [PATCH 153/297] Fix plotly#3030: Add changelog entry --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3dc4e9284..663e6f1b23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## [UNRELEASED] +## Added +- [#3669](https://github.com/plotly/dash/pull/3669) Selection for DataTable cleared with custom action settings + ## Added - [#3523](https://github.com/plotly/dash/pull/3523) Fall back to background callback function names if source cannot be found From 98ba64e896722d8a844851bbeeb1d77852fc4d9b Mon Sep 17 00:00:00 2001 From: philippe Date: Tue, 7 Apr 2026 10:55:08 -0400 Subject: [PATCH 154/297] fix lint --- dash/backends/_fastapi.py | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 867e9a25b0..4e6266146f 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -1,6 +1,5 @@ from __future__ import annotations -import asyncio from contextvars import copy_context, ContextVar import json from typing import TYPE_CHECKING, Any, Callable, Dict @@ -13,6 +12,7 @@ import os import subprocess import threading +import traceback try: from fastapi import FastAPI, Request, Response, Body @@ -32,7 +32,6 @@ from dash.exceptions import PreventUpdate from .base_server import BaseDashServer, RequestAdapter, ResponseAdapter from ._utils import format_traceback_html -import traceback if TYPE_CHECKING: # pragma: no cover - typing only from dash import Dash @@ -126,8 +125,14 @@ async def _initialize_dev_tools(self) -> None: async def _setup_timing(self, request: Request) -> None: """Set up timing information for the request.""" try: - request.state.json_body = await request.json() if request.headers.get("content-type", "").startswith("application/json") else None - except: + request.state.json_body = ( + await request.json() + if request.headers.get("content-type", "").startswith( + "application/json" + ) + else None + ) + except Exception: # pylint: disable=broad-exception-caught request.state.json_body = None if self.enable_timing: request.state.timing_information = { @@ -187,9 +192,8 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: try: dash_app = get_app() dash_app.backend._setup_catchall() - except: - print("Error during catch-all setup:") - print(traceback.format_exc()) + except Exception: # pylint: disable=broad-exception-caught + traceback.print_exc() await self._initialize_dev_tools() await self.app(scope, receive, send) return @@ -286,24 +290,24 @@ async def index(_request: Request): dash_app._add_url("", index, methods=["GET"]) def setup_catchall(self, dash_app: Dash): - '''This is needed to ensure that all routes are handled by FastAPI + """This is needed to ensure that all routes are handled by FastAPI and passed through the middleware, which is necessary for features like authentication and timing to work correctly on all routes. FastAPI will match this catch-all route for any path that isn't matched by a more specific route, allowing the middleware to - process the request and then return the appropriate response (e.g., 404 if no Dash route matches).''' - + process the request and then return the appropriate response (e.g., 404 if no Dash route matches).""" def _setup_catchall(self): try: - print("Setting up catch-all route for unmatched paths") + print("Setting up catch-all route for unmatched paths", file=sys.stderr) dash_app = get_app() + async def catchall(_request: Request): return Response(content=dash_app.index(), media_type="text/html") # pylint: disable=protected-access self.add_url_rule("{path:path}", catchall, methods=["GET"]) - except: - print(traceback.format_exc()) + except Exception: # pylint: disable=broad-exception-caught + traceback.print_exc() def add_url_rule( self, @@ -313,7 +317,10 @@ def add_url_rule( methods: list[str] | None = None, include_in_schema: bool = False, ): - print(f"Adding URL rule: {rule} -> {view_func} (endpoint: {endpoint}, methods: {methods})") + print( + f"Adding URL rule: {rule} -> {view_func} (endpoint: {endpoint}, methods: {methods})", + file=sys.stderr, + ) if rule == "": rule = "/" if isinstance(view_func, str): @@ -504,7 +511,7 @@ def add_redirect_rule(self, app, fullname, path): ) def serve_callback(self, dash_app: Dash): - async def _dispatch(request: Request): + async def _dispatch(request: Request): # pylint: disable=unused-argument # pylint: disable=protected-access body = self.request_adapter().get_json() cb_ctx = dash_app._initialize_context( @@ -666,7 +673,7 @@ def origin(self): def path(self): return self._request.url.path - async def _get_json(self, request: Request=None): + async def _get_json(self, request: Request = None): req = self._request if not hasattr(req.state, "json_body"): req.state.json_body = await request.json() From 229539ee668802be5add1b0d0e57ce40aff9f2d9 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 8 Apr 2026 09:05:11 -0400 Subject: [PATCH 155/297] set test typing to not run on master --- .github/workflows/testing.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 76b749b971..ac31ffa6dc 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -94,6 +94,7 @@ jobs: test-typing: name: Typing Tests runs-on: ubuntu-latest + if: github.ref_name != 'master' needs: build timeout-minutes: 30 strategy: From f5b0aecc2d64f953f330c7ec5fe313a8204c16d2 Mon Sep 17 00:00:00 2001 From: terminalchai Date: Thu, 9 Apr 2026 00:39:51 +0530 Subject: [PATCH 156/297] docs: add slider mark changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8c5d00179..a78eabf786 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## Fixed - [#3690](https://github.com/plotly/dash/pull/3690) Fixes Input when min or max is set to None +- [#3723](https://github.com/plotly/dash/pull/3723) Fix misaligned `dcc.Slider` marks when some labels are empty strings ## [4.1.0] - 2026-03-23 From 874afd4ce30c8e712c299cf3f0b452a73139d293 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 9 Apr 2026 11:49:34 -0400 Subject: [PATCH 157/297] Initialize ai agents documentation --- .ai/ARCHITECTURE.md | 775 ++++++++++++++++++++++++++++++++ .ai/COMMANDS.md | 81 ++++ .ai/COMPONENTS.md | 182 ++++++++ .ai/README.md | 48 ++ .ai/RENDERER.md | 317 +++++++++++++ .ai/TESTING.md | 486 ++++++++++++++++++++ .ai/TROUBLESHOOTING.md | 329 ++++++++++++++ .github/copilot-instructions.md | 42 ++ AGENTS.md | 42 ++ CLAUDE.md | 48 ++ 10 files changed, 2350 insertions(+) create mode 100644 .ai/ARCHITECTURE.md create mode 100644 .ai/COMMANDS.md create mode 100644 .ai/COMPONENTS.md create mode 100644 .ai/README.md create mode 100644 .ai/RENDERER.md create mode 100644 .ai/TESTING.md create mode 100644 .ai/TROUBLESHOOTING.md create mode 100644 .github/copilot-instructions.md create mode 100644 AGENTS.md create mode 100644 CLAUDE.md diff --git a/.ai/ARCHITECTURE.md b/.ai/ARCHITECTURE.md new file mode 100644 index 0000000000..ca6816ccf9 --- /dev/null +++ b/.ai/ARCHITECTURE.md @@ -0,0 +1,775 @@ +# Architecture + +## Python Backend Framework + +- **`dash/dash.py`** - Main `Dash` application class (~2000 lines). Orchestrates Flask server, layout management, callback registration, routing, and asset serving. Key methods: `layout` property, `callback()`, `clientside_callback()`, `run()`. + +- **`dash/_callback.py`** - Callback registration and execution. Contains `callback()` decorator (usable as `@dash.callback` without app instance), `clientside_callback()`, and `register_callback()` which inserts callbacks into the callback map. + +- **`dash/dependencies.py`** - Dependency classes for callbacks: + - `Input` - Triggers callback when value changes + - `Output` - Component property to update (supports `allow_duplicate=True`) + - `State` - Read value without triggering callback + - `ClientsideFunction` - Reference to JS function for clientside callbacks + - Wildcards: `MATCH`, `ALL`, `ALLSMALLER` for pattern-matching IDs + +- **`dash/development/base_component.py`** - `Component` base class with `ComponentMeta` metaclass. All Dash components inherit from this. Components auto-register in `ComponentRegistry` and serialize to JSON via `to_plotly_json()`. + +- **`dash/_pages.py`** - Multi-page app support. `PAGE_REGISTRY` holds registered pages, `register_page()` decorator registers page modules with routes. + +## Layout System + +The layout defines the UI as a tree of components: + +```python +app.layout = html.Div([ + dcc.Input(id='input', value='initial'), + html.Div(id='output') +]) +``` + +- **Static layout**: Assigned directly as a component tree +- **Dynamic layout**: Assigned as a function that returns components (called on each page load, useful for per-session state) +- Layout is serialized to JSON and sent to the React frontend via `/_dash-layout` +- Components can contain other components via `children` prop +- Component IDs can be strings or dicts (for pattern-matching callbacks) + +## Callback Types + +### 1. Regular Callbacks + +`@app.callback` or `@dash.callback`: + +```python +@app.callback(Output('output', 'children'), Input('input', 'value')) +def update(value): + return f'You entered: {value}' +``` + +Server-side Python function called when inputs change. Outputs update component properties. + +### 2. Clientside Callbacks + +`app.clientside_callback`: + +```python +app.clientside_callback( + """function(value) { return 'You entered: ' + value; }""", + Output('output', 'children'), + Input('input', 'value') +) +``` + +JavaScript function runs in browser. Faster for simple transformations, no server round-trip. Can reference `window.dash_clientside.namespace.function_name` or inline JS string. + +### 3. Background Callbacks + +`background=True`: + +```python +@app.callback(Output('output', 'children'), Input('btn', 'n_clicks'), + background=True, manager=diskcache_manager, + running=[(Output('btn', 'disabled'), True, False)], + progress=[Output('progress', 'value')]) +def compute(set_progress, n_clicks): + for i in range(10): + set_progress(i * 10) + time.sleep(1) + return 'Done' +``` + +Callbacks executed in separate process via Celery or Diskcache manager. Supports `progress` updates, `running` state changes, and `cancel` inputs. See [Background Callbacks](#background-callbacks) section for details. + +### 4. Pattern-Matching Callbacks + +```python +@app.callback( + Output({'type': 'output', 'index': MATCH}, 'children'), + Input({'type': 'input', 'index': MATCH}, 'value') +) +def update(value): + return value +``` + +Use dict IDs with wildcards (`MATCH`, `ALL`, `ALLSMALLER`) to target dynamically-generated components. + +## Server Routes + +- `/_dash-layout` - Returns initial component tree as JSON +- `/_dash-dependencies` - Returns callback definitions +- `/_dash-update-component` - Executes callbacks, returns updated props +- `/_dash-component-suites//` - Serves component JS/CSS assets +- `/assets/` - Serves static assets from app's assets folder + +## Frontend (dash-renderer) + +**`dash/dash-renderer/src/`** contains the TypeScript/React frontend. See [RENDERER.md](RENDERER.md) for detailed documentation on: + +- Layout traversal (`crawlLayout`) and `children_props` +- Component resolution from `window[namespace][type]` +- Callback triggering via `setProps` and `notifyObservers` +- Redux store structure (layout, paths, callbacks, graphs) +- Observer system for callback processing +- `window.dash_clientside` API +- `window.dash_component_api` API + +### React Version + +Dash supports multiple React versions. Configured in `dash/_dash_renderer.py`. + +**Available versions:** 18.3.1 (default), 18.2.0, 16.14.0 + +Set via environment variable (experimental): + +```bash +REACT_VERSION=16.14.0 python app.py +``` + +Or programmatically before creating the app: + +```python +from dash._dash_renderer import _set_react_version +_set_react_version("16.14.0") + +from dash import Dash +app = Dash(__name__) +``` + +This is useful for compatibility with older component libraries that require React 16. + +## Pages System + +Multi-page apps use `dash/_pages.py` with automatic routing via `dcc.Location`. + +### Page Registration + +Each page module calls `register_page()`: + +```python +# pages/analytics.py +from dash import register_page, html + +register_page(__name__) # infers path /analytics from module name + +layout = html.Div("Analytics page") +``` + +- **`PAGE_REGISTRY`** - `OrderedDict` storing all registered pages with metadata +- **`register_page(module, path=None, ...)`** - Registers page with inferred or explicit path, title, description, image + +### Page Container + +When `use_pages=True`, Dash injects `page_container` as the layout (`dash/dash.py:148-158`): + +```python +page_container = html.Div([ + dcc.Location(id="_pages_location", refresh="callback-nav"), + html.Div(id="_pages_content"), # current page layout injected here + dcc.Store(id="_pages_store"), # stores page title/metadata +]) +``` + +### Routing Mechanism + +1. `dcc.Location` tracks browser URL changes +2. Internal callback listens to `pathname` and `search` inputs +3. `_path_to_page()` matches URL to registered page in `PAGE_REGISTRY` +4. Page layout injected into `_pages_content` div + +### Path Templates (Dynamic Routes) + +Pages can capture URL variables: + +```python +register_page(__name__, path_template="/asset/") + +def layout(asset_id=None): + return html.Div(f"Asset: {asset_id}") +``` + +`_parse_path_variables()` extracts variables via regex and passes them as kwargs to the layout function. + +### Auto-Discovery + +`_import_layouts_from_pages()` walks the `pages/` folder: +- Skips files starting with `_` or `.` +- Only imports `.py` files containing `register_page` +- Auto-assigns `layout` attribute from each module to the registry + +### Page Ordering + +Pages sorted by: numeric `order` → string `order` → no order → module name. Home page (`/`) defaults to order `0`. + +## Assets and Static Files + +### Asset Directory + +The `assets/` folder is automatically scanned at startup (`dash/dash.py:_walk_assets_directory`): + +- `.css` files → appended to stylesheets +- `.js` files → appended to scripts +- `favicon.ico` → used as app favicon +- Files matching `assets_ignore` regex are skipped + +### Loading Order + +Resources load in this order (`dash/dash.py:1127-1165`): + +1. React dependencies (from dash-renderer) +2. Component library scripts (dash-html-components, dash-core-components, etc.) +3. External scripts (`external_scripts` parameter) +4. Dash renderer bundle +5. Clientside callback scripts (inline) + +CSS follows similar ordering with external stylesheets first. + +### Fingerprinting and Caching + +Component assets use fingerprinted URLs for cache busting (`dash/fingerprint.py`): + +``` +/_dash-component-suites/dash_core_components/dash_core_components.v2_14_0m1699900000.min.js +``` + +- Fingerprinted resources: 1-year cache header +- Non-fingerprinted: ETag validation +- Asset files: query string `?m={modification_time}` + +### Configuration Options + +```python +Dash( + assets_folder='assets', # path to assets directory + assets_url_path='assets', # URL path segment + assets_ignore='.*ignored.*', # regex to skip files + assets_external_path=None, # CDN base URL for assets + serve_locally=True, # True=local files, False=CDN + external_scripts=[], # additional JS URLs + external_stylesheets=[], # additional CSS URLs +) +``` + +### Asset URL Generation + +`app.get_asset_url(path)` returns the correct URL accounting for `requests_pathname_prefix` (important for Dash Enterprise deployments where apps have URL prefixes). + +## Error Handling + +### Debug Mode + +Debug mode enables developer tools (`dash/dash.py:_setup_dev_tools`): + +```python +app.run(debug=True) +# Or via environment: DASH_DEBUG=true +``` + +### Dev Tools Options + +```python +app.enable_dev_tools( + dev_tools_ui=True, # show error UI overlay + dev_tools_props_check=True, # validate component prop types + dev_tools_serve_dev_bundles=True, # use development JS (better errors) + dev_tools_hot_reload=True, # auto-reload on file changes + dev_tools_prune_errors=True, # strip internal frames from tracebacks +) +``` + +Environment variables: `DASH_DEBUG`, `DASH_UI`, `DASH_PROPS_CHECK`, `DASH_HOT_RELOAD`, etc. + +### Callback Exceptions + +**`PreventUpdate`** - Skip updating outputs without error: + +```python +from dash.exceptions import PreventUpdate + +@app.callback(Output('out', 'children'), Input('in', 'value')) +def update(value): + if not value: + raise PreventUpdate + return value +``` + +**`no_update`** - Skip specific outputs in multi-output callbacks: + +```python +from dash import no_update + +@app.callback(Output('a', 'children'), Output('b', 'children'), Input('in', 'value')) +def update(value): + return value, no_update # only updates 'a' +``` + +### Error Handlers + +Callbacks support `on_error` for custom error handling: + +```python +def handle_error(err): + logging.error(f"Callback failed: {err}") + return "Error occurred" # returned to output + +@app.callback(Output('out', 'children'), Input('in', 'value'), on_error=handle_error) +def update(value): + return 1 / 0 # triggers error handler +``` + +App-level error handler set via constructor. + +### Validation + +- **Layout validation**: When `suppress_callback_exceptions=False` (default), checks that callback IDs exist in layout +- **Callback validation**: `dev_tools_validate_callbacks=True` checks for circular dependencies +- **Props checking**: Validates component prop types against schema in dev mode + +### Hot Reload + +When enabled, a watch thread monitors: +- `assets/` folder for CSS/JS changes +- Component package directories + +Frontend polls `/_reload-hash` and triggers reload when hash changes. Configurable via `hot_reload_interval` (default 3s) and `hot_reload_watch_interval` (default 0.5s). + +## Background Callbacks + +Background callbacks execute in separate processes, allowing the main server to remain responsive. Managed by `dash/background_callback/managers/`. + +### Definition + +```python +from dash import callback, Input, Output +from dash.background_callback import DiskcacheManager + +cache_manager = DiskcacheManager() + +@callback( + Output("result", "children"), + Input("button", "n_clicks"), + background=True, + manager=cache_manager, + interval=500, # polling interval in ms +) +def compute(n_clicks): + # Expensive computation + return result +``` + +### Callback Managers + +**`DiskcacheManager`** (`dash/background_callback/managers/diskcache_manager.py`): +- Uses `diskcache.Cache` for persistent storage +- Spawns `multiprocess.Process` for each job +- Results stored on disk, survives server restarts +- Good for single-server deployments + +**`CeleryManager`** (`dash/background_callback/managers/celery_manager.py`): +- Requires Celery app with result backend (Redis/RabbitMQ) +- Jobs distributed across Celery workers +- Supports horizontal scaling +- Good for production multi-worker deployments + +```python +from celery import Celery +from dash.background_callback import CeleryManager + +celery_app = Celery(__name__, broker="redis://localhost:6379/0") +cache_manager = CeleryManager(celery_app) +``` + +### Progress Updates + +The `progress` parameter defines outputs updated during execution: + +```python +@callback( + Output("result", "children"), + Input("button", "n_clicks"), + progress=Output("progress-bar", "value"), + progress_default=0, + background=True, + manager=cache_manager, +) +def compute(set_progress, n_clicks): + for i in range(100): + set_progress(i) + time.sleep(0.1) + return "Complete" +``` + +- `set_progress` is injected as first argument when `progress` is specified +- Can be single Output or list of Outputs +- `progress_default` sets value when callback not running + +### Running State + +The `running` parameter updates outputs while the job executes: + +```python +@callback( + Output("result", "children"), + Input("button", "n_clicks"), + running=[ + (Output("button", "disabled"), True, False), + (Output("status", "children"), "Computing...", "Ready"), + ], + background=True, + manager=cache_manager, +) +def compute(n_clicks): + time.sleep(5) + return "Done" +``` + +Each tuple: `(Output, value_while_running, value_when_complete)` + +### Cancellation + +The `cancel` parameter specifies inputs that abort the job: + +```python +@callback( + Output("result", "children"), + Input("start-btn", "n_clicks"), + cancel=[Input("cancel-btn", "n_clicks")], + background=True, + manager=cache_manager, +) +def compute(n_clicks): + # Job terminates if cancel-btn clicked + return result +``` + +Managers call `terminate_job()` which kills the process (Diskcache) or revokes the task (Celery). + +### Result Caching + +Results can be cached to avoid recomputation: + +```python +def get_user_id(): + return flask.session.get("user_id") + +cache_manager = DiskcacheManager( + cache_by=[get_user_id], # cache key includes user ID + expire=3600, # TTL in seconds +) +``` + +- `cache_by` - List of functions whose return values are included in cache key +- `expire` - Time-to-live for cached results +- `cache_args_to_ignore` - Argument indices to exclude from cache key + +### How It Works + +1. **Initial request**: Frontend triggers callback, backend returns `cacheKey` and `job` ID +2. **Polling**: Frontend polls `/_dash-update-component?cacheKey=...&job=...` at configured interval +3. **Progress**: Each poll returns current progress value if set +4. **Completion**: When job finishes, poll returns final result +5. **Cleanup**: Results cleared from cache (unless `cache_by` specified) + +Cache key is SHA256 hash of: function source + arguments + triggered inputs + cache_by values. + +### Key Files + +- `dash/_callback.py:188-219` - Background spec construction +- `dash/background_callback/managers/__init__.py` - `BaseBackgroundCallbackManager` abstract class +- `dash/background_callback/managers/diskcache_manager.py` - Diskcache implementation +- `dash/background_callback/managers/celery_manager.py` - Celery implementation +- `dash/dash-renderer/src/actions/callbacks.ts:458-685` - Frontend polling logic + +## Jupyter Integration + +Dash apps can run directly in Jupyter notebooks and JupyterLab. The integration is handled by `dash/_jupyter.py`. + +### Display Modes + +```python +app.run( + jupyter_mode="inline", # Display in notebook cell (default) + jupyter_width="100%", # IFrame width + jupyter_height=650, # IFrame height in pixels +) +``` + +| Mode | Behavior | +|------|----------| +| `"inline"` | App displays in notebook cell via IFrame | +| `"external"` | Prints URL, user opens in browser tab | +| `"jupyterlab"` | Opens in dedicated JupyterLab tab | +| `"tab"` | Auto-opens URL in new browser tab | + +### How It Works + +1. `app.run()` detects Jupyter environment via `get_ipython()` +2. Flask server starts in background daemon thread +3. Jupyter comm protocol negotiates proxy configuration +4. App displays according to selected mode + +``` +app.run() in notebook + ↓ +Detect Jupyter → Start Flask in background thread + ↓ +Comm request → Extension responds with base_url + ↓ +Compute dashboard URL with proxy path + ↓ +Display: IFrame (inline) / URL (external) / Tab (jupyterlab) +``` + +### Notebook Extension + +Classic Jupyter notebooks use `dash/nbextension/`: + +- `main.js` - Registers "dash" comm target +- `dash.json` - Extension loader configuration + +The extension handles comm messages: +- `base_url_request` → responds with server URL and base path +- Enables proper proxy routing in JupyterHub environments + +### JupyterLab Extension + +JupyterLab uses `@plotly/dash-jupyterlab/`: + +- `src/index.ts` - TypeScript plugin implementing `JupyterFrontEndPlugin` +- `DashIFrameWidget` - Lumino widget for rendering apps in tabs + +Handles messages: +- `base_url_request` → responds with JupyterLab server config +- `show` → creates dedicated tab with IFrame widget + +Compatible with JupyterLab 2.x, 3.x, and 4.x. + +### Proxy Configuration + +In JupyterHub/proxy environments, the extension negotiates `requests_pathname_prefix`: + +```python +# Computed from Jupyter base path +requests_pathname_prefix = "/user/username/proxy/8050/" +``` + +This ensures callbacks route correctly through the Jupyter proxy. + +### Google Colab + +Special handling for Colab: +- Uses `google.colab.output.serve_kernel_port_as_iframe()` for inline +- Uses `google.colab.output.serve_kernel_port_as_window()` for external +- Only supports "inline" and "external" modes + +### Key Files + +- `dash/_jupyter.py` - `JupyterDash` class, comm handling, server thread +- `dash/nbextension/main.js` - Classic notebook extension +- `@plotly/dash-jupyterlab/src/index.ts` - JupyterLab extension + +## Configuration Reference + +### Dash() Constructor Parameters + +**Basic Setup:** +- `name` - Flask app name (default: infers from `__name__`) +- `server` - Flask instance or `True` to create new (default: `True`) +- `title` - Browser tab title (default: `"Dash"`) +- `update_title` - Title during callbacks (default: `"Updating..."`) + +**Assets & Resources:** +- `assets_folder` - Path to assets directory (default: `"assets"`) +- `assets_url_path` - URL path for assets (default: `"assets"`) +- `assets_ignore` - Regex to exclude assets (default: `""`) +- `serve_locally` - Serve from local vs CDN (default: `True`) +- `external_scripts` - Additional JS URLs +- `external_stylesheets` - Additional CSS URLs + +**Routing:** +- `url_base_pathname` - Base URL prefix for entire app +- `requests_pathname_prefix` - Prefix for AJAX requests +- `routes_pathname_prefix` - Prefix for API routes + +**Multi-Page:** +- `use_pages` - Enable pages system (default: auto-detect) +- `pages_folder` - Path to pages directory (default: `"pages"`) + +**Behavior:** +- `suppress_callback_exceptions` - Skip callback validation (default: `False`) +- `prevent_initial_callbacks` - Skip callbacks on load (default: `False`) +- `background_callback_manager` - DiskcacheManager or CeleryManager +- `on_error` - Global callback error handler + +### app.run() Parameters + +- `host` - Server IP (default: `"127.0.0.1"`, env: `HOST`) +- `port` - Server port (default: `8050`, env: `PORT`) +- `debug` - Enable dev tools (default: `False`, env: `DASH_DEBUG`) +- `jupyter_mode` - Display mode: `"inline"`, `"external"`, `"tab"` + +### Environment Variables + +| Variable | Purpose | +|----------|---------| +| `DASH_DEBUG` | Enable debug mode | +| `DASH_URL_BASE_PATHNAME` | Base URL prefix | +| `DASH_SUPPRESS_CALLBACK_EXCEPTIONS` | Skip validation | +| `DASH_HOT_RELOAD` | Enable hot reload | +| `DASH_PROPS_CHECK` | Validate prop types | +| `DASH_PRUNE_ERRORS` | Simplify tracebacks | +| `HOST` | Server host | +| `PORT` | Server port | + +## Stores and Client-Side State + +### dcc.Store + +Store data client-side with configurable persistence: + +```python +dcc.Store(id='my-store', storage_type='local', data={'key': 'value'}) +``` + +| Storage Type | Persists | Scope | Use Case | +|--------------|----------|-------|----------| +| `'memory'` | Page view only | Tab | Temporary state, debugging | +| `'session'` | Browser session | Tab | Form state, filters | +| `'local'` | Forever | All tabs | User preferences, settings | + +**Usage pattern:** +```python +@app.callback(Output('output', 'children'), Input('store', 'data')) +def use_store(data): + return data['key'] + +@app.callback(Output('store', 'data'), Input('input', 'value')) +def update_store(value): + return {'key': value} +``` + +### Component Persistence + +Automatically persist user edits to component props: + +```python +dcc.Dropdown( + id='dropdown', + options=[...], + persistence=True, # Enable persistence + persistence_type='local', # local, session, or memory + persisted_props=['value'], # Props to persist (default varies by component) +) +``` + +- **`persistence`** - `True` or unique key to enable +- **`persistence_type`** - Storage backend (default: `'local'`) +- **`persisted_props`** - List of prop names to persist + +Supported components: Input, Dropdown, Checklist, RadioItems, Slider, RangeSlider, DatePickerSingle, DatePickerRange, Textarea, Tabs, DataTable. + +### When to Use Each + +| Need | Solution | +|------|----------| +| Server-controlled state | `dcc.Store` with callbacks | +| Remember user selections | Component `persistence=True` | +| Share state across tabs | `dcc.Store` with `storage_type='local'` | +| Session-only state | `persistence_type='session'` | + +## Async Callbacks + +Dash supports `async def` callbacks for non-blocking execution. + +### Setup + +```bash +pip install dash[async] +``` + +Async is auto-enabled when `asgiref` is detected. Or explicitly: + +```python +app = Dash(__name__, use_async=True) +``` + +### Usage + +```python +import asyncio + +@app.callback(Output('output', 'children'), Input('input', 'value')) +async def async_update(value): + await asyncio.sleep(1) # Non-blocking + return f"Processed: {value}" +``` + +### Key Points + +- Regular async callbacks are **non-blocking** - multiple can run concurrently +- Background callbacks also support `async def` +- Jupyter uses `nest_asyncio` for event loop compatibility +- Without `dash[async]`, coroutines raise an error + +### Async with Background Callbacks + +```python +@app.callback( + Output('result', 'children'), + Input('btn', 'n_clicks'), + background=True, + manager=diskcache_manager, +) +async def async_background(n_clicks): + await asyncio.sleep(5) + return "Done" +``` + +Both DiskcacheManager and CeleryManager support async functions via `asyncio.run()`. + +## Security + +### XSS Protection + +Dash automatically sanitizes dangerous URLs in components: + +- Blocked protocols: `javascript:`, `vbscript:` +- Protected attributes: `href`, `src`, `action`, `formAction` +- Dangerous URLs replaced with `about:blank` + +Components with URL sanitization: `html.A`, `html.Form`, `html.Iframe`, `html.Embed`, `html.Object`, `html.Button`. + +### Content Security Policy (CSP) + +Generate hashes for inline scripts to use with CSP middleware: + +```python +from flask_talisman import Talisman + +Talisman(app.server, content_security_policy={ + "default-src": "'self'", + "script-src": ["'self'"] + app.csp_hashes() +}) +``` + +`app.csp_hashes(hash_algorithm='sha256')` returns base64-encoded hashes. + +### Callback Security + +- **`suppress_callback_exceptions=False`** (default) - Validates all callback IDs exist in layout +- **`prevent_initial_callbacks=True`** - Prevents callbacks firing on page load (can also set per-callback with `prevent_initial_call`) + +### Meta Tag Sanitization + +Meta tag values are HTML-escaped to prevent injection: + +```python +app = Dash(__name__, meta_tags=[ + {"name": "description", "content": "Safe "} +]) +``` + +### Key Files + +- `dash/dash-renderer/src/utils/clientsideFunctions.ts` - URL sanitization (`clean_url`) +- `dash/dash.py:csp_hashes()` - CSP hash generation +- `tests/integration/security/` - Security test coverage diff --git a/.ai/COMMANDS.md b/.ai/COMMANDS.md new file mode 100644 index 0000000000..4c155d87b7 --- /dev/null +++ b/.ai/COMMANDS.md @@ -0,0 +1,81 @@ +# Commands + +## Initial Setup + +```bash +# Create and activate virtual environment +python3 -m venv venv +source venv/bin/activate # Windows: source venv/scripts/activate + +# Install Python dependencies +pip install -e .[ci,dev,testing,celery,diskcache] + +# Install Node dependencies +npm ci +``` + +## Building + +```bash +# Full build (Linux/Mac) +npm run build + +# Full build (Windows - use Bash terminal, not PowerShell/CMD) +npm run first-build + +# Build single component after changes +dash-update-components "dash-core-components" # or dash-html-components, dash-table + +# Build renderer only +cd dash/dash-renderer && renderer build +``` + +## Testing + +Tests use pytest with Selenium/ChromeDriver. ChromeDriver must match your Chrome version. See [TESTING.md](TESTING.md) for fixtures, patterns, and detailed documentation. + +```bash +# Run all tests +npm run test + +# Unit tests only +pytest tests/unit + +# Integration tests (requires ChromeDriver) +pytest tests/integration + +# Run specific test by name +pytest -k test_name + +# Run tests matching pattern +pytest -k cbcx # runs all tests with "cbcx" in name + +# Renderer unit tests (Jest) +cd dash/dash-renderer && npm run test + +# Setup test components before running integration tests +npm run setup-tests.py +``` + +## Linting + +Linting runs automatically on commit via husky pre-commit hook and lint-staged (`.lintstagedrc.js`). You typically don't need to run these manually. + +**Pre-commit runs on staged files:** +- Python (`dash/`, `tests/`): pylint, flake8, black --check +- JavaScript/TypeScript: eslint, prettier --check (per component package) + +**Manual commands** (if needed): + +```bash +# Run all linters +npm run lint + +# Individual linters +npm run private::lint.black # Check Black formatting +npm run private::lint.flake8 # Flake8 +npm run private::lint.pylint-dash # Pylint on dash/ + +# Auto-format Python with Black +npm run private::format.black +``` diff --git a/.ai/COMPONENTS.md b/.ai/COMPONENTS.md new file mode 100644 index 0000000000..6d76b6a202 --- /dev/null +++ b/.ai/COMPONENTS.md @@ -0,0 +1,182 @@ +# Component System + +The component system bridges React components to Python with auto-generated wrappers. + +## Generation Pipeline + +``` +React/TypeScript Source + ↓ + extract-meta.js (Node.js) + ├── react-docgen (for .js/.jsx - parses PropTypes) + └── TypeScript Compiler API (for .tsx - parses type definitions) + ↓ + metadata.json + ↓ + dash-generate-components (Python CLI) + ↓ + Python component classes (+ R/Julia if requested) +``` + +### Key Files + +- **`dash/extract-meta.js`** - Node.js script that extracts component metadata. For JavaScript components, uses `react-docgen` to parse PropTypes. For TypeScript components, uses the TypeScript Compiler API to parse type definitions and convert them to metadata format. + +- **`dash/development/component_generator.py`** - CLI entry point (`dash-generate-components`). Orchestrates metadata extraction and code generation. + +- **`dash/development/_py_components_generation.py`** - Generates Python class files from metadata. Creates typed `__init__` methods, docstrings, and prop validation. + +- **`dash/development/_py_prop_typing.py`** - Maps JavaScript/TypeScript types to Python types (e.g., `arrayOf` → `typing.Sequence`, `shape` → `TypedDict`). + +- **`dash/development/_generate_prop_types.py`** - For TypeScript components, generates a `proptypes.js` file since TSX doesn't have runtime PropTypes. + +## Component JSON Structure + +Components serialize to `{type, namespace, props}` via `to_plotly_json()` in `base_component.py`: + +```python +# Python component +html.Div(id='my-div', children='Hello') + +# Serializes to JSON +{ + "type": "Div", + "namespace": "dash_html_components", + "props": { + "id": "my-div", + "children": "Hello" + } +} +``` + +This JSON is sent to the frontend via `/_dash-layout` (initial load) and `/_dash-update-component` (callback responses). + +## Frontend Component Resolution + +Components must be available on the frontend at `window[namespace][type]`: + +```javascript +// Component packages register themselves +window.dash_html_components = { + Div: DivComponent, + Span: SpanComponent, + // ... +}; + +window.dash_core_components = { + Dropdown: DropdownComponent, + Graph: GraphComponent, + // ... +}; +``` + +The renderer resolves components via `registry.js`: + +```javascript +resolve: (component) => { + const {type, namespace} = component; + return window[namespace][type]; // Returns React component class +} +``` + +## Package Structure + +### `_imports_.py` + +Auto-generated by `generate_imports()` in `_py_components_generation.py`: + +```python +from .Dropdown import Dropdown +from .Graph import Graph +from .Input import Input +# ... one import per component + +__all__ = [ + "Dropdown", + "Graph", + "Input", + # ... +] +``` + +### `__init__.py` + +Manually maintained, imports from `_imports_.py`: + +```python +from ._imports_ import * # Re-exports all components +from ._imports_ import __all__ as _components + +# Read version from package-info.json +with open(os.path.join(_basepath, "package-info.json")) as f: + package = json.load(f) +__version__ = package["version"] + +# Define JavaScript assets to serve +_js_dist = [ + { + "relative_package_path": "dash_core_components.js", + "namespace": "dash", + }, + # async chunks, source maps, proptypes.js for dev, etc. +] + +# Attach _js_dist to each component class +for _component in _components: + setattr(locals()[_component], "_js_dist", _js_dist) +``` + +## Resource System (`_js_dist` / `_css_dist`) + +**`dash/resources.py`** manages JavaScript and CSS asset loading for components. + +### Resource Entry Structure + +```python +{ + "relative_package_path": "dcc/dash_core_components.js", # Path within package + "external_url": "https://unpkg.com/...", # CDN fallback + "namespace": "dash", # JS namespace + "async": True | "eager" | "lazy", # Async loading mode + "dynamic": True, # Loaded on demand (source maps) + "dev_package_path": "dcc/proptypes.js", # Dev-only path + "dev_only": True, # Only in dev mode +} +``` + +### Resource Loading Flow + +1. Each component class has `_js_dist` (and optionally `_css_dist`) attribute set in `__init__.py` +2. When component is imported, `ComponentMeta` registers module in `ComponentRegistry.registry` +3. `ComponentRegistry.get_resources("_js_dist")` iterates registered modules, collects all `_js_dist` lists +4. `Scripts` / `Css` classes in `resources.py` filter resources based on config: + - `serve_locally=True`: Use `relative_package_path`, serve via `/_dash-component-suites/` + - `serve_locally=False`: Use `external_url` (CDN) + - `eager_loading=True`: Load async resources immediately + - `dev_bundles=True`: Include `dev_package_path` resources + +### Async Loading Modes + +- `async: True` - Dynamic unless `eager_loading` is enabled +- `async: "lazy"` - Always loaded dynamically (on-demand) +- `async: "eager"` - Loaded dynamically only if server isn't in eager mode + +## Creating New Components + +1. Write React component with PropTypes (JS) or TypeScript props interface (TSX) +2. Run `dash-generate-components src/lib/components -p package_name` +3. Generated Python wrapper goes to `package_name/ComponentName.py` +4. `_imports_.py` is auto-generated with imports for all components +5. For TSX, `proptypes.js` is also generated for runtime prop validation +6. Bundle with webpack, register on `window[namespace]` +7. Update `__init__.py` to set `_js_dist` on components + +## Built-in Component Packages + +Managed as a Lerna monorepo in `components/`: + +- **`components/dash-core-components/`** - Interactive components (Dropdown, Slider, Graph, Input, etc.) +- **`components/dash-html-components/`** - HTML element wrappers (Div, Span, H1, etc.) +- **`components/dash-table/`** - DataTable component (deprecated in favor of dash-ag-grid) + +Use `dash-update-components "component-name"` to rebuild after changes. diff --git a/.ai/README.md b/.ai/README.md new file mode 100644 index 0000000000..7d94909213 --- /dev/null +++ b/.ai/README.md @@ -0,0 +1,48 @@ +# Dash AI Agent Guide + +This directory contains documentation for AI coding assistants working with the Dash codebase. + +## Quick Links + +- [Commands](./COMMANDS.md) - Build, test, and lint commands +- [Architecture](./ARCHITECTURE.md) - Backend, callbacks, pages, assets, errors, background callbacks, Jupyter, config, stores, async, security +- [Renderer](./RENDERER.md) - Frontend, crawlLayout, Redux store, clientside API, component API +- [Components](./COMPONENTS.md) - Component generation, package structure, resource system +- [Testing](./TESTING.md) - Testing framework, fixtures, patterns, type compliance +- [Troubleshooting](./TROUBLESHOOTING.md) - Common errors and solutions + +## Project Overview + +Dash is a Python framework for building reactive web-based data visualization applications. Built on Plotly.js, React, and Flask, it ties UI elements (dropdowns, sliders, graphs) directly to analytical Python code. + +## Key Directories + +``` +dash/ +├── dash/ # Main Python package +│ ├── dash.py # Core Dash app class +│ ├── _callback.py # Callback registration/execution +│ ├── dependencies.py # Input/Output/State classes +│ ├── _pages.py # Multi-page app support +│ ├── development/ # Component generation tools +│ ├── dash-renderer/ # TypeScript/React frontend +│ └── dcc/, html/, dash_table/ # Built-in components +├── components/ # Component source packages (Lerna monorepo) +│ ├── dash-core-components/ +│ ├── dash-html-components/ +│ └── dash-table/ +├── tests/ +│ ├── unit/ # pytest unit tests +│ ├── integration/ # Selenium browser tests +│ ├── compliance/ # Type checking (pyright/mypy) +│ └── background_callback/ # Background callback tests +└── requirements/ # Modular dependency files +``` + +## Code Review Conventions + +Emoji used in reviews: +- `:dancer:` - Can merge +- `:tiger2:` - Needs more tests +- `:snake:` - Security concern +- `:pill:` - Performance issue diff --git a/.ai/RENDERER.md b/.ai/RENDERER.md new file mode 100644 index 0000000000..d258f49899 --- /dev/null +++ b/.ai/RENDERER.md @@ -0,0 +1,317 @@ +# Dash Renderer + +The dash-renderer is the TypeScript/React frontend that powers Dash applications. Located in `dash/dash-renderer/src/`. + +## Initialization Flow + +``` +1. DashRenderer constructor + └─ ReactDOM.createRoot('#react-entry-point') + └─ + +2. AppProvider creates Redux store + └─ Registers observers for callback processing + +3. APIController fetches from server + ├─ GET /_dash-layout → component tree + ├─ GET /_dash-dependencies → callback definitions + └─ Dispatches setLayout, setGraphs, setPaths + +4. Config includes children_props from ComponentRegistry + └─ Stored in window.__dashprivate_childrenProps + +5. hydrateInitialOutputs() + ├─ Validates callbacks against layout + ├─ Triggers initial callbacks + └─ Sets appLifecycle: 'HYDRATED' + +6. DashWrapper renders component tree +``` + +## Layout Traversal (crawlLayout) + +The layout is traversed using `crawlLayout` (`actions/utils.js`). This algorithm: + +1. **For arrays**: Iterates each child, following extra paths for nested components +2. **For objects (components)**: + - Applies the visitor function to the component + - Follows `props.children` if present + - Follows additional paths from `children_props` config + +### children_props + +Each component class defines `_children_props` listing props that contain nested components. This is: +1. Generated from React component PropTypes/TypeScript during component generation +2. Stored on the Python component class as `_children_props` +3. Collected into `ComponentRegistry.children_props` when components are imported +4. Sent to frontend via config (`dash.py:933`) +5. Stored in `window.__dashprivate_childrenProps` on the frontend + +```python +# Example: Python component class +class Dropdown(Component): + _children_props = ['options.[].label', 'options.[].title'] + # ... +``` + +### Pattern Syntax + +| Pattern | Meaning | Example | +|---------|---------|---------| +| `children` | Direct children prop | Standard | +| `prop.[]` | Array items are components | `options.[]` | +| `prop.[].sub` | `sub` prop of array items | `options.[].label` | +| `prop.{}` | Object values are components | Dynamic keys | +| `prop.{}.sub` | `sub` prop of object values | Nested dynamic | + +### How crawlLayout Works + +```javascript +crawlLayout(object, func, currentPath, extraPath) + +// For each component: +// 1. Call func(object, currentPath) +// 2. If props.children exists, crawl it +// 3. For each path in children_props[namespace][type]: +// - Parse the pattern (handle [], {}) +// - Crawl that path to find nested components +``` + +## Component Resolution + +Components are resolved from `window[namespace][type]`: + +```javascript +// Component packages register on window +window.dash_html_components = { Div, Span, H1, ... }; +window.dash_core_components = { Dropdown, Graph, Input, ... }; + +// Registry.js resolves {type, namespace} → React component +Registry.resolve({type: 'Div', namespace: 'dash_html_components'}) +// → window.dash_html_components.Div +``` + +## Callback Triggering + +Callbacks are triggered by two sources: + +### 1. Component setProps + +When a component calls `setProps`, it triggers callbacks watching those props: + +```javascript +// Component calls setProps +this.props.setProps({ value: newValue }); + +// DashWrapper.tsx handles this: +// 1. dispatch(updateProps(...)) → Updates layout in Redux +// 2. dispatch(notifyObservers(...)) → Finds and queues callbacks +``` + +`notifyObservers` calls `includeObservers` to find callbacks with matching inputs: + +```javascript +// actions/index.js +export function notifyObservers({id, props}) { + return async function (dispatch, getState) { + const {graphs, paths} = getState(); + dispatch( + addRequestedCallbacks(includeObservers(id, props, graphs, paths)) + ); + }; +} +``` + +### 2. Callback Results + +When a callback completes and updates component props, it also triggers dependent callbacks via `includeObservers` in the `executedCallbacks` observer. + +## Callback Processing + +Once callbacks are added to the queue, observers process them through states: + +``` +REQUESTED → PRIORITIZED → EXECUTING → EXECUTED → STORED + ↓ + WATCHED (promises) + ↓ + BLOCKED (waiting on deps) +``` + +### Observer Chain + +1. **requestedCallbacks**: Deduplicates, checks dependencies, moves ready → prioritized +2. **prioritizedCallbacks**: Sorts by priority, executes (max 12 concurrent) +3. **executingCallbacks**: Tracks running callbacks, handles promises +4. **executedCallbacks**: Applies results to layout, triggers dependent callbacks +5. **isLoading**: Tracks loading state for `dcc.Loading` + +## Redux Store + +### Key Slices + +```typescript +{ + layout: { ... }, // Component tree + + layoutHashes: { // Change tracking for memoization + "path": { hash, changedProps } + }, + + paths: { // ID → path mapping + strs: { "my-id": [...path] }, + objs: { "type,index": [...] } // Wildcards + }, + + callbacks: { // Pipeline states + requested, prioritized, blocked, + executing, watched, executed, stored + }, + + graphs: { // Dependency graph + inputMap: { "id": { "prop": [callbacks] } } + }, + + config: { + children_props: { ... }, // From ComponentRegistry + // ... + }, + + isLoading: boolean +} +``` + +### Paths System + +Maps component IDs to their location in layout: + +```typescript +// String IDs +paths.strs["my-dropdown"] = ["layout", "props", "children", 2, "props"] + +// Wildcard IDs (pattern-matching) +paths.objs["type,index"] = [ + { values: ["filter", 0], path: [...] }, + { values: ["filter", 1], path: [...] } +] +``` + +## window.dash_clientside + +The clientside callback API (`utils/clientsideFunctions.ts`): + +```javascript +window.dash_clientside = { + no_update, // Return to skip output + PreventUpdate, // Throw to cancel callback + callback_context, // Current callback info + set_props, // Update props from clientside + clean_url, // URL sanitization + Patch // Partial prop updates +} +``` + +### callback_context + +Available during callback execution: + +```javascript +window.dash_clientside.callback_context = { + triggered: [{ prop_id: "btn.n_clicks", value: 1 }], + triggered_id: "btn", + inputs: { "input.value": "hello" }, + states: { "store.data": {...} } +} +``` + +### Registering Clientside Functions + +```javascript +// In assets/clientside.js +window.dash_clientside = window.dash_clientside || {}; +window.dash_clientside.my_namespace = { + my_function: function(input_value) { + return input_value.toUpperCase(); + } +}; +``` + +### set_props + +Update component props directly from clientside: + +```javascript +// By string ID +window.dash_clientside.set_props('my-component', { value: 'new' }); + +// By pattern-matching ID +window.dash_clientside.set_props({ type: 'input', index: 0 }, { value: 'new' }); +``` + +## window.dash_component_api + +API for components to interact with Dash (`dashApi.ts`): + +```javascript +window.dash_component_api = { + ExternalWrapper, // Render outside main tree + DashContext, // React Context + useDashContext, // Hook for context + getLayout, // Get props by ID/path + stringifyId // Convert wildcard IDs +} +``` + +### getLayout + +Retrieve component props: + +```javascript +const props = window.dash_component_api.getLayout('my-dropdown'); +// → { id: 'my-dropdown', options: [...], value: 'a' } +``` + +### useDashContext + +Hook for components: + +```typescript +const { + componentPath, + isLoading, + useSelector, + useDispatch +} = useDashContext(); +``` + +## Memoization + +DashWrapper uses hash-based memoization. `layoutHashes` tracks which components changed: + +```typescript +layoutHashes["0,props,children"] = { + hash: 42, // Increments on change + changedProps: { value: true } +} +``` + +Components only re-render when their hash changes. + +## Key Files + +| File | Purpose | +|------|---------| +| `DashRenderer.js` | Entry point | +| `AppProvider.react.tsx` | Redux store setup | +| `APIController.react.js` | Fetches layout, hydrates app | +| `wrapper/DashWrapper.tsx` | Component rendering, setProps | +| `actions/utils.js` | `crawlLayout` algorithm | +| `registry.js` | Component resolution | +| `reducers/layout.js` | Layout state | +| `reducers/callbacks.ts` | Callback pipeline | +| `reducers/config.js` | Stores children_props | +| `actions/index.js` | `notifyObservers` | +| `actions/dependencies_ts.ts` | `includeObservers`, callback matching | +| `observers/*.ts` | Callback processing | +| `utils/clientsideFunctions.ts` | Clientside API | +| `dashApi.ts` | Component API | diff --git a/.ai/TESTING.md b/.ai/TESTING.md new file mode 100644 index 0000000000..443dbaf856 --- /dev/null +++ b/.ai/TESTING.md @@ -0,0 +1,486 @@ +# Testing + +Dash includes a pytest/Selenium testing framework for unit and integration tests. Located in `dash/testing/`. + +## Quick Start + +```bash +# Install testing dependencies +pip install -e .[testing] + +# Run all tests +pytest tests/ + +# Run unit tests +pytest tests/unit/ + +# Run integration tests +pytest tests/integration/ + +# Run specific test +pytest tests/integration/callbacks/test_basic.py::test_name + +# Headless mode (CI) +pytest --headless tests/integration/ +``` + +## Fixtures + +The main fixture is `dash_duo` - a composite of server + browser: + +```python +def test_basic_callback(dash_duo): + app = Dash(__name__) + app.layout = html.Div([ + html.Button("Click", id="btn", n_clicks=0), + html.Div(id="output") + ]) + + @app.callback(Output("output", "children"), Input("btn", "n_clicks")) + def update(n): + return f"Clicked {n} times" + + dash_duo.start_server(app) + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal("#output", "Clicked 1 times") +``` + +### Available Fixtures + +| Fixture | Description | +|---------|-------------| +| `dash_duo` | Threaded server + browser (default for integration tests) | +| `dash_duo_mp` | Multi-process server + browser | +| `dash_br` | Browser only (no server) | +| `dash_thread_server` | Threaded server only | +| `dash_process_server` | Process-based server only | +| `dashr` | DashR server + browser | +| `dashjl` | Dash.jl server + browser | + +## Browser Methods + +### Element Selection + +```python +dash_duo.find_element("#my-id") # Single element by CSS selector +dash_duo.find_elements(".my-class") # All matching elements +dash_duo.wait_for_element("#loading") # Wait for element to appear +dash_duo.wait_for_element_by_id("output") # Wait by ID +``` + +### Wait Conditions + +```python +# Wait for exact text +dash_duo.wait_for_text_to_equal("#output", "Expected text") + +# Wait for text containing substring +dash_duo.wait_for_contains_text("#output", "partial") + +# Wait for CSS class +dash_duo.wait_for_class_to_equal("#elem", "active") +dash_duo.wait_for_contains_class("#elem", "loading") + +# Wait for CSS property +dash_duo.wait_for_style_to_equal("#elem", "display", "none") + +# Wait for element removal +dash_duo.wait_for_no_elements("#spinner") + +# Custom timeout (default 10s) +dash_duo.wait_for_text_to_equal("#slow", "Done", timeout=30) +``` + +### Interactions + +```python +# Click +dash_duo.find_element("#btn").click() +dash_duo.multiple_click("#btn", clicks=5) + +# Input +elem = dash_duo.find_element("#input") +elem.send_keys("hello") +dash_duo.clear_input("#input") + +# Dropdown +dash_duo.select_dcc_dropdown("#dropdown", value="option1") +dash_duo.select_dcc_dropdown("#dropdown", index=2) + +# Graph interactions +dash_duo.click_at_coord_fractions("#graph", 0.5, 0.5) # Click center +dash_duo.zoom_in_graph_by_ratio("#graph", 0.5, 0.25, 0.5, 0.75) +``` + +### State Inspection + +```python +# Redux state +dash_duo.redux_state_is_loading # True if callbacks running +dash_duo.redux_state_paths # Component paths +dash_duo.redux_state_rqs # Pending requests + +# Storage +dash_duo.get_local_storage("store-id") +dash_duo.get_session_storage("session-id") +dash_duo.clear_storage() + +# DOM access (BeautifulSoup) +dom = dash_duo.dash_outerhtml_dom +assert dom.find(id="my-component") is not None + +# Browser logs (Chrome only) +logs = dash_duo.get_logs() +assert logs == [] # No console errors +``` + +## Application Runners + +Runners manage server lifecycle: + +| Runner | How It Works | Use Case | +|--------|--------------|----------| +| `ThreadedRunner` | Daemon thread | Fast, default | +| `ProcessRunner` | Subprocess + waitress | Production-like | +| `MultiProcessRunner` | Multiprocessing | Multi-worker tests | +| `RRunner` | Rscript subprocess | DashR | +| `JuliaRunner` | Julia subprocess | Dash.jl | + +```python +def test_with_process_server(dash_process_server): + app = Dash(__name__) + app.layout = html.Div("Hello") + + dash_process_server(app) + response = requests.get(dash_process_server.url) + assert response.status_code == 200 +``` + +## Wait Utilities + +For custom wait conditions (`dash/testing/wait.py`): + +```python +from dash.testing.wait import until, until_not + +# Poll until condition is True +until( + lambda: dash_duo.find_element("#status").text == "Ready", + timeout=10, + poll=0.5, + msg="Status never became Ready" +) + +# Poll until condition is False +until_not( + lambda: dash_duo.redux_state_is_loading, + timeout=5 +) +``` + +## Percy Visual Testing + +Percy integration for visual regression testing: + +```python +def test_visual_appearance(dash_duo): + app = Dash(__name__) + app.layout = html.Div([...]) + + dash_duo.start_server(app) + + # Basic snapshot + dash_duo.percy_snapshot("dashboard-initial") + + # Wait for callbacks before snapshot + dash_duo.percy_snapshot( + name="dashboard-loaded", + wait_for_callbacks=True + ) + + # Convert canvas elements to images (for graphs) + dash_duo.percy_snapshot( + name="graph-render", + convert_canvases=True + ) + + # Responsive widths + dash_duo.percy_snapshot( + name="responsive", + widths=[375, 768, 1280] + ) +``` + +Navigate and snapshot in one call: + +```python +dash_duo.visit_and_snapshot( + resource_path="/page2", + hook_id="page2-content", + wait_for_callbacks=True +) +``` + +## CLI Options + +```bash +# Browser selection +pytest --webdriver Chrome # Default +pytest --webdriver Firefox + +# Headless mode +pytest --headless + +# Selenium Grid +pytest --remote --remote-url http://grid:4444/wd/hub + +# Percy +pytest --percy-assets tests/assets +pytest --nopercyfinalize # Don't finalize Percy build + +# Debugging +pytest --pause # Pause with pdb after page load +``` + +## Test Organization + +``` +tests/ # Core Dash tests +├── unit/ # Fast tests, no browser +├── integration/ # Browser-based tests +│ ├── callbacks/ # Callback behavior +│ ├── clientside/ # Clientside callbacks +│ ├── dash/ # Core app features +│ ├── dash_assets/ # Asset loading +│ ├── devtools/ # Dev tools UI +│ ├── multi_page/ # Pages system +│ ├── renderer/ # Frontend rendering +│ └── security/ # Security features +├── async_tests/ # Async callback tests +├── background_callback/ # Background callback tests +├── backend_tests/ # Server-side tests +└── compliance/ # Type checking compliance + └── test_typing.py # pyright/mypy validation + +components/dash-core-components/tests/ # DCC component tests +├── unit/ # Unit tests +└── integration/ # Per-component browser tests + ├── dropdown/ + ├── graph/ + ├── input/ + ├── slider/ + ├── store/ + ├── upload/ + └── ... + +components/dash-html-components/tests/ # HTML component tests +├── test_dash_html_components.py +├── test_div_tabIndex.py +└── test_integration.py + +components/dash-table/tests/ # DataTable tests +├── unit/ # Python unit tests +├── js-unit/ # JavaScript unit tests +├── selenium/ # Browser tests +└── visual/ # Visual regression tests + +dash/dash-renderer/tests/ # Renderer JS tests +├── isAppReady.test.js +└── persistence.test.js +``` + +### Running Component Tests + +```bash +# DCC tests +pytest components/dash-core-components/tests/ + +# Specific DCC component +pytest components/dash-core-components/tests/integration/dropdown/ + +# HTML components +pytest components/dash-html-components/tests/ + +# DataTable +pytest components/dash-table/tests/selenium/ + +# Renderer JS tests +cd dash/dash-renderer && npm test +``` + +## Type Checking Compliance + +The `tests/compliance/test_typing.py` tests validate that Dash code passes static type checkers (pyright, mypy). This ensures type annotations are correct and users get proper IDE support. + +### What It Tests + +1. **Component prop types** - Validates generated TypeScript component types work correctly: + ```python + # Should pass - correct type + TypeScriptComponent(a_string='hello') + + # Should fail - wrong type + TypeScriptComponent(a_string=123) # Expected str, got int + ``` + +2. **Layout types** - Validates layout accepts correct children types: + ```python + # Valid - components, strings, numbers + html.Div([html.H2('Title'), 'text', 123]) + + # Invalid - dict in children + html.Div([{'invalid': 'dict'}]) + ``` + +3. **Callback return types** - Validates callback returns match Output type: + ```python + @callback(Output("out", "children"), Input("in", "value")) + def update() -> html.Div: + return html.Div('Valid') # OK + return [] # Type error + ``` + +### Running Type Checks + +```bash +# Run compliance tests +pytest tests/compliance/ + +# Run pyright directly +pyright dash/ + +# Run mypy directly (Python 3.10+) +mypy dash/ +``` + +### Type Checkers Used + +| Checker | Python Version | Notes | +|---------|---------------|-------| +| pyright | All | Primary checker, always runs | +| mypy | 3.10+ | Runs on Python 3.10 and above | + +## Common Patterns + +### Testing Callbacks + +```python +def test_callback_updates_output(dash_duo): + app = Dash(__name__) + app.layout = html.Div([ + dcc.Input(id="input", value=""), + html.Div(id="output") + ]) + + @app.callback(Output("output", "children"), Input("input", "value")) + def update(value): + return f"You typed: {value}" + + dash_duo.start_server(app) + + input_elem = dash_duo.find_element("#input") + input_elem.send_keys("hello") + + dash_duo.wait_for_text_to_equal("#output", "You typed: hello") + assert dash_duo.get_logs() == [] +``` + +### Testing Loading States + +```python +def test_loading_indicator(dash_duo): + app = Dash(__name__) + app.layout = html.Div([ + html.Button("Load", id="btn"), + dcc.Loading(html.Div(id="output")) + ]) + + @app.callback(Output("output", "children"), Input("btn", "n_clicks")) + def slow_update(n): + time.sleep(1) + return "Loaded" + + dash_duo.start_server(app) + dash_duo.find_element("#btn").click() + + # Verify loading state appears + dash_duo.wait_for_element(".dash-spinner") + + # Then verify it completes + dash_duo.wait_for_text_to_equal("#output", "Loaded") + dash_duo.wait_for_no_elements(".dash-spinner") +``` + +### Testing Background Callbacks + +```python +def test_background_callback(dash_duo, diskcache_manager): + app = Dash(__name__) + app.layout = html.Div([ + html.Button("Start", id="btn"), + html.Div(id="progress"), + html.Div(id="result") + ]) + + @app.callback( + Output("result", "children"), + Input("btn", "n_clicks"), + progress=Output("progress", "children"), + background=True, + manager=diskcache_manager, + ) + def compute(set_progress, n): + for i in range(5): + set_progress(f"{i*20}%") + time.sleep(0.1) + return "Done" + + dash_duo.start_server(app) + dash_duo.find_element("#btn").click() + + dash_duo.wait_for_contains_text("#progress", "%") + dash_duo.wait_for_text_to_equal("#result", "Done") +``` + +### Testing Multi-Page Apps + +```python +def test_page_navigation(dash_duo): + app = Dash(__name__, use_pages=True) + # pages/ directory contains page modules + + dash_duo.start_server(app) + + # Test home page + dash_duo.wait_for_element("#home-content") + + # Navigate to another page + dash_duo.find_element('a[href="/about"]').click() + dash_duo.wait_for_element("#about-content") + + # Check URL updated + assert "/about" in dash_duo.driver.current_url +``` + +## Key Files + +| File | Purpose | +|------|---------| +| `dash/testing/plugin.py` | Pytest plugin, fixture definitions | +| `dash/testing/browser.py` | Browser class with Selenium wrapper | +| `dash/testing/composite.py` | DashComposite (server + browser) | +| `dash/testing/application_runners.py` | Server runners | +| `dash/testing/wait.py` | Wait utilities and conditions | +| `dash/testing/dash_page.py` | Redux state access mixin | +| `dash/testing/errors.py` | Custom exceptions | + +## Errors + +```python +from dash.testing.errors import ( + TestingTimeoutError, # Wait condition timed out + DashAppLoadingError, # App failed to load + ServerCloseError, # Server didn't stop cleanly + BrowserError, # Browser/WebDriver issue +) +``` diff --git a/.ai/TROUBLESHOOTING.md b/.ai/TROUBLESHOOTING.md new file mode 100644 index 0000000000..c8419646a3 --- /dev/null +++ b/.ai/TROUBLESHOOTING.md @@ -0,0 +1,329 @@ +# Troubleshooting + +Common issues and solutions when working with Dash. + +## Callback Errors + +### "Callback error updating [component]" + +**Cause:** Exception raised inside callback function. + +**Solution:** +1. Check the terminal for the full traceback +2. Enable debug mode: `app.run(debug=True)` +3. Add error handling: +```python +@app.callback(Output('out', 'children'), Input('in', 'value'), on_error=lambda e: f"Error: {e}") +def update(value): + ... +``` + +### "A nonexistent object was used in an `Input`..." + +**Cause:** Callback references component ID that doesn't exist in layout. + +**Solutions:** +1. Check for typos in component IDs +2. For dynamic layouts, set `suppress_callback_exceptions=True`: +```python +app = Dash(__name__, suppress_callback_exceptions=True) +``` +3. Use pattern-matching callbacks for dynamic components + +### "Circular dependency detected" + +**Cause:** Callback output is also its own input (directly or indirectly). + +**Solution:** Restructure callbacks to break the cycle. Use `State` instead of `Input` where possible, or split into multiple callbacks. + +### Callback not firing + +**Possible causes:** +1. `prevent_initial_call=True` blocking first execution +2. Input component doesn't exist yet (dynamic layout) +3. Component ID mismatch (check spelling, check dict IDs match exactly) + +**Debug:** Add `print()` at callback start to verify it's being called. + +## Layout Errors + +### "Invalid component type" + +**Cause:** Passing non-component to layout (e.g., raw dict, unsupported type). + +**Solution:** Ensure all layout children are Dash components, strings, or numbers: +```python +# Wrong +html.Div([{'key': 'value'}]) + +# Right +html.Div([html.Span('value')]) +``` + +### Components not rendering + +**Possible causes:** +1. Missing `id` prop (required for callbacks) +2. JavaScript error - check browser console +3. Component library not installed or imported + +**Debug:** Check browser DevTools console for errors. + +## Import Errors + +### "No module named 'dash_core_components'" + +**Cause:** Using old import style. + +**Solution:** Use new unified imports: +```python +# Old (deprecated) +import dash_core_components as dcc +import dash_html_components as html + +# New +from dash import dcc, html +``` + +### "ImportError: cannot import name 'X' from 'dash'" + +**Cause:** Feature not available in installed Dash version. + +**Solution:** Upgrade Dash: +```bash +pip install --upgrade dash +``` + +## Server Errors + +### "Address already in use" + +**Cause:** Port 8050 (or specified port) is occupied. + +**Solutions:** +1. Use different port: `app.run(port=8051)` +2. Kill existing process: `lsof -i :8050` then `kill ` +3. Set via environment: `PORT=8051 python app.py` + +### Hot reload not working + +**Possible causes:** +1. `debug=False` (hot reload requires debug mode) +2. File outside watched directories +3. Syntax error preventing reload + +**Solution:** +```python +app.run( + debug=True, + dev_tools_hot_reload=True, + extra_hot_reload_paths=['./custom_modules/'] +) +``` + +### "Working outside of application context" + +**Cause:** Accessing Flask context outside request (e.g., in background thread). + +**Solution:** Use `flask.current_app` inside callbacks, or pass data explicitly rather than using context. + +## Background Callback Issues + +### Background callback never completes + +**Possible causes:** +1. Manager not configured correctly +2. Celery worker not running (for CeleryManager) +3. Exception in callback (check worker logs) + +**Debug:** Check diskcache directory or Celery worker output for errors. + +### "No such process" errors with DiskcacheManager + +**Cause:** Process terminated unexpectedly. + +**Solution:** Check for exceptions in the callback. Ensure `psutil` is installed. + +### Progress updates not showing + +**Cause:** `set_progress` not being called, or wrong output specified. + +**Solution:** Ensure `progress` parameter matches an Output that exists: +```python +@app.callback( + Output('result', 'children'), + Input('btn', 'n_clicks'), + progress=Output('progress', 'children'), # Must exist in layout + background=True, + manager=manager, +) +def compute(set_progress, n): + set_progress("Working...") # Call this + ... +``` + +## Async Callback Issues + +### "You are trying to use a coroutine without dash[async]" + +**Cause:** Using `async def` callback without async dependencies. + +**Solution:** +```bash +pip install dash[async] +``` + +### Event loop errors in Jupyter + +**Cause:** Conflicting event loops. + +**Solution:** Dash automatically applies `nest_asyncio` in Jupyter. If issues persist: +```python +import nest_asyncio +nest_asyncio.apply() +``` + +## Multi-Page App Issues + +### Pages not discovered + +**Possible causes:** +1. Files don't contain `register_page(__name__)` +2. Files start with `_` or `.` (ignored) +3. Wrong `pages_folder` path + +**Solution:** Ensure each page file has: +```python +from dash import register_page +register_page(__name__) + +layout = ... +``` + +### "Page not found" for registered page + +**Cause:** Path mismatch or routing issue. + +**Debug:** Check `dash.page_registry` to see registered pages and their paths: +```python +from dash import page_registry +print(list(page_registry.values())) +``` + +## Component-Specific Issues + +### Dropdown options not updating + +**Cause:** Options list reference didn't change (same list object). + +**Solution:** Return new list object: +```python +# Wrong - mutating existing list +options.append(new_option) +return options + +# Right - return new list +return options + [new_option] +``` + +### Graph not updating + +**Possible causes:** +1. Returning same figure object (reference equality) +2. Missing `figure` in Output + +**Solution:** Create new figure object: +```python +return go.Figure(data=[...], layout={...}) # New object each time +``` + +### DataTable slow with large data + +**Solutions:** +1. Enable virtualization: `virtualization=True` +2. Use pagination: `page_size=20, page_action='native'` +3. Filter data server-side before sending + +## Testing Issues + +### ChromeDriver version mismatch + +**Error:** "session not created: This version of ChromeDriver only supports Chrome version X" + +**Solution:** Update ChromeDriver to match your Chrome version: +```bash +# Check Chrome version +google-chrome --version + +# Install matching chromedriver +pip install chromedriver-autoinstaller +``` + +### Tests hanging + +**Possible causes:** +1. Callback never completing +2. Element selector not finding element +3. Timeout too short + +**Solution:** Add explicit waits with longer timeout: +```python +dash_duo.wait_for_text_to_equal("#output", "expected", timeout=30) +``` + +### "Element not interactable" + +**Cause:** Element hidden, overlapped, or not yet rendered. + +**Solution:** Wait for element to be visible: +```python +dash_duo.wait_for_element("#button") +element = dash_duo.find_element("#button") +element.click() +``` + +## Build Issues + +### "Component build failed" + +**Possible causes:** +1. Node modules not installed: `npm ci` +2. Syntax error in React component +3. Missing dependencies + +**Solution:** Check build output, ensure `npm ci` was run in component directory. + +### "Module not found" after build + +**Cause:** Python package not installed in editable mode. + +**Solution:** +```bash +pip install -e . +``` + +## Performance Issues + +### App slow to load + +**Solutions:** +1. Use `eager_loading=False` (default) for lazy component loading +2. Minimize assets in `assets/` folder +3. Use `serve_locally=False` to serve from CDN + +### Callbacks slow + +**Solutions:** +1. Use `background=True` for expensive computations +2. Cache results with `@cache.memoize` or similar +3. Use clientside callbacks for simple transformations +4. Reduce data sent to/from server + +### Memory growing over time + +**Possible causes:** +1. Storing data in global variables +2. Background callback results not being cleaned up +3. Large figures being cached + +**Solution:** Use `dcc.Store` for state, set `expire` on background managers, avoid global mutable state. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000000..9b2826a80c --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,42 @@ +# Copilot Instructions + +This file provides guidance to GitHub Copilot when working with this repository. + +For detailed documentation, see the [`.ai/`](../.ai/) directory: +- [Commands](../.ai/COMMANDS.md) - Build, test, lint +- [Architecture](../.ai/ARCHITECTURE.md) - Backend, layout, callbacks +- [Components](../.ai/COMPONENTS.md) - Component system, generation, resources + +## Project Overview + +Dash is a Python framework for building reactive web-based data visualization applications. Built on Plotly.js, React, and Flask. + +## Quick Reference + +```bash +# Setup +pip install -e .[ci,dev,testing,celery,diskcache] && npm ci + +# Build +npm run build # Linux/Mac +npm run first-build # Windows (use Bash) +dash-update-components "dash-core-components" # Single component + +# Test +pytest tests/unit # Unit tests +pytest tests/integration # Integration tests +pytest -k test_name # Specific test + +# Lint +npm run lint # All linters +npm run private::format.black # Auto-format Python +``` + +## Key Files + +- `dash/dash.py` - Main Dash app class, layout, callbacks, routing +- `dash/_callback.py` - `@callback` decorator and execution +- `dash/dependencies.py` - `Input`, `Output`, `State`, wildcards +- `dash/development/base_component.py` - Component base class, `to_plotly_json()` +- `dash/dash-renderer/` - TypeScript/React frontend +- `components/` - Component packages (dcc, html, table) diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..ce07a42d40 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,42 @@ +# AGENTS.md + +This file provides guidance to AI coding assistants working with this repository. + +For detailed documentation, see the [`.ai/`](.ai/) directory: +- [Commands](.ai/COMMANDS.md) - Build, test, lint +- [Architecture](.ai/ARCHITECTURE.md) - Backend, layout, callbacks +- [Components](.ai/COMPONENTS.md) - Component system, generation, resources + +## Project Overview + +Dash is a Python framework for building reactive web-based data visualization applications. Built on Plotly.js, React, and Flask. + +## Quick Reference + +```bash +# Setup +pip install -e .[ci,dev,testing,celery,diskcache] && npm ci + +# Build +npm run build # Linux/Mac +npm run first-build # Windows (use Bash) +dash-update-components "dash-core-components" # Single component + +# Test +pytest tests/unit # Unit tests +pytest tests/integration # Integration tests +pytest -k test_name # Specific test + +# Lint +npm run lint # All linters +npm run private::format.black # Auto-format Python +``` + +## Key Files + +- `dash/dash.py` - Main Dash app class, layout, callbacks, routing +- `dash/_callback.py` - `@callback` decorator and execution +- `dash/dependencies.py` - `Input`, `Output`, `State`, wildcards +- `dash/development/base_component.py` - Component base class, `to_plotly_json()` +- `dash/dash-renderer/` - TypeScript/React frontend +- `components/` - Component packages (dcc, html, table) diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000000..be36e0949e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,48 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Required Reading + +**At the start of each session, read the documentation in `.ai/` before making changes:** + +1. `.ai/COMMANDS.md` - Build, test, lint commands +2. `.ai/ARCHITECTURE.md` - Backend, callbacks, pages, assets, errors, background callbacks, Jupyter, config, stores, async, security +3. `.ai/RENDERER.md` - Frontend, crawlLayout, Redux store, clientside API, component API +4. `.ai/COMPONENTS.md` - Component system, generation, resources +5. `.ai/TESTING.md` - Testing framework, fixtures, patterns, type compliance +6. `.ai/TROUBLESHOOTING.md` - Common errors and solutions + +## Project Overview + +Dash is a Python framework for building reactive web-based data visualization applications. Built on Plotly.js, React, and Flask. + +## Quick Reference + +```bash +# Setup +pip install -e .[ci,dev,testing,celery,diskcache] && npm ci + +# Build +npm run build # Linux/Mac +npm run first-build # Windows (use Bash) +dash-update-components "dash-core-components" # Single component + +# Test +pytest tests/unit # Unit tests +pytest tests/integration # Integration tests +pytest -k test_name # Specific test + +# Lint +npm run lint # All linters +npm run private::format.black # Auto-format Python +``` + +## Key Files + +- `dash/dash.py` - Main Dash app class, layout, callbacks, routing +- `dash/_callback.py` - `@callback` decorator and execution +- `dash/dependencies.py` - `Input`, `Output`, `State`, wildcards +- `dash/development/base_component.py` - Component base class, `to_plotly_json()` +- `dash/dash-renderer/` - TypeScript/React frontend +- `components/` - Component packages (dcc, html, table) From c9e23cc38abc96fd0bfa3f8a3d3a42045ec372d9 Mon Sep 17 00:00:00 2001 From: philippe Date: Fri, 10 Apr 2026 11:35:42 -0400 Subject: [PATCH 158/297] fix fastapi websocket --- dash/backends/_fastapi.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 4e6266146f..edb5bade27 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -188,6 +188,7 @@ async def _handle_error( async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: # Handle lifespan events (startup/shutdown) + if scope["type"] == "lifespan": try: dash_app = get_app() @@ -199,7 +200,7 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: return # Non-HTTP/WebSocket scopes pass through - if scope["type"] not in ("http", "websocket"): + if scope["type"] != "http": await self.app(scope, receive, send) return From 0af47f130417c0d3310ea545ef43dc1ae1c9f8e9 Mon Sep 17 00:00:00 2001 From: philippe Date: Fri, 10 Apr 2026 11:38:19 -0400 Subject: [PATCH 159/297] remove leftover prints --- dash/backends/_fastapi.py | 5 ----- dash/dash.py | 1 - 2 files changed, 6 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index edb5bade27..4e5bdad621 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -299,7 +299,6 @@ def setup_catchall(self, dash_app: Dash): def _setup_catchall(self): try: - print("Setting up catch-all route for unmatched paths", file=sys.stderr) dash_app = get_app() async def catchall(_request: Request): @@ -318,10 +317,6 @@ def add_url_rule( methods: list[str] | None = None, include_in_schema: bool = False, ): - print( - f"Adding URL rule: {rule} -> {view_func} (endpoint: {endpoint}, methods: {methods})", - file=sys.stderr, - ) if rule == "": rule = "/" if isinstance(view_func, str): diff --git a/dash/dash.py b/dash/dash.py index d17c3c4e4e..ea53edf341 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -637,7 +637,6 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches self._got_first_request = {"pages": False, "setup_server": False} if server: - print(f"init app from server {server}") self.init_app() self.logger.setLevel(logging.INFO) From 1b0bef9b133de92f60120b2ec1af91351ecfaa9a Mon Sep 17 00:00:00 2001 From: Philippe Duval Date: Fri, 10 Apr 2026 14:11:20 -0400 Subject: [PATCH 160/297] Update .ai/TESTING.md Co-authored-by: Adrian Borrmann --- .ai/TESTING.md | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/.ai/TESTING.md b/.ai/TESTING.md index 443dbaf856..2e2e562482 100644 --- a/.ai/TESTING.md +++ b/.ai/TESTING.md @@ -8,21 +8,31 @@ Dash includes a pytest/Selenium testing framework for unit and integration tests # Install testing dependencies pip install -e .[testing] -# Run all tests -pytest tests/ +## Running tests — CRITICAL RULES -# Run unit tests -pytest tests/unit/ +You must activate the virtual environment before running any tests. -# Run integration tests -pytest tests/integration/ +### Unit tests -# Run specific test -pytest tests/integration/callbacks/test_basic.py::test_name +``` +source .venv/bin/activate && python -m pytest "tests/unit/" 2>&1 +``` + +### Integration tests + +Always work with a specific test or test file. NEVER run all integration tests at once. -# Headless mode (CI) -pytest --headless tests/integration/ ``` +source .venv/bin/activate && python -m pytest tests/integration/callbacks/test_basic_callback.py --headless -xvs 2>&1 +``` + +**NEVER truncate test output so aggressively that you cannot see failures.** +`tail -5` or `tail -10` is NEVER acceptable — you will miss the error details and waste time re-running. +Always use `tail -50` at minimum, or omit the tail entirely for short test runs. + +**NEVER use `grep "FAILED"` to filter test output** — it hides the actual error messages. + +When a test fails, you MUST be able to see the assertion error, traceback, and context in a SINGLE run. If your command truncates this, your command is wrong. ## Fixtures From ddaf2f6430b63c10f4b241ba03fef207f41b9885 Mon Sep 17 00:00:00 2001 From: philippe Date: Fri, 10 Apr 2026 14:17:47 -0400 Subject: [PATCH 161/297] trim down AGENTS.md --- AGENTS.md | 48 ++++++++---------------------------------------- 1 file changed, 8 insertions(+), 40 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ce07a42d40..0e97d223fc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,42 +1,10 @@ # AGENTS.md -This file provides guidance to AI coding assistants working with this repository. - -For detailed documentation, see the [`.ai/`](.ai/) directory: -- [Commands](.ai/COMMANDS.md) - Build, test, lint -- [Architecture](.ai/ARCHITECTURE.md) - Backend, layout, callbacks -- [Components](.ai/COMPONENTS.md) - Component system, generation, resources - -## Project Overview - -Dash is a Python framework for building reactive web-based data visualization applications. Built on Plotly.js, React, and Flask. - -## Quick Reference - -```bash -# Setup -pip install -e .[ci,dev,testing,celery,diskcache] && npm ci - -# Build -npm run build # Linux/Mac -npm run first-build # Windows (use Bash) -dash-update-components "dash-core-components" # Single component - -# Test -pytest tests/unit # Unit tests -pytest tests/integration # Integration tests -pytest -k test_name # Specific test - -# Lint -npm run lint # All linters -npm run private::format.black # Auto-format Python -``` - -## Key Files - -- `dash/dash.py` - Main Dash app class, layout, callbacks, routing -- `dash/_callback.py` - `@callback` decorator and execution -- `dash/dependencies.py` - `Input`, `Output`, `State`, wildcards -- `dash/development/base_component.py` - Component base class, `to_plotly_json()` -- `dash/dash-renderer/` - TypeScript/React frontend -- `components/` - Component packages (dcc, html, table) +For guidance on working with this repository, see the [`.ai/`](.ai/) directory: + +- [COMMANDS.md](.ai/COMMANDS.md) - Build, test, lint +- [ARCHITECTURE.md](.ai/ARCHITECTURE.md) - Backend, callbacks, layout +- [RENDERER.md](.ai/RENDERER.md) - Frontend, React, Redux +- [COMPONENTS.md](.ai/COMPONENTS.md) - Component system +- [TESTING.md](.ai/TESTING.md) - Testing patterns +- [TROUBLESHOOTING.md](.ai/TROUBLESHOOTING.md) - Common issues From cf19476f4c876662a8205a5756c5b63357971663 Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Fri, 10 Apr 2026 13:02:51 -0600 Subject: [PATCH 162/297] fix: Add `displayNotifier` to Graph config --- .../dash-core-components/src/components/Graph.react.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/dash-core-components/src/components/Graph.react.js b/components/dash-core-components/src/components/Graph.react.js index 770c9defd6..94dab4559c 100644 --- a/components/dash-core-components/src/components/Graph.react.js +++ b/components/dash-core-components/src/components/Graph.react.js @@ -550,6 +550,11 @@ PlotlyGraph.propTypes = { * plot rather than registering them globally. */ locales: PropTypes.object, + + /** + * Determines whether or not notifier is displayed + */ + displayNotifier: PropTypes.bool, }), /** From 982e2382319fdfc264ba3bee4dd0256298c69a25 Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Fri, 10 Apr 2026 13:42:44 -0600 Subject: [PATCH 163/297] Remove schema/config comparison test --- .../integration/tab/test_tabs_with_graphs.py | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/components/dash-core-components/tests/integration/tab/test_tabs_with_graphs.py b/components/dash-core-components/tests/integration/tab/test_tabs_with_graphs.py index 7b98de6d39..b7525f00f9 100644 --- a/components/dash-core-components/tests/integration/tab/test_tabs_with_graphs.py +++ b/components/dash-core-components/tests/integration/tab/test_tabs_with_graphs.py @@ -1,7 +1,5 @@ from dash import Dash, Input, Output, dcc, html from dash.exceptions import PreventUpdate -import json -import os import pytest from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC @@ -185,43 +183,4 @@ def on_click_update_graph(n_clicks): time.sleep(1) dash_dcc.percy_snapshot(f"Tabs-2 rendered ({is_eager})") - # do some extra tests while we're here - # and have access to Graph and plotly.js - check_graph_config_shape(dash_dcc) - - assert dash_dcc.get_logs() == [] - - -def check_graph_config_shape(dash_dcc): - config_schema = dash_dcc.driver.execute_script( - "return Plotly.PlotSchema.get().config;" - ) - with open(os.path.join(dcc.__path__[0], "metadata.json")) as meta: - graph_meta = json.load(meta)["src/components/Graph.react.js"] - config_prop_shape = graph_meta["props"]["config"]["type"]["value"] - - ignored_config = [ - "setBackground", - "showSources", - "logging", - "globalTransforms", - "notifyOnLogging", - "role", - "typesetMath", - ] - - def crawl(schema, props): - for prop_name in props: - assert prop_name in schema - - for item_name, item in schema.items(): - if item_name in ignored_config: - continue - - assert item_name in props - if "valType" not in item: - crawl(item, props[item_name]["value"]) - - crawl(config_schema, config_prop_shape) - assert dash_dcc.get_logs() == [] From 254a697de2db16d07a4d100295b6d89b1b2928ec Mon Sep 17 00:00:00 2001 From: zach Date: Fri, 10 Apr 2026 23:57:10 -0700 Subject: [PATCH 164/297] Add missing stacklevel=2 to 9 warnings.warn() calls Without stacklevel, warnings.warn() reports the location of the warn() call itself rather than the caller's location, making it harder for users to identify the source of the warning in their own code. This adds stacklevel=2 to all 9 warnings.warn() calls across 7 files that were missing it. --- dash/_callback_context.py | 3 +++ dash/dash.py | 3 ++- dash/development/_jl_components_generation.py | 3 ++- dash/development/_r_components_generation.py | 3 ++- dash/development/base_component.py | 2 +- dash/resources.py | 3 ++- dash/testing/browser.py | 2 +- 7 files changed, 13 insertions(+), 6 deletions(-) diff --git a/dash/_callback_context.py b/dash/_callback_context.py index 09faf6f9a3..f4e12693a7 100644 --- a/dash/_callback_context.py +++ b/dash/_callback_context.py @@ -177,6 +177,7 @@ def outputs_list(self): warnings.warn( "outputs_list is deprecated, use outputs_grouping instead", DeprecationWarning, + stacklevel=2, ) return getattr(_get_context_value(), "outputs_list", []) @@ -188,6 +189,7 @@ def inputs_list(self): warnings.warn( "inputs_list is deprecated, use args_grouping instead", DeprecationWarning, + stacklevel=2, ) return getattr(_get_context_value(), "inputs_list", []) @@ -199,6 +201,7 @@ def states_list(self): warnings.warn( "states_list is deprecated, use args_grouping instead", DeprecationWarning, + stacklevel=2, ) return getattr(_get_context_value(), "states_list", []) diff --git a/dash/dash.py b/dash/dash.py index 122cf54dd6..5666dc0ce7 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -643,7 +643,8 @@ def __init__( # pylint: disable=too-many-statements if self.__class__.__name__ == "JupyterDash": warnings.warn( "JupyterDash is deprecated, use Dash instead.\n" - "See https://dash.plotly.com/dash-in-jupyter for more details." + "See https://dash.plotly.com/dash-in-jupyter for more details.", + stacklevel=2, ) self.setup_startup_routes() diff --git a/dash/development/_jl_components_generation.py b/dash/development/_jl_components_generation.py index 771ac0180a..4b7a7be4e1 100644 --- a/dash/development/_jl_components_generation.py +++ b/dash/development/_jl_components_generation.py @@ -468,7 +468,8 @@ def generate_class_string(name, props, description, project_shortname, prefix): ( 'WARNING: prop "{}" in component "{}" is a Julia keyword' " - REMOVED FROM THE JULIA COMPONENT" - ).format(item, name) + ).format(item, name), + stacklevel=2, ) default_paramtext += ", ".join(":{}".format(p) for p in prop_keys) diff --git a/dash/development/_r_components_generation.py b/dash/development/_r_components_generation.py index 18ac60d5d8..e392dc9aca 100644 --- a/dash/development/_r_components_generation.py +++ b/dash/development/_r_components_generation.py @@ -216,7 +216,8 @@ def generate_class_string(name, props, project_shortname, prefix): ( 'WARNING: prop "{}" in component "{}" is an R keyword' " - REMOVED FROM THE R COMPONENT" - ).format(item, name) + ).format(item, name), + stacklevel=2, ) default_argtext += ", ".join("{}=NULL".format(p) for p in prop_keys) diff --git a/dash/development/base_component.py b/dash/development/base_component.py index 02579ff2e2..0e93af5e3e 100644 --- a/dash/development/base_component.py +++ b/dash/development/base_component.py @@ -451,7 +451,7 @@ def _validate_deprecation(self): _ns = getattr(self, "_namespace", "") deprecation_message = _deprecated_components.get(_ns, {}).get(_type) if deprecation_message: - warnings.warn(DeprecationWarning(textwrap.dedent(deprecation_message))) + warnings.warn(DeprecationWarning(textwrap.dedent(deprecation_message)), stacklevel=2) ComponentSingleType = typing.Union[str, int, float, Component, None] diff --git a/dash/resources.py b/dash/resources.py index e197b6753e..62fddb24af 100644 --- a/dash/resources.py +++ b/dash/resources.py @@ -111,7 +111,8 @@ def _filter_resources( "or `app.css.append_css`, use `external_scripts` " "or `external_stylesheets` instead.\n" "See https://dash.plotly.com/external-resources" - ) + ), + stacklevel=2, ) continue else: diff --git a/dash/testing/browser.py b/dash/testing/browser.py index 8a82399a97..09af45c76d 100644 --- a/dash/testing/browser.py +++ b/dash/testing/browser.py @@ -624,7 +624,7 @@ def get_logs(self): for entry in self.driver.get_log("browser") if entry["timestamp"] > self._last_ts ] - warnings.warn("get_logs always return None with webdrivers other than Chrome") + warnings.warn("get_logs always return None with webdrivers other than Chrome", stacklevel=2) return None def reset_log_timestamp(self): From ee6fd6fab3f275488723b5cb321206e3bcfe8075 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Apr 2026 09:31:25 +0000 Subject: [PATCH 165/297] Bump axios in the npm-dependencies-security group across 1 directory Bumps the npm-dependencies-security group with 1 update in the / directory: [axios](https://github.com/axios/axios). Updates `axios` from 1.12.0 to 1.15.0 - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.12.0...v1.15.0) --- updated-dependencies: - dependency-name: axios dependency-version: 1.15.0 dependency-type: indirect dependency-group: npm-dependencies-security ... Signed-off-by: dependabot[bot] --- package-lock.json | 273 +++++++++++++++++++++++++--------------------- 1 file changed, 150 insertions(+), 123 deletions(-) diff --git a/package-lock.json b/package-lock.json index 810b726d69..f8bfb043c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -687,12 +687,6 @@ "node": "^14.15.0 || >=16.0.0" } }, - "node_modules/@ltd/j-toml": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/@ltd/j-toml/-/j-toml-1.38.0.tgz", - "integrity": "sha512-lYtBcmvHustHQtg4X7TXUu1Xa/tbLC3p2wLvgQI+fWVySguVZJF60Snxijw5EiohumxZbR10kWYFFebh1zotiw==", - "dev": true - }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", @@ -1460,9 +1454,9 @@ } }, "node_modules/@nx/nx-darwin-arm64": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-22.6.4.tgz", - "integrity": "sha512-KuUQ9t8pxIO+Px1kbjA0XDLOU6XoAsijl0ssIMRYN1w5ly+0k/KglWt7qgwDockkaLRHkQ3YSR8I2LJXJE+Vig==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-22.6.5.tgz", + "integrity": "sha512-qT77Omkg5xQuL2+pDbneX2tI+XW5ZeayMylu7UUgK8OhTrAkJLKjpuYRH4xT5XBipxbDtlxmO3aLS3Ib1pKzJQ==", "cpu": [ "arm64" ], @@ -1473,9 +1467,9 @@ ] }, "node_modules/@nx/nx-darwin-x64": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-22.6.4.tgz", - "integrity": "sha512-FB2XL2+ixbRI1fddz4oW+9MhoJASoTD8Ai4q5+B1OUPftgarIPLxaqI8TWba30Bos2AiYDofMJPf9uhBmLDH5Q==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-22.6.5.tgz", + "integrity": "sha512-9jICxb7vfJ56y/7Yuh3b/n1QJqWxO9xnXKYEs6SO8xPoW/KomVckILGc1C6RQSs6/3ixVJC7k1Dh1wm5tKPFrg==", "cpu": [ "x64" ], @@ -1486,9 +1480,9 @@ ] }, "node_modules/@nx/nx-freebsd-x64": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-22.6.4.tgz", - "integrity": "sha512-qNsXhlflc77afjcRKCn7bqI8l/HPEjKhQRFs8wfKbAfNw3XEASc0EZtBV/TStLGV6PEZQldVBaId5FBMp8GW6Q==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-22.6.5.tgz", + "integrity": "sha512-6B1wEKpqz5dI3AGMqttAVnA6M3DB/besAtuGyQiymK9ROlta1iuWgCcIYwcCQyhLn2Rx7vqj447KKcgCa8HlVw==", "cpu": [ "x64" ], @@ -1499,9 +1493,9 @@ ] }, "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-22.6.4.tgz", - "integrity": "sha512-rjfnii0xGe8SQqsO/DDHeJSjbqp2H5fOEgZlaYXDGOwQeLZ1TQplEdx8hyI/ErAUwVO3YHnzoMtmachBQOlspw==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-22.6.5.tgz", + "integrity": "sha512-xV50B8mnDPboct7JkAHftajI02s+8FszA8WTzhore+YGR+lEKHTLpucwGEaQuMlSdLplH7pQix4B4uK5pcMhZw==", "cpu": [ "arm" ], @@ -1512,9 +1506,9 @@ ] }, "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-22.6.4.tgz", - "integrity": "sha512-x6Zim1STewCXuHBCgoy2TO0586UlwH4RNCobn0mTiPd1jt7nU+fNqo3SpY8RzY1KmBfgcO48BBrfykPE9YWMpg==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-22.6.5.tgz", + "integrity": "sha512-2JkWuMGj+HpW6oPAvU5VdAx1afTnEbiM10Y3YOrl3fipWV4BiP5VDx762QTrfCraP4hl6yqTgvTe7F9xaby+jQ==", "cpu": [ "arm64" ], @@ -1525,9 +1519,9 @@ ] }, "node_modules/@nx/nx-linux-arm64-musl": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-22.6.4.tgz", - "integrity": "sha512-vYOqdgXIhtHFWdtnonp/jFfmfkyNPTu1JEdXuJpSxwUQdV2dWqS/l3HVPVWHXDrVKofPafK3M72jMvoWoaOQ6g==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-22.6.5.tgz", + "integrity": "sha512-Z/zMqFClnEyqDXouJKEPoWVhMQIif5F0YuECWBYjd3ZLwQsXGTItoh+6Wm3XF/nGMA2uLOHyTq/X7iFXQY3RzA==", "cpu": [ "arm64" ], @@ -1538,9 +1532,9 @@ ] }, "node_modules/@nx/nx-linux-x64-gnu": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-22.6.4.tgz", - "integrity": "sha512-UfWUDlOzlvQNVa1mnqOFxzvUwoGfM2o9ruhwYRoFm3XJbVYnjINyQsdcHwwDJItJP04LZzLPxA1+O8sU+Oqg6A==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-22.6.5.tgz", + "integrity": "sha512-FlotSyqNnaXSn0K+yWw+hRdYBwusABrPgKLyixfJIYRzsy+xPKN6pON6vZfqGwzuWF/9mEGReRz+iM8PiW0XSg==", "cpu": [ "x64" ], @@ -1551,9 +1545,9 @@ ] }, "node_modules/@nx/nx-linux-x64-musl": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-22.6.4.tgz", - "integrity": "sha512-dwXpcyin4ScD5gH9FdhiNnOqFXclXLFBDTyRCEOlRUbOPayF9YEcH0PPIf9uWmwP3tshhAdr5sg9DLN+r7M3xg==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-22.6.5.tgz", + "integrity": "sha512-RVOe2qcwhoIx6mxQURPjUfAW5SEOmT2gdhewvdcvX9ICq1hj5B2VarmkhTg0qroO7xiyqOqwq26mCzoV2I3NgQ==", "cpu": [ "x64" ], @@ -1564,9 +1558,9 @@ ] }, "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-22.6.4.tgz", - "integrity": "sha512-KqjJbFWhKJaKjET3Ep8hltXPizO0EstF4yfmp3oepWVn11poagc2MT1pf/tnRf6cdD88wd0bmw/83Ng6WUQ3Uw==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-22.6.5.tgz", + "integrity": "sha512-ZqurqI8VuYnsr2Kn4K4t+Gx6j/BZdf6qz/6Tv4A7XQQ6oNYVQgTqoNEFj+CCkVaIe6aIdCWpousFLqs+ZgBqYQ==", "cpu": [ "arm64" ], @@ -1577,9 +1571,9 @@ ] }, "node_modules/@nx/nx-win32-x64-msvc": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-22.6.4.tgz", - "integrity": "sha512-CIL9m6uilGGr/eU+41/+aVWUnEcq+j1EDynUX2A4InLTbAN0ylte4Af+72mvipNiqJgDkjKaNzOCQDnp8QBjEQ==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-22.6.5.tgz", + "integrity": "sha512-i2QFBJIuaYg9BHxrrnBV4O7W9rVL2k0pSIdk/rRp3EYJEU93iUng+qbZiY9wh1xvmXuUCE2G7TRd+8/SG/RFKg==", "cpu": [ "x64" ], @@ -2282,14 +2276,14 @@ } }, "node_modules/axios": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.0.tgz", - "integrity": "sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz", + "integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^2.1.0" } }, "node_modules/balanced-match": { @@ -6760,24 +6754,23 @@ } }, "node_modules/nx": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/nx/-/nx-22.6.4.tgz", - "integrity": "sha512-WEaCnLKeO9RhQAOBMfXgYO/Lx5wL4ARCtRGiYCjJtAJIZ5kcVn4uPKL2Xz1xekpF7ef/+YNrUQSrblx47Ms9Rg==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/nx/-/nx-22.6.5.tgz", + "integrity": "sha512-VRKhDAt684dXNSz9MNjE7MekkCfQF41P2PSx5jEWQjDEP1Z4jFZbyeygWs5ZyOroG7/n0MoWAJTe6ftvIcBOAg==", "dev": true, "hasInstallScript": true, "dependencies": { - "@ltd/j-toml": "^1.38.0", "@napi-rs/wasm-runtime": "0.2.4", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "3.0.2", "@zkochan/js-yaml": "0.0.7", - "axios": "1.12.0", + "axios": "1.15.0", "cli-cursor": "3.1.0", "cli-spinners": "2.6.1", "cliui": "^8.0.1", "dotenv": "~16.4.5", "dotenv-expand": "~11.0.6", - "ejs": "^3.1.7", + "ejs": "5.0.1", "enquirer": "~2.3.6", "figures": "3.2.0", "flat": "^5.0.2", @@ -6793,6 +6786,7 @@ "picocolors": "^1.1.0", "resolve.exports": "2.0.3", "semver": "^7.6.3", + "smol-toml": "1.6.1", "string-width": "^4.2.3", "tar-stream": "~2.2.0", "tmp": "~0.2.1", @@ -6808,16 +6802,16 @@ "nx-cloud": "bin/nx-cloud.js" }, "optionalDependencies": { - "@nx/nx-darwin-arm64": "22.6.4", - "@nx/nx-darwin-x64": "22.6.4", - "@nx/nx-freebsd-x64": "22.6.4", - "@nx/nx-linux-arm-gnueabihf": "22.6.4", - "@nx/nx-linux-arm64-gnu": "22.6.4", - "@nx/nx-linux-arm64-musl": "22.6.4", - "@nx/nx-linux-x64-gnu": "22.6.4", - "@nx/nx-linux-x64-musl": "22.6.4", - "@nx/nx-win32-arm64-msvc": "22.6.4", - "@nx/nx-win32-x64-msvc": "22.6.4" + "@nx/nx-darwin-arm64": "22.6.5", + "@nx/nx-darwin-x64": "22.6.5", + "@nx/nx-freebsd-x64": "22.6.5", + "@nx/nx-linux-arm-gnueabihf": "22.6.5", + "@nx/nx-linux-arm64-gnu": "22.6.5", + "@nx/nx-linux-arm64-musl": "22.6.5", + "@nx/nx-linux-x64-gnu": "22.6.5", + "@nx/nx-linux-x64-musl": "22.6.5", + "@nx/nx-win32-arm64-msvc": "22.6.5", + "@nx/nx-win32-x64-msvc": "22.6.5" }, "peerDependencies": { "@swc-node/register": "^1.11.1", @@ -6853,6 +6847,18 @@ "node": "18 || 20 || >=22" } }, + "node_modules/nx/node_modules/ejs": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-5.0.1.tgz", + "integrity": "sha512-COqBPFMxuPTPspXl2DkVYaDS3HtrD1GpzOGkNTJ1IYkifq/r9h8SVEFrjA3D9/VJGOEoMQcrlhpntcSUrM8k6A==", + "dev": true, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.12.18" + } + }, "node_modules/nx/node_modules/minimatch": { "version": "10.2.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", @@ -7561,10 +7567,13 @@ "dev": true }, "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "dev": true, + "engines": { + "node": ">=10" + } }, "node_modules/quick-lru": { "version": "4.0.1", @@ -8016,6 +8025,18 @@ "npm": ">= 3.0.0" } }, + "node_modules/smol-toml": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz", + "integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==", + "dev": true, + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, "node_modules/socks": { "version": "2.8.7", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", @@ -9307,12 +9328,6 @@ "npmlog": "^6.0.2" } }, - "@ltd/j-toml": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/@ltd/j-toml/-/j-toml-1.38.0.tgz", - "integrity": "sha512-lYtBcmvHustHQtg4X7TXUu1Xa/tbLC3p2wLvgQI+fWVySguVZJF60Snxijw5EiohumxZbR10kWYFFebh1zotiw==", - "dev": true - }, "@napi-rs/wasm-runtime": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", @@ -9877,72 +9892,72 @@ } }, "@nx/nx-darwin-arm64": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-22.6.4.tgz", - "integrity": "sha512-KuUQ9t8pxIO+Px1kbjA0XDLOU6XoAsijl0ssIMRYN1w5ly+0k/KglWt7qgwDockkaLRHkQ3YSR8I2LJXJE+Vig==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-22.6.5.tgz", + "integrity": "sha512-qT77Omkg5xQuL2+pDbneX2tI+XW5ZeayMylu7UUgK8OhTrAkJLKjpuYRH4xT5XBipxbDtlxmO3aLS3Ib1pKzJQ==", "dev": true, "optional": true }, "@nx/nx-darwin-x64": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-22.6.4.tgz", - "integrity": "sha512-FB2XL2+ixbRI1fddz4oW+9MhoJASoTD8Ai4q5+B1OUPftgarIPLxaqI8TWba30Bos2AiYDofMJPf9uhBmLDH5Q==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-22.6.5.tgz", + "integrity": "sha512-9jICxb7vfJ56y/7Yuh3b/n1QJqWxO9xnXKYEs6SO8xPoW/KomVckILGc1C6RQSs6/3ixVJC7k1Dh1wm5tKPFrg==", "dev": true, "optional": true }, "@nx/nx-freebsd-x64": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-22.6.4.tgz", - "integrity": "sha512-qNsXhlflc77afjcRKCn7bqI8l/HPEjKhQRFs8wfKbAfNw3XEASc0EZtBV/TStLGV6PEZQldVBaId5FBMp8GW6Q==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-22.6.5.tgz", + "integrity": "sha512-6B1wEKpqz5dI3AGMqttAVnA6M3DB/besAtuGyQiymK9ROlta1iuWgCcIYwcCQyhLn2Rx7vqj447KKcgCa8HlVw==", "dev": true, "optional": true }, "@nx/nx-linux-arm-gnueabihf": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-22.6.4.tgz", - "integrity": "sha512-rjfnii0xGe8SQqsO/DDHeJSjbqp2H5fOEgZlaYXDGOwQeLZ1TQplEdx8hyI/ErAUwVO3YHnzoMtmachBQOlspw==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-22.6.5.tgz", + "integrity": "sha512-xV50B8mnDPboct7JkAHftajI02s+8FszA8WTzhore+YGR+lEKHTLpucwGEaQuMlSdLplH7pQix4B4uK5pcMhZw==", "dev": true, "optional": true }, "@nx/nx-linux-arm64-gnu": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-22.6.4.tgz", - "integrity": "sha512-x6Zim1STewCXuHBCgoy2TO0586UlwH4RNCobn0mTiPd1jt7nU+fNqo3SpY8RzY1KmBfgcO48BBrfykPE9YWMpg==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-22.6.5.tgz", + "integrity": "sha512-2JkWuMGj+HpW6oPAvU5VdAx1afTnEbiM10Y3YOrl3fipWV4BiP5VDx762QTrfCraP4hl6yqTgvTe7F9xaby+jQ==", "dev": true, "optional": true }, "@nx/nx-linux-arm64-musl": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-22.6.4.tgz", - "integrity": "sha512-vYOqdgXIhtHFWdtnonp/jFfmfkyNPTu1JEdXuJpSxwUQdV2dWqS/l3HVPVWHXDrVKofPafK3M72jMvoWoaOQ6g==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-22.6.5.tgz", + "integrity": "sha512-Z/zMqFClnEyqDXouJKEPoWVhMQIif5F0YuECWBYjd3ZLwQsXGTItoh+6Wm3XF/nGMA2uLOHyTq/X7iFXQY3RzA==", "dev": true, "optional": true }, "@nx/nx-linux-x64-gnu": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-22.6.4.tgz", - "integrity": "sha512-UfWUDlOzlvQNVa1mnqOFxzvUwoGfM2o9ruhwYRoFm3XJbVYnjINyQsdcHwwDJItJP04LZzLPxA1+O8sU+Oqg6A==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-22.6.5.tgz", + "integrity": "sha512-FlotSyqNnaXSn0K+yWw+hRdYBwusABrPgKLyixfJIYRzsy+xPKN6pON6vZfqGwzuWF/9mEGReRz+iM8PiW0XSg==", "dev": true, "optional": true }, "@nx/nx-linux-x64-musl": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-22.6.4.tgz", - "integrity": "sha512-dwXpcyin4ScD5gH9FdhiNnOqFXclXLFBDTyRCEOlRUbOPayF9YEcH0PPIf9uWmwP3tshhAdr5sg9DLN+r7M3xg==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-22.6.5.tgz", + "integrity": "sha512-RVOe2qcwhoIx6mxQURPjUfAW5SEOmT2gdhewvdcvX9ICq1hj5B2VarmkhTg0qroO7xiyqOqwq26mCzoV2I3NgQ==", "dev": true, "optional": true }, "@nx/nx-win32-arm64-msvc": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-22.6.4.tgz", - "integrity": "sha512-KqjJbFWhKJaKjET3Ep8hltXPizO0EstF4yfmp3oepWVn11poagc2MT1pf/tnRf6cdD88wd0bmw/83Ng6WUQ3Uw==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-22.6.5.tgz", + "integrity": "sha512-ZqurqI8VuYnsr2Kn4K4t+Gx6j/BZdf6qz/6Tv4A7XQQ6oNYVQgTqoNEFj+CCkVaIe6aIdCWpousFLqs+ZgBqYQ==", "dev": true, "optional": true }, "@nx/nx-win32-x64-msvc": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-22.6.4.tgz", - "integrity": "sha512-CIL9m6uilGGr/eU+41/+aVWUnEcq+j1EDynUX2A4InLTbAN0ylte4Af+72mvipNiqJgDkjKaNzOCQDnp8QBjEQ==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-22.6.5.tgz", + "integrity": "sha512-i2QFBJIuaYg9BHxrrnBV4O7W9rVL2k0pSIdk/rRp3EYJEU93iUng+qbZiY9wh1xvmXuUCE2G7TRd+8/SG/RFKg==", "dev": true, "optional": true }, @@ -10478,14 +10493,14 @@ "version": "1.0.5" }, "axios": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.0.tgz", - "integrity": "sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz", + "integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==", "dev": true, "requires": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^2.1.0" } }, "balanced-match": { @@ -13511,33 +13526,32 @@ } }, "nx": { - "version": "22.6.4", - "resolved": "https://registry.npmjs.org/nx/-/nx-22.6.4.tgz", - "integrity": "sha512-WEaCnLKeO9RhQAOBMfXgYO/Lx5wL4ARCtRGiYCjJtAJIZ5kcVn4uPKL2Xz1xekpF7ef/+YNrUQSrblx47Ms9Rg==", + "version": "22.6.5", + "resolved": "https://registry.npmjs.org/nx/-/nx-22.6.5.tgz", + "integrity": "sha512-VRKhDAt684dXNSz9MNjE7MekkCfQF41P2PSx5jEWQjDEP1Z4jFZbyeygWs5ZyOroG7/n0MoWAJTe6ftvIcBOAg==", "dev": true, "requires": { - "@ltd/j-toml": "^1.38.0", "@napi-rs/wasm-runtime": "0.2.4", - "@nx/nx-darwin-arm64": "22.6.4", - "@nx/nx-darwin-x64": "22.6.4", - "@nx/nx-freebsd-x64": "22.6.4", - "@nx/nx-linux-arm-gnueabihf": "22.6.4", - "@nx/nx-linux-arm64-gnu": "22.6.4", - "@nx/nx-linux-arm64-musl": "22.6.4", - "@nx/nx-linux-x64-gnu": "22.6.4", - "@nx/nx-linux-x64-musl": "22.6.4", - "@nx/nx-win32-arm64-msvc": "22.6.4", - "@nx/nx-win32-x64-msvc": "22.6.4", + "@nx/nx-darwin-arm64": "22.6.5", + "@nx/nx-darwin-x64": "22.6.5", + "@nx/nx-freebsd-x64": "22.6.5", + "@nx/nx-linux-arm-gnueabihf": "22.6.5", + "@nx/nx-linux-arm64-gnu": "22.6.5", + "@nx/nx-linux-arm64-musl": "22.6.5", + "@nx/nx-linux-x64-gnu": "22.6.5", + "@nx/nx-linux-x64-musl": "22.6.5", + "@nx/nx-win32-arm64-msvc": "22.6.5", + "@nx/nx-win32-x64-msvc": "22.6.5", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "3.0.2", "@zkochan/js-yaml": "0.0.7", - "axios": "1.12.0", + "axios": "1.15.0", "cli-cursor": "3.1.0", "cli-spinners": "2.6.1", "cliui": "^8.0.1", "dotenv": "~16.4.5", "dotenv-expand": "~11.0.6", - "ejs": "^3.1.7", + "ejs": "5.0.1", "enquirer": "~2.3.6", "figures": "3.2.0", "flat": "^5.0.2", @@ -13553,6 +13567,7 @@ "picocolors": "^1.1.0", "resolve.exports": "2.0.3", "semver": "^7.6.3", + "smol-toml": "1.6.1", "string-width": "^4.2.3", "tar-stream": "~2.2.0", "tmp": "~0.2.1", @@ -13579,6 +13594,12 @@ "balanced-match": "^4.0.2" } }, + "ejs": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-5.0.1.tgz", + "integrity": "sha512-COqBPFMxuPTPspXl2DkVYaDS3HtrD1GpzOGkNTJ1IYkifq/r9h8SVEFrjA3D9/VJGOEoMQcrlhpntcSUrM8k6A==", + "dev": true + }, "minimatch": { "version": "10.2.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", @@ -14077,9 +14098,9 @@ "dev": true }, "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", "dev": true }, "quick-lru": { @@ -14363,6 +14384,12 @@ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true }, + "smol-toml": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz", + "integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==", + "dev": true + }, "socks": { "version": "2.8.7", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", From a3f233a236eaee10f2df8df33fbcb4e6906027fc Mon Sep 17 00:00:00 2001 From: philippe Date: Mon, 13 Apr 2026 09:04:31 -0400 Subject: [PATCH 166/297] remove quick reference from claude.md --- CLAUDE.md | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index be36e0949e..61cc22b9cb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,27 +17,6 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co Dash is a Python framework for building reactive web-based data visualization applications. Built on Plotly.js, React, and Flask. -## Quick Reference - -```bash -# Setup -pip install -e .[ci,dev,testing,celery,diskcache] && npm ci - -# Build -npm run build # Linux/Mac -npm run first-build # Windows (use Bash) -dash-update-components "dash-core-components" # Single component - -# Test -pytest tests/unit # Unit tests -pytest tests/integration # Integration tests -pytest -k test_name # Specific test - -# Lint -npm run lint # All linters -npm run private::format.black # Auto-format Python -``` - ## Key Files - `dash/dash.py` - Main Dash app class, layout, callbacks, routing From cac28e46e7e55365451c964f0816705a063e3ad6 Mon Sep 17 00:00:00 2001 From: philippe Date: Mon, 13 Apr 2026 11:00:43 -0400 Subject: [PATCH 167/297] version 4.2.0rc0 --- dash/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/version.py b/dash/version.py index 7039708762..25b76de3c3 100644 --- a/dash/version.py +++ b/dash/version.py @@ -1 +1 @@ -__version__ = "4.1.0" +__version__ = "4.2.0rc0" From 4ff49b58de95ca7a0ee83113f4b1b674ae599686 Mon Sep 17 00:00:00 2001 From: philippe Date: Mon, 13 Apr 2026 11:06:23 -0400 Subject: [PATCH 168/297] update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49782ccf04..3709fbd2e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,12 @@ This project adheres to [Semantic Versioning](https://semver.org/). - [#3609](https://github.com/plotly/dash/pull/3609) Add backward compat alias for _Wildcard - [#3672](https://github.com/plotly/dash/pull/3672) Improve browser performance when app contains a large number of pattern matching callback callbacks. Exposes an api endpoint to fetch the latest computeGraph call. +# [4.2.0rc0] - 2026-04-13 + +## Fixed + +- Fix websocket used in the same FastAPI server. Fix [#3636](https://github.com/plotly/dash/issues/3636) +- Fix FastAPI url paths order. Fix [3667](https://github.com/plotly/dash/issues/3667) # [4.1.0rc0] - 2026-02-23 From 20834e229a8c17f1c2d0af9edb658578e3245475 Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Mon, 13 Apr 2026 13:05:45 -0600 Subject: [PATCH 169/297] Fix tab key not working in dropdowns in Safari --- .../src/components/css/dropdown.css | 6 ++ .../src/fragments/Dropdown.tsx | 39 ++++++++ .../tests/integration/dropdown/test_a11y.py | 90 +++++++++++++++++++ 3 files changed, 135 insertions(+) diff --git a/components/dash-core-components/src/components/css/dropdown.css b/components/dash-core-components/src/components/css/dropdown.css index 5667b85060..6a74a79df0 100644 --- a/components/dash-core-components/src/components/css/dropdown.css +++ b/components/dash-core-components/src/components/css/dropdown.css @@ -55,6 +55,12 @@ cursor: not-allowed; } +.dash-dropdown-focus-target { + position: absolute; + opacity: 0; + pointer-events: none; +} + .dash-dropdown-value { max-width: 100%; text-align: left; diff --git a/components/dash-core-components/src/fragments/Dropdown.tsx b/components/dash-core-components/src/fragments/Dropdown.tsx index 6a838fb1df..cc3f1f230c 100644 --- a/components/dash-core-components/src/fragments/Dropdown.tsx +++ b/components/dash-core-components/src/fragments/Dropdown.tsx @@ -313,6 +313,7 @@ const Dropdown = (props: DropdownProps) => { const relevantKeys = [ 'ArrowDown', 'ArrowUp', + 'Tab', 'PageDown', 'PageUp', 'Home', @@ -342,6 +343,19 @@ const Dropdown = (props: DropdownProps) => { let nextIndex: number; switch (e.key) { + case 'Tab': { + // Trap Tab inside the popover so Safari (which + // skips non-text inputs) can navigate options. + const next = current + (e.shiftKey ? -1 : 1); + if (next < minIndex) { + nextIndex = maxIndex; + } else if (next > maxIndex) { + nextIndex = minIndex; + } else { + nextIndex = next; + } + break; + } case 'ArrowDown': nextIndex = current < maxIndex ? current + 1 : minIndex; break; @@ -408,12 +422,37 @@ const Dropdown = (props: DropdownProps) => { const popover = ( + {/* Safari skips - )} - - - - -
- + placeholder={end_date_placeholder_text} + disabled={disabled} + dir={direction} + aria-label={end_date_placeholder_text} + /> + {clearable && !disabled && ( + + + + )} + + + + + + e.preventDefault() + : undefined + } + onOpenAutoFocus={e => e.preventDefault()} + onCloseAutoFocus={e => { + e.preventDefault(); + // Only focus if focus is not already on one of the inputs + const inputs: (Element | null)[] = [ + startInputRef.current, + endInputRef.current, + ]; + if (inputs.includes(document.activeElement)) { + return; + } + + // Keeps focus on the component when the calendar closes + if (!startInputValue) { + startInputRef.current?.focus(); + } else { + endInputRef.current?.focus(); + } + }} + > + {with_full_screen_portal && ( + + )} + + + + + ); }; diff --git a/components/dash-core-components/src/fragments/DatePickerSingle.tsx b/components/dash-core-components/src/fragments/DatePickerSingle.tsx index 527e654b0d..f572ed629d 100644 --- a/components/dash-core-components/src/fragments/DatePickerSingle.tsx +++ b/components/dash-core-components/src/fragments/DatePickerSingle.tsx @@ -167,128 +167,127 @@ const DatePickerSingle = ({ } return ( - -
- - -
{ - e.preventDefault(); - if (!isCalendarOpen && !disabled) { - setIsCalendarOpen(true); - } +
+ + + +
{ + e.preventDefault(); + if (!isCalendarOpen && !disabled) { + setIsCalendarOpen(true); + } + }} + > + { + inputRef.current = node; }} - > - { - inputRef.current = node; - }} - type="text" - id={accessibleId} - inputClassName="dash-datepicker-input dash-datepicker-end-date" - value={inputValue} - onChange={e => setInputValue(e.target?.value)} - onKeyDown={handleInputKeyDown} - placeholder={placeholder} - disabled={disabled} - dir={direction} - aria-label={placeholder} - /> - {clearable && !disabled && !!date && ( - - - - )} + type="text" + id={accessibleId} + inputClassName="dash-datepicker-input dash-datepicker-end-date" + value={inputValue} + onChange={e => setInputValue(e.target?.value)} + onKeyDown={handleInputKeyDown} + placeholder={placeholder} + disabled={disabled} + dir={direction} + aria-label={placeholder} + /> + {clearable && !disabled && !!date && ( + + + + )} - -
-
+ +
+ - - e.preventDefault() - : undefined + + e.preventDefault() + : undefined + } + onOpenAutoFocus={e => e.preventDefault()} + onCloseAutoFocus={e => { + e.preventDefault(); + // Only focus if focus is not already on the input + if ( + document.activeElement !== inputRef.current + ) { + inputRef.current?.focus(); } - onOpenAutoFocus={e => e.preventDefault()} - onCloseAutoFocus={e => { - e.preventDefault(); - // Only focus if focus is not already on the input - if ( - document.activeElement !== inputRef.current - ) { - inputRef.current?.focus(); + }} + > + {with_full_screen_portal && ( + + )} + { + if (!selection) { + return; + } + setInternalDate(selection); + if (!stay_open_on_select) { + setIsCalendarOpen(false); } }} - > - {with_full_screen_portal && ( - - )} - { - if (!selection) { - return; - } - setInternalDate(selection); - if (!stay_open_on_select) { - setIsCalendarOpen(false); - } - }} - /> - - - -
- + /> + + +
+
); }; From 773b60a30fdb9814fe629a701959dbc6123f63f0 Mon Sep 17 00:00:00 2001 From: AnnMarueW Date: Tue, 19 May 2026 10:09:06 -0700 Subject: [PATCH 276/297] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13c0fc585b..6f23d8401a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). - [#3740](https://github.com/plotly/dash/pull/3740) Fix cannot tab into dropdowns in Safari - [#2462](https://github.com/plotly/dash/issues/2462) Allow `MATCH` in `Input`/`State` when the callback's `Output` has no wildcards (fixed-id Output, no Output, or `ALL`-only wildcard Output). `ALLSMALLER` still requires a corresponding `MATCH` in an Output. - [#3759](https://github.com/plotly/dash/pull/3759) Fix the issue where `Patch` objects cannot be updated via `set_props()` in `websocket` callback. Fix [#3742](https://github.com/plotly/dash/issues/3742) +- [#3789](https://github.com/plotly/dash/pull/3789) Fixed extra wrapper in `DatePickerRange` and `DatePickerSingle` causing styling and layout issues. ## [4.2.0rc3] - 2026-05-12 From 4538d66066985cfb50afcaeaef2cf403fd96469c Mon Sep 17 00:00:00 2001 From: philippe Date: Tue, 19 May 2026 13:40:14 -0400 Subject: [PATCH 277/297] address review comments --- .../src/MessageRouter.ts | 50 +++++++++++-------- .../src/WebSocketManager.ts | 34 ++++++++++--- @plotly/dash-websocket-worker/src/types.ts | 5 +- dash/backends/ws.py | 10 ++-- .../src/observers/websocketObserver.ts | 4 +- tests/websocket/test_ws_props.py | 42 ++++++++++++++++ 6 files changed, 109 insertions(+), 36 deletions(-) diff --git a/@plotly/dash-websocket-worker/src/MessageRouter.ts b/@plotly/dash-websocket-worker/src/MessageRouter.ts index 09cc9fd4fa..157da4fcfc 100644 --- a/@plotly/dash-websocket-worker/src/MessageRouter.ts +++ b/@plotly/dash-websocket-worker/src/MessageRouter.ts @@ -70,7 +70,7 @@ export class MessageRouter { public handleServerMessage(message: unknown): void { // Handle batched messages (array of messages) if (Array.isArray(message)) { - this.handleBatchedMessages(message); + this.handleBatchedMessages(message as WorkerMessage[]); return; } @@ -102,26 +102,32 @@ export class MessageRouter { /** * Handle a batch of messages from the server. * Groups set_props by renderer and forwards as a single batch message. - * @param messages Array of messages + * + * Note: set_props messages are processed before other message types. + * This is intentional - batching groups all set_props for efficiency, + * and the relative order within set_props is preserved. + * + * @param messages Array of messages (may include server-only types like heartbeat_ack) */ - private handleBatchedMessages(messages: unknown[]): void { + private handleBatchedMessages(messages: WorkerMessage[]): void { // Group set_props by renderer, keep others separate const setPropsPayloadsByRenderer: Map = new Map(); const otherMessages: WorkerMessage[] = []; - for (const message of messages) { - const msg = message as WorkerMessage; - // Skip heartbeat_ack - already handled by WebSocketManager - if ((msg as any).type === 'heartbeat_ack') { + for (const msg of messages) { + // Skip heartbeat_ack - server-only type, already handled by WebSocketManager + if (msg.type === WorkerMessageType.HEARTBEAT_ACK) { continue; } if (msg.type === WorkerMessageType.SET_PROPS) { const setPropsMsg = msg as SetPropsMessage; const rendererId = setPropsMsg.rendererId; - if (!setPropsPayloadsByRenderer.has(rendererId)) { - setPropsPayloadsByRenderer.set(rendererId, []); + const existing = setPropsPayloadsByRenderer.get(rendererId); + if (existing) { + existing.push(setPropsMsg.payload); + } else { + setPropsPayloadsByRenderer.set(rendererId, [setPropsMsg.payload]); } - setPropsPayloadsByRenderer.get(rendererId)!.push(setPropsMsg.payload); } else { otherMessages.push(msg); } @@ -130,17 +136,19 @@ export class MessageRouter { // Forward batched set_props to each renderer for (const [rendererId, payloads] of setPropsPayloadsByRenderer) { const port = this.renderers.get(rendererId); - if (port) { - try { - port.postMessage({ - type: WorkerMessageType.SET_PROPS_BATCH, - rendererId, - payload: payloads - }); - } catch (error) { - console.warn(`Failed to forward batch to renderer ${rendererId}, removing`); - this.renderers.delete(rendererId); - } + if (!port) { + console.warn(`Renderer ${rendererId} not found for batch, skipping`); + continue; + } + try { + port.postMessage({ + type: WorkerMessageType.SET_PROPS_BATCH, + rendererId, + payload: payloads + }); + } catch (error) { + console.warn(`Failed to forward batch to renderer ${rendererId}, removing`); + this.renderers.delete(rendererId); } } diff --git a/@plotly/dash-websocket-worker/src/WebSocketManager.ts b/@plotly/dash-websocket-worker/src/WebSocketManager.ts index 6deae1d6ca..d96a0d8e68 100644 --- a/@plotly/dash-websocket-worker/src/WebSocketManager.ts +++ b/@plotly/dash-websocket-worker/src/WebSocketManager.ts @@ -1,3 +1,12 @@ +/** + * Message received from the server. + * Can be a WorkerMessage or a heartbeat_ack. + */ +interface ServerMessage { + type: string; + [key: string]: unknown; +} + /** * Configuration options for WebSocket connection. */ @@ -193,20 +202,29 @@ export class WebSocketManager { private handleMessage(event: MessageEvent): void { try { - const data = JSON.parse(event.data); + const data: ServerMessage | ServerMessage[] = JSON.parse(event.data); // Handle batched messages - check for heartbeat_ack in the batch if (Array.isArray(data)) { + let hasHeartbeatAck = false; + let hasOtherMessages = false; for (const msg of data) { - if (msg && msg.type === 'heartbeat_ack') { - this.clearHeartbeatTimeout(); - break; + if (msg.type === 'heartbeat_ack') { + hasHeartbeatAck = true; + } else { + hasOtherMessages = true; } } - // Track activity and forward batch for processing - this.lastActivityTime = Date.now(); - if (this.onMessage) { - this.onMessage(data); + if (hasHeartbeatAck) { + this.clearHeartbeatTimeout(); + } + // Only track activity if there are non-heartbeat messages + // This matches the single-message behavior + if (hasOtherMessages) { + this.lastActivityTime = Date.now(); + if (this.onMessage) { + this.onMessage(data); + } } return; } diff --git a/@plotly/dash-websocket-worker/src/types.ts b/@plotly/dash-websocket-worker/src/types.ts index 0bf06d68b1..5d1ff80bf0 100644 --- a/@plotly/dash-websocket-worker/src/types.ts +++ b/@plotly/dash-websocket-worker/src/types.ts @@ -15,7 +15,10 @@ export enum WorkerMessageType { SET_PROPS = 'set_props', SET_PROPS_BATCH = 'set_props_batch', GET_PROPS_REQUEST = 'get_props_request', - ERROR = 'error' + ERROR = 'error', + + // Server -> Worker (not forwarded to renderer) + HEARTBEAT_ACK = 'heartbeat_ack' } /** diff --git a/dash/backends/ws.py b/dash/backends/ws.py index 8730ee009a..f44913d873 100644 --- a/dash/backends/ws.py +++ b/dash/backends/ws.py @@ -202,10 +202,11 @@ async def run_ws_sender( Args: send_text: Async function to send text data over WebSocket outbound_queue: janus.Queue instance for receiving messages (strings) - batch_delay: Time in seconds to wait for additional messages (default: 5ms) + batch_delay: Time in seconds to wait for additional messages (default: 5ms). + Set to 0 to disable batching and send messages immediately. """ q = outbound_queue.async_q - messages: list = [] + messages: list[str] = [] try: while True: # Wait indefinitely for first message, then use timeout for batching @@ -221,7 +222,10 @@ async def run_ws_sender( await _send_batched(send_text, messages) messages = [] continue - messages.append(msg) + if not batch_delay: + await send_text(msg) + else: + messages.append(msg) except asyncio.TimeoutError: await _send_batched(send_text, messages) messages = [] diff --git a/dash/dash-renderer/src/observers/websocketObserver.ts b/dash/dash-renderer/src/observers/websocketObserver.ts index f01cb2928c..daa3238773 100644 --- a/dash/dash-renderer/src/observers/websocketObserver.ts +++ b/dash/dash-renderer/src/observers/websocketObserver.ts @@ -131,9 +131,7 @@ export async function initializeWebSocket( }; // Handle single SET_PROPS message - workerClient.onSetProps = (payload: SetPropsPayload) => { - processSetProps(payload); - }; + workerClient.onSetProps = processSetProps; // Handle batched SET_PROPS_BATCH message workerClient.onSetPropsBatch = (payloads: SetPropsPayload[]) => { diff --git a/tests/websocket/test_ws_props.py b/tests/websocket/test_ws_props.py index a86402954d..88af40f99f 100644 --- a/tests/websocket/test_ws_props.py +++ b/tests/websocket/test_ws_props.py @@ -399,6 +399,48 @@ async def update_list(n): assert dash_duo.get_logs() == [] +def test_ws047b_set_props_batch_many_updates(dash_duo): + """Test that many rapid set_props calls are batched and all arrive correctly.""" + app = Dash(__name__, backend="fastapi", websocket_callbacks=True) + + app.layout = html.Div( + [ + html.Button("Update Many", id="btn"), + *[html.Div("0", id=f"output-{i}") for i in range(10)], + html.Div(id="result"), + ] + ) + + @app.callback(Output("result", "children"), Input("btn", "n_clicks")) + async def update_many(n): + if not n: + raise PreventUpdate + + # Rapid-fire set_props calls without any await between them + # These should be batched together by the server + for i in range(10): + set_props(f"output-{i}", {"children": f"{n}"}) + + return f"Done {n}" + + dash_duo.start_server(app) + + dash_duo.find_element("#btn").click() + + # All outputs should be updated + dash_duo.wait_for_text_to_equal("#result", "Done 1", timeout=10) + for i in range(10): + dash_duo.wait_for_text_to_equal(f"#output-{i}", "1") + + # Click again to verify batching works consistently + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal("#result", "Done 2", timeout=10) + for i in range(10): + dash_duo.wait_for_text_to_equal(f"#output-{i}", "2") + + assert dash_duo.get_logs() == [] + + def test_ws048_set_props_dynamic_match_callback(dash_duo): """Test set_props injecting components with pattern-matching IDs that trigger MATCH callbacks.""" app = Dash(__name__, backend="fastapi", websocket_callbacks=True) From ea718629aae0b989631a061730d7495dd0c4c021 Mon Sep 17 00:00:00 2001 From: Philippe Duval Date: Tue, 19 May 2026 13:41:51 -0400 Subject: [PATCH 278/297] Update components/dash-core-components/src/fragments/Graph.react.js Co-authored-by: Cameron DeCoster --- components/dash-core-components/src/fragments/Graph.react.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dash-core-components/src/fragments/Graph.react.js b/components/dash-core-components/src/fragments/Graph.react.js index fbe477fd37..875ae70253 100644 --- a/components/dash-core-components/src/fragments/Graph.react.js +++ b/components/dash-core-components/src/fragments/Graph.react.js @@ -457,7 +457,7 @@ class PlotlyGraph extends Component { key => key === 'shapes' || key.startsWith('shapes[') ); if (hasShapeChanges) { - const {figure} = this.props; + const {figure = {}} = this.props; const currentShapes = figure?.layout?.shapes; const newShapes = gd.layout.shapes; if (!equals(currentShapes, newShapes)) { From c35799043fdc550a505fc31b25558216fa2d406a Mon Sep 17 00:00:00 2001 From: philippe Date: Tue, 19 May 2026 14:38:15 -0400 Subject: [PATCH 279/297] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13c0fc585b..3f16cf6e80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## [UNRELEASED] ## Added +- [#3783](https://github.com/plotly/dash/pull/3783) Add batching/debouncing for websocket `set_props` messages to reduce lag when updating multiple components in a loop. Configurable via `websocket_batch_delay` (default 5ms, set to 0 to disable). - [#3669](https://github.com/plotly/dash/pull/3669) Selection for DataTable cleared with custom action settings - [#3680](https://github.com/plotly/dash/pull/3680) Added `search_order` prop to `Dropdown` to allow users to preserve original option order during search - Added `csrf_token_name` and `csrf_header_name` config options to allow configuring the CSRF cookie and header names. Fixes [#729](https://github.com/plotly/dash/issues/729) From 7afaac8d867499b366cc0fd1044f9e1136ccad0f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 May 2026 07:08:24 +0000 Subject: [PATCH 280/297] Bump serialize-javascript and terser-webpack-plugin Removes [serialize-javascript](https://github.com/yahoo/serialize-javascript). It's no longer used after updating ancestor dependency [terser-webpack-plugin](https://github.com/webpack/minimizer-webpack-plugin). These dependencies need to be updated together. Removes `serialize-javascript` Updates `terser-webpack-plugin` from 5.3.14 to 5.6.0 - [Release notes](https://github.com/webpack/minimizer-webpack-plugin/releases) - [Changelog](https://github.com/webpack/minimizer-webpack-plugin/blob/main/CHANGELOG.md) - [Commits](https://github.com/webpack/minimizer-webpack-plugin/compare/v5.3.14...v5.6.0) --- updated-dependencies: - dependency-name: serialize-javascript dependency-version: dependency-type: indirect - dependency-name: terser-webpack-plugin dependency-version: 5.6.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .../dash-component-plugins/package-lock.json | 77 ++++++++----------- 1 file changed, 33 insertions(+), 44 deletions(-) diff --git a/@plotly/dash-component-plugins/package-lock.json b/@plotly/dash-component-plugins/package-lock.json index 56e714d672..faf3958494 100644 --- a/@plotly/dash-component-plugins/package-lock.json +++ b/@plotly/dash-component-plugins/package-lock.json @@ -2873,15 +2873,6 @@ "node": ">=6" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/react": { "version": "16.14.0", "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", @@ -3071,15 +3062,6 @@ "semver": "bin/semver.js" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -3187,15 +3169,14 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.14", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", - "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-Eum+5ajkaOhf5KbM26osvv21kLD7BaGqQ1UA4Ami4arYwylmGUQTgHFpHDdmJod1q4QXa66p0to/FBKID+J1vA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "engines": { @@ -3209,12 +3190,39 @@ "webpack": "^5.1.0" }, "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, "@swc/core": { "optional": true }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, "esbuild": { "optional": true }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, "uglify-js": { "optional": true } @@ -5633,15 +5641,6 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, "react": { "version": "16.14.0", "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", @@ -5790,15 +5789,6 @@ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true }, - "serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, "shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -5873,15 +5863,14 @@ } }, "terser-webpack-plugin": { - "version": "5.3.14", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", - "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-Eum+5ajkaOhf5KbM26osvv21kLD7BaGqQ1UA4Ami4arYwylmGUQTgHFpHDdmJod1q4QXa66p0to/FBKID+J1vA==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "dependencies": { From c26542491756b8bc6d053cfc41ffe406931126ee Mon Sep 17 00:00:00 2001 From: philippe Date: Tue, 26 May 2026 16:52:49 -0400 Subject: [PATCH 281/297] improved websocket connection management --- .../src/WebSocketManager.ts | 8 + @plotly/dash-websocket-worker/src/types.ts | 1 + @plotly/dash-websocket-worker/src/worker.ts | 7 + dash/backends/_fastapi.py | 32 +- dash/backends/_quart.py | 32 +- dash/backends/_ws_registry.py | 166 +++++++ dash/backends/ws.py | 157 ++++-- .../src/observers/websocketObserver.ts | 60 +++ dash/dash-renderer/src/utils/workerClient.ts | 14 + tests/websocket/test_ws_reconnect.py | 449 ++++++++++++++++++ 10 files changed, 879 insertions(+), 47 deletions(-) create mode 100644 dash/backends/_ws_registry.py create mode 100644 tests/websocket/test_ws_reconnect.py diff --git a/@plotly/dash-websocket-worker/src/WebSocketManager.ts b/@plotly/dash-websocket-worker/src/WebSocketManager.ts index d96a0d8e68..942917f075 100644 --- a/@plotly/dash-websocket-worker/src/WebSocketManager.ts +++ b/@plotly/dash-websocket-worker/src/WebSocketManager.ts @@ -144,6 +144,14 @@ export class WebSocketManager { return this.ws !== null && this.ws.readyState === WebSocket.OPEN; } + /** + * Reset the activity timer. + * Call this when a tab becomes visible to prevent inactivity timeout. + */ + public resetActivity(): void { + this.lastActivityTime = Date.now(); + } + private createConnection(): void { if (!this.serverUrl) { return; diff --git a/@plotly/dash-websocket-worker/src/types.ts b/@plotly/dash-websocket-worker/src/types.ts index 5d1ff80bf0..3d88af068a 100644 --- a/@plotly/dash-websocket-worker/src/types.ts +++ b/@plotly/dash-websocket-worker/src/types.ts @@ -7,6 +7,7 @@ export enum WorkerMessageType { DISCONNECT = 'disconnect', CALLBACK_REQUEST = 'callback_request', GET_PROPS_RESPONSE = 'get_props_response', + TAB_VISIBLE = 'tab_visible', // Worker -> Renderer CONNECTED = 'connected', diff --git a/@plotly/dash-websocket-worker/src/worker.ts b/@plotly/dash-websocket-worker/src/worker.ts index 0e68f0b09a..e28d0c1583 100644 --- a/@plotly/dash-websocket-worker/src/worker.ts +++ b/@plotly/dash-websocket-worker/src/worker.ts @@ -122,6 +122,13 @@ self.onconnect = (event: MessageEvent) => { break; } + case WorkerMessageType.TAB_VISIBLE: { + // Reset activity timer when tab becomes visible + // This prevents inactivity timeout while user is viewing the tab + wsManager.resetActivity(); + break; + } + default: // Forward other messages through the router router.handleRendererMessage(message.rendererId, message); diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index c46fb4ffc5..b619c040c9 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -50,6 +50,7 @@ SHUTDOWN_SIGNAL, DISCONNECTED, ) +from ._ws_registry import ActiveCallbackRegistry from ._utils import format_traceback_html if TYPE_CHECKING: # pragma: no cover - typing only @@ -677,6 +678,12 @@ def serve_websocket_callback(self, dash_app: "Dash"): dash_app, "_websocket_allowed_origins", [] ) # pylint: disable=protected-access + # Initialize registry on dash_app if not present + # pylint: disable=protected-access + if not hasattr(dash_app, "_ws_callback_registry"): + dash_app._ws_callback_registry = ActiveCallbackRegistry() + registry: ActiveCallbackRegistry = dash_app._ws_callback_registry + def validate_origin(origin: str | None, host: str | None) -> str | None: """Validate WebSocket origin. Returns error message or None if valid.""" if not origin: @@ -723,6 +730,8 @@ async def websocket_handler(websocket: WebSocket): executor = self.get_callback_executor() # Track pending callback futures pending_callbacks: Dict[str, concurrent.futures.Future] = {} + # Track current renderer ID for this connection + current_renderer_id: str | None = None # Start sender task to drain outbound queue (sends pre-serialized text) # pylint: disable=protected-access @@ -753,6 +762,22 @@ async def websocket_handler(websocket: WebSocket): renderer_id = message.get("rendererId", "") payload = message.get("payload", {}) + # Update current renderer ID for cleanup + current_renderer_id = renderer_id + + # Adopt connection for this renderer (allows reconnection) + # Called for every callback to ensure registry entry exists + # (entry may have been cleaned up after previous callback) + registry.adopt_connection( + renderer_id, + outbound_queue, + pending_get_props, + shutdown_event, + ) + + # Register this callback with the registry + registry.register_callback(renderer_id) + # Validate that the callback is allowed to use WebSocket transport # pylint: disable=protected-access _validate.validate_websocket_callback_request( @@ -761,12 +786,13 @@ async def websocket_handler(websocket: WebSocket): dash_app._websocket_callbacks, ) - # Create WebSocket callback instance with outbound queue + # Create WebSocket callback instance with registry ws_cb = DashWebsocketCallback( pending_get_props, renderer_id, outbound_queue, shutdown_event, + registry=registry, ) # Submit callback to executor @@ -786,6 +812,7 @@ async def websocket_handler(websocket: WebSocket): request_id, renderer_id, shutdown_event, + registry=registry, ) ) pending_callbacks[request_id] = future @@ -821,6 +848,9 @@ async def websocket_handler(websocket: WebSocket): # Cancel any pending futures for f in pending_callbacks.values(): f.cancel() + # Cleanup registry entry if no active callbacks + if current_renderer_id is not None: + registry.cleanup_renderer(current_renderer_id) self.server.add_api_websocket_route(ws_path, websocket_handler) diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 881fd6466f..31d9668d36 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -55,6 +55,7 @@ SHUTDOWN_SIGNAL, DISCONNECTED, ) +from ._ws_registry import ActiveCallbackRegistry from ._utils import format_traceback_html if TYPE_CHECKING: @@ -521,6 +522,12 @@ def serve_websocket_callback(self, dash_app: "Dash"): # pylint: disable=protected-access allowed_origins = getattr(dash_app, "_websocket_allowed_origins", []) + # Initialize registry on dash_app if not present + # pylint: disable=protected-access + if not hasattr(dash_app, "_ws_callback_registry"): + dash_app._ws_callback_registry = ActiveCallbackRegistry() + registry: ActiveCallbackRegistry = dash_app._ws_callback_registry + @self.server.websocket(ws_path) async def websocket_handler(): # pylint: disable=too-many-branches ws = websocket @@ -564,6 +571,8 @@ async def websocket_handler(): # pylint: disable=too-many-branches executor = self.get_callback_executor() # Track pending callback futures pending_callbacks: Dict[str, concurrent.futures.Future] = {} + # Track current renderer ID for this connection + current_renderer_id: str | None = None # Start sender task to drain outbound queue (sends pre-serialized text) # pylint: disable=protected-access @@ -601,6 +610,22 @@ async def websocket_handler(): # pylint: disable=too-many-branches renderer_id = message.get("rendererId", "") payload = message.get("payload", {}) + # Update current renderer ID for cleanup + current_renderer_id = renderer_id + + # Adopt connection for this renderer (allows reconnection) + # Called for every callback to ensure registry entry exists + # (entry may have been cleaned up after previous callback) + registry.adopt_connection( + renderer_id, + outbound_queue, + pending_get_props, + connection_shutdown_event, + ) + + # Register this callback with the registry + registry.register_callback(renderer_id) + # Validate that the callback is allowed to use WebSocket transport # pylint: disable=protected-access _validate.validate_websocket_callback_request( @@ -609,12 +634,13 @@ async def websocket_handler(): # pylint: disable=too-many-branches dash_app._websocket_callbacks, ) - # Create WebSocket callback instance with outbound queue + # Create WebSocket callback instance with registry ws_cb = DashWebsocketCallback( pending_get_props, renderer_id, outbound_queue, connection_shutdown_event, + registry=registry, ) # Submit callback to executor @@ -634,6 +660,7 @@ async def websocket_handler(): # pylint: disable=too-many-branches request_id, renderer_id, connection_shutdown_event, + registry=registry, ) ) pending_callbacks[request_id] = future @@ -672,6 +699,9 @@ async def websocket_handler(): # pylint: disable=too-many-branches # Cancel any pending futures for f in pending_callbacks.values(): f.cancel() + # Cleanup registry entry if no active callbacks + if current_renderer_id is not None: + registry.cleanup_renderer(current_renderer_id) class QuartRequestAdapter(RequestAdapter): diff --git a/dash/backends/_ws_registry.py b/dash/backends/_ws_registry.py new file mode 100644 index 0000000000..4ab1132d6a --- /dev/null +++ b/dash/backends/_ws_registry.py @@ -0,0 +1,166 @@ +"""WebSocket callback registry for handling reconnections. + +This module provides a registry that tracks active callbacks per renderer, +allowing callbacks to persist across WebSocket reconnections. +""" + +from __future__ import annotations + +import threading +from dataclasses import dataclass, field +from typing import TYPE_CHECKING, Any, Dict, Optional + +if TYPE_CHECKING: + import queue + import janus + + +@dataclass +class RendererState: + """State for a single renderer's WebSocket connection.""" + + outbound_queue: "janus.Queue[str]" + pending_get_props: Dict[str, "queue.Queue[Any]"] + shutdown_event: threading.Event + active_callback_count: int = 0 + lock: threading.Lock = field(default_factory=threading.Lock) + + +class ActiveCallbackRegistry: + """Registry for active WebSocket callbacks that persists across reconnections. + + When a WebSocket disconnects and reconnects, callbacks that are still running + can "adopt" the new connection's queues to continue sending updates. + + Thread-safe for access from both the main event loop and worker threads. + """ + + def __init__(self) -> None: + self._renderers: Dict[str, RendererState] = {} + self._lock = threading.Lock() + + def adopt_connection( + self, + renderer_id: str, + outbound_queue: "janus.Queue[str]", + pending_get_props: Dict[str, "queue.Queue[Any]"], + shutdown_event: threading.Event, + ) -> None: + """Associate new connection with existing callbacks for this renderer. + + When a WebSocket reconnects, this method updates the queues and shutdown + event so that running callbacks can use the new connection. + + Args: + renderer_id: The renderer ID for this connection + outbound_queue: janus.Queue for sending messages + pending_get_props: Dict to track pending get_props requests + shutdown_event: Event signaling connection closure + """ + with self._lock: + if renderer_id in self._renderers: + state = self._renderers[renderer_id] + with state.lock: + state.outbound_queue = outbound_queue + state.pending_get_props = pending_get_props + state.shutdown_event = shutdown_event + else: + self._renderers[renderer_id] = RendererState( + outbound_queue=outbound_queue, + pending_get_props=pending_get_props, + shutdown_event=shutdown_event, + active_callback_count=0, + ) + + def register_callback(self, renderer_id: str) -> None: + """Register a new active callback for this renderer. + + Args: + renderer_id: The renderer ID + """ + with self._lock: + if renderer_id in self._renderers: + state = self._renderers[renderer_id] + with state.lock: + state.active_callback_count += 1 + + def unregister_callback(self, renderer_id: str) -> None: + """Unregister a completed callback for this renderer. + + If no active callbacks remain, the renderer state is cleaned up. + + Args: + renderer_id: The renderer ID + """ + with self._lock: + if renderer_id in self._renderers: + state = self._renderers[renderer_id] + with state.lock: + state.active_callback_count -= 1 + if state.active_callback_count <= 0: + del self._renderers[renderer_id] + + def get_queue(self, renderer_id: str) -> Optional["janus.Queue[str]"]: + """Get current outbound queue for renderer (thread-safe). + + Args: + renderer_id: The renderer ID + + Returns: + The current outbound queue, or None if renderer not found + """ + with self._lock: + state = self._renderers.get(renderer_id) + if state is None: + return None + with state.lock: + return state.outbound_queue + + def get_pending_get_props( + self, renderer_id: str + ) -> Optional[Dict[str, "queue.Queue[Any]"]]: + """Get current pending_get_props dict for renderer (thread-safe). + + Args: + renderer_id: The renderer ID + + Returns: + The current pending_get_props dict, or None if renderer not found + """ + with self._lock: + state = self._renderers.get(renderer_id) + if state is None: + return None + with state.lock: + return state.pending_get_props + + def is_shutdown(self, renderer_id: str) -> bool: + """Check if current connection is shutdown. + + Args: + renderer_id: The renderer ID + + Returns: + True if shutdown event is set or renderer not found, False otherwise + """ + with self._lock: + state = self._renderers.get(renderer_id) + if state is None: + return True + with state.lock: + return state.shutdown_event.is_set() + + def cleanup_renderer(self, renderer_id: str) -> None: + """Clean up renderer state when connection closes. + + Only removes if no active callbacks remain. + + Args: + renderer_id: The renderer ID to clean up + """ + with self._lock: + state = self._renderers.get(renderer_id) + if state is not None: + with state.lock: + if state.active_callback_count <= 0: + del self._renderers[renderer_id] diff --git a/dash/backends/ws.py b/dash/backends/ws.py index f44913d873..adebdf2c4a 100644 --- a/dash/backends/ws.py +++ b/dash/backends/ws.py @@ -25,6 +25,7 @@ if TYPE_CHECKING: import dash from .base_server import ResponseAdapter + from ._ws_registry import ActiveCallbackRegistry SHUTDOWN_SIGNAL = "__shutdown__" @@ -41,6 +42,10 @@ class DashWebsocketCallback: Uses janus.Queue for outbound messages (serialized with to_json) and queue.Queue for get_props responses, enabling thread-safe communication between worker threads and the main event loop. + + Supports two modes: + 1. Registry mode: Uses ActiveCallbackRegistry to allow queue adoption on reconnect + 2. Direct mode: Uses direct queue references (legacy, for backwards compatibility) """ def __init__( @@ -49,6 +54,7 @@ def __init__( renderer_id: str, outbound_queue: janus.Queue[str], shutdown_event: "threading.Event", + registry: "ActiveCallbackRegistry | None" = None, ): """Initialize the WebSocket callback interface. @@ -58,26 +64,46 @@ def __init__( renderer_id: The renderer ID for routing messages back to the correct client outbound_queue: janus.Queue for thread-safe outbound messaging. shutdown_event: Event signaling the websocket connection has closed. + registry: Optional registry for handling reconnections. If provided, + the callback will use the registry to get current queues, allowing + it to survive reconnections. """ self._pending_get_props = pending_get_props self._renderer_id = renderer_id self._outbound_queue = outbound_queue self._shutdown_event = shutdown_event + self._registry = registry @property def is_shutdown(self) -> bool: """Check if the websocket connection has been shut down.""" + if self._registry is not None: + return self._registry.is_shutdown(self._renderer_id) return self._shutdown_event.is_set() + def _get_outbound_queue(self) -> janus.Queue[str] | None: + """Get the current outbound queue (may be updated on reconnect).""" + if self._registry is not None: + return self._registry.get_queue(self._renderer_id) + return self._outbound_queue + + def _get_pending_get_props(self) -> Dict[str, queue.Queue[Any]] | None: + """Get the current pending_get_props dict (may be updated on reconnect).""" + if self._registry is not None: + return self._registry.get_pending_get_props(self._renderer_id) + return self._pending_get_props + def _queue_message(self, msg: dict) -> None: """Serialize and queue message for sending (thread-safe, non-blocking). Uses to_json for proper serialization of Dash components. Does nothing if the connection has been shut down. """ - if self._shutdown_event.is_set(): + if self.is_shutdown: return - self._outbound_queue.sync_q.put_nowait(cast(str, to_json(msg))) + outbound_queue = self._get_outbound_queue() + if outbound_queue is not None: + outbound_queue.sync_q.put_nowait(cast(str, to_json(msg))) async def set_prop(self, component_id: str, prop_name: str, value: Any) -> None: """Send immediate prop update to the client via WebSocket. @@ -115,7 +141,11 @@ async def get_prop( WebsocketDisconnected: If the websocket connection has been closed. TimeoutError: If the response doesn't arrive within the timeout. """ - if self._shutdown_event.is_set(): + if self.is_shutdown: + raise WebsocketDisconnected() + + pending_get_props = self._get_pending_get_props() + if pending_get_props is None: raise WebsocketDisconnected() request_id = str(uuid.uuid4()) @@ -128,7 +158,7 @@ async def get_prop( # Use standard queue.Queue for response response_queue: queue.Queue = queue.Queue() - self._pending_get_props[request_id] = response_queue + pending_get_props[request_id] = response_queue # Queue the outbound request via janus sync interface self._queue_message(msg) @@ -146,7 +176,10 @@ async def get_prop( f"Timeout waiting for {component_id}.{prop_name}" ) from exc finally: - self._pending_get_props.pop(request_id, None) + # Get fresh reference in case of reconnection + current_pending = self._get_pending_get_props() + if current_pending is not None: + current_pending.pop(request_id, None) def create_ws_context( @@ -219,21 +252,26 @@ async def run_ws_sender( return if msg == FLUSH_SIGNAL: if messages: - await _send_batched(send_text, messages) + if not await _send_batched(send_text, messages): + return # Connection closed messages = [] continue if not batch_delay: - await send_text(msg) + try: + await send_text(msg) + except Exception: # WebSocketDisconnect, RuntimeError, etc. + return # Connection closed else: messages.append(msg) except asyncio.TimeoutError: - await _send_batched(send_text, messages) + if not await _send_batched(send_text, messages): + return # Connection closed messages = [] except asyncio.CancelledError: pass -async def _send_batched(send_text: Callable[[str], Any], messages: list) -> None: +async def _send_batched(send_text: Callable[[str], Any], messages: list) -> bool: """Send messages as a batch. Single messages are sent as-is. Multiple messages are wrapped @@ -242,12 +280,19 @@ async def _send_batched(send_text: Callable[[str], Any], messages: list) -> None Args: send_text: Async function to send text data over WebSocket messages: List of pre-serialized JSON message strings + + Returns: + True if send succeeded, False if connection was closed """ - if len(messages) == 1: - await send_text(messages[0]) - else: - # Wrap in array: "[msg1,msg2,msg3]" - await send_text("[" + ",".join(messages) + "]") + try: + if len(messages) == 1: + await send_text(messages[0]) + else: + # Wrap in array: "[msg1,msg2,msg3]" + await send_text("[" + ",".join(messages) + "]") + return True + except Exception: # WebSocketDisconnect, RuntimeError, etc. + return False # Connection closed, cleanup handled by main loop def make_callback_done_handler( @@ -256,6 +301,7 @@ def make_callback_done_handler( request_id: str, renderer_id: str, shutdown_event: threading.Event, + registry: "ActiveCallbackRegistry | None" = None, ) -> Callable[[concurrent.futures.Future], None]: """Create a done callback handler for executor futures. @@ -268,52 +314,73 @@ def make_callback_done_handler( request_id: The request ID for the callback response renderer_id: The renderer ID for routing the response shutdown_event: Event signaling the websocket connection has closed. + registry: Optional registry for managing callback lifecycle. Returns: A callback function suitable for Future.add_done_callback() """ + def _is_shutdown() -> bool: + """Check if connection is shutdown (registry-aware).""" + if registry is not None: + return registry.is_shutdown(renderer_id) + return shutdown_event.is_set() + + def _get_queue() -> janus.Queue[str] | None: + """Get current outbound queue (may change on reconnect).""" + if registry is not None: + return registry.get_queue(renderer_id) + return outbound_queue + def on_done(f: concurrent.futures.Future) -> None: try: - if shutdown_event.is_set(): + if _is_shutdown(): return result = f.result() - outbound_queue.sync_q.put_nowait( - cast( - str, - to_json( - { - "type": "callback_response", - "rendererId": renderer_id, - "requestId": request_id, - "payload": result, - } - ), + current_queue = _get_queue() + if current_queue is not None: + current_queue.sync_q.put_nowait( + cast( + str, + to_json( + { + "type": "callback_response", + "rendererId": renderer_id, + "requestId": request_id, + "payload": result, + } + ), + ) ) - ) except Exception as e: # pylint: disable=broad-exception-caught - if shutdown_event.is_set(): + if _is_shutdown(): return - outbound_queue.sync_q.put_nowait( - cast( - str, - to_json( - { - "type": "callback_response", - "rendererId": renderer_id, - "requestId": request_id, - "payload": { - "status": "error", - "message": str(e), - }, - } - ), + current_queue = _get_queue() + if current_queue is not None: + current_queue.sync_q.put_nowait( + cast( + str, + to_json( + { + "type": "callback_response", + "rendererId": renderer_id, + "requestId": request_id, + "payload": { + "status": "error", + "message": str(e), + }, + } + ), + ) ) - ) finally: pending_callbacks.pop(request_id, None) - if not shutdown_event.is_set(): - outbound_queue.sync_q.put_nowait(FLUSH_SIGNAL) + if registry is not None: + registry.unregister_callback(renderer_id) + if not _is_shutdown(): + current_queue = _get_queue() + if current_queue is not None: + current_queue.sync_q.put_nowait(FLUSH_SIGNAL) return on_done diff --git a/dash/dash-renderer/src/observers/websocketObserver.ts b/dash/dash-renderer/src/observers/websocketObserver.ts index daa3238773..24dc5a39d4 100644 --- a/dash/dash-renderer/src/observers/websocketObserver.ts +++ b/dash/dash-renderer/src/observers/websocketObserver.ts @@ -18,6 +18,8 @@ import { GetPropsRequestPayload } from '../utils/workerClient'; import {DashConfig} from '../config'; +import {addRequestedCallbacks} from '../actions/callbacks'; +import {makeResolvedCallback, resolveDeps} from '../actions/dependencies_ts'; /** * Parse a component ID that may be a stringified JSON object. @@ -175,13 +177,53 @@ export async function initializeWebSocket( workerClient.sendGetPropsResponse(requestId, result); }; + // Track connection state for reconnection handling + let wasDisconnected = false; + // Handle connection events workerClient.onConnected = () => { console.log('[Dash] WebSocket connected'); + + // On reconnect (not initial connect), re-trigger persistent callbacks + if (wasDisconnected) { + console.log( + '[Dash] Reconnected - re-triggering persistent callbacks' + ); + const state = store.getState(); + const {graphs} = state; + + if (graphs?.callbacks) { + const persistentCallbacks = graphs.callbacks.reduce( + (acc: any[], cb: any) => { + // Only re-trigger no-output callbacks with no inputs + // These are the "persistent" callbacks that should restart + if (cb.noOutput && cb.inputs.length === 0) { + const resolved = makeResolvedCallback( + cb, + resolveDeps(), + '' + ); + resolved.initialCall = true; + acc.push(resolved); + } + return acc; + }, + [] + ); + + if (persistentCallbacks.length > 0) { + console.log( + `[Dash] Re-triggering ${persistentCallbacks.length} persistent callback(s)` + ); + store.dispatch(addRequestedCallbacks(persistentCallbacks)); + } + } + } }; workerClient.onDisconnected = (reason?: string) => { console.log(`[Dash] WebSocket disconnected: ${reason}`); + wasDisconnected = true; }; workerClient.onError = (message: string, code?: string) => { @@ -201,6 +243,24 @@ export async function initializeWebSocket( } catch (error) { console.error('[Dash] Failed to connect to WebSocket worker:', error); } + + // Handle tab visibility changes + document.addEventListener('visibilitychange', () => { + if (document.visibilityState === 'visible') { + if (workerClient.connected) { + // Tab visible and connected - reset inactivity timer + workerClient.notifyTabVisible(); + } else { + // Tab visible but disconnected - reconnect + console.log('[Dash] Tab visible, reconnecting WebSocket...'); + workerClient + .ensureConnected(config) + .catch(err => + console.error('[Dash] Failed to reconnect:', err) + ); + } + } + }); } /** diff --git a/dash/dash-renderer/src/utils/workerClient.ts b/dash/dash-renderer/src/utils/workerClient.ts index 01584bf20c..ebfb1223eb 100644 --- a/dash/dash-renderer/src/utils/workerClient.ts +++ b/dash/dash-renderer/src/utils/workerClient.ts @@ -10,6 +10,7 @@ export enum WorkerMessageType { DISCONNECT = 'disconnect', CALLBACK_REQUEST = 'callback_request', GET_PROPS_RESPONSE = 'get_props_response', + TAB_VISIBLE = 'tab_visible', CONNECTED = 'connected', DISCONNECTED = 'disconnected', CALLBACK_RESPONSE = 'callback_response', @@ -251,6 +252,19 @@ class WorkerClient { return this.isConnected; } + /** + * Notify the worker that the tab is now visible. + * This resets the inactivity timer to prevent timeout while user is viewing. + */ + public notifyTabVisible(): void { + if (this.worker && this.isConnected) { + this.worker.port.postMessage({ + type: WorkerMessageType.TAB_VISIBLE, + rendererId: this.rendererId + }); + } + } + private handleMessage(event: MessageEvent): void { const message = event.data; diff --git a/tests/websocket/test_ws_reconnect.py b/tests/websocket/test_ws_reconnect.py new file mode 100644 index 0000000000..64826ab1e6 --- /dev/null +++ b/tests/websocket/test_ws_reconnect.py @@ -0,0 +1,449 @@ +""" +WebSocket reconnection and disconnect handling tests. + +Tests: +- Callback continuity after WebSocket reconnection +- Registry tracks active callbacks correctly +- Disconnect handling doesn't cause error spam +- Long-running callbacks survive reconnection +""" + +import asyncio +import time +import threading + +from dash import Dash, html, Input, Output, set_props +from dash.backends._ws_registry import ActiveCallbackRegistry + + +class TestActiveCallbackRegistry: + """Unit tests for the ActiveCallbackRegistry class.""" + + def test_registry_adopt_creates_entry(self): + """Test that adopt_connection creates a new registry entry.""" + registry = ActiveCallbackRegistry() + + # Mock queue-like object + class MockQueue: + def __init__(self): + self.sync_q = None + + outbound_queue = MockQueue() + pending_get_props = {} + shutdown_event = threading.Event() + + registry.adopt_connection( + "renderer1", outbound_queue, pending_get_props, shutdown_event + ) + + assert registry.get_queue("renderer1") == outbound_queue + assert registry.get_pending_get_props("renderer1") == pending_get_props + assert not registry.is_shutdown("renderer1") + + def test_registry_callback_lifecycle(self): + """Test register/unregister callback with cleanup.""" + registry = ActiveCallbackRegistry() + + class MockQueue: + def __init__(self): + self.sync_q = None + + outbound_queue = MockQueue() + shutdown_event = threading.Event() + + registry.adopt_connection("renderer1", outbound_queue, {}, shutdown_event) + + # Register callback + registry.register_callback("renderer1") + assert not registry.is_shutdown("renderer1") + + # Unregister - should clean up entry since count becomes 0 + registry.unregister_callback("renderer1") + assert registry.is_shutdown("renderer1") # Returns True when not found + + def test_registry_multiple_callbacks(self): + """Test that multiple callbacks keep entry alive.""" + registry = ActiveCallbackRegistry() + + class MockQueue: + def __init__(self): + self.sync_q = None + + outbound_queue = MockQueue() + shutdown_event = threading.Event() + + registry.adopt_connection("renderer1", outbound_queue, {}, shutdown_event) + + # Register two callbacks + registry.register_callback("renderer1") + registry.register_callback("renderer1") + + # Unregister one - entry should still exist + registry.unregister_callback("renderer1") + assert not registry.is_shutdown("renderer1") + + # Unregister second - now should be cleaned up + registry.unregister_callback("renderer1") + assert registry.is_shutdown("renderer1") + + def test_registry_adopt_after_cleanup(self): + """Test that adopt_connection works after cleanup.""" + registry = ActiveCallbackRegistry() + + class MockQueue: + def __init__(self): + self.sync_q = None + + outbound_queue = MockQueue() + shutdown_event = threading.Event() + + # First connection + registry.adopt_connection("renderer1", outbound_queue, {}, shutdown_event) + registry.register_callback("renderer1") + registry.unregister_callback("renderer1") # Cleans up + + # Re-adopt after cleanup + registry.adopt_connection("renderer1", outbound_queue, {}, shutdown_event) + assert not registry.is_shutdown("renderer1") + + def test_registry_adopt_updates_existing(self): + """Test that adopt_connection updates queues for existing entry.""" + registry = ActiveCallbackRegistry() + + class MockQueue: + def __init__(self, name): + self.name = name + self.sync_q = None + + old_queue = MockQueue("old") + new_queue = MockQueue("new") + old_shutdown = threading.Event() + new_shutdown = threading.Event() + + registry.adopt_connection("renderer1", old_queue, {}, old_shutdown) + registry.register_callback("renderer1") # Keep entry alive + + assert registry.get_queue("renderer1").name == "old" + + # Simulate reconnection + registry.adopt_connection("renderer1", new_queue, {}, new_shutdown) + + assert registry.get_queue("renderer1").name == "new" + + def test_registry_shutdown_event_respected(self): + """Test that shutdown event is checked correctly.""" + registry = ActiveCallbackRegistry() + + class MockQueue: + def __init__(self): + self.sync_q = None + + outbound_queue = MockQueue() + shutdown_event = threading.Event() + + registry.adopt_connection("renderer1", outbound_queue, {}, shutdown_event) + + assert not registry.is_shutdown("renderer1") + + shutdown_event.set() + + assert registry.is_shutdown("renderer1") + + def test_registry_unknown_renderer_is_shutdown(self): + """Test that unknown renderer IDs report as shutdown.""" + registry = ActiveCallbackRegistry() + + assert registry.is_shutdown("unknown_renderer") + assert registry.get_queue("unknown_renderer") is None + assert registry.get_pending_get_props("unknown_renderer") is None + + +def test_ws030_multiple_callbacks_same_connection(dash_duo): + """Test multiple sequential callbacks on the same WebSocket connection.""" + app = Dash(__name__, backend="fastapi", websocket_callbacks=True) + + app.layout = html.Div( + [ + html.Button("Click", id="btn", n_clicks=0), + html.Div("0", id="output"), + ] + ) + + @app.callback(Output("output", "children"), Input("btn", "n_clicks")) + def on_click(n_clicks): + return str(n_clicks or 0) + + dash_duo.start_server(app) + + dash_duo.wait_for_text_to_equal("#output", "0") + + # Multiple clicks - each should work via the same connection + for i in range(1, 6): + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal("#output", str(i)) + + assert dash_duo.get_logs() == [] + + +def test_ws031_rapid_callbacks_registry_handling(dash_duo): + """Test that rapid callbacks are handled correctly by registry.""" + app = Dash(__name__, backend="fastapi", websocket_callbacks=True) + + app.layout = html.Div( + [ + html.Button("Rapid Click", id="btn", n_clicks=0), + html.Div("0", id="output"), + ] + ) + + @app.callback(Output("output", "children"), Input("btn", "n_clicks")) + def on_click(n_clicks): + return str(n_clicks or 0) + + dash_duo.start_server(app) + + dash_duo.wait_for_text_to_equal("#output", "0") + + # Rapid clicks without waiting + for _ in range(10): + dash_duo.find_element("#btn").click() + time.sleep(0.05) # 50ms between clicks + + # Should eventually reach 10 + dash_duo.wait_for_text_to_equal("#output", "10", timeout=10) + + assert dash_duo.get_logs() == [] + + +def test_ws032_long_callback_with_set_props(dash_duo): + """Test long-running callback with intermediate set_props updates.""" + app = Dash(__name__, backend="fastapi", websocket_callbacks=True) + + app.layout = html.Div( + [ + html.Button("Start", id="btn", n_clicks=0), + html.Div("ready", id="status"), + html.Div("0", id="progress"), + ] + ) + + @app.callback( + Output("status", "children"), + Input("btn", "n_clicks"), + prevent_initial_call=True, + ) + async def long_task(n_clicks): + set_props("status", {"children": "running"}) + + # Simulate progress updates + for i in range(1, 6): + set_props("progress", {"children": str(i * 20)}) + await asyncio.sleep(0.1) + + return "done" + + dash_duo.start_server(app) + + dash_duo.wait_for_text_to_equal("#status", "ready") + + dash_duo.find_element("#btn").click() + + # Should see intermediate updates + dash_duo.wait_for_text_to_equal("#status", "done", timeout=10) + dash_duo.wait_for_text_to_equal("#progress", "100") + + assert dash_duo.get_logs() == [] + + +def test_ws033_callback_after_reconnect(dash_duo): + """Test that callbacks work after WebSocket reconnection.""" + app = Dash( + __name__, + backend="fastapi", + websocket_callbacks=True, + websocket_inactivity_timeout=2000, # 2 seconds + ) + + app.layout = html.Div( + [ + html.Button("Click", id="btn", n_clicks=0), + html.Div("0", id="output"), + ] + ) + + @app.callback(Output("output", "children"), Input("btn", "n_clicks")) + def on_click(n_clicks): + return str(n_clicks or 0) + + dash_duo.start_server(app) + + dash_duo.wait_for_text_to_equal("#output", "0") + + # First click + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal("#output", "1") + + # Wait for connection to timeout + time.sleep(3) + + # Click after reconnection - should still work + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal("#output", "2") + + # Multiple clicks after reconnection + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal("#output", "3") + + assert dash_duo.get_logs() == [] + + +def test_ws034_concurrent_callbacks(dash_duo): + """Test multiple concurrent callbacks from different inputs.""" + app = Dash(__name__, backend="fastapi", websocket_callbacks=True) + + app.layout = html.Div( + [ + html.Button("Button A", id="btn-a", n_clicks=0), + html.Button("Button B", id="btn-b", n_clicks=0), + html.Div("a:0", id="output-a"), + html.Div("b:0", id="output-b"), + ] + ) + + @app.callback(Output("output-a", "children"), Input("btn-a", "n_clicks")) + async def on_click_a(n_clicks): + await asyncio.sleep(0.1) # Small delay to ensure overlap + return f"a:{n_clicks or 0}" + + @app.callback(Output("output-b", "children"), Input("btn-b", "n_clicks")) + async def on_click_b(n_clicks): + await asyncio.sleep(0.1) + return f"b:{n_clicks or 0}" + + dash_duo.start_server(app) + + dash_duo.wait_for_text_to_equal("#output-a", "a:0") + dash_duo.wait_for_text_to_equal("#output-b", "b:0") + + # Click both buttons rapidly + dash_duo.find_element("#btn-a").click() + dash_duo.find_element("#btn-b").click() + + dash_duo.wait_for_text_to_equal("#output-a", "a:1") + dash_duo.wait_for_text_to_equal("#output-b", "b:1") + + # More concurrent clicks + dash_duo.find_element("#btn-a").click() + dash_duo.find_element("#btn-b").click() + dash_duo.find_element("#btn-a").click() + + dash_duo.wait_for_text_to_equal("#output-a", "a:3") + dash_duo.wait_for_text_to_equal("#output-b", "b:2") + + assert dash_duo.get_logs() == [] + + +def test_ws035_callback_survives_inactivity_timeout(dash_duo): + """Test that long callback completes even when inactivity timeout triggers mid-execution. + + This is the key test for Issue #3788: when a callback runs longer than the + inactivity timeout without sending updates, the WebSocket disconnects and + reconnects. The callback should still complete and send its result via the + new connection. + """ + app = Dash( + __name__, + backend="fastapi", + websocket_callbacks=True, + websocket_inactivity_timeout=2000, # 2 seconds + ) + + app.layout = html.Div( + [ + html.Button("Start", id="btn", n_clicks=0), + html.Div("ready", id="output"), + ] + ) + + @app.callback( + Output("output", "children"), + Input("btn", "n_clicks"), + prevent_initial_call=True, + ) + async def silent_long_task(n_clicks): + # Wait longer than inactivity timeout WITHOUT sending any updates + # This will trigger WebSocket disconnect/reconnect mid-callback + await asyncio.sleep(5) + return f"completed:{n_clicks}" + + dash_duo.start_server(app) + + dash_duo.wait_for_text_to_equal("#output", "ready") + + # Start the long task + dash_duo.find_element("#btn").click() + + # Should complete despite inactivity timeout triggering during execution + dash_duo.wait_for_text_to_equal("#output", "completed:1", timeout=15) + + # Verify subsequent callbacks also work + dash_duo.find_element("#btn").click() + dash_duo.wait_for_text_to_equal("#output", "completed:2", timeout=15) + + assert dash_duo.get_logs() == [] + + +def test_ws036_set_props_after_reconnect(dash_duo): + """Test that set_props works after WebSocket reconnects mid-callback. + + This tests the registry's ability to adopt new queues so that + set_props calls use the new connection after reconnection. + """ + app = Dash( + __name__, + backend="fastapi", + websocket_callbacks=True, + websocket_inactivity_timeout=2000, # 2 seconds + ) + + app.layout = html.Div( + [ + html.Button("Start", id="btn", n_clicks=0), + html.Div("ready", id="status"), + html.Div("0", id="progress"), + ] + ) + + @app.callback( + Output("status", "children"), + Input("btn", "n_clicks"), + prevent_initial_call=True, + ) + async def task_with_late_set_props(n_clicks): + set_props("status", {"children": "started"}) + set_props("progress", {"children": "10"}) + + # Wait long enough for inactivity timeout to trigger + await asyncio.sleep(5) + + # These set_props calls happen AFTER reconnection + # They should still work via the adopted queue + set_props("progress", {"children": "100"}) + + return "done" + + dash_duo.start_server(app) + + dash_duo.wait_for_text_to_equal("#status", "ready") + + dash_duo.find_element("#btn").click() + + # Should see initial updates + dash_duo.wait_for_text_to_equal("#status", "started", timeout=5) + dash_duo.wait_for_text_to_equal("#progress", "10", timeout=5) + + # Should see final update after reconnection + dash_duo.wait_for_text_to_equal("#progress", "100", timeout=15) + dash_duo.wait_for_text_to_equal("#status", "done", timeout=5) + + assert dash_duo.get_logs() == [] From 21278e0ffd2a05d6c9586427d33fc40bf832a261 Mon Sep 17 00:00:00 2001 From: philippe Date: Tue, 26 May 2026 17:05:55 -0400 Subject: [PATCH 282/297] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62d49513c5..a262be18b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). - [#3669](https://github.com/plotly/dash/pull/3669) Selection for DataTable cleared with custom action settings - [#3680](https://github.com/plotly/dash/pull/3680) Added `search_order` prop to `Dropdown` to allow users to preserve original option order during search - Added `csrf_token_name` and `csrf_header_name` config options to allow configuring the CSRF cookie and header names. Fixes [#729](https://github.com/plotly/dash/issues/729) +- [#3797](https://github.com/plotly/dash/pull/3797) Improved websocket callback management. ## Added - [#3523](https://github.com/plotly/dash/pull/3523) Fall back to background callback function names if source cannot be found From 6f6442f0b185f32d876900b4d55f8ce89e06c62a Mon Sep 17 00:00:00 2001 From: philippe Date: Tue, 26 May 2026 18:52:22 -0400 Subject: [PATCH 283/297] lint fix --- dash/backends/ws.py | 81 ++++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/dash/backends/ws.py b/dash/backends/ws.py index adebdf2c4a..807a167ab7 100644 --- a/dash/backends/ws.py +++ b/dash/backends/ws.py @@ -242,35 +242,62 @@ async def run_ws_sender( messages: list[str] = [] try: while True: - # Wait indefinitely for first message, then use timeout for batching - timeout = batch_delay if messages else None - try: - msg = await asyncio.wait_for(q.get(), timeout=timeout) - if msg == SHUTDOWN_SIGNAL: - if messages: - await _send_batched(send_text, messages) - return - if msg == FLUSH_SIGNAL: - if messages: - if not await _send_batched(send_text, messages): - return # Connection closed - messages = [] - continue - if not batch_delay: - try: - await send_text(msg) - except Exception: # WebSocketDisconnect, RuntimeError, etc. - return # Connection closed - else: - messages.append(msg) - except asyncio.TimeoutError: - if not await _send_batched(send_text, messages): - return # Connection closed - messages = [] + result = await _process_ws_message(q, send_text, messages, batch_delay) + if result is False: + return except asyncio.CancelledError: pass +async def _process_ws_message( + q: "janus._AsyncQueueProxy[str]", + send_text: Callable[[str], Any], + messages: list[str], + batch_delay: float, +) -> bool | None: + """Process a single WebSocket message from the queue. + + Args: + q: The async queue to read from + send_text: Async function to send text data over WebSocket + messages: List to accumulate messages for batching (mutated in place) + batch_delay: Batch delay in seconds + + Returns: + True to continue processing, False to stop the sender loop, + None to continue (same as True but used for continue semantics). + """ + timeout = batch_delay if messages else None + try: + msg = await asyncio.wait_for(q.get(), timeout=timeout) + except asyncio.TimeoutError: + if not await _send_batched(send_text, messages): + return False + messages.clear() + return True + + if msg == SHUTDOWN_SIGNAL: + if messages: + await _send_batched(send_text, messages) + return False + + if msg == FLUSH_SIGNAL: + if messages and not await _send_batched(send_text, messages): + return False + messages.clear() + return None + + if not batch_delay: + try: + await send_text(msg) + except Exception: # pylint: disable=broad-exception-caught + return False # WebSocketDisconnect, RuntimeError, etc. + else: + messages.append(msg) + + return True + + async def _send_batched(send_text: Callable[[str], Any], messages: list) -> bool: """Send messages as a batch. @@ -291,8 +318,8 @@ async def _send_batched(send_text: Callable[[str], Any], messages: list) -> bool # Wrap in array: "[msg1,msg2,msg3]" await send_text("[" + ",".join(messages) + "]") return True - except Exception: # WebSocketDisconnect, RuntimeError, etc. - return False # Connection closed, cleanup handled by main loop + except Exception: # pylint: disable=broad-exception-caught + return False # WebSocketDisconnect, RuntimeError, etc. def make_callback_done_handler( From 2f42201532cb2d5892197f18f0703d6f42c4c2a6 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 27 May 2026 16:39:25 -0400 Subject: [PATCH 284/297] fix lint --- dash/backends/ws.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/dash/backends/ws.py b/dash/backends/ws.py index 807a167ab7..8ee2cf11c1 100644 --- a/dash/backends/ws.py +++ b/dash/backends/ws.py @@ -254,7 +254,7 @@ async def _process_ws_message( send_text: Callable[[str], Any], messages: list[str], batch_delay: float, -) -> bool | None: +) -> bool: """Process a single WebSocket message from the queue. Args: @@ -264,17 +264,15 @@ async def _process_ws_message( batch_delay: Batch delay in seconds Returns: - True to continue processing, False to stop the sender loop, - None to continue (same as True but used for continue semantics). + True to continue processing, False to stop the sender loop. """ timeout = batch_delay if messages else None try: msg = await asyncio.wait_for(q.get(), timeout=timeout) except asyncio.TimeoutError: - if not await _send_batched(send_text, messages): - return False + success = await _send_batched(send_text, messages) messages.clear() - return True + return success if msg == SHUTDOWN_SIGNAL: if messages: @@ -282,10 +280,9 @@ async def _process_ws_message( return False if msg == FLUSH_SIGNAL: - if messages and not await _send_batched(send_text, messages): - return False + success = not messages or await _send_batched(send_text, messages) messages.clear() - return None + return success if not batch_delay: try: From f02a947030c23a479472e8decb8f73f7fefa82c6 Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 27 May 2026 17:46:31 -0400 Subject: [PATCH 285/297] fix blueprint registering and double init --- dash/backends/_fastapi.py | 5 +++++ dash/backends/_flask.py | 4 ++++ dash/backends/_quart.py | 5 ++++- dash/dash.py | 3 +++ tests/unit/test_configs.py | 40 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 1 deletion(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index c46fb4ffc5..960bfd2e1f 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -272,6 +272,11 @@ def create_app(name: str = "__main__", config: Dict[str, Any] | None = None): def register_assets_blueprint( self, blueprint_name: str, assets_url_path: str, assets_folder: str ): + # Check if route is already mounted to avoid duplicate registration + # This can happen when init_app() is called multiple times + for route in self.server.routes: + if getattr(route, "name", None) == blueprint_name: + return try: self.server.mount( assets_url_path, diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index 00c8730d8a..4ebae2bada 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -86,6 +86,10 @@ def create_app(name: str = "__main__", config: Dict[str, Any] | None = None): def register_assets_blueprint( self, blueprint_name: str, assets_url_path: str, assets_folder: str ): + # Check if blueprint is already registered to avoid duplicate registration + # This can happen when init_app() is called multiple times (e.g., with flask run) + if blueprint_name in self.server.blueprints: + return bp = Blueprint( blueprint_name, __name__, diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 881fd6466f..8b161962b0 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -122,7 +122,10 @@ def create_app( def register_assets_blueprint( self, blueprint_name: str, assets_url_path: str, assets_folder: str # type: ignore[name-defined] ): - + # Check if blueprint is already registered to avoid duplicate registration + # This can happen when init_app() is called multiple times (e.g., with quart run) + if blueprint_name in self.server.blueprints: + return bp = Blueprint( blueprint_name, __name__, diff --git a/dash/dash.py b/dash/dash.py index e5316f3be9..7a1cdcd47d 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -731,6 +731,9 @@ def init_app(self, app: Optional[Any] = None, **kwargs) -> None: ) if app is not None: self.server = app + # Also update the backend's server reference so routes are registered + # on the correct server (important when using server=False pattern) + self.backend.server = app bp_prefix = config.routes_pathname_prefix.replace("/", "_").replace(".", "_") assets_blueprint_name = f"{bp_prefix}dash_assets" self.backend.register_assets_blueprint( diff --git a/tests/unit/test_configs.py b/tests/unit/test_configs.py index 415eb61540..461b8d7994 100644 --- a/tests/unit/test_configs.py +++ b/tests/unit/test_configs.py @@ -524,3 +524,43 @@ def test_csrf_config_read_only(): app.config.csrf_token_name = "something_else" with pytest.raises(AttributeError): app.config.csrf_header_name = "something_else" + + +def test_init_app_with_flask_run_pattern(): + """Test that init_app works correctly with the flask run pattern. + + This tests the fix for https://github.com/plotly/dash/issues/3787 + where using flask run would cause a ValueError about duplicate blueprint + registration because init_app was called twice (once automatically in + __init__ with server=True, and once by the user in their create_app factory). + """ + # Simulate the flask run pattern where: + # 1. Dash app is created with server=True (default) + # 2. User's create_app factory calls init_app with their Flask server + external_server = Flask("external_test") + app = Dash(__name__) + + # This should NOT raise "ValueError: The name '_dash_assets' is already registered" + app.init_app(external_server) + + # Verify the backend now uses the external server + assert app.server is external_server + assert app.backend.server is external_server + + +def test_init_app_server_false_pattern(): + """Test that init_app works correctly when server=False is used. + + This tests the fix for https://github.com/plotly/dash/issues/3787 + where using server=False and then calling init_app would result in + 404 errors because the backend's server reference was not updated. + """ + external_server = Flask("external_test_false") + app = Dash(__name__, server=False) + + # Call init_app with the external server + app.init_app(external_server) + + # Verify both the app and backend use the external server + assert app.server is external_server + assert app.backend.server is external_server From c0da66531ba0544f30834684bd560f9b0fe952d7 Mon Sep 17 00:00:00 2001 From: AnnMarueW Date: Thu, 28 May 2026 07:38:14 -0700 Subject: [PATCH 286/297] update after review --- components/dash-core-components/src/utils/dropdownSearch.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/dash-core-components/src/utils/dropdownSearch.ts b/components/dash-core-components/src/utils/dropdownSearch.ts index 079bba0290..6f9fc7f88e 100644 --- a/components/dash-core-components/src/utils/dropdownSearch.ts +++ b/components/dash-core-components/src/utils/dropdownSearch.ts @@ -80,8 +80,8 @@ export function sanitizeDropdownOptions( export function filterOptions( options: SanitizedOptions, - searchValue?: string, - searchOrder?: string + searchValue?: DropdownProps['search_value'], + searchOrder?: DropdownProps['search_order'] ): DetailedOption[] { if (!searchValue) { return options.options; From cfac954c0546b52e9fda33e4dae3c77fd657118a Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 28 May 2026 12:09:19 -0400 Subject: [PATCH 287/297] update changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62d49513c5..bf826f2e39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,9 @@ This project adheres to [Semantic Versioning](https://semver.org/). - [#3669](https://github.com/plotly/dash/pull/3669) Selection for DataTable cleared with custom action settings - [#3680](https://github.com/plotly/dash/pull/3680) Added `search_order` prop to `Dropdown` to allow users to preserve original option order during search - Added `csrf_token_name` and `csrf_header_name` config options to allow configuring the CSRF cookie and header names. Fixes [#729](https://github.com/plotly/dash/issues/729) - -## Added - [#3523](https://github.com/plotly/dash/pull/3523) Fall back to background callback function names if source cannot be found +- [#3785](https://github.com/plotly/dash/pull/3785) Fix patch with dcc.Graph figure. +- [#3785](https://github.com/plotly/dash/pull/3785) Fix dcc.Graph not sending duplicate clicks because it had the same payload by adding a timestamp in the click event object. ## Fixed - [#3690](https://github.com/plotly/dash/pull/3690) Fixes Input when min or max is set to None From 7ecedb9cc353c402035e7efe63cc973065142f50 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 28 May 2026 12:23:00 -0400 Subject: [PATCH 288/297] deep clone dcc graph figure layout --- .../dash-core-components/src/fragments/Graph.react.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/components/dash-core-components/src/fragments/Graph.react.js b/components/dash-core-components/src/fragments/Graph.react.js index 875ae70253..14edaaba61 100644 --- a/components/dash-core-components/src/fragments/Graph.react.js +++ b/components/dash-core-components/src/fragments/Graph.react.js @@ -9,6 +9,7 @@ import { mergeDeepRight, omit, type, + clone, } from 'ramda'; import PropTypes from 'prop-types'; import {graphPropTypes, graphDefaultProps} from '../components/Graph.react'; @@ -313,12 +314,12 @@ class PlotlyGraph extends Component { return mergeDeepRight(config, this.getConfigOverride(responsive)); } - getLayout(layout, responsive) { - if (!layout) { - return layout; + getLayout(originalLayout, responsive) { + if (!originalLayout) { + return originalLayout; } // Clone layout to avoid mutating the original (important for Patch) - layout = {...layout}; + const layout = clone(originalLayout); const override = this.getLayoutOverride(responsive); const {override: prev_override, originals: prev_originals} = this.state; // Store the original data that we're about to override @@ -341,7 +342,7 @@ class PlotlyGraph extends Component { for (const key in override) { layout[key] = override[key]; } - return layout; // not really a clone + return layout; } getConfigOverride(responsive) { From 2b0a7d1188cdd5bc1212a83f117141830bf6158a Mon Sep 17 00:00:00 2001 From: AnnMarueW Date: Thu, 28 May 2026 16:11:12 -0700 Subject: [PATCH 289/297] fix: use stable keys for virtualized dropdown rows --- components/dash-core-components/src/utils/optionRendering.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/dash-core-components/src/utils/optionRendering.tsx b/components/dash-core-components/src/utils/optionRendering.tsx index 0715107bb5..4f9179299f 100644 --- a/components/dash-core-components/src/utils/optionRendering.tsx +++ b/components/dash-core-components/src/utils/optionRendering.tsx @@ -400,6 +400,9 @@ export const OptionsList = forwardRef( className="dash-options-list-virtualized" onItemsRendered={handleItemsRendered} itemData={itemData} + itemKey={(index, data) => + String(data.options[index]?.value ?? index) + } > {Row} From 3892cd4484515c837869a3b27e9b14d9635cefb5 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 28 May 2026 19:28:34 -0400 Subject: [PATCH 290/297] remove ActiveCallbackRegistry & callback adoption --- .ai/ARCHITECTURE.md | 14 ++ dash/backends/_fastapi.py | 32 +--- dash/backends/_quart.py | 32 +--- dash/backends/_ws_registry.py | 166 ------------------ dash/backends/ws.py | 121 ++++++-------- tests/websocket/test_ws_reconnect.py | 242 +++------------------------ 6 files changed, 90 insertions(+), 517 deletions(-) delete mode 100644 dash/backends/_ws_registry.py diff --git a/.ai/ARCHITECTURE.md b/.ai/ARCHITECTURE.md index 84f553978c..da9913a13f 100644 --- a/.ai/ARCHITECTURE.md +++ b/.ai/ARCHITECTURE.md @@ -968,6 +968,7 @@ WebSocket callbacks can stream updates to the client during execution using `set ```python import asyncio from dash import callback, Output, Input, set_props, ctx +from dash.exceptions import PreventUpdate @callback( Output('result', 'children'), @@ -981,6 +982,9 @@ async def long_running_task(n_clicks): # Stream progress updates to the client for i in range(100): + # IMPORTANT: Check is_shutdown in loops to detect disconnections + if ws.is_shutdown: + raise PreventUpdate # Exit gracefully on disconnect await asyncio.sleep(0.1) set_props('progress-bar', {'value': i + 1}) set_props('status', {'children': f'Processing step {i + 1}/100...'}) @@ -991,9 +995,19 @@ async def long_running_task(n_clicks): return f"Completed! Input was: {current_value}" ``` +**IMPORTANT - Checking `is_shutdown` in Loops:** + +Long-running callbacks that use loops **must** check `ws.is_shutdown` to detect when the WebSocket connection has closed. Without this check: +- Callbacks continue running after the client disconnects, wasting server resources +- `set_props` calls go to a closed connection and are lost +- The callback result is never delivered to the client + +Only "persistent callbacks" (callbacks with no Output and no Input that use only `set_props`) are automatically restarted when the WebSocket reconnects. Regular callbacks with outputs are not restarted. + **API:** - `set_props(component_id, props_dict)` - Stream prop updates immediately to client - `ctx.websocket` - Get WebSocket interface (returns `None` if not in WS context) +- `ws.is_shutdown` - Check if the WebSocket connection has been closed - `await ws.get_prop(component_id, prop_name)` - Read current prop value from client - `await ws.set_prop(component_id, prop_name, value)` - Set single prop (async version) - `await ws.close(code, reason)` - Close the WebSocket connection diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index b619c040c9..027b94bed4 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -50,7 +50,6 @@ SHUTDOWN_SIGNAL, DISCONNECTED, ) -from ._ws_registry import ActiveCallbackRegistry from ._utils import format_traceback_html if TYPE_CHECKING: # pragma: no cover - typing only @@ -678,12 +677,6 @@ def serve_websocket_callback(self, dash_app: "Dash"): dash_app, "_websocket_allowed_origins", [] ) # pylint: disable=protected-access - # Initialize registry on dash_app if not present - # pylint: disable=protected-access - if not hasattr(dash_app, "_ws_callback_registry"): - dash_app._ws_callback_registry = ActiveCallbackRegistry() - registry: ActiveCallbackRegistry = dash_app._ws_callback_registry - def validate_origin(origin: str | None, host: str | None) -> str | None: """Validate WebSocket origin. Returns error message or None if valid.""" if not origin: @@ -730,8 +723,6 @@ async def websocket_handler(websocket: WebSocket): executor = self.get_callback_executor() # Track pending callback futures pending_callbacks: Dict[str, concurrent.futures.Future] = {} - # Track current renderer ID for this connection - current_renderer_id: str | None = None # Start sender task to drain outbound queue (sends pre-serialized text) # pylint: disable=protected-access @@ -762,22 +753,6 @@ async def websocket_handler(websocket: WebSocket): renderer_id = message.get("rendererId", "") payload = message.get("payload", {}) - # Update current renderer ID for cleanup - current_renderer_id = renderer_id - - # Adopt connection for this renderer (allows reconnection) - # Called for every callback to ensure registry entry exists - # (entry may have been cleaned up after previous callback) - registry.adopt_connection( - renderer_id, - outbound_queue, - pending_get_props, - shutdown_event, - ) - - # Register this callback with the registry - registry.register_callback(renderer_id) - # Validate that the callback is allowed to use WebSocket transport # pylint: disable=protected-access _validate.validate_websocket_callback_request( @@ -786,13 +761,12 @@ async def websocket_handler(websocket: WebSocket): dash_app._websocket_callbacks, ) - # Create WebSocket callback instance with registry + # Create WebSocket callback instance ws_cb = DashWebsocketCallback( pending_get_props, renderer_id, outbound_queue, shutdown_event, - registry=registry, ) # Submit callback to executor @@ -812,7 +786,6 @@ async def websocket_handler(websocket: WebSocket): request_id, renderer_id, shutdown_event, - registry=registry, ) ) pending_callbacks[request_id] = future @@ -848,9 +821,6 @@ async def websocket_handler(websocket: WebSocket): # Cancel any pending futures for f in pending_callbacks.values(): f.cancel() - # Cleanup registry entry if no active callbacks - if current_renderer_id is not None: - registry.cleanup_renderer(current_renderer_id) self.server.add_api_websocket_route(ws_path, websocket_handler) diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 31d9668d36..daac2dd3f6 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -55,7 +55,6 @@ SHUTDOWN_SIGNAL, DISCONNECTED, ) -from ._ws_registry import ActiveCallbackRegistry from ._utils import format_traceback_html if TYPE_CHECKING: @@ -522,12 +521,6 @@ def serve_websocket_callback(self, dash_app: "Dash"): # pylint: disable=protected-access allowed_origins = getattr(dash_app, "_websocket_allowed_origins", []) - # Initialize registry on dash_app if not present - # pylint: disable=protected-access - if not hasattr(dash_app, "_ws_callback_registry"): - dash_app._ws_callback_registry = ActiveCallbackRegistry() - registry: ActiveCallbackRegistry = dash_app._ws_callback_registry - @self.server.websocket(ws_path) async def websocket_handler(): # pylint: disable=too-many-branches ws = websocket @@ -571,8 +564,6 @@ async def websocket_handler(): # pylint: disable=too-many-branches executor = self.get_callback_executor() # Track pending callback futures pending_callbacks: Dict[str, concurrent.futures.Future] = {} - # Track current renderer ID for this connection - current_renderer_id: str | None = None # Start sender task to drain outbound queue (sends pre-serialized text) # pylint: disable=protected-access @@ -610,22 +601,6 @@ async def websocket_handler(): # pylint: disable=too-many-branches renderer_id = message.get("rendererId", "") payload = message.get("payload", {}) - # Update current renderer ID for cleanup - current_renderer_id = renderer_id - - # Adopt connection for this renderer (allows reconnection) - # Called for every callback to ensure registry entry exists - # (entry may have been cleaned up after previous callback) - registry.adopt_connection( - renderer_id, - outbound_queue, - pending_get_props, - connection_shutdown_event, - ) - - # Register this callback with the registry - registry.register_callback(renderer_id) - # Validate that the callback is allowed to use WebSocket transport # pylint: disable=protected-access _validate.validate_websocket_callback_request( @@ -634,13 +609,12 @@ async def websocket_handler(): # pylint: disable=too-many-branches dash_app._websocket_callbacks, ) - # Create WebSocket callback instance with registry + # Create WebSocket callback instance ws_cb = DashWebsocketCallback( pending_get_props, renderer_id, outbound_queue, connection_shutdown_event, - registry=registry, ) # Submit callback to executor @@ -660,7 +634,6 @@ async def websocket_handler(): # pylint: disable=too-many-branches request_id, renderer_id, connection_shutdown_event, - registry=registry, ) ) pending_callbacks[request_id] = future @@ -699,9 +672,6 @@ async def websocket_handler(): # pylint: disable=too-many-branches # Cancel any pending futures for f in pending_callbacks.values(): f.cancel() - # Cleanup registry entry if no active callbacks - if current_renderer_id is not None: - registry.cleanup_renderer(current_renderer_id) class QuartRequestAdapter(RequestAdapter): diff --git a/dash/backends/_ws_registry.py b/dash/backends/_ws_registry.py deleted file mode 100644 index 4ab1132d6a..0000000000 --- a/dash/backends/_ws_registry.py +++ /dev/null @@ -1,166 +0,0 @@ -"""WebSocket callback registry for handling reconnections. - -This module provides a registry that tracks active callbacks per renderer, -allowing callbacks to persist across WebSocket reconnections. -""" - -from __future__ import annotations - -import threading -from dataclasses import dataclass, field -from typing import TYPE_CHECKING, Any, Dict, Optional - -if TYPE_CHECKING: - import queue - import janus - - -@dataclass -class RendererState: - """State for a single renderer's WebSocket connection.""" - - outbound_queue: "janus.Queue[str]" - pending_get_props: Dict[str, "queue.Queue[Any]"] - shutdown_event: threading.Event - active_callback_count: int = 0 - lock: threading.Lock = field(default_factory=threading.Lock) - - -class ActiveCallbackRegistry: - """Registry for active WebSocket callbacks that persists across reconnections. - - When a WebSocket disconnects and reconnects, callbacks that are still running - can "adopt" the new connection's queues to continue sending updates. - - Thread-safe for access from both the main event loop and worker threads. - """ - - def __init__(self) -> None: - self._renderers: Dict[str, RendererState] = {} - self._lock = threading.Lock() - - def adopt_connection( - self, - renderer_id: str, - outbound_queue: "janus.Queue[str]", - pending_get_props: Dict[str, "queue.Queue[Any]"], - shutdown_event: threading.Event, - ) -> None: - """Associate new connection with existing callbacks for this renderer. - - When a WebSocket reconnects, this method updates the queues and shutdown - event so that running callbacks can use the new connection. - - Args: - renderer_id: The renderer ID for this connection - outbound_queue: janus.Queue for sending messages - pending_get_props: Dict to track pending get_props requests - shutdown_event: Event signaling connection closure - """ - with self._lock: - if renderer_id in self._renderers: - state = self._renderers[renderer_id] - with state.lock: - state.outbound_queue = outbound_queue - state.pending_get_props = pending_get_props - state.shutdown_event = shutdown_event - else: - self._renderers[renderer_id] = RendererState( - outbound_queue=outbound_queue, - pending_get_props=pending_get_props, - shutdown_event=shutdown_event, - active_callback_count=0, - ) - - def register_callback(self, renderer_id: str) -> None: - """Register a new active callback for this renderer. - - Args: - renderer_id: The renderer ID - """ - with self._lock: - if renderer_id in self._renderers: - state = self._renderers[renderer_id] - with state.lock: - state.active_callback_count += 1 - - def unregister_callback(self, renderer_id: str) -> None: - """Unregister a completed callback for this renderer. - - If no active callbacks remain, the renderer state is cleaned up. - - Args: - renderer_id: The renderer ID - """ - with self._lock: - if renderer_id in self._renderers: - state = self._renderers[renderer_id] - with state.lock: - state.active_callback_count -= 1 - if state.active_callback_count <= 0: - del self._renderers[renderer_id] - - def get_queue(self, renderer_id: str) -> Optional["janus.Queue[str]"]: - """Get current outbound queue for renderer (thread-safe). - - Args: - renderer_id: The renderer ID - - Returns: - The current outbound queue, or None if renderer not found - """ - with self._lock: - state = self._renderers.get(renderer_id) - if state is None: - return None - with state.lock: - return state.outbound_queue - - def get_pending_get_props( - self, renderer_id: str - ) -> Optional[Dict[str, "queue.Queue[Any]"]]: - """Get current pending_get_props dict for renderer (thread-safe). - - Args: - renderer_id: The renderer ID - - Returns: - The current pending_get_props dict, or None if renderer not found - """ - with self._lock: - state = self._renderers.get(renderer_id) - if state is None: - return None - with state.lock: - return state.pending_get_props - - def is_shutdown(self, renderer_id: str) -> bool: - """Check if current connection is shutdown. - - Args: - renderer_id: The renderer ID - - Returns: - True if shutdown event is set or renderer not found, False otherwise - """ - with self._lock: - state = self._renderers.get(renderer_id) - if state is None: - return True - with state.lock: - return state.shutdown_event.is_set() - - def cleanup_renderer(self, renderer_id: str) -> None: - """Clean up renderer state when connection closes. - - Only removes if no active callbacks remain. - - Args: - renderer_id: The renderer ID to clean up - """ - with self._lock: - state = self._renderers.get(renderer_id) - if state is not None: - with state.lock: - if state.active_callback_count <= 0: - del self._renderers[renderer_id] diff --git a/dash/backends/ws.py b/dash/backends/ws.py index 8ee2cf11c1..a4b302f215 100644 --- a/dash/backends/ws.py +++ b/dash/backends/ws.py @@ -25,7 +25,6 @@ if TYPE_CHECKING: import dash from .base_server import ResponseAdapter - from ._ws_registry import ActiveCallbackRegistry SHUTDOWN_SIGNAL = "__shutdown__" @@ -43,9 +42,24 @@ class DashWebsocketCallback: queue.Queue for get_props responses, enabling thread-safe communication between worker threads and the main event loop. - Supports two modes: - 1. Registry mode: Uses ActiveCallbackRegistry to allow queue adoption on reconnect - 2. Direct mode: Uses direct queue references (legacy, for backwards compatibility) + IMPORTANT: For long-running callbacks that use loops (e.g., streaming updates), + you MUST check `ws.is_shutdown` in your loop to detect disconnections: + + @callback(Input('btn', 'n_clicks')) # No Output - uses set_props only + async def long_running(n_clicks): + ws = ctx.websocket + while True: + if ws and ws.is_shutdown: + raise PreventUpdate # Exit gracefully on disconnect + set_props('progress', {'value': get_data()}) + await asyncio.sleep(0.1) + + Without this check, callbacks will continue running after the client disconnects, + wasting server resources. + + Note: Only "persistent callbacks" (callbacks with no Output and no Input that use + only set_props) are automatically restarted when the WebSocket reconnects. Regular + callbacks with outputs are not restarted. """ def __init__( @@ -54,7 +68,6 @@ def __init__( renderer_id: str, outbound_queue: janus.Queue[str], shutdown_event: "threading.Event", - registry: "ActiveCallbackRegistry | None" = None, ): """Initialize the WebSocket callback interface. @@ -64,33 +77,23 @@ def __init__( renderer_id: The renderer ID for routing messages back to the correct client outbound_queue: janus.Queue for thread-safe outbound messaging. shutdown_event: Event signaling the websocket connection has closed. - registry: Optional registry for handling reconnections. If provided, - the callback will use the registry to get current queues, allowing - it to survive reconnections. """ self._pending_get_props = pending_get_props self._renderer_id = renderer_id self._outbound_queue = outbound_queue self._shutdown_event = shutdown_event - self._registry = registry @property def is_shutdown(self) -> bool: """Check if the websocket connection has been shut down.""" - if self._registry is not None: - return self._registry.is_shutdown(self._renderer_id) return self._shutdown_event.is_set() def _get_outbound_queue(self) -> janus.Queue[str] | None: - """Get the current outbound queue (may be updated on reconnect).""" - if self._registry is not None: - return self._registry.get_queue(self._renderer_id) + """Get the outbound queue.""" return self._outbound_queue def _get_pending_get_props(self) -> Dict[str, queue.Queue[Any]] | None: - """Get the current pending_get_props dict (may be updated on reconnect).""" - if self._registry is not None: - return self._registry.get_pending_get_props(self._renderer_id) + """Get the pending_get_props dict.""" return self._pending_get_props def _queue_message(self, msg: dict) -> None: @@ -325,7 +328,6 @@ def make_callback_done_handler( request_id: str, renderer_id: str, shutdown_event: threading.Event, - registry: "ActiveCallbackRegistry | None" = None, ) -> Callable[[concurrent.futures.Future], None]: """Create a done callback handler for executor futures. @@ -338,73 +340,52 @@ def make_callback_done_handler( request_id: The request ID for the callback response renderer_id: The renderer ID for routing the response shutdown_event: Event signaling the websocket connection has closed. - registry: Optional registry for managing callback lifecycle. Returns: A callback function suitable for Future.add_done_callback() """ - def _is_shutdown() -> bool: - """Check if connection is shutdown (registry-aware).""" - if registry is not None: - return registry.is_shutdown(renderer_id) - return shutdown_event.is_set() - - def _get_queue() -> janus.Queue[str] | None: - """Get current outbound queue (may change on reconnect).""" - if registry is not None: - return registry.get_queue(renderer_id) - return outbound_queue - def on_done(f: concurrent.futures.Future) -> None: try: - if _is_shutdown(): + if shutdown_event.is_set(): return result = f.result() - current_queue = _get_queue() - if current_queue is not None: - current_queue.sync_q.put_nowait( - cast( - str, - to_json( - { - "type": "callback_response", - "rendererId": renderer_id, - "requestId": request_id, - "payload": result, - } - ), - ) + outbound_queue.sync_q.put_nowait( + cast( + str, + to_json( + { + "type": "callback_response", + "rendererId": renderer_id, + "requestId": request_id, + "payload": result, + } + ), ) + ) except Exception as e: # pylint: disable=broad-exception-caught - if _is_shutdown(): + if shutdown_event.is_set(): return - current_queue = _get_queue() - if current_queue is not None: - current_queue.sync_q.put_nowait( - cast( - str, - to_json( - { - "type": "callback_response", - "rendererId": renderer_id, - "requestId": request_id, - "payload": { - "status": "error", - "message": str(e), - }, - } - ), - ) + outbound_queue.sync_q.put_nowait( + cast( + str, + to_json( + { + "type": "callback_response", + "rendererId": renderer_id, + "requestId": request_id, + "payload": { + "status": "error", + "message": str(e), + }, + } + ), ) + ) finally: pending_callbacks.pop(request_id, None) - if registry is not None: - registry.unregister_callback(renderer_id) - if not _is_shutdown(): - current_queue = _get_queue() - if current_queue is not None: - current_queue.sync_q.put_nowait(FLUSH_SIGNAL) + if not shutdown_event.is_set(): + outbound_queue.sync_q.put_nowait(FLUSH_SIGNAL) return on_done diff --git a/tests/websocket/test_ws_reconnect.py b/tests/websocket/test_ws_reconnect.py index 64826ab1e6..51eeb38ae3 100644 --- a/tests/websocket/test_ws_reconnect.py +++ b/tests/websocket/test_ws_reconnect.py @@ -3,159 +3,15 @@ Tests: - Callback continuity after WebSocket reconnection -- Registry tracks active callbacks correctly - Disconnect handling doesn't cause error spam -- Long-running callbacks survive reconnection +- Long-running callbacks with is_shutdown check """ import asyncio import time -import threading -from dash import Dash, html, Input, Output, set_props -from dash.backends._ws_registry import ActiveCallbackRegistry - - -class TestActiveCallbackRegistry: - """Unit tests for the ActiveCallbackRegistry class.""" - - def test_registry_adopt_creates_entry(self): - """Test that adopt_connection creates a new registry entry.""" - registry = ActiveCallbackRegistry() - - # Mock queue-like object - class MockQueue: - def __init__(self): - self.sync_q = None - - outbound_queue = MockQueue() - pending_get_props = {} - shutdown_event = threading.Event() - - registry.adopt_connection( - "renderer1", outbound_queue, pending_get_props, shutdown_event - ) - - assert registry.get_queue("renderer1") == outbound_queue - assert registry.get_pending_get_props("renderer1") == pending_get_props - assert not registry.is_shutdown("renderer1") - - def test_registry_callback_lifecycle(self): - """Test register/unregister callback with cleanup.""" - registry = ActiveCallbackRegistry() - - class MockQueue: - def __init__(self): - self.sync_q = None - - outbound_queue = MockQueue() - shutdown_event = threading.Event() - - registry.adopt_connection("renderer1", outbound_queue, {}, shutdown_event) - - # Register callback - registry.register_callback("renderer1") - assert not registry.is_shutdown("renderer1") - - # Unregister - should clean up entry since count becomes 0 - registry.unregister_callback("renderer1") - assert registry.is_shutdown("renderer1") # Returns True when not found - - def test_registry_multiple_callbacks(self): - """Test that multiple callbacks keep entry alive.""" - registry = ActiveCallbackRegistry() - - class MockQueue: - def __init__(self): - self.sync_q = None - - outbound_queue = MockQueue() - shutdown_event = threading.Event() - - registry.adopt_connection("renderer1", outbound_queue, {}, shutdown_event) - - # Register two callbacks - registry.register_callback("renderer1") - registry.register_callback("renderer1") - - # Unregister one - entry should still exist - registry.unregister_callback("renderer1") - assert not registry.is_shutdown("renderer1") - - # Unregister second - now should be cleaned up - registry.unregister_callback("renderer1") - assert registry.is_shutdown("renderer1") - - def test_registry_adopt_after_cleanup(self): - """Test that adopt_connection works after cleanup.""" - registry = ActiveCallbackRegistry() - - class MockQueue: - def __init__(self): - self.sync_q = None - - outbound_queue = MockQueue() - shutdown_event = threading.Event() - - # First connection - registry.adopt_connection("renderer1", outbound_queue, {}, shutdown_event) - registry.register_callback("renderer1") - registry.unregister_callback("renderer1") # Cleans up - - # Re-adopt after cleanup - registry.adopt_connection("renderer1", outbound_queue, {}, shutdown_event) - assert not registry.is_shutdown("renderer1") - - def test_registry_adopt_updates_existing(self): - """Test that adopt_connection updates queues for existing entry.""" - registry = ActiveCallbackRegistry() - - class MockQueue: - def __init__(self, name): - self.name = name - self.sync_q = None - - old_queue = MockQueue("old") - new_queue = MockQueue("new") - old_shutdown = threading.Event() - new_shutdown = threading.Event() - - registry.adopt_connection("renderer1", old_queue, {}, old_shutdown) - registry.register_callback("renderer1") # Keep entry alive - - assert registry.get_queue("renderer1").name == "old" - - # Simulate reconnection - registry.adopt_connection("renderer1", new_queue, {}, new_shutdown) - - assert registry.get_queue("renderer1").name == "new" - - def test_registry_shutdown_event_respected(self): - """Test that shutdown event is checked correctly.""" - registry = ActiveCallbackRegistry() - - class MockQueue: - def __init__(self): - self.sync_q = None - - outbound_queue = MockQueue() - shutdown_event = threading.Event() - - registry.adopt_connection("renderer1", outbound_queue, {}, shutdown_event) - - assert not registry.is_shutdown("renderer1") - - shutdown_event.set() - - assert registry.is_shutdown("renderer1") - - def test_registry_unknown_renderer_is_shutdown(self): - """Test that unknown renderer IDs report as shutdown.""" - registry = ActiveCallbackRegistry() - - assert registry.is_shutdown("unknown_renderer") - assert registry.get_queue("unknown_renderer") is None - assert registry.get_pending_get_props("unknown_renderer") is None +from dash import Dash, html, Input, Output, set_props, ctx +from dash.exceptions import PreventUpdate def test_ws030_multiple_callbacks_same_connection(dash_duo): @@ -185,8 +41,8 @@ def on_click(n_clicks): assert dash_duo.get_logs() == [] -def test_ws031_rapid_callbacks_registry_handling(dash_duo): - """Test that rapid callbacks are handled correctly by registry.""" +def test_ws031_rapid_callbacks(dash_duo): + """Test that rapid callbacks are handled correctly.""" app = Dash(__name__, backend="fastapi", websocket_callbacks=True) app.layout = html.Div( @@ -343,61 +199,12 @@ async def on_click_b(n_clicks): assert dash_duo.get_logs() == [] -def test_ws035_callback_survives_inactivity_timeout(dash_duo): - """Test that long callback completes even when inactivity timeout triggers mid-execution. - - This is the key test for Issue #3788: when a callback runs longer than the - inactivity timeout without sending updates, the WebSocket disconnects and - reconnects. The callback should still complete and send its result via the - new connection. - """ - app = Dash( - __name__, - backend="fastapi", - websocket_callbacks=True, - websocket_inactivity_timeout=2000, # 2 seconds - ) - - app.layout = html.Div( - [ - html.Button("Start", id="btn", n_clicks=0), - html.Div("ready", id="output"), - ] - ) - - @app.callback( - Output("output", "children"), - Input("btn", "n_clicks"), - prevent_initial_call=True, - ) - async def silent_long_task(n_clicks): - # Wait longer than inactivity timeout WITHOUT sending any updates - # This will trigger WebSocket disconnect/reconnect mid-callback - await asyncio.sleep(5) - return f"completed:{n_clicks}" - - dash_duo.start_server(app) - - dash_duo.wait_for_text_to_equal("#output", "ready") - - # Start the long task - dash_duo.find_element("#btn").click() - - # Should complete despite inactivity timeout triggering during execution - dash_duo.wait_for_text_to_equal("#output", "completed:1", timeout=15) - - # Verify subsequent callbacks also work - dash_duo.find_element("#btn").click() - dash_duo.wait_for_text_to_equal("#output", "completed:2", timeout=15) - - assert dash_duo.get_logs() == [] - - -def test_ws036_set_props_after_reconnect(dash_duo): - """Test that set_props works after WebSocket reconnects mid-callback. +def test_ws035_long_callback_with_shutdown_check(dash_duo): + """Test long-running callback that properly checks is_shutdown. - This tests the registry's ability to adopt new queues so that - set_props calls use the new connection after reconnection. + Long-running callbacks should check ws.is_shutdown in their loops to + detect disconnections and exit gracefully. This prevents wasted server + resources when the client disconnects. """ app = Dash( __name__, @@ -419,16 +226,17 @@ def test_ws036_set_props_after_reconnect(dash_duo): Input("btn", "n_clicks"), prevent_initial_call=True, ) - async def task_with_late_set_props(n_clicks): - set_props("status", {"children": "started"}) - set_props("progress", {"children": "10"}) - - # Wait long enough for inactivity timeout to trigger - await asyncio.sleep(5) + async def long_task_with_shutdown_check(n_clicks): + ws = ctx.websocket + set_props("status", {"children": "running"}) - # These set_props calls happen AFTER reconnection - # They should still work via the adopted queue - set_props("progress", {"children": "100"}) + # Properly check is_shutdown in the loop + for i in range(1, 11): + if ws and ws.is_shutdown: + # Exit gracefully on disconnect + raise PreventUpdate + set_props("progress", {"children": str(i * 10)}) + await asyncio.sleep(0.2) return "done" @@ -438,12 +246,8 @@ async def task_with_late_set_props(n_clicks): dash_duo.find_element("#btn").click() - # Should see initial updates - dash_duo.wait_for_text_to_equal("#status", "started", timeout=5) - dash_duo.wait_for_text_to_equal("#progress", "10", timeout=5) - - # Should see final update after reconnection - dash_duo.wait_for_text_to_equal("#progress", "100", timeout=15) - dash_duo.wait_for_text_to_equal("#status", "done", timeout=5) + # Should see progress updates and complete + dash_duo.wait_for_text_to_equal("#status", "done", timeout=10) + dash_duo.wait_for_text_to_equal("#progress", "100") assert dash_duo.get_logs() == [] From be60884b0e2e8296c138cff5a486c06485c0c42c Mon Sep 17 00:00:00 2001 From: AnnMarueW Date: Thu, 28 May 2026 16:55:06 -0700 Subject: [PATCH 291/297] add test --- .../integration/dropdown/test_search_value.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/components/dash-core-components/tests/integration/dropdown/test_search_value.py b/components/dash-core-components/tests/integration/dropdown/test_search_value.py index 83b1b9f59b..2c65b26565 100644 --- a/components/dash-core-components/tests/integration/dropdown/test_search_value.py +++ b/components/dash-core-components/tests/integration/dropdown/test_search_value.py @@ -107,3 +107,41 @@ def send_key(key): last_option.click() dash_duo.wait_for_text_to_equal("#output", "value=opt_100") + + +def test_ddsv003_dropdown_virtualized_component_label_filtering(dash_duo): + app = Dash(__name__) + + options = [ + { + "label": html.Div(["Item ", html.Span(f"#{i}")]), + "value": f"item_{i}", + "search": f"item_{i}", + } + for i in range(1, 2000) + ] + + app.layout = html.Div( + [ + dcc.Dropdown( + id="dd", + options=options, + value="item_1", + searchable=True, + clearable=True, + ) + ] + ) + + dash_duo.start_server(app) + + dropdown = dash_duo.find_element("#dd") + dropdown.click() + + search = dash_duo.find_element(".dash-dropdown-search") + + # trigger filtering path that used to crash virtualized list + search.send_keys("199") + sleep(.5) + + assert dash_duo.get_logs() == [] From 01b57fb746f48ceeac7164026b392796a0a3c223 Mon Sep 17 00:00:00 2001 From: AnnMarueW Date: Thu, 28 May 2026 17:00:49 -0700 Subject: [PATCH 292/297] add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24877dc2ea..f7c10f3d73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). - [#3768](https://github.com/plotly/dash/pull/3768) Improved `Dropdown` search performance for large options lists - [#3759](https://github.com/plotly/dash/pull/3759) Fix the issue where `Patch` objects cannot be updated via `set_props()` in `websocket` callback. Fix [#3742](https://github.com/plotly/dash/issues/3742) - [#3789](https://github.com/plotly/dash/pull/3789) Fixed extra wrapper in `DatePickerRange` and `DatePickerSingle` causing styling and layout issues. +- [#3799](https://github.com/plotly/dash/pull/3799) Fixed dropdown crash when filtering large datasets with component-based labels by using stable item keys for virtualized rows. ## [4.2.0rc3] - 2026-05-12 From 3988d1c3a9dcbdf1d3f6f86fd8ac14169b46af19 Mon Sep 17 00:00:00 2001 From: AnnMarueW Date: Thu, 28 May 2026 18:04:59 -0700 Subject: [PATCH 293/297] lint --- .../tests/integration/dropdown/test_search_value.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dash-core-components/tests/integration/dropdown/test_search_value.py b/components/dash-core-components/tests/integration/dropdown/test_search_value.py index 2c65b26565..ca33cec315 100644 --- a/components/dash-core-components/tests/integration/dropdown/test_search_value.py +++ b/components/dash-core-components/tests/integration/dropdown/test_search_value.py @@ -142,6 +142,6 @@ def test_ddsv003_dropdown_virtualized_component_label_filtering(dash_duo): # trigger filtering path that used to crash virtualized list search.send_keys("199") - sleep(.5) + sleep(0.5) assert dash_duo.get_logs() == [] From 81f148f0329c35698f188db87fd3540633f9affb Mon Sep 17 00:00:00 2001 From: philippe Date: Fri, 29 May 2026 12:21:33 -0400 Subject: [PATCH 294/297] init app check instead of backend blueprint check --- dash/backends/_fastapi.py | 5 ----- dash/backends/_flask.py | 4 ---- dash/backends/_quart.py | 4 ---- dash/dash.py | 10 ++++++++++ 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/dash/backends/_fastapi.py b/dash/backends/_fastapi.py index 960bfd2e1f..c46fb4ffc5 100644 --- a/dash/backends/_fastapi.py +++ b/dash/backends/_fastapi.py @@ -272,11 +272,6 @@ def create_app(name: str = "__main__", config: Dict[str, Any] | None = None): def register_assets_blueprint( self, blueprint_name: str, assets_url_path: str, assets_folder: str ): - # Check if route is already mounted to avoid duplicate registration - # This can happen when init_app() is called multiple times - for route in self.server.routes: - if getattr(route, "name", None) == blueprint_name: - return try: self.server.mount( assets_url_path, diff --git a/dash/backends/_flask.py b/dash/backends/_flask.py index 4ebae2bada..00c8730d8a 100644 --- a/dash/backends/_flask.py +++ b/dash/backends/_flask.py @@ -86,10 +86,6 @@ def create_app(name: str = "__main__", config: Dict[str, Any] | None = None): def register_assets_blueprint( self, blueprint_name: str, assets_url_path: str, assets_folder: str ): - # Check if blueprint is already registered to avoid duplicate registration - # This can happen when init_app() is called multiple times (e.g., with flask run) - if blueprint_name in self.server.blueprints: - return bp = Blueprint( blueprint_name, __name__, diff --git a/dash/backends/_quart.py b/dash/backends/_quart.py index 8b161962b0..8ffd729901 100644 --- a/dash/backends/_quart.py +++ b/dash/backends/_quart.py @@ -122,10 +122,6 @@ def create_app( def register_assets_blueprint( self, blueprint_name: str, assets_url_path: str, assets_folder: str # type: ignore[name-defined] ): - # Check if blueprint is already registered to avoid duplicate registration - # This can happen when init_app() is called multiple times (e.g., with quart run) - if blueprint_name in self.server.blueprints: - return bp = Blueprint( blueprint_name, __name__, diff --git a/dash/dash.py b/dash/dash.py index 7a1cdcd47d..76157a5ceb 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -135,6 +135,8 @@ _ID_STORE = "_pages_store" _ID_DUMMY = "_pages_dummy" +_UNINITIALIZED = object() # Sentinel for tracking init_app state + DASH_VERSION_URL = "https://dash-version.plotly.com:8080/current_version" # Handles the case in a newly cloned environment where the components are not yet generated. @@ -734,6 +736,14 @@ def init_app(self, app: Optional[Any] = None, **kwargs) -> None: # Also update the backend's server reference so routes are registered # on the correct server (important when using server=False pattern) self.backend.server = app + + # Skip registration if already initialized on this server + # This prevents double registration when init_app() is called multiple times + # (e.g., with flask run pattern where __init__ calls init_app, then user does too) + if getattr(self, "_initialized_server", _UNINITIALIZED) is self.server: + return + self._initialized_server = self.server + bp_prefix = config.routes_pathname_prefix.replace("/", "_").replace(".", "_") assets_blueprint_name = f"{bp_prefix}dash_assets" self.backend.register_assets_blueprint( From 8c2329fe263862a5cdb604f6c61230de63b3bff2 Mon Sep 17 00:00:00 2001 From: philippe Date: Mon, 1 Jun 2026 12:30:49 -0400 Subject: [PATCH 295/297] add configuration for heartbeat and proper te\sts for reconnect --- .ai/ARCHITECTURE.md | 2 ++ @plotly/dash-websocket-worker/src/types.ts | 1 + @plotly/dash-websocket-worker/src/worker.ts | 14 +++++++++++--- dash/dash-renderer/src/config.ts | 1 + dash/dash-renderer/src/utils/workerClient.ts | 11 ++++++++--- dash/dash.py | 3 +++ tests/websocket/test_ws_inactivity.py | 5 +++++ tests/websocket/test_ws_reconnect.py | 2 ++ 8 files changed, 33 insertions(+), 6 deletions(-) diff --git a/.ai/ARCHITECTURE.md b/.ai/ARCHITECTURE.md index da9913a13f..6566ef8085 100644 --- a/.ai/ARCHITECTURE.md +++ b/.ai/ARCHITECTURE.md @@ -905,12 +905,14 @@ app = Dash( server=server, websocket_callbacks=True, websocket_inactivity_timeout=300000, # 5 minutes (default) + websocket_heartbeat_interval=30000, # 30 seconds (default) websocket_allowed_origins=['https://example.com'], ) ``` - **`websocket_callbacks`** - Enable WebSocket for all callbacks (default: `False`) - **`websocket_inactivity_timeout`** - Close WebSocket after period of inactivity in milliseconds (default: `300000` = 5 minutes). Heartbeats do not count as activity. Set to `0` to disable timeout. Connection automatically reconnects when needed. +- **`websocket_heartbeat_interval`** - Interval for heartbeat/keep-alive checks in milliseconds (default: `30000` = 30 seconds). Also determines how frequently inactivity timeout is checked. - **`websocket_allowed_origins`** - List of allowed origins for WebSocket connections (security) ### Architecture diff --git a/@plotly/dash-websocket-worker/src/types.ts b/@plotly/dash-websocket-worker/src/types.ts index 3d88af068a..fdc8112ada 100644 --- a/@plotly/dash-websocket-worker/src/types.ts +++ b/@plotly/dash-websocket-worker/src/types.ts @@ -40,6 +40,7 @@ export interface ConnectMessage extends WorkerMessage { payload: { serverUrl: string; inactivityTimeout?: number; + heartbeatInterval?: number; }; } diff --git a/@plotly/dash-websocket-worker/src/worker.ts b/@plotly/dash-websocket-worker/src/worker.ts index e28d0c1583..d2860c6974 100644 --- a/@plotly/dash-websocket-worker/src/worker.ts +++ b/@plotly/dash-websocket-worker/src/worker.ts @@ -81,16 +81,24 @@ self.onconnect = (event: MessageEvent) => { const rendererId = connectMsg.rendererId; const newServerUrl = connectMsg.payload.serverUrl; const inactivityTimeout = connectMsg.payload.inactivityTimeout; + const heartbeatInterval = connectMsg.payload.heartbeatInterval; // Register the renderer router.registerRenderer(rendererId, port); rendererIds.add(rendererId); - console.log(`[DashWSWorker] Renderer ${rendererId} connected, inactivityTimeout: ${inactivityTimeout}`); + console.log(`[DashWSWorker] Renderer ${rendererId} connected, inactivityTimeout: ${inactivityTimeout}, heartbeatInterval: ${heartbeatInterval}`); - // Update inactivity timeout if provided + // Update config if provided + const configUpdate: {inactivityTimeout?: number; heartbeatInterval?: number} = {}; if (typeof inactivityTimeout === 'number') { - wsManager.setConfig({ inactivityTimeout }); + configUpdate.inactivityTimeout = inactivityTimeout; + } + if (typeof heartbeatInterval === 'number') { + configUpdate.heartbeatInterval = heartbeatInterval; + } + if (Object.keys(configUpdate).length > 0) { + wsManager.setConfig(configUpdate); } // Connect to server if not already connected diff --git a/dash/dash-renderer/src/config.ts b/dash/dash-renderer/src/config.ts index 6eb9e27b58..86d804bb57 100644 --- a/dash/dash-renderer/src/config.ts +++ b/dash/dash-renderer/src/config.ts @@ -27,6 +27,7 @@ export type DashConfig = { url: string; worker_url: string; inactivity_timeout?: number; + heartbeat_interval?: number; }; csrf_token_name?: string; csrf_header_name?: string; diff --git a/dash/dash-renderer/src/utils/workerClient.ts b/dash/dash-renderer/src/utils/workerClient.ts index ebfb1223eb..1c07a4c1c3 100644 --- a/dash/dash-renderer/src/utils/workerClient.ts +++ b/dash/dash-renderer/src/utils/workerClient.ts @@ -87,11 +87,13 @@ class WorkerClient { * @param workerUrl URL to the SharedWorker script * @param serverUrl WebSocket server URL * @param inactivityTimeout Optional inactivity timeout in ms + * @param heartbeatInterval Optional heartbeat interval in ms */ public async connect( workerUrl: string, serverUrl: string, - inactivityTimeout?: number + inactivityTimeout?: number, + heartbeatInterval?: number ): Promise { if (this.worker) { // Already connected @@ -120,7 +122,8 @@ class WorkerClient { rendererId: this.rendererId, payload: { serverUrl, - inactivityTimeout + inactivityTimeout, + heartbeatInterval } }); @@ -160,6 +163,7 @@ class WorkerClient { url?: string; worker_url?: string; inactivity_timeout?: number; + heartbeat_interval?: number; }; }): Promise { // Already connected @@ -191,7 +195,8 @@ class WorkerClient { await this.connect( config.websocket.worker_url, wsUrl, - config.websocket.inactivity_timeout + config.websocket.inactivity_timeout, + config.websocket.heartbeat_interval ); } diff --git a/dash/dash.py b/dash/dash.py index 76157a5ceb..f547b95b56 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -488,6 +488,7 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches websocket_callbacks: Optional[bool] = False, websocket_allowed_origins: Optional[List[str]] = None, websocket_inactivity_timeout: Optional[int] = 300000, + websocket_heartbeat_interval: Optional[int] = 30000, websocket_batch_delay: Optional[float] = 0.005, **obsolete, ): @@ -648,6 +649,7 @@ def __init__( # pylint: disable=too-many-statements, too-many-branches self._websocket_callbacks = websocket_callbacks self._websocket_allowed_origins = websocket_allowed_origins or [] self._websocket_inactivity_timeout = websocket_inactivity_timeout + self._websocket_heartbeat_interval = websocket_heartbeat_interval self._websocket_batch_delay = websocket_batch_delay self.logger = logging.getLogger(__name__) @@ -998,6 +1000,7 @@ def _config(self): "url": self.config.requests_pathname_prefix + "_dash-ws-callback", "worker_url": self._get_worker_url(), "inactivity_timeout": self._websocket_inactivity_timeout, + "heartbeat_interval": self._websocket_heartbeat_interval, } return config diff --git a/tests/websocket/test_ws_inactivity.py b/tests/websocket/test_ws_inactivity.py index 8dd95e1094..f9242b9af9 100644 --- a/tests/websocket/test_ws_inactivity.py +++ b/tests/websocket/test_ws_inactivity.py @@ -19,6 +19,7 @@ def test_ws020_inactivity_timeout_closes(dash_duo): backend="fastapi", websocket_callbacks=True, websocket_inactivity_timeout=3000, # 3 seconds for testing + websocket_heartbeat_interval=1000, # 1 second - check inactivity frequently ) app.layout = html.Div( @@ -54,6 +55,7 @@ def test_ws021_activity_resets_timer(dash_duo): backend="fastapi", websocket_callbacks=True, websocket_inactivity_timeout=4000, # 4 seconds + websocket_heartbeat_interval=1000, # 1 second - check inactivity frequently ) app.layout = html.Div( @@ -88,6 +90,7 @@ def test_ws022_quick_successive_callbacks(dash_duo): backend="fastapi", websocket_callbacks=True, websocket_inactivity_timeout=5000, + websocket_heartbeat_interval=1000, # 1 second - check inactivity frequently ) app.layout = html.Div( @@ -121,6 +124,7 @@ def test_ws023_auto_reconnect_after_timeout(dash_duo): backend="fastapi", websocket_callbacks=True, websocket_inactivity_timeout=2000, # 2 seconds + websocket_heartbeat_interval=1000, # 1 second - check inactivity frequently ) app.layout = html.Div( @@ -164,6 +168,7 @@ def test_ws024_long_callback_doesnt_timeout(dash_duo): backend="fastapi", websocket_callbacks=True, websocket_inactivity_timeout=3000, # 3 seconds + websocket_heartbeat_interval=1000, # 1 second - check inactivity frequently ) app.layout = html.Div( diff --git a/tests/websocket/test_ws_reconnect.py b/tests/websocket/test_ws_reconnect.py index 51eeb38ae3..e7e5efd065 100644 --- a/tests/websocket/test_ws_reconnect.py +++ b/tests/websocket/test_ws_reconnect.py @@ -118,6 +118,7 @@ def test_ws033_callback_after_reconnect(dash_duo): backend="fastapi", websocket_callbacks=True, websocket_inactivity_timeout=2000, # 2 seconds + websocket_heartbeat_interval=1000, # 1 second - check inactivity frequently ) app.layout = html.Div( @@ -211,6 +212,7 @@ def test_ws035_long_callback_with_shutdown_check(dash_duo): backend="fastapi", websocket_callbacks=True, websocket_inactivity_timeout=2000, # 2 seconds + websocket_heartbeat_interval=1000, # 1 second - check inactivity frequently ) app.layout = html.Div( From 6c3fdab80eb2f84a3a9cedd920e5e82f3fe8290c Mon Sep 17 00:00:00 2001 From: philippe Date: Mon, 1 Jun 2026 15:01:48 -0400 Subject: [PATCH 296/297] Version 4.2.0 --- CHANGELOG.md | 110 +- .../dash-core-components/package-lock.json | 1394 ++++---- components/dash-core-components/package.json | 2 +- .../dash-html-components/package-lock.json | 2610 +++++++-------- components/dash-html-components/package.json | 2 +- components/dash-table/package-lock.json | 1430 ++++----- components/dash-table/package.json | 2 +- dash/_dash_renderer.py | 4 +- dash/dash-renderer/package-lock.json | 2855 +++++++++-------- dash/dash-renderer/package.json | 2 +- dash/version.py | 2 +- 11 files changed, 4295 insertions(+), 4118 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de46b967d3..32dc3f3136 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,45 +4,92 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## [UNRELEASED] -## Added -- [#3783](https://github.com/plotly/dash/pull/3783) Add batching/debouncing for websocket `set_props` messages to reduce lag when updating multiple components in a loop. Configurable via `websocket_batch_delay` (default 5ms, set to 0 to disable). -- [#3669](https://github.com/plotly/dash/pull/3669) Selection for DataTable cleared with custom action settings -- [#3680](https://github.com/plotly/dash/pull/3680) Added `search_order` prop to `Dropdown` to allow users to preserve original option order during search -- Added `csrf_token_name` and `csrf_header_name` config options to allow configuring the CSRF cookie and header names. Fixes [#729](https://github.com/plotly/dash/issues/729) -- [#3797](https://github.com/plotly/dash/pull/3797) Improved websocket callback management. -- [#3523](https://github.com/plotly/dash/pull/3523) Fall back to background callback function names if source cannot be found -- [#3785](https://github.com/plotly/dash/pull/3785) Fix patch with dcc.Graph figure. -- [#3785](https://github.com/plotly/dash/pull/3785) Fix dcc.Graph not sending duplicate clicks because it had the same payload by adding a timestamp in the click event object. +## [4.2.0] - 2026-06-01 - *The Freedom Update* -## Fixed -- [#3690](https://github.com/plotly/dash/pull/3690) Fixes Input when min or max is set to None -- [#3723](https://github.com/plotly/dash/pull/3723) Fix misaligned `dcc.Slider` marks when some labels are empty strings -- [#3738](https://github.com/plotly/dash/pull/3738) Add missing `stacklevel=2` to `warnings.warn()` calls so warnings report the caller's location instead of internal Dash source lines -- [#3740](https://github.com/plotly/dash/pull/3740) Fix cannot tab into dropdowns in Safari -- [#2462](https://github.com/plotly/dash/issues/2462) Allow `MATCH` in `Input`/`State` when the callback's `Output` has no wildcards (fixed-id Output, no Output, or `ALL`-only wildcard Output). `ALLSMALLER` still requires a corresponding `MATCH` in an Output. -- [#3768](https://github.com/plotly/dash/pull/3768) Improved `Dropdown` search performance for large options lists -- [#3759](https://github.com/plotly/dash/pull/3759) Fix the issue where `Patch` objects cannot be updated via `set_props()` in `websocket` callback. Fix [#3742](https://github.com/plotly/dash/issues/3742) -- [#3789](https://github.com/plotly/dash/pull/3789) Fixed extra wrapper in `DatePickerRange` and `DatePickerSingle` causing styling and layout issues. -- [#3799](https://github.com/plotly/dash/pull/3799) Fixed dropdown crash when filtering large datasets with component-based labels by using stable item keys for virtualized rows. +This release marks a major milestone for Dash, bringing unprecedented flexibility to how you build and deploy your applications. -## [4.2.0rc3] - 2026-05-12 +### 🚀 Multiple Backend Support +Dash is no longer tied to Flask. You can now run your Dash apps on **FastAPI** or **Quart**, or even bring your own backend implementation: -- [#3771](https://github.com/plotly/dash/pull/3771) Add persistent callbacks and no inputs/no outputs callback support. -- Rename ctx.get_websocket to ctx.websocket +```python +# FastAPI backend +app = Dash(__name__, backend="fastapi") -## [4.2.0rc2] - 2026-05-01 +# Quart backend (async-native) +app = Dash(__name__, backend="quart") -## Fixed -- [#3759](https://github.com/plotly/dash/pull/3759) Fix the error when using `set_props()` to update component-type properties in the `websocket` callback. -- Add threadpool for running websocket callbacks. +# Or use an existing server +from fastapi import FastAPI +server = FastAPI() +app = Dash(__name__, server=server) +``` + +Install with `pip install dash[fastapi]` or `pip install dash[quart]`. + +### ⚡ Websocket Callbacks +Real-time, bidirectional communication is here. Websocket callbacks enable persistent connections for live updates without polling: + +```python +@callback( + Output("live-output", "children"), + Input("trigger", "n_clicks"), + websocket=True, + persistent=True +) +def live_updates(n_clicks): + ws = ctx.websocket + while True: + data = fetch_live_data() + ws.send(Output("live-output", "children", data)) + time.sleep(1) +``` -## [4.2.0rc1] - 2026-04-13 +### 🔓 Relaxed Pattern Matching Rules +`MATCH` wildcards are now allowed in `Input` and `State` even when your `Output` has no wildcards, making dynamic UIs simpler to build: + +```python +@callback( + Output("summary", "children"), # Fixed ID output + Input({"type": "item", "index": MATCH}, "value") # MATCH input - now allowed! +) +def update_summary(value): + return f"Selected: {value}" +``` + +--- ## Added +- [#3783](https://github.com/plotly/dash/pull/3783) Add batching/debouncing for websocket `set_props` messages to reduce lag when updating multiple components in a loop. Configurable via `websocket_batch_delay` (default 5ms, set to 0 to disable). +- [#3669](https://github.com/plotly/dash/pull/3669) Selection for DataTable cleared with custom action settings. +- [#3680](https://github.com/plotly/dash/pull/3680) Added `search_order` prop to `Dropdown` to allow users to preserve original option order during search. +- [#3745](https://github.com/plotly/dash/pull/3745) Added `csrf_token_name` and `csrf_header_name` config options to allow configuring the CSRF cookie and header names. Fixes [#729](https://github.com/plotly/dash/issues/729). +- [#3797](https://github.com/plotly/dash/pull/3797) Improved websocket callback management with heartbeat configuration and proper reconnection handling. +- [#3523](https://github.com/plotly/dash/pull/3523) Fall back to background callback function names if source cannot be found. +- [#3771](https://github.com/plotly/dash/pull/3771) Add persistent callbacks and no inputs/no outputs callback support. - [#3742](https://github.com/plotly/dash/pull/3742) Add websocket callbacks to fastapi and quart backends. +- [#3737](https://github.com/plotly/dash/pull/3737) Add `displayNotifier` to `dcc.Graph` config props. ## Changed -- [#3691] Improve static typing for `dash.callback` by preserving wrapped callback signatures, and add callback typing coverage in compliance plus new callback decorator unit and integration tests. +- [#3746](https://github.com/plotly/dash/pull/3746) Improve static typing for `dash.callback` by preserving wrapped callback signatures, and add callback typing coverage in compliance plus new callback decorator unit and integration tests. Fixes [#3691](https://github.com/plotly/dash/issues/3691). +- Rename `ctx.get_websocket` to `ctx.websocket`. +- Add threadpool for running websocket callbacks. + +## Fixed +- [#3690](https://github.com/plotly/dash/pull/3690) Fix `dcc.Input` when min or max is set to None. +- [#3723](https://github.com/plotly/dash/pull/3723) Fix misaligned `dcc.Slider` marks when some labels are empty strings. +- [#3738](https://github.com/plotly/dash/pull/3738) Add missing `stacklevel=2` to `warnings.warn()` calls so warnings report the caller's location instead of internal Dash source lines. +- [#3740](https://github.com/plotly/dash/pull/3740) Fix cannot tab into dropdowns in Safari. +- [#3756](https://github.com/plotly/dash/pull/3756) Allow `MATCH` in `Input`/`State` when the callback's `Output` has no wildcards (fixed-id Output, no Output, or `ALL`-only wildcard Output). `ALLSMALLER` still requires a corresponding `MATCH` in an Output. Fixes [#2462](https://github.com/plotly/dash/issues/2462). +- [#3768](https://github.com/plotly/dash/pull/3768) Improved `Dropdown` search performance for large options lists. +- [#3759](https://github.com/plotly/dash/pull/3759) Fix the issue where `Patch` objects cannot be updated via `set_props()` in `websocket` callback. Fix [#3742](https://github.com/plotly/dash/issues/3742). +- [#3789](https://github.com/plotly/dash/pull/3789) Fixed extra wrapper in `DatePickerRange` and `DatePickerSingle` causing styling and layout issues. +- [#3799](https://github.com/plotly/dash/pull/3799) Fixed dropdown crash when filtering large datasets with component-based labels by using stable item keys for virtualized rows. +- [#3785](https://github.com/plotly/dash/pull/3785) Fix patch with `dcc.Graph` figure. Fix `dcc.Graph` not sending duplicate clicks because it had the same payload by adding a timestamp in the click event object. +- [#3798](https://github.com/plotly/dash/pull/3798) Fix blueprint registering and double init when using `flask run` command. Fixes [#3787](https://github.com/plotly/dash/issues/3787). +- [#3734](https://github.com/plotly/dash/pull/3734) Fix websocket used in the same FastAPI server. Fixes [#3636](https://github.com/plotly/dash/issues/3636). +- [#3668](https://github.com/plotly/dash/pull/3668) Fix FastAPI url paths order. Fixes [#3667](https://github.com/plotly/dash/issues/3667). +- [#3641](https://github.com/plotly/dash/pull/3641) Fix `dcc.Loading` spinner not triggering when callback `Output` uses the `ALL` wildcard. Fixes [#3619](https://github.com/plotly/dash/issues/3619). +- [#3570](https://github.com/plotly/dash/pull/3570) Fix components not remounting when passed from a parent object. Fixes [#3330](https://github.com/plotly/dash/issues/3330). ## [4.1.0] - 2026-03-23 @@ -59,13 +106,6 @@ This project adheres to [Semantic Versioning](https://semver.org/). - [#3609](https://github.com/plotly/dash/pull/3609) Add backward compat alias for _Wildcard - [#3672](https://github.com/plotly/dash/pull/3672) Improve browser performance when app contains a large number of pattern matching callback callbacks. Exposes an api endpoint to fetch the latest computeGraph call. -# [4.2.0rc0] - 2026-04-13 - -## Fixed - -- Fix websocket used in the same FastAPI server. Fix [#3636](https://github.com/plotly/dash/issues/3636) -- Fix FastAPI url paths order. Fix [3667](https://github.com/plotly/dash/issues/3667) - # [4.1.0rc0] - 2026-02-23 ## Added diff --git a/components/dash-core-components/package-lock.json b/components/dash-core-components/package-lock.json index aa57e966ce..b838bafda8 100644 --- a/components/dash-core-components/package-lock.json +++ b/components/dash-core-components/package-lock.json @@ -1,12 +1,12 @@ { "name": "dash-core-components", - "version": "4.1.0", + "version": "4.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dash-core-components", - "version": "4.1.0", + "version": "4.2.0", "license": "MIT", "dependencies": { "@fortawesome/fontawesome-svg-core": "1.2.36", @@ -133,9 +133,9 @@ "license": "ISC" }, "node_modules/@babel/cli": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.28.6.tgz", - "integrity": "sha512-6EUNcuBbNkj08Oj4gAZ+BUU8yLCgKzgVX4gaTh09Ya2C8ICM4P+G30g4m3akRxSYAp3A/gnWchrNst7px4/nUQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.29.7.tgz", + "integrity": "sha512-/75HwRbAYPqXv/Ax1h7Fg3IZfXgdU98jnA8H93/m/QBaPV3Hp5ICoLqzGYye1yHBCgpmXvtqgSUN8oOKX5tojQ==", "dev": true, "license": "MIT", "dependencies": { @@ -163,12 +163,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -177,29 +177,29 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", - "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", - "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "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", @@ -216,9 +216,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.28.6.tgz", - "integrity": "sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.29.7.tgz", + "integrity": "sha512-zxt+UJTOMKvUt3yOg+D58MLuz334pHp93qifMFcjIIO+9hN6t+ufw2gi7vDPMpxvfnHRR+3VVXvIjineCcgyXw==", "dev": true, "license": "MIT", "dependencies": { @@ -244,13 +244,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", - "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6", + "@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" @@ -260,26 +260,26 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "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==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.6", - "@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" @@ -289,18 +289,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", - "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.6", + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", "semver": "^6.3.1" }, "engines": { @@ -311,13 +311,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", - "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz", + "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-annotate-as-pure": "^7.29.7", "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, @@ -329,67 +329,67 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", - "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "debug": "^4.4.1", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", "lodash.debounce": "^4.0.8", - "resolve": "^1.22.10" + "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", - "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "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==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -399,22 +399,22 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "dev": true, "license": "MIT", "engines": { @@ -422,15 +422,15 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", - "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz", + "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-wrap-function": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-wrap-function": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -440,15 +440,15 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", - "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.28.6" + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -458,81 +458,81 @@ } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", "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-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==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "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==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "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==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", - "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz", + "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", - "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.28.6" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -542,14 +542,14 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", - "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz", + "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -559,13 +559,13 @@ } }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz", + "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -575,13 +575,30 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz", + "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz", + "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -591,15 +608,15 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz", + "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -609,14 +626,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", - "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz", + "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -705,13 +722,13 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", - "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz", + "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -721,13 +738,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", - "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -763,13 +780,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -889,13 +906,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz", + "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -921,13 +938,13 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", - "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -937,15 +954,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.6.tgz", - "integrity": "sha512-9knsChgsMzBV5Yh3kkhrZNxH3oCYAfMBkNNaVN4cP2RVlFPe8wYdwwcnOsAbkdDoV9UjFtOXWrWB52M8W4jNeA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz", + "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -955,15 +972,15 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", - "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz", + "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -973,13 +990,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", - "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz", + "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -989,13 +1006,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", - "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz", + "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1005,14 +1022,14 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", - "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz", + "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1022,14 +1039,14 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", - "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz", + "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1039,18 +1056,18 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", - "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz", + "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1060,14 +1077,14 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", - "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.29.7.tgz", + "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/template": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/template": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1077,14 +1094,14 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", - "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz", + "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1094,14 +1111,14 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", - "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz", + "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1111,13 +1128,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", - "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz", + "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1127,14 +1144,14 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.28.6.tgz", - "integrity": "sha512-5suVoXjC14lUN6ZL9OLKIHCNVWCrqGqlmEp/ixdXjvgnEl/kauLvvMO/Xw9NyMc95Joj1AeLVPVMvibBgSoFlA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1144,13 +1161,13 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz", + "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1160,14 +1177,14 @@ } }, "node_modules/@babel/plugin-transform-explicit-resource-management": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", - "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz", + "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1177,13 +1194,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", - "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz", + "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1193,13 +1210,13 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz", + "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1209,14 +1226,14 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", - "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz", + "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1226,15 +1243,15 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", - "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz", + "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1244,13 +1261,13 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", - "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz", + "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1260,13 +1277,13 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", - "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz", + "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1276,13 +1293,13 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", - "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz", + "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1292,13 +1309,13 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", - "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz", + "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1308,14 +1325,14 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", - "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz", + "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1325,14 +1342,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", - "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz", + "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1342,16 +1359,16 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz", - "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz", + "integrity": "sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.5" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1361,14 +1378,14 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", - "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz", + "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1378,14 +1395,14 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1395,13 +1412,13 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", - "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz", + "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1411,13 +1428,13 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", - "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz", + "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1427,13 +1444,13 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", - "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz", + "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1443,17 +1460,17 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", - "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz", + "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.6" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1463,14 +1480,14 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", - "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz", + "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1480,13 +1497,13 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", - "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz", + "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1496,14 +1513,14 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", - "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz", + "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1513,13 +1530,13 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", - "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz", + "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1529,14 +1546,14 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", - "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz", + "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1546,15 +1563,15 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", - "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz", + "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1564,13 +1581,13 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", - "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz", + "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1580,13 +1597,13 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz", - "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.29.7.tgz", + "integrity": "sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1596,17 +1613,17 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", - "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.29.7.tgz", + "integrity": "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1616,13 +1633,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz", - "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.29.7.tgz", + "integrity": "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.27.1" + "@babel/plugin-transform-react-jsx": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1632,14 +1649,14 @@ } }, "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz", - "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.29.7.tgz", + "integrity": "sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1649,13 +1666,13 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.6.tgz", - "integrity": "sha512-eZhoEZHYQLL5uc1gS5e9/oTknS0sSSAtd5TkKMUp3J+S/CaUjagc0kOUPsEbDmMeva0nC3WWl4SxVY6+OBuxfw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.7.tgz", + "integrity": "sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1665,14 +1682,14 @@ } }, "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", - "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz", + "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1682,13 +1699,13 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", - "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz", + "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1698,13 +1715,13 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", - "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.29.7.tgz", + "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1714,14 +1731,14 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", - "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.29.7.tgz", + "integrity": "sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1731,13 +1748,13 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", - "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.29.7.tgz", + "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1747,13 +1764,13 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", - "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.29.7.tgz", + "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1763,13 +1780,13 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", - "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz", + "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1779,17 +1796,17 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz", - "integrity": "sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.29.7.tgz", + "integrity": "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-syntax-typescript": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-syntax-typescript": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1799,13 +1816,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", - "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz", + "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1815,14 +1832,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", - "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz", + "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1832,14 +1849,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", - "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz", + "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1849,14 +1866,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", - "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz", + "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1866,81 +1883,82 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.6.tgz", - "integrity": "sha512-GaTI4nXDrs7l0qaJ6Rg06dtOXTBCG6TMDB44zbqofCIC4PqC7SEvmFFtpxzCDw9W5aJ7RKVshgXTLvLdBFV/qw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.7.tgz", + "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.28.6", - "@babel/plugin-syntax-import-attributes": "^7.28.6", + "@babel/plugin-syntax-import-assertions": "^7.29.7", + "@babel/plugin-syntax-import-attributes": "^7.29.7", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.28.6", - "@babel/plugin-transform-async-to-generator": "^7.28.6", - "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.6", - "@babel/plugin-transform-class-properties": "^7.28.6", - "@babel/plugin-transform-class-static-block": "^7.28.6", - "@babel/plugin-transform-classes": "^7.28.6", - "@babel/plugin-transform-computed-properties": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-dotall-regex": "^7.28.6", - "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.28.6", - "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-explicit-resource-management": "^7.28.6", - "@babel/plugin-transform-exponentiation-operator": "^7.28.6", - "@babel/plugin-transform-export-namespace-from": "^7.27.1", - "@babel/plugin-transform-for-of": "^7.27.1", - "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.28.6", - "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", - "@babel/plugin-transform-member-expression-literals": "^7.27.1", - "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.28.6", - "@babel/plugin-transform-modules-systemjs": "^7.28.5", - "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", - "@babel/plugin-transform-numeric-separator": "^7.28.6", - "@babel/plugin-transform-object-rest-spread": "^7.28.6", - "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.28.6", - "@babel/plugin-transform-optional-chaining": "^7.28.6", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/plugin-transform-private-methods": "^7.28.6", - "@babel/plugin-transform-private-property-in-object": "^7.28.6", - "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.28.6", - "@babel/plugin-transform-regexp-modifiers": "^7.28.6", - "@babel/plugin-transform-reserved-words": "^7.27.1", - "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.28.6", - "@babel/plugin-transform-sticky-regex": "^7.27.1", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/plugin-transform-typeof-symbol": "^7.27.1", - "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.28.6", - "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", + "@babel/plugin-transform-arrow-functions": "^7.29.7", + "@babel/plugin-transform-async-generator-functions": "^7.29.7", + "@babel/plugin-transform-async-to-generator": "^7.29.7", + "@babel/plugin-transform-block-scoped-functions": "^7.29.7", + "@babel/plugin-transform-block-scoping": "^7.29.7", + "@babel/plugin-transform-class-properties": "^7.29.7", + "@babel/plugin-transform-class-static-block": "^7.29.7", + "@babel/plugin-transform-classes": "^7.29.7", + "@babel/plugin-transform-computed-properties": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-dotall-regex": "^7.29.7", + "@babel/plugin-transform-duplicate-keys": "^7.29.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-dynamic-import": "^7.29.7", + "@babel/plugin-transform-explicit-resource-management": "^7.29.7", + "@babel/plugin-transform-exponentiation-operator": "^7.29.7", + "@babel/plugin-transform-export-namespace-from": "^7.29.7", + "@babel/plugin-transform-for-of": "^7.29.7", + "@babel/plugin-transform-function-name": "^7.29.7", + "@babel/plugin-transform-json-strings": "^7.29.7", + "@babel/plugin-transform-literals": "^7.29.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.29.7", + "@babel/plugin-transform-member-expression-literals": "^7.29.7", + "@babel/plugin-transform-modules-amd": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-modules-systemjs": "^7.29.7", + "@babel/plugin-transform-modules-umd": "^7.29.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-new-target": "^7.29.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7", + "@babel/plugin-transform-numeric-separator": "^7.29.7", + "@babel/plugin-transform-object-rest-spread": "^7.29.7", + "@babel/plugin-transform-object-super": "^7.29.7", + "@babel/plugin-transform-optional-catch-binding": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/plugin-transform-private-methods": "^7.29.7", + "@babel/plugin-transform-private-property-in-object": "^7.29.7", + "@babel/plugin-transform-property-literals": "^7.29.7", + "@babel/plugin-transform-regenerator": "^7.29.7", + "@babel/plugin-transform-regexp-modifiers": "^7.29.7", + "@babel/plugin-transform-reserved-words": "^7.29.7", + "@babel/plugin-transform-shorthand-properties": "^7.29.7", + "@babel/plugin-transform-spread": "^7.29.7", + "@babel/plugin-transform-sticky-regex": "^7.29.7", + "@babel/plugin-transform-template-literals": "^7.29.7", + "@babel/plugin-transform-typeof-symbol": "^7.29.7", + "@babel/plugin-transform-unicode-escapes": "^7.29.7", + "@babel/plugin-transform-unicode-property-regex": "^7.29.7", + "@babel/plugin-transform-unicode-regex": "^7.29.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.29.7", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.14", - "babel-plugin-polyfill-corejs3": "^0.13.0", - "babel-plugin-polyfill-regenerator": "^0.6.5", - "core-js-compat": "^3.43.0", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", "semver": "^6.3.1" }, "engines": { @@ -1965,18 +1983,18 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz", - "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.29.7.tgz", + "integrity": "sha512-C+PV1TFUPTmBQGoPBL8j2QmLpZ117YTCwxIZeJOM96GbYMFSc7/pOXU5lVykwnZxyTqQxRsvoRk6f2FktZgGHA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-transform-react-display-name": "^7.28.0", - "@babel/plugin-transform-react-jsx": "^7.27.1", - "@babel/plugin-transform-react-jsx-development": "^7.27.1", - "@babel/plugin-transform-react-pure-annotations": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-transform-react-display-name": "^7.29.7", + "@babel/plugin-transform-react-jsx": "^7.29.7", + "@babel/plugin-transform-react-jsx-development": "^7.29.7", + "@babel/plugin-transform-react-pure-annotations": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1986,17 +2004,17 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", - "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.29.7.tgz", + "integrity": "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@babel/plugin-transform-typescript": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-typescript": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -2017,31 +2035,31 @@ } }, "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@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.28.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", - "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6", + "@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": { @@ -2049,13 +2067,13 @@ } }, "node_modules/@babel/types": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", - "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -4779,28 +4797,10 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "license": "MIT" }, "node_modules/@types/fast-isnumeric": { @@ -6033,14 +6033,14 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", - "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.7", - "@babel/helper-define-polyfill-provider": "^0.6.5", + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" }, "peerDependencies": { @@ -6048,27 +6048,27 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", - "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5", - "core-js-compat": "^3.43.0" + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", - "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5" + "@babel/helper-define-polyfill-provider": "^0.6.8" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -6254,11 +6254,12 @@ } }, "node_modules/browserify-sign": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", - "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.6.tgz", + "integrity": "sha512-sd+Q65fjlWCYWtZKXiKfrUc8d+4jtp/8f0W2NkwzLtoW4bI6UDnWusLWIurHnmurW0XShIRxpwiOX4EoPtXUAg==", + "license": "ISC", "dependencies": { - "bn.js": "^5.2.2", + "bn.js": "^5.2.3", "browserify-rsa": "^4.1.1", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", @@ -6829,13 +6830,13 @@ "hasInstallScript": true }, "node_modules/core-js-compat": { - "version": "3.44.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.44.0.tgz", - "integrity": "sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.25.1" + "browserslist": "^4.28.1" }, "funding": { "type": "opencollective", @@ -7163,9 +7164,9 @@ } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -7496,13 +7497,13 @@ "dev": true }, "node_modules/enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.1.tgz", + "integrity": "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.3" }, "engines": { "node": ">=10.13.0" @@ -7707,9 +7708,9 @@ } }, "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "license": "MIT" }, "node_modules/es-object-atoms": { @@ -8372,9 +8373,9 @@ "dev": true }, "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "funding": [ { "type": "github", @@ -8384,7 +8385,8 @@ "type": "opencollective", "url": "https://opencollective.com/fastify" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/fastest-levenshtein": { "version": "1.0.16", @@ -12302,7 +12304,8 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -12431,9 +12434,9 @@ } }, "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", "license": "MIT", "engines": { "node": ">=6.11.5" @@ -12514,6 +12517,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } @@ -12669,20 +12673,10 @@ "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==" }, "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -12763,9 +12757,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.10.tgz", - "integrity": "sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "dev": true, "funding": [ { @@ -12773,6 +12767,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -13607,9 +13602,9 @@ } }, "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { @@ -13625,10 +13620,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -13852,9 +13848,10 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", - "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" }, @@ -14380,13 +14377,14 @@ } }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -14945,10 +14943,11 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -15373,9 +15372,9 @@ "license": "MIT" }, "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "license": "MIT", "engines": { "node": ">=6" @@ -15386,9 +15385,9 @@ } }, "node_modules/terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", + "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -15404,9 +15403,10 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", - "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", @@ -15424,21 +15424,48 @@ "webpack": "^5.1.0" }, "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, "@swc/core": { "optional": true }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, "esbuild": { "optional": true }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, "uglify-js": { "optional": true } } }, "node_modules/terser/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -16276,9 +16303,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", - "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", @@ -16299,36 +16326,34 @@ } }, "node_modules/webpack": { - "version": "5.104.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", - "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", + "version": "5.107.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.2.tgz", + "integrity": "sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==", "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.4", - "es-module-lexer": "^2.0.0", + "enhanced-resolve": "^5.22.0", + "es-module-lexer": "^2.1.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.4.4", - "webpack-sources": "^3.3.3" + "terser-webpack-plugin": "^5.5.0", + "watchpack": "^2.5.1", + "webpack-sources": "^3.5.0" }, "bin": { "webpack": "bin/webpack.js" @@ -16415,18 +16440,18 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", "license": "MIT", "engines": { "node": ">=10.13.0" } }, "node_modules/webpack/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -16790,9 +16815,9 @@ } }, "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "dev": true, "license": "MIT", "engines": { @@ -16852,7 +16877,8 @@ "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" }, "node_modules/yargs": { "version": "16.2.0", diff --git a/components/dash-core-components/package.json b/components/dash-core-components/package.json index ffe7de1d2f..0d3583c9df 100644 --- a/components/dash-core-components/package.json +++ b/components/dash-core-components/package.json @@ -1,6 +1,6 @@ { "name": "dash-core-components", - "version": "4.1.0", + "version": "4.2.0", "description": "Core component suite for Dash", "repository": { "type": "git", diff --git a/components/dash-html-components/package-lock.json b/components/dash-html-components/package-lock.json index 22e9d65461..4a311a311b 100644 --- a/components/dash-html-components/package-lock.json +++ b/components/dash-html-components/package-lock.json @@ -1,12 +1,12 @@ { "name": "dash-html-components", - "version": "4.1.0", + "version": "4.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "dash-html-components", - "version": "4.1.0", + "version": "4.2.0", "license": "MIT", "dependencies": { "prop-types": "^15.8.1", @@ -46,9 +46,9 @@ } }, "node_modules/@babel/cli": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.28.6.tgz", - "integrity": "sha512-6EUNcuBbNkj08Oj4gAZ+BUU8yLCgKzgVX4gaTh09Ya2C8ICM4P+G30g4m3akRxSYAp3A/gnWchrNst7px4/nUQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.29.7.tgz", + "integrity": "sha512-/75HwRbAYPqXv/Ax1h7Fg3IZfXgdU98jnA8H93/m/QBaPV3Hp5ICoLqzGYye1yHBCgpmXvtqgSUN8oOKX5tojQ==", "dev": true, "license": "MIT", "dependencies": { @@ -76,13 +76,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "version": "7.29.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.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -91,9 +91,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", - "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "engines": { @@ -101,21 +101,21 @@ } }, "node_modules/@babel/core": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", - "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", + "version": "7.29.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.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6", + "@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", @@ -132,9 +132,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.28.6.tgz", - "integrity": "sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.29.7.tgz", + "integrity": "sha512-zxt+UJTOMKvUt3yOg+D58MLuz334pHp93qifMFcjIIO+9hN6t+ufw2gi7vDPMpxvfnHRR+3VVXvIjineCcgyXw==", "dev": true, "license": "MIT", "dependencies": { @@ -160,14 +160,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", - "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", + "version": "7.29.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.28.6", - "@babel/types": "^7.28.6", + "@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" @@ -177,27 +177,27 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "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.28.6", - "@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" @@ -207,18 +207,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", - "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.6", + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", "semver": "^6.3.1" }, "engines": { @@ -229,13 +229,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", - "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz", + "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-annotate-as-pure": "^7.29.7", "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, @@ -247,26 +247,26 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", - "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "debug": "^4.4.1", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", "lodash.debounce": "^4.0.8", - "resolve": "^1.22.10" + "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "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": { @@ -274,43 +274,43 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", - "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "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.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "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.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -320,22 +320,22 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "dev": true, "license": "MIT", "engines": { @@ -343,15 +343,15 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", - "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz", + "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-wrap-function": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-wrap-function": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -361,15 +361,15 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", - "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.28.6" + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -379,23 +379,23 @@ } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", "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-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": { @@ -403,9 +403,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "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": { @@ -413,9 +413,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": { @@ -423,42 +423,42 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", - "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz", + "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", - "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "version": "7.29.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.28.6" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -468,14 +468,14 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", - "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz", + "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -485,13 +485,13 @@ } }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz", + "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -501,13 +501,30 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz", + "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz", + "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -517,15 +534,15 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz", + "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -535,14 +552,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", - "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz", + "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -564,13 +581,13 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", - "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz", + "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -580,13 +597,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", - "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -596,13 +613,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -628,13 +645,13 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", - "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -644,15 +661,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.6.tgz", - "integrity": "sha512-9knsChgsMzBV5Yh3kkhrZNxH3oCYAfMBkNNaVN4cP2RVlFPe8wYdwwcnOsAbkdDoV9UjFtOXWrWB52M8W4jNeA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz", + "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -662,15 +679,15 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", - "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz", + "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -680,13 +697,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", - "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz", + "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -696,13 +713,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", - "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz", + "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -712,14 +729,14 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", - "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz", + "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -729,14 +746,14 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", - "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz", + "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -746,18 +763,18 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", - "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz", + "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -767,14 +784,14 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", - "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.29.7.tgz", + "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/template": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/template": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -784,14 +801,14 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", - "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz", + "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -801,14 +818,14 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", - "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz", + "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -818,13 +835,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", - "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz", + "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -834,14 +851,14 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.28.6.tgz", - "integrity": "sha512-5suVoXjC14lUN6ZL9OLKIHCNVWCrqGqlmEp/ixdXjvgnEl/kauLvvMO/Xw9NyMc95Joj1AeLVPVMvibBgSoFlA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -851,13 +868,13 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz", + "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -867,14 +884,14 @@ } }, "node_modules/@babel/plugin-transform-explicit-resource-management": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", - "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz", + "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -884,13 +901,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", - "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz", + "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -900,13 +917,13 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz", + "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -916,14 +933,14 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", - "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz", + "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -933,15 +950,15 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", - "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz", + "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -951,13 +968,13 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", - "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz", + "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -967,13 +984,13 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", - "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz", + "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -983,13 +1000,13 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", - "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz", + "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -999,13 +1016,13 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", - "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz", + "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1015,14 +1032,14 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", - "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz", + "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1032,14 +1049,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", - "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz", + "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1049,16 +1066,16 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz", - "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz", + "integrity": "sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.5" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1068,14 +1085,14 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", - "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz", + "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1085,14 +1102,14 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1102,13 +1119,13 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", - "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz", + "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1118,13 +1135,13 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", - "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz", + "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1134,13 +1151,13 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", - "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz", + "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1150,17 +1167,17 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", - "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz", + "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.6" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1170,14 +1187,14 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", - "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz", + "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1187,13 +1204,13 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", - "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz", + "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1203,14 +1220,14 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", - "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz", + "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1220,13 +1237,13 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", - "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz", + "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1236,14 +1253,14 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", - "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz", + "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1253,15 +1270,15 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", - "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz", + "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1271,13 +1288,13 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", - "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz", + "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1287,13 +1304,13 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz", - "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.29.7.tgz", + "integrity": "sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1303,17 +1320,17 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", - "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.29.7.tgz", + "integrity": "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1323,13 +1340,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz", - "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.29.7.tgz", + "integrity": "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.27.1" + "@babel/plugin-transform-react-jsx": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1339,14 +1356,14 @@ } }, "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz", - "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.29.7.tgz", + "integrity": "sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1356,13 +1373,13 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.6.tgz", - "integrity": "sha512-eZhoEZHYQLL5uc1gS5e9/oTknS0sSSAtd5TkKMUp3J+S/CaUjagc0kOUPsEbDmMeva0nC3WWl4SxVY6+OBuxfw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.7.tgz", + "integrity": "sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1372,14 +1389,14 @@ } }, "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", - "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz", + "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1389,13 +1406,13 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", - "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz", + "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1405,13 +1422,13 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", - "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.29.7.tgz", + "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1421,14 +1438,14 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", - "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.29.7.tgz", + "integrity": "sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1438,13 +1455,13 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", - "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.29.7.tgz", + "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1454,13 +1471,13 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", - "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.29.7.tgz", + "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1470,13 +1487,13 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", - "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz", + "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1486,13 +1503,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", - "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz", + "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1502,14 +1519,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", - "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz", + "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1519,14 +1536,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", - "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz", + "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1536,14 +1553,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", - "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz", + "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1553,81 +1570,82 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.6.tgz", - "integrity": "sha512-GaTI4nXDrs7l0qaJ6Rg06dtOXTBCG6TMDB44zbqofCIC4PqC7SEvmFFtpxzCDw9W5aJ7RKVshgXTLvLdBFV/qw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.7.tgz", + "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.28.6", - "@babel/plugin-syntax-import-attributes": "^7.28.6", + "@babel/plugin-syntax-import-assertions": "^7.29.7", + "@babel/plugin-syntax-import-attributes": "^7.29.7", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.28.6", - "@babel/plugin-transform-async-to-generator": "^7.28.6", - "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.6", - "@babel/plugin-transform-class-properties": "^7.28.6", - "@babel/plugin-transform-class-static-block": "^7.28.6", - "@babel/plugin-transform-classes": "^7.28.6", - "@babel/plugin-transform-computed-properties": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-dotall-regex": "^7.28.6", - "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.28.6", - "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-explicit-resource-management": "^7.28.6", - "@babel/plugin-transform-exponentiation-operator": "^7.28.6", - "@babel/plugin-transform-export-namespace-from": "^7.27.1", - "@babel/plugin-transform-for-of": "^7.27.1", - "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.28.6", - "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", - "@babel/plugin-transform-member-expression-literals": "^7.27.1", - "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.28.6", - "@babel/plugin-transform-modules-systemjs": "^7.28.5", - "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", - "@babel/plugin-transform-numeric-separator": "^7.28.6", - "@babel/plugin-transform-object-rest-spread": "^7.28.6", - "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.28.6", - "@babel/plugin-transform-optional-chaining": "^7.28.6", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/plugin-transform-private-methods": "^7.28.6", - "@babel/plugin-transform-private-property-in-object": "^7.28.6", - "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.28.6", - "@babel/plugin-transform-regexp-modifiers": "^7.28.6", - "@babel/plugin-transform-reserved-words": "^7.27.1", - "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.28.6", - "@babel/plugin-transform-sticky-regex": "^7.27.1", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/plugin-transform-typeof-symbol": "^7.27.1", - "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.28.6", - "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", + "@babel/plugin-transform-arrow-functions": "^7.29.7", + "@babel/plugin-transform-async-generator-functions": "^7.29.7", + "@babel/plugin-transform-async-to-generator": "^7.29.7", + "@babel/plugin-transform-block-scoped-functions": "^7.29.7", + "@babel/plugin-transform-block-scoping": "^7.29.7", + "@babel/plugin-transform-class-properties": "^7.29.7", + "@babel/plugin-transform-class-static-block": "^7.29.7", + "@babel/plugin-transform-classes": "^7.29.7", + "@babel/plugin-transform-computed-properties": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-dotall-regex": "^7.29.7", + "@babel/plugin-transform-duplicate-keys": "^7.29.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-dynamic-import": "^7.29.7", + "@babel/plugin-transform-explicit-resource-management": "^7.29.7", + "@babel/plugin-transform-exponentiation-operator": "^7.29.7", + "@babel/plugin-transform-export-namespace-from": "^7.29.7", + "@babel/plugin-transform-for-of": "^7.29.7", + "@babel/plugin-transform-function-name": "^7.29.7", + "@babel/plugin-transform-json-strings": "^7.29.7", + "@babel/plugin-transform-literals": "^7.29.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.29.7", + "@babel/plugin-transform-member-expression-literals": "^7.29.7", + "@babel/plugin-transform-modules-amd": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-modules-systemjs": "^7.29.7", + "@babel/plugin-transform-modules-umd": "^7.29.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-new-target": "^7.29.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7", + "@babel/plugin-transform-numeric-separator": "^7.29.7", + "@babel/plugin-transform-object-rest-spread": "^7.29.7", + "@babel/plugin-transform-object-super": "^7.29.7", + "@babel/plugin-transform-optional-catch-binding": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/plugin-transform-private-methods": "^7.29.7", + "@babel/plugin-transform-private-property-in-object": "^7.29.7", + "@babel/plugin-transform-property-literals": "^7.29.7", + "@babel/plugin-transform-regenerator": "^7.29.7", + "@babel/plugin-transform-regexp-modifiers": "^7.29.7", + "@babel/plugin-transform-reserved-words": "^7.29.7", + "@babel/plugin-transform-shorthand-properties": "^7.29.7", + "@babel/plugin-transform-spread": "^7.29.7", + "@babel/plugin-transform-sticky-regex": "^7.29.7", + "@babel/plugin-transform-template-literals": "^7.29.7", + "@babel/plugin-transform-typeof-symbol": "^7.29.7", + "@babel/plugin-transform-unicode-escapes": "^7.29.7", + "@babel/plugin-transform-unicode-property-regex": "^7.29.7", + "@babel/plugin-transform-unicode-regex": "^7.29.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.29.7", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.14", - "babel-plugin-polyfill-corejs3": "^0.13.0", - "babel-plugin-polyfill-regenerator": "^0.6.5", - "core-js-compat": "^3.43.0", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", "semver": "^6.3.1" }, "engines": { @@ -1652,18 +1670,18 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz", - "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.29.7.tgz", + "integrity": "sha512-C+PV1TFUPTmBQGoPBL8j2QmLpZ117YTCwxIZeJOM96GbYMFSc7/pOXU5lVykwnZxyTqQxRsvoRk6f2FktZgGHA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-transform-react-display-name": "^7.28.0", - "@babel/plugin-transform-react-jsx": "^7.27.1", - "@babel/plugin-transform-react-jsx-development": "^7.27.1", - "@babel/plugin-transform-react-pure-annotations": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-transform-react-display-name": "^7.29.7", + "@babel/plugin-transform-react-jsx": "^7.29.7", + "@babel/plugin-transform-react-jsx-development": "^7.29.7", + "@babel/plugin-transform-react-pure-annotations": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1685,33 +1703,33 @@ } }, "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "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.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@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.28.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", - "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "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.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6", + "@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": { @@ -1719,14 +1737,14 @@ } }, "node_modules/@babel/types": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", - "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "version": "7.29.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.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -2119,30 +2137,10 @@ "node": ">=14" } }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "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" }, @@ -2165,13 +2163,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "25.0.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.10.tgz", - "integrity": "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==", + "version": "25.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", + "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.16.0" + "undici-types": ">=7.24.0 <7.24.7" } }, "node_modules/@types/triple-beam": { @@ -2685,14 +2683,14 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", - "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.7", - "@babel/helper-define-polyfill-provider": "^0.6.5", + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" }, "peerDependencies": { @@ -2700,27 +2698,27 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", - "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5", - "core-js-compat": "^3.43.0" + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", - "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5" + "@babel/helper-define-polyfill-provider": "^0.6.8" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -3092,13 +3090,13 @@ "dev": true }, "node_modules/core-js-compat": { - "version": "3.44.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.44.0.tgz", - "integrity": "sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.25.1" + "browserslist": "^4.28.1" }, "funding": { "type": "opencollective", @@ -3159,9 +3157,9 @@ } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -3286,14 +3284,14 @@ "dev": true }, "node_modules/enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.1.tgz", + "integrity": "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.3" }, "engines": { "node": ">=10.13.0" @@ -3431,6 +3429,16 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "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-iterator-helpers": { "version": "1.0.15", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", @@ -3454,9 +3462,9 @@ } }, "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "dev": true, "license": "MIT" }, @@ -3997,9 +4005,9 @@ "dev": true }, "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "dev": true, "funding": [ { @@ -4010,7 +4018,8 @@ "type": "opencollective", "url": "https://opencollective.com/fastify" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/fastest-levenshtein": { "version": "1.0.16", @@ -5228,12 +5237,6 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -5335,9 +5338,9 @@ } }, "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", "dev": true, "license": "MIT", "engines": { @@ -5475,6 +5478,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } @@ -5541,22 +5545,11 @@ } }, "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "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, - "dependencies": { - "mime-db": "1.52.0" - }, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -6519,13 +6512,14 @@ } }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -7217,9 +7211,9 @@ } }, "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "dev": true, "license": "MIT", "engines": { @@ -7231,9 +7225,9 @@ } }, "node_modules/terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", + "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -7250,10 +7244,11 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", - "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", @@ -7271,21 +7266,48 @@ "webpack": "^5.1.0" }, "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, "@swc/core": { "optional": true }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, "esbuild": { "optional": true }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, "uglify-js": { "optional": true } } }, "node_modules/terser/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", "bin": { @@ -7485,9 +7507,9 @@ } }, "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", "dev": true, "license": "MIT" }, @@ -7606,9 +7628,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", - "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, "license": "MIT", "dependencies": { @@ -7620,37 +7642,35 @@ } }, "node_modules/webpack": { - "version": "5.104.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", - "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", + "version": "5.107.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.2.tgz", + "integrity": "sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.4", - "es-module-lexer": "^2.0.0", + "enhanced-resolve": "^5.22.0", + "es-module-lexer": "^2.1.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.4.4", - "webpack-sources": "^3.3.3" + "terser-webpack-plugin": "^5.5.0", + "watchpack": "^2.5.1", + "webpack-sources": "^3.5.0" }, "bin": { "webpack": "bin/webpack.js" @@ -7737,9 +7757,9 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", "dev": true, "license": "MIT", "engines": { @@ -7747,9 +7767,9 @@ } }, "node_modules/webpack/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", "bin": { @@ -8047,7 +8067,8 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yargs": { "version": "16.2.0", @@ -8097,9 +8118,9 @@ "dev": true }, "@babel/cli": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.28.6.tgz", - "integrity": "sha512-6EUNcuBbNkj08Oj4gAZ+BUU8yLCgKzgVX4gaTh09Ya2C8ICM4P+G30g4m3akRxSYAp3A/gnWchrNst7px4/nUQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.29.7.tgz", + "integrity": "sha512-/75HwRbAYPqXv/Ax1h7Fg3IZfXgdU98jnA8H93/m/QBaPV3Hp5ICoLqzGYye1yHBCgpmXvtqgSUN8oOKX5tojQ==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.28", @@ -8114,37 +8135,37 @@ } }, "@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "@babel/compat-data": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", - "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true }, "@babel/core": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", - "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "requires": { + "@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", @@ -8154,9 +8175,9 @@ } }, "@babel/eslint-parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.28.6.tgz", - "integrity": "sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.29.7.tgz", + "integrity": "sha512-zxt+UJTOMKvUt3yOg+D58MLuz334pHp93qifMFcjIIO+9hN6t+ufw2gi7vDPMpxvfnHRR+3VVXvIjineCcgyXw==", "dev": true, "requires": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", @@ -8173,258 +8194,268 @@ } }, "@babel/generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", - "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dev": true, "requires": { - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6", + "@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" } }, "@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", "dev": true, "requires": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.29.7" } }, "@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "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, "requires": { - "@babel/compat-data": "^7.28.6", - "@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" } }, "@babel/helper-create-class-features-plugin": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", - "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.6", + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", "semver": "^6.3.1" } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", - "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz", + "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-annotate-as-pure": "^7.29.7", "regexpu-core": "^6.3.1", "semver": "^6.3.1" } }, "@babel/helper-define-polyfill-provider": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", - "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", "dev": true, "requires": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "debug": "^4.4.1", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", "lodash.debounce": "^4.0.8", - "resolve": "^1.22.10" + "resolve": "^1.22.11" } }, "@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "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 }, "@babel/helper-member-expression-to-functions": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", - "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", "dev": true, "requires": { - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "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, "requires": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "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, "requires": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/helper-optimise-call-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", "dev": true, "requires": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.29.7" } }, "@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "dev": true }, "@babel/helper-remap-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", - "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz", + "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-wrap-function": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-wrap-function": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/helper-replace-supers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", - "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.28.6" + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", "dev": true, "requires": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@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 }, "@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "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 }, "@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 }, "@babel/helper-wrap-function": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", - "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz", + "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", "dev": true, "requires": { - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "requires": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@babel/parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", - "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "version": "7.29.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, "requires": { - "@babel/types": "^7.28.6" + "@babel/types": "^7.29.7" } }, "@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", - "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz", + "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz", + "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz", + "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" + } + }, + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz", + "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" } }, "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz", + "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7" } }, "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", - "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz", + "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-proposal-private-property-in-object": { @@ -8435,30 +8466,30 @@ "requires": {} }, "@babel/plugin-syntax-import-assertions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", - "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz", + "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-syntax-import-attributes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", - "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-syntax-unicode-sets-regex": { @@ -8472,620 +8503,621 @@ } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", - "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-async-generator-functions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.6.tgz", - "integrity": "sha512-9knsChgsMzBV5Yh3kkhrZNxH3oCYAfMBkNNaVN4cP2RVlFPe8wYdwwcnOsAbkdDoV9UjFtOXWrWB52M8W4jNeA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz", + "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", - "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz", + "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", - "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz", + "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", - "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz", + "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-class-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", - "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz", + "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-class-static-block": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", - "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz", + "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-classes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", - "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz", + "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-transform-computed-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", - "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.29.7.tgz", + "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/template": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/template": "^7.29.7" } }, "@babel/plugin-transform-destructuring": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", - "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz", + "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", - "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz", + "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", - "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz", + "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.28.6.tgz", - "integrity": "sha512-5suVoXjC14lUN6ZL9OLKIHCNVWCrqGqlmEp/ixdXjvgnEl/kauLvvMO/Xw9NyMc95Joj1AeLVPVMvibBgSoFlA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-dynamic-import": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz", + "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-explicit-resource-management": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", - "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz", + "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", - "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz", + "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-export-namespace-from": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz", + "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-for-of": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", - "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz", + "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" } }, "@babel/plugin-transform-function-name": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", - "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz", + "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==", "dev": true, "requires": { - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-transform-json-strings": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", - "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz", + "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", - "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz", + "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-logical-assignment-operators": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", - "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz", + "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", - "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz", + "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", - "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz", + "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", - "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz", + "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz", - "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz", + "integrity": "sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.5" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", - "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz", + "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-new-target": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", - "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz", + "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", - "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz", + "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-numeric-separator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", - "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz", + "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-object-rest-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", - "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz", + "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", "dev": true, "requires": { - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.6" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-transform-object-super": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", - "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz", + "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7" } }, "@babel/plugin-transform-optional-catch-binding": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", - "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz", + "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-optional-chaining": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", - "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz", + "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" } }, "@babel/plugin-transform-parameters": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", - "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz", + "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-private-methods": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", - "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz", + "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-private-property-in-object": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", - "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz", + "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-property-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", - "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz", + "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-react-display-name": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz", - "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.29.7.tgz", + "integrity": "sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-react-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", - "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.29.7.tgz", + "integrity": "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@babel/plugin-transform-react-jsx-development": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz", - "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.29.7.tgz", + "integrity": "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==", "dev": true, "requires": { - "@babel/plugin-transform-react-jsx": "^7.27.1" + "@babel/plugin-transform-react-jsx": "^7.29.7" } }, "@babel/plugin-transform-react-pure-annotations": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz", - "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.29.7.tgz", + "integrity": "sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-regenerator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.6.tgz", - "integrity": "sha512-eZhoEZHYQLL5uc1gS5e9/oTknS0sSSAtd5TkKMUp3J+S/CaUjagc0kOUPsEbDmMeva0nC3WWl4SxVY6+OBuxfw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.7.tgz", + "integrity": "sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-regexp-modifiers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", - "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz", + "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", - "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz", + "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", - "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.29.7.tgz", + "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", - "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.29.7.tgz", + "integrity": "sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", - "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.29.7.tgz", + "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-template-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", - "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.29.7.tgz", + "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", - "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz", + "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-unicode-escapes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", - "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz", + "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-unicode-property-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", - "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz", + "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", - "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz", + "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-unicode-sets-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", - "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz", + "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/preset-env": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.6.tgz", - "integrity": "sha512-GaTI4nXDrs7l0qaJ6Rg06dtOXTBCG6TMDB44zbqofCIC4PqC7SEvmFFtpxzCDw9W5aJ7RKVshgXTLvLdBFV/qw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.7.tgz", + "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.28.6", - "@babel/plugin-syntax-import-attributes": "^7.28.6", + "@babel/plugin-syntax-import-assertions": "^7.29.7", + "@babel/plugin-syntax-import-attributes": "^7.29.7", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.28.6", - "@babel/plugin-transform-async-to-generator": "^7.28.6", - "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.6", - "@babel/plugin-transform-class-properties": "^7.28.6", - "@babel/plugin-transform-class-static-block": "^7.28.6", - "@babel/plugin-transform-classes": "^7.28.6", - "@babel/plugin-transform-computed-properties": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-dotall-regex": "^7.28.6", - "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.28.6", - "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-explicit-resource-management": "^7.28.6", - "@babel/plugin-transform-exponentiation-operator": "^7.28.6", - "@babel/plugin-transform-export-namespace-from": "^7.27.1", - "@babel/plugin-transform-for-of": "^7.27.1", - "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.28.6", - "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", - "@babel/plugin-transform-member-expression-literals": "^7.27.1", - "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.28.6", - "@babel/plugin-transform-modules-systemjs": "^7.28.5", - "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", - "@babel/plugin-transform-numeric-separator": "^7.28.6", - "@babel/plugin-transform-object-rest-spread": "^7.28.6", - "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.28.6", - "@babel/plugin-transform-optional-chaining": "^7.28.6", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/plugin-transform-private-methods": "^7.28.6", - "@babel/plugin-transform-private-property-in-object": "^7.28.6", - "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.28.6", - "@babel/plugin-transform-regexp-modifiers": "^7.28.6", - "@babel/plugin-transform-reserved-words": "^7.27.1", - "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.28.6", - "@babel/plugin-transform-sticky-regex": "^7.27.1", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/plugin-transform-typeof-symbol": "^7.27.1", - "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.28.6", - "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", + "@babel/plugin-transform-arrow-functions": "^7.29.7", + "@babel/plugin-transform-async-generator-functions": "^7.29.7", + "@babel/plugin-transform-async-to-generator": "^7.29.7", + "@babel/plugin-transform-block-scoped-functions": "^7.29.7", + "@babel/plugin-transform-block-scoping": "^7.29.7", + "@babel/plugin-transform-class-properties": "^7.29.7", + "@babel/plugin-transform-class-static-block": "^7.29.7", + "@babel/plugin-transform-classes": "^7.29.7", + "@babel/plugin-transform-computed-properties": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-dotall-regex": "^7.29.7", + "@babel/plugin-transform-duplicate-keys": "^7.29.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-dynamic-import": "^7.29.7", + "@babel/plugin-transform-explicit-resource-management": "^7.29.7", + "@babel/plugin-transform-exponentiation-operator": "^7.29.7", + "@babel/plugin-transform-export-namespace-from": "^7.29.7", + "@babel/plugin-transform-for-of": "^7.29.7", + "@babel/plugin-transform-function-name": "^7.29.7", + "@babel/plugin-transform-json-strings": "^7.29.7", + "@babel/plugin-transform-literals": "^7.29.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.29.7", + "@babel/plugin-transform-member-expression-literals": "^7.29.7", + "@babel/plugin-transform-modules-amd": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-modules-systemjs": "^7.29.7", + "@babel/plugin-transform-modules-umd": "^7.29.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-new-target": "^7.29.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7", + "@babel/plugin-transform-numeric-separator": "^7.29.7", + "@babel/plugin-transform-object-rest-spread": "^7.29.7", + "@babel/plugin-transform-object-super": "^7.29.7", + "@babel/plugin-transform-optional-catch-binding": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/plugin-transform-private-methods": "^7.29.7", + "@babel/plugin-transform-private-property-in-object": "^7.29.7", + "@babel/plugin-transform-property-literals": "^7.29.7", + "@babel/plugin-transform-regenerator": "^7.29.7", + "@babel/plugin-transform-regexp-modifiers": "^7.29.7", + "@babel/plugin-transform-reserved-words": "^7.29.7", + "@babel/plugin-transform-shorthand-properties": "^7.29.7", + "@babel/plugin-transform-spread": "^7.29.7", + "@babel/plugin-transform-sticky-regex": "^7.29.7", + "@babel/plugin-transform-template-literals": "^7.29.7", + "@babel/plugin-transform-typeof-symbol": "^7.29.7", + "@babel/plugin-transform-unicode-escapes": "^7.29.7", + "@babel/plugin-transform-unicode-property-regex": "^7.29.7", + "@babel/plugin-transform-unicode-regex": "^7.29.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.29.7", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.14", - "babel-plugin-polyfill-corejs3": "^0.13.0", - "babel-plugin-polyfill-regenerator": "^0.6.5", - "core-js-compat": "^3.43.0", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", "semver": "^6.3.1" } }, @@ -9101,17 +9133,17 @@ } }, "@babel/preset-react": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz", - "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.29.7.tgz", + "integrity": "sha512-C+PV1TFUPTmBQGoPBL8j2QmLpZ117YTCwxIZeJOM96GbYMFSc7/pOXU5lVykwnZxyTqQxRsvoRk6f2FktZgGHA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-transform-react-display-name": "^7.28.0", - "@babel/plugin-transform-react-jsx": "^7.27.1", - "@babel/plugin-transform-react-jsx-development": "^7.27.1", - "@babel/plugin-transform-react-pure-annotations": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-transform-react-display-name": "^7.29.7", + "@babel/plugin-transform-react-jsx": "^7.29.7", + "@babel/plugin-transform-react-jsx-development": "^7.29.7", + "@babel/plugin-transform-react-pure-annotations": "^7.29.7" } }, "@babel/runtime": { @@ -9124,39 +9156,39 @@ } }, "@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "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, "requires": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@babel/traverse": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", - "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "dev": true, "requires": { - "@babel/code-frame": "^7.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6", + "@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" } }, "@babel/types": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", - "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" } }, "@bcoe/v8-coverage": { @@ -9450,30 +9482,10 @@ "dev": true, "optional": true }, - "@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true }, "@types/istanbul-lib-coverage": { @@ -9495,12 +9507,12 @@ "dev": true }, "@types/node": { - "version": "25.0.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.10.tgz", - "integrity": "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==", + "version": "25.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", + "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", "dev": true, "requires": { - "undici-types": "~7.16.0" + "undici-types": ">=7.24.0 <7.24.7" } }, "@types/triple-beam": { @@ -9909,33 +9921,33 @@ } }, "babel-plugin-polyfill-corejs2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", - "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", "dev": true, "requires": { - "@babel/compat-data": "^7.27.7", - "@babel/helper-define-polyfill-provider": "^0.6.5", + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" } }, "babel-plugin-polyfill-corejs3": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", - "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.6.5", - "core-js-compat": "^3.43.0" + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" } }, "babel-plugin-polyfill-regenerator": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", - "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.6.5" + "@babel/helper-define-polyfill-provider": "^0.6.8" } }, "balanced-match": { @@ -10211,12 +10223,12 @@ "dev": true }, "core-js-compat": { - "version": "3.44.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.44.0.tgz", - "integrity": "sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", "dev": true, "requires": { - "browserslist": "^4.25.1" + "browserslist": "^4.28.1" } }, "cross-env": { @@ -10258,9 +10270,9 @@ "dev": true }, "debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "requires": { "ms": "^2.1.3" @@ -10363,13 +10375,13 @@ "dev": true }, "enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.1.tgz", + "integrity": "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==", "dev": true, "requires": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.3" } }, "entities": { @@ -10476,6 +10488,12 @@ } } }, + "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 + }, "es-iterator-helpers": { "version": "1.0.15", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", @@ -10499,9 +10517,9 @@ } }, "es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "dev": true }, "es-set-tostringtag": { @@ -10915,9 +10933,9 @@ "dev": true }, "fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "dev": true }, "fastest-levenshtein": { @@ -11785,12 +11803,6 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -11873,9 +11885,9 @@ } }, "loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", "dev": true }, "locate-path": { @@ -12043,20 +12055,11 @@ } }, "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "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 }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "requires": { - "mime-db": "1.52.0" - } - }, "min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -12760,12 +12763,13 @@ "dev": true }, "resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", "dev": true, "requires": { - "is-core-module": "^2.16.0", + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -13260,15 +13264,15 @@ "dev": true }, "tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "dev": true }, "terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", + "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", "dev": true, "requires": { "@jridgewell/source-map": "^0.3.3", @@ -13278,9 +13282,9 @@ }, "dependencies": { "acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true }, "commander": { @@ -13292,9 +13296,9 @@ } }, "terser-webpack-plugin": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", - "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.25", @@ -13445,9 +13449,9 @@ } }, "undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", "dev": true }, "unicode-canonical-property-names-ecmascript": { @@ -13525,9 +13529,9 @@ } }, "watchpack": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", - "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, "requires": { "glob-to-regexp": "^0.4.1", @@ -13535,42 +13539,40 @@ } }, "webpack": { - "version": "5.104.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", - "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", + "version": "5.107.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.2.tgz", + "integrity": "sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==", "dev": true, "requires": { - "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.4", - "es-module-lexer": "^2.0.0", + "enhanced-resolve": "^5.22.0", + "es-module-lexer": "^2.1.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.4.4", - "webpack-sources": "^3.3.3" + "terser-webpack-plugin": "^5.5.0", + "watchpack": "^2.5.1", + "webpack-sources": "^3.5.0" }, "dependencies": { "acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true }, "acorn-import-phases": { @@ -13639,9 +13641,9 @@ } }, "webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", "dev": true }, "which": { diff --git a/components/dash-html-components/package.json b/components/dash-html-components/package.json index 370ab42051..5db89aa61b 100644 --- a/components/dash-html-components/package.json +++ b/components/dash-html-components/package.json @@ -1,6 +1,6 @@ { "name": "dash-html-components", - "version": "4.1.0", + "version": "4.2.0", "description": "Vanilla HTML components for Dash", "main": "lib/index.js", "repository": { diff --git a/components/dash-table/package-lock.json b/components/dash-table/package-lock.json index 6d5f97c43a..b3af038be3 100644 --- a/components/dash-table/package-lock.json +++ b/components/dash-table/package-lock.json @@ -1,12 +1,12 @@ { "name": "dash-table", - "version": "7.1.0", + "version": "7.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dash-table", - "version": "7.1.0", + "version": "7.2.0", "license": "MIT", "devDependencies": { "@babel/cli": "^7.28.6", @@ -84,9 +84,9 @@ } }, "node_modules/@babel/cli": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.28.6.tgz", - "integrity": "sha512-6EUNcuBbNkj08Oj4gAZ+BUU8yLCgKzgVX4gaTh09Ya2C8ICM4P+G30g4m3akRxSYAp3A/gnWchrNst7px4/nUQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.29.7.tgz", + "integrity": "sha512-/75HwRbAYPqXv/Ax1h7Fg3IZfXgdU98jnA8H93/m/QBaPV3Hp5ICoLqzGYye1yHBCgpmXvtqgSUN8oOKX5tojQ==", "dev": true, "license": "MIT", "dependencies": { @@ -114,13 +114,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "version": "7.29.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.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -129,9 +129,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", - "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "engines": { @@ -139,21 +139,21 @@ } }, "node_modules/@babel/core": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", - "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", + "version": "7.29.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.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6", + "@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", @@ -170,14 +170,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", - "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", + "version": "7.29.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.28.6", - "@babel/types": "^7.28.6", + "@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" @@ -187,27 +187,27 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "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.28.6", - "@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" @@ -217,18 +217,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", - "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.6", + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", "semver": "^6.3.1" }, "engines": { @@ -239,13 +239,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", - "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz", + "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-annotate-as-pure": "^7.29.7", "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, @@ -257,26 +257,26 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", - "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "debug": "^4.4.1", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", "lodash.debounce": "^4.0.8", - "resolve": "^1.22.10" + "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "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": { @@ -284,43 +284,43 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", - "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "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.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "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.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -330,22 +330,22 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "dev": true, "license": "MIT", "engines": { @@ -353,15 +353,15 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", - "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz", + "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-wrap-function": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-wrap-function": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -371,15 +371,15 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", - "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.28.6" + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -389,23 +389,23 @@ } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", "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-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": { @@ -413,9 +413,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "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": { @@ -423,9 +423,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": { @@ -433,42 +433,42 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", - "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz", + "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", - "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "version": "7.29.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.28.6" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -478,14 +478,14 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", - "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz", + "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -495,13 +495,13 @@ } }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz", + "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -511,13 +511,30 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz", + "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz", + "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -527,15 +544,15 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz", + "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -545,14 +562,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", - "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz", + "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -588,13 +605,13 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", - "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz", + "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -604,13 +621,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", - "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -620,13 +637,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -653,13 +670,13 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", - "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -669,15 +686,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.6.tgz", - "integrity": "sha512-9knsChgsMzBV5Yh3kkhrZNxH3oCYAfMBkNNaVN4cP2RVlFPe8wYdwwcnOsAbkdDoV9UjFtOXWrWB52M8W4jNeA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz", + "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -687,15 +704,15 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", - "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz", + "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -705,13 +722,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", - "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz", + "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -721,13 +738,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", - "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz", + "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -737,14 +754,14 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", - "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz", + "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -754,14 +771,14 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", - "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz", + "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -771,18 +788,18 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", - "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz", + "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -792,14 +809,14 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", - "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.29.7.tgz", + "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/template": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/template": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -809,14 +826,14 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", - "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz", + "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -826,14 +843,14 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", - "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz", + "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -843,13 +860,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", - "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz", + "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -859,14 +876,14 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.28.6.tgz", - "integrity": "sha512-5suVoXjC14lUN6ZL9OLKIHCNVWCrqGqlmEp/ixdXjvgnEl/kauLvvMO/Xw9NyMc95Joj1AeLVPVMvibBgSoFlA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -876,13 +893,13 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz", + "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -892,14 +909,14 @@ } }, "node_modules/@babel/plugin-transform-explicit-resource-management": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", - "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz", + "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -909,13 +926,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", - "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz", + "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -925,13 +942,13 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz", + "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -941,14 +958,14 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", - "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz", + "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -958,15 +975,15 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", - "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz", + "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -976,13 +993,13 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", - "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz", + "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -992,13 +1009,13 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", - "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz", + "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1008,13 +1025,13 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", - "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz", + "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1024,13 +1041,13 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", - "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz", + "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1040,14 +1057,14 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", - "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz", + "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1057,14 +1074,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", - "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz", + "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1074,16 +1091,16 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz", - "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz", + "integrity": "sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.5" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1093,14 +1110,14 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", - "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz", + "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1110,14 +1127,14 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1127,13 +1144,13 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", - "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz", + "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1143,13 +1160,13 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", - "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz", + "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1159,13 +1176,13 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", - "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz", + "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1175,17 +1192,17 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", - "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz", + "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.6" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1195,14 +1212,14 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", - "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz", + "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1212,13 +1229,13 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", - "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz", + "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1228,14 +1245,14 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", - "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz", + "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1245,13 +1262,13 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", - "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz", + "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1261,14 +1278,14 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", - "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz", + "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1278,15 +1295,15 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", - "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz", + "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1296,13 +1313,13 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", - "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz", + "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1312,13 +1329,13 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz", - "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.29.7.tgz", + "integrity": "sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1328,17 +1345,17 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", - "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.29.7.tgz", + "integrity": "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1348,13 +1365,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz", - "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.29.7.tgz", + "integrity": "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.27.1" + "@babel/plugin-transform-react-jsx": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1364,14 +1381,14 @@ } }, "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz", - "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.29.7.tgz", + "integrity": "sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1381,13 +1398,13 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.6.tgz", - "integrity": "sha512-eZhoEZHYQLL5uc1gS5e9/oTknS0sSSAtd5TkKMUp3J+S/CaUjagc0kOUPsEbDmMeva0nC3WWl4SxVY6+OBuxfw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.7.tgz", + "integrity": "sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1397,14 +1414,14 @@ } }, "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", - "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz", + "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1414,13 +1431,13 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", - "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz", + "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1430,13 +1447,13 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", - "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.29.7.tgz", + "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1446,14 +1463,14 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", - "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.29.7.tgz", + "integrity": "sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1463,13 +1480,13 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", - "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.29.7.tgz", + "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1479,13 +1496,13 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", - "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.29.7.tgz", + "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1495,13 +1512,13 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", - "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz", + "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1511,13 +1528,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", - "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz", + "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1527,14 +1544,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", - "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz", + "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1544,14 +1561,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", - "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz", + "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1561,14 +1578,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", - "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz", + "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1590,81 +1607,82 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.6.tgz", - "integrity": "sha512-GaTI4nXDrs7l0qaJ6Rg06dtOXTBCG6TMDB44zbqofCIC4PqC7SEvmFFtpxzCDw9W5aJ7RKVshgXTLvLdBFV/qw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.7.tgz", + "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.28.6", - "@babel/plugin-syntax-import-attributes": "^7.28.6", + "@babel/plugin-syntax-import-assertions": "^7.29.7", + "@babel/plugin-syntax-import-attributes": "^7.29.7", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.28.6", - "@babel/plugin-transform-async-to-generator": "^7.28.6", - "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.6", - "@babel/plugin-transform-class-properties": "^7.28.6", - "@babel/plugin-transform-class-static-block": "^7.28.6", - "@babel/plugin-transform-classes": "^7.28.6", - "@babel/plugin-transform-computed-properties": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-dotall-regex": "^7.28.6", - "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.28.6", - "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-explicit-resource-management": "^7.28.6", - "@babel/plugin-transform-exponentiation-operator": "^7.28.6", - "@babel/plugin-transform-export-namespace-from": "^7.27.1", - "@babel/plugin-transform-for-of": "^7.27.1", - "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.28.6", - "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", - "@babel/plugin-transform-member-expression-literals": "^7.27.1", - "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.28.6", - "@babel/plugin-transform-modules-systemjs": "^7.28.5", - "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", - "@babel/plugin-transform-numeric-separator": "^7.28.6", - "@babel/plugin-transform-object-rest-spread": "^7.28.6", - "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.28.6", - "@babel/plugin-transform-optional-chaining": "^7.28.6", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/plugin-transform-private-methods": "^7.28.6", - "@babel/plugin-transform-private-property-in-object": "^7.28.6", - "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.28.6", - "@babel/plugin-transform-regexp-modifiers": "^7.28.6", - "@babel/plugin-transform-reserved-words": "^7.27.1", - "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.28.6", - "@babel/plugin-transform-sticky-regex": "^7.27.1", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/plugin-transform-typeof-symbol": "^7.27.1", - "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.28.6", - "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", + "@babel/plugin-transform-arrow-functions": "^7.29.7", + "@babel/plugin-transform-async-generator-functions": "^7.29.7", + "@babel/plugin-transform-async-to-generator": "^7.29.7", + "@babel/plugin-transform-block-scoped-functions": "^7.29.7", + "@babel/plugin-transform-block-scoping": "^7.29.7", + "@babel/plugin-transform-class-properties": "^7.29.7", + "@babel/plugin-transform-class-static-block": "^7.29.7", + "@babel/plugin-transform-classes": "^7.29.7", + "@babel/plugin-transform-computed-properties": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-dotall-regex": "^7.29.7", + "@babel/plugin-transform-duplicate-keys": "^7.29.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-dynamic-import": "^7.29.7", + "@babel/plugin-transform-explicit-resource-management": "^7.29.7", + "@babel/plugin-transform-exponentiation-operator": "^7.29.7", + "@babel/plugin-transform-export-namespace-from": "^7.29.7", + "@babel/plugin-transform-for-of": "^7.29.7", + "@babel/plugin-transform-function-name": "^7.29.7", + "@babel/plugin-transform-json-strings": "^7.29.7", + "@babel/plugin-transform-literals": "^7.29.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.29.7", + "@babel/plugin-transform-member-expression-literals": "^7.29.7", + "@babel/plugin-transform-modules-amd": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-modules-systemjs": "^7.29.7", + "@babel/plugin-transform-modules-umd": "^7.29.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-new-target": "^7.29.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7", + "@babel/plugin-transform-numeric-separator": "^7.29.7", + "@babel/plugin-transform-object-rest-spread": "^7.29.7", + "@babel/plugin-transform-object-super": "^7.29.7", + "@babel/plugin-transform-optional-catch-binding": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/plugin-transform-private-methods": "^7.29.7", + "@babel/plugin-transform-private-property-in-object": "^7.29.7", + "@babel/plugin-transform-property-literals": "^7.29.7", + "@babel/plugin-transform-regenerator": "^7.29.7", + "@babel/plugin-transform-regexp-modifiers": "^7.29.7", + "@babel/plugin-transform-reserved-words": "^7.29.7", + "@babel/plugin-transform-shorthand-properties": "^7.29.7", + "@babel/plugin-transform-spread": "^7.29.7", + "@babel/plugin-transform-sticky-regex": "^7.29.7", + "@babel/plugin-transform-template-literals": "^7.29.7", + "@babel/plugin-transform-typeof-symbol": "^7.29.7", + "@babel/plugin-transform-unicode-escapes": "^7.29.7", + "@babel/plugin-transform-unicode-property-regex": "^7.29.7", + "@babel/plugin-transform-unicode-regex": "^7.29.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.29.7", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.14", - "babel-plugin-polyfill-corejs3": "^0.13.0", - "babel-plugin-polyfill-regenerator": "^0.6.5", - "core-js-compat": "^3.43.0", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", "semver": "^6.3.1" }, "engines": { @@ -1690,18 +1708,18 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz", - "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.29.7.tgz", + "integrity": "sha512-C+PV1TFUPTmBQGoPBL8j2QmLpZ117YTCwxIZeJOM96GbYMFSc7/pOXU5lVykwnZxyTqQxRsvoRk6f2FktZgGHA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-transform-react-display-name": "^7.28.0", - "@babel/plugin-transform-react-jsx": "^7.27.1", - "@babel/plugin-transform-react-jsx-development": "^7.27.1", - "@babel/plugin-transform-react-pure-annotations": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-transform-react-display-name": "^7.29.7", + "@babel/plugin-transform-react-jsx": "^7.29.7", + "@babel/plugin-transform-react-jsx-development": "^7.29.7", + "@babel/plugin-transform-react-pure-annotations": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1721,33 +1739,33 @@ } }, "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "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.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@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.28.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", - "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "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.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6", + "@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": { @@ -1755,14 +1773,14 @@ } }, "node_modules/@babel/types": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", - "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "version": "7.29.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.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -2413,32 +2431,10 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "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" }, @@ -3554,14 +3550,14 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", - "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.7", - "@babel/helper-define-polyfill-provider": "^0.6.5", + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" }, "peerDependencies": { @@ -3569,27 +3565,27 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", - "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5", - "core-js-compat": "^3.43.0" + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", - "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5" + "@babel/helper-define-polyfill-provider": "^0.6.8" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -3680,10 +3676,11 @@ "dev": true }, "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", "dev": true, + "license": "MIT", "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", @@ -3693,7 +3690,7 @@ "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", - "qs": "~6.14.0", + "qs": "~6.15.1", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" @@ -3863,12 +3860,13 @@ } }, "node_modules/browserify-sign": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", - "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.6.tgz", + "integrity": "sha512-sd+Q65fjlWCYWtZKXiKfrUc8d+4jtp/8f0W2NkwzLtoW4bI6UDnWusLWIurHnmurW0XShIRxpwiOX4EoPtXUAg==", "dev": true, + "license": "ISC", "dependencies": { - "bn.js": "^5.2.2", + "bn.js": "^5.2.3", "browserify-rsa": "^4.1.1", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", @@ -4688,13 +4686,13 @@ "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.44.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.44.0.tgz", - "integrity": "sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.25.1" + "browserslist": "^4.28.1" }, "funding": { "type": "opencollective", @@ -4981,9 +4979,9 @@ } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -5354,21 +5352,22 @@ } }, "node_modules/engine.io": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", - "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", + "version": "6.6.8", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.8.tgz", + "integrity": "sha512-2agL3ueZhqxoVrfmntO8yuVj+uNSlIOnhykYHk3Cq0ShYPdUjjUiSJrQvXjq01I9jAuI0Zl2YO8Evv5Mqytm5g==", "dev": true, "license": "MIT", "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", + "@types/ws": "^8.5.12", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.7.2", "cors": "~2.8.5", - "debug": "~4.3.1", + "debug": "~4.4.1", "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" + "ws": "~8.20.1" }, "engines": { "node": ">=10.2.0" @@ -5384,33 +5383,15 @@ "node": ">=10.0.0" } }, - "node_modules/engine.io/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.1.tgz", + "integrity": "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.3" }, "engines": { "node": ">=10.13.0" @@ -5589,9 +5570,9 @@ } }, "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "dev": true, "license": "MIT" }, @@ -5957,14 +5938,15 @@ } }, "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", "dev": true, + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "~1.20.3", + "body-parser": "~1.20.5", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", @@ -5983,7 +5965,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "~6.14.0", + "qs": "~6.15.1", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", @@ -6114,9 +6096,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "dev": true, "funding": [ { @@ -8163,13 +8145,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -8566,9 +8541,9 @@ } }, "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", "dev": true, "license": "MIT", "engines": { @@ -9101,9 +9076,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "dev": true, "funding": [ { @@ -10038,9 +10013,9 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { @@ -10058,7 +10033,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -10288,10 +10263,11 @@ } }, "node_modules/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" }, @@ -10799,13 +10775,14 @@ "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -11724,32 +11701,14 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", - "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.7.tgz", + "integrity": "sha512-e0LyK91f3cUxTmv95/KzoLg47+zF+s/sbxRGDNsyG4dmIP8ZSX8ax6byOxfJXeNNtS/8AZlfD+uP7gBeR7DLlg==", "dev": true, "license": "MIT", "dependencies": { - "debug": "~4.3.4", - "ws": "~8.17.1" - } - }, - "node_modules/socket.io-adapter/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "debug": "~4.4.1", + "ws": "~8.20.1" } }, "node_modules/socket.io-parser": { @@ -12216,9 +12175,9 @@ } }, "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "dev": true, "license": "MIT", "engines": { @@ -12230,9 +12189,9 @@ } }, "node_modules/terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", + "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -12249,10 +12208,11 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", - "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", @@ -12270,21 +12230,48 @@ "webpack": "^5.1.0" }, "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, "@swc/core": { "optional": true }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, "esbuild": { "optional": true }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, "uglify-js": { "optional": true } } }, "node_modules/terser/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", "bin": { @@ -12364,10 +12351,11 @@ } }, "node_modules/tmp": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.14" } @@ -12954,9 +12942,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", - "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, "license": "MIT", "dependencies": { @@ -12988,37 +12976,35 @@ } }, "node_modules/webpack": { - "version": "5.104.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", - "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", + "version": "5.107.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.2.tgz", + "integrity": "sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.4", - "es-module-lexer": "^2.0.0", + "enhanced-resolve": "^5.22.0", + "es-module-lexer": "^2.1.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.4.4", - "webpack-sources": "^3.3.3" + "terser-webpack-plugin": "^5.5.0", + "watchpack": "^2.5.1", + "webpack-sources": "^3.5.0" }, "bin": { "webpack": "bin/webpack.js" @@ -13208,28 +13194,6 @@ "@types/send": "*" } }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/webpack-merge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", @@ -13251,9 +13215,9 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", "dev": true, "license": "MIT", "engines": { @@ -13261,9 +13225,9 @@ } }, "node_modules/webpack/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", "bin": { @@ -13286,6 +13250,16 @@ "acorn": "^8.14.0" } }, + "node_modules/webpack/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/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -13553,9 +13527,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "dev": true, "license": "MIT", "engines": { diff --git a/components/dash-table/package.json b/components/dash-table/package.json index 295517a4c9..149acdc254 100644 --- a/components/dash-table/package.json +++ b/components/dash-table/package.json @@ -1,6 +1,6 @@ { "name": "dash-table", - "version": "7.1.0", + "version": "7.2.0", "description": "Dash table", "repository": { "type": "git", diff --git a/dash/_dash_renderer.py b/dash/_dash_renderer.py index 5574131d10..6d159338dc 100644 --- a/dash/_dash_renderer.py +++ b/dash/_dash_renderer.py @@ -1,7 +1,7 @@ import os from typing import Any, List, Dict -__version__ = "3.1.0" +__version__ = "3.2.0" _available_react_versions = {"18.3.1", "18.2.0", "16.14.0"} _available_reactdom_versions = {"18.3.1", "18.2.0", "16.14.0"} @@ -65,7 +65,7 @@ def _set_react_version(v_react, v_reactdom=None): { "relative_package_path": "dash-renderer/build/dash_renderer.min.js", "dev_package_path": "dash-renderer/build/dash_renderer.dev.js", - "external_url": "https://unpkg.com/dash-renderer@3.1.0" + "external_url": "https://unpkg.com/dash-renderer@3.2.0" "/build/dash_renderer.min.js", "namespace": "dash", }, diff --git a/dash/dash-renderer/package-lock.json b/dash/dash-renderer/package-lock.json index e9f1b989ac..26519251ec 100644 --- a/dash/dash-renderer/package-lock.json +++ b/dash/dash-renderer/package-lock.json @@ -1,12 +1,12 @@ { "name": "dash-renderer", - "version": "3.1.0", + "version": "3.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "dash-renderer", - "version": "3.1.0", + "version": "3.2.0", "license": "MIT", "dependencies": { "@babel/polyfill": "^7.12.1", @@ -73,9 +73,9 @@ } }, "node_modules/@babel/cli": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.28.6.tgz", - "integrity": "sha512-6EUNcuBbNkj08Oj4gAZ+BUU8yLCgKzgVX4gaTh09Ya2C8ICM4P+G30g4m3akRxSYAp3A/gnWchrNst7px4/nUQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.29.7.tgz", + "integrity": "sha512-/75HwRbAYPqXv/Ax1h7Fg3IZfXgdU98jnA8H93/m/QBaPV3Hp5ICoLqzGYye1yHBCgpmXvtqgSUN8oOKX5tojQ==", "dev": true, "license": "MIT", "dependencies": { @@ -129,13 +129,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "version": "7.29.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.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -144,9 +144,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", - "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "engines": { @@ -154,21 +154,21 @@ } }, "node_modules/@babel/core": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", - "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", + "version": "7.29.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.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6", + "@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", @@ -185,14 +185,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", - "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", + "version": "7.29.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.28.6", - "@babel/types": "^7.28.6", + "@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" @@ -202,27 +202,27 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "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.28.6", - "@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" @@ -232,18 +232,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", - "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.6", + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", "semver": "^6.3.1" }, "engines": { @@ -254,13 +254,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", - "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz", + "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-annotate-as-pure": "^7.29.7", "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, @@ -272,17 +272,17 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", - "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "debug": "^4.4.1", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", "lodash.debounce": "^4.0.8", - "resolve": "^1.22.10" + "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -314,9 +314,9 @@ "license": "MIT" }, "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "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": { @@ -324,43 +324,43 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", - "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "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.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "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.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -370,22 +370,22 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "dev": true, "license": "MIT", "engines": { @@ -393,15 +393,15 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", - "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz", + "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-wrap-function": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-wrap-function": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -411,15 +411,15 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", - "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.28.6" + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -429,23 +429,23 @@ } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", "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-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": { @@ -453,9 +453,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "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": { @@ -463,9 +463,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": { @@ -473,42 +473,42 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", - "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz", + "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", - "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "version": "7.29.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.28.6" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -518,14 +518,14 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", - "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz", + "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -535,13 +535,13 @@ } }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz", + "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -551,13 +551,30 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz", + "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz", + "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -567,15 +584,15 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz", + "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -585,14 +602,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", - "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz", + "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -630,13 +647,13 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", - "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz", + "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -646,13 +663,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", - "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -662,13 +679,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -678,13 +695,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz", + "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -710,13 +727,13 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", - "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -726,15 +743,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.6.tgz", - "integrity": "sha512-9knsChgsMzBV5Yh3kkhrZNxH3oCYAfMBkNNaVN4cP2RVlFPe8wYdwwcnOsAbkdDoV9UjFtOXWrWB52M8W4jNeA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz", + "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -744,15 +761,15 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", - "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz", + "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -762,13 +779,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", - "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz", + "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -778,13 +795,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", - "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz", + "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -794,14 +811,14 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", - "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz", + "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -811,14 +828,14 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", - "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz", + "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -828,18 +845,18 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", - "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz", + "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -849,14 +866,14 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", - "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.29.7.tgz", + "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/template": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/template": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -866,14 +883,14 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", - "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz", + "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -883,14 +900,14 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", - "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz", + "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -900,13 +917,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", - "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz", + "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -916,14 +933,14 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.28.6.tgz", - "integrity": "sha512-5suVoXjC14lUN6ZL9OLKIHCNVWCrqGqlmEp/ixdXjvgnEl/kauLvvMO/Xw9NyMc95Joj1AeLVPVMvibBgSoFlA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -933,13 +950,13 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz", + "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -949,14 +966,14 @@ } }, "node_modules/@babel/plugin-transform-explicit-resource-management": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", - "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz", + "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -966,13 +983,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", - "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz", + "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -982,13 +999,13 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz", + "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -998,14 +1015,14 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", - "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz", + "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1015,15 +1032,15 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", - "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz", + "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1033,13 +1050,13 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", - "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz", + "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1049,13 +1066,13 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", - "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz", + "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1065,13 +1082,13 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", - "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz", + "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1081,13 +1098,13 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", - "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz", + "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1097,14 +1114,14 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", - "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz", + "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1114,14 +1131,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", - "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz", + "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1131,16 +1148,16 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz", - "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz", + "integrity": "sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.5" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1150,14 +1167,14 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", - "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz", + "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1167,14 +1184,14 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1184,13 +1201,13 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", - "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz", + "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1200,13 +1217,13 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", - "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz", + "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1216,13 +1233,13 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", - "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz", + "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1232,17 +1249,17 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", - "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz", + "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.6" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1252,14 +1269,14 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", - "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz", + "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1269,13 +1286,13 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", - "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz", + "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1285,14 +1302,14 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", - "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz", + "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1302,13 +1319,13 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", - "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz", + "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1318,14 +1335,14 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", - "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz", + "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1335,15 +1352,15 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", - "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz", + "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1353,13 +1370,13 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", - "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz", + "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1384,13 +1401,13 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz", - "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.29.7.tgz", + "integrity": "sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1400,17 +1417,17 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", - "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.29.7.tgz", + "integrity": "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1420,13 +1437,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz", - "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.29.7.tgz", + "integrity": "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.27.1" + "@babel/plugin-transform-react-jsx": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1436,14 +1453,14 @@ } }, "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz", - "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.29.7.tgz", + "integrity": "sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1453,13 +1470,13 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.6.tgz", - "integrity": "sha512-eZhoEZHYQLL5uc1gS5e9/oTknS0sSSAtd5TkKMUp3J+S/CaUjagc0kOUPsEbDmMeva0nC3WWl4SxVY6+OBuxfw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.7.tgz", + "integrity": "sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1469,14 +1486,14 @@ } }, "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", - "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz", + "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1486,13 +1503,13 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", - "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz", + "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1502,13 +1519,13 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", - "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.29.7.tgz", + "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1518,14 +1535,14 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", - "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.29.7.tgz", + "integrity": "sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1535,13 +1552,13 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", - "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.29.7.tgz", + "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1551,13 +1568,13 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", - "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.29.7.tgz", + "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1567,13 +1584,13 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", - "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz", + "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1583,17 +1600,17 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz", - "integrity": "sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.29.7.tgz", + "integrity": "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-syntax-typescript": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-syntax-typescript": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1603,13 +1620,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", - "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz", + "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1619,14 +1636,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", - "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz", + "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1636,14 +1653,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", - "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz", + "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1653,14 +1670,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", - "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz", + "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1685,81 +1702,82 @@ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/@babel/preset-env": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.6.tgz", - "integrity": "sha512-GaTI4nXDrs7l0qaJ6Rg06dtOXTBCG6TMDB44zbqofCIC4PqC7SEvmFFtpxzCDw9W5aJ7RKVshgXTLvLdBFV/qw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.7.tgz", + "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", + "@babel/compat-data": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.28.6", - "@babel/plugin-syntax-import-attributes": "^7.28.6", + "@babel/plugin-syntax-import-assertions": "^7.29.7", + "@babel/plugin-syntax-import-attributes": "^7.29.7", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.28.6", - "@babel/plugin-transform-async-to-generator": "^7.28.6", - "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.6", - "@babel/plugin-transform-class-properties": "^7.28.6", - "@babel/plugin-transform-class-static-block": "^7.28.6", - "@babel/plugin-transform-classes": "^7.28.6", - "@babel/plugin-transform-computed-properties": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-dotall-regex": "^7.28.6", - "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.28.6", - "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-explicit-resource-management": "^7.28.6", - "@babel/plugin-transform-exponentiation-operator": "^7.28.6", - "@babel/plugin-transform-export-namespace-from": "^7.27.1", - "@babel/plugin-transform-for-of": "^7.27.1", - "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.28.6", - "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", - "@babel/plugin-transform-member-expression-literals": "^7.27.1", - "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.28.6", - "@babel/plugin-transform-modules-systemjs": "^7.28.5", - "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", - "@babel/plugin-transform-numeric-separator": "^7.28.6", - "@babel/plugin-transform-object-rest-spread": "^7.28.6", - "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.28.6", - "@babel/plugin-transform-optional-chaining": "^7.28.6", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/plugin-transform-private-methods": "^7.28.6", - "@babel/plugin-transform-private-property-in-object": "^7.28.6", - "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.28.6", - "@babel/plugin-transform-regexp-modifiers": "^7.28.6", - "@babel/plugin-transform-reserved-words": "^7.27.1", - "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.28.6", - "@babel/plugin-transform-sticky-regex": "^7.27.1", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/plugin-transform-typeof-symbol": "^7.27.1", - "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.28.6", - "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", + "@babel/plugin-transform-arrow-functions": "^7.29.7", + "@babel/plugin-transform-async-generator-functions": "^7.29.7", + "@babel/plugin-transform-async-to-generator": "^7.29.7", + "@babel/plugin-transform-block-scoped-functions": "^7.29.7", + "@babel/plugin-transform-block-scoping": "^7.29.7", + "@babel/plugin-transform-class-properties": "^7.29.7", + "@babel/plugin-transform-class-static-block": "^7.29.7", + "@babel/plugin-transform-classes": "^7.29.7", + "@babel/plugin-transform-computed-properties": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-dotall-regex": "^7.29.7", + "@babel/plugin-transform-duplicate-keys": "^7.29.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-dynamic-import": "^7.29.7", + "@babel/plugin-transform-explicit-resource-management": "^7.29.7", + "@babel/plugin-transform-exponentiation-operator": "^7.29.7", + "@babel/plugin-transform-export-namespace-from": "^7.29.7", + "@babel/plugin-transform-for-of": "^7.29.7", + "@babel/plugin-transform-function-name": "^7.29.7", + "@babel/plugin-transform-json-strings": "^7.29.7", + "@babel/plugin-transform-literals": "^7.29.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.29.7", + "@babel/plugin-transform-member-expression-literals": "^7.29.7", + "@babel/plugin-transform-modules-amd": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-modules-systemjs": "^7.29.7", + "@babel/plugin-transform-modules-umd": "^7.29.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-new-target": "^7.29.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7", + "@babel/plugin-transform-numeric-separator": "^7.29.7", + "@babel/plugin-transform-object-rest-spread": "^7.29.7", + "@babel/plugin-transform-object-super": "^7.29.7", + "@babel/plugin-transform-optional-catch-binding": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/plugin-transform-private-methods": "^7.29.7", + "@babel/plugin-transform-private-property-in-object": "^7.29.7", + "@babel/plugin-transform-property-literals": "^7.29.7", + "@babel/plugin-transform-regenerator": "^7.29.7", + "@babel/plugin-transform-regexp-modifiers": "^7.29.7", + "@babel/plugin-transform-reserved-words": "^7.29.7", + "@babel/plugin-transform-shorthand-properties": "^7.29.7", + "@babel/plugin-transform-spread": "^7.29.7", + "@babel/plugin-transform-sticky-regex": "^7.29.7", + "@babel/plugin-transform-template-literals": "^7.29.7", + "@babel/plugin-transform-typeof-symbol": "^7.29.7", + "@babel/plugin-transform-unicode-escapes": "^7.29.7", + "@babel/plugin-transform-unicode-property-regex": "^7.29.7", + "@babel/plugin-transform-unicode-regex": "^7.29.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.29.7", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.14", - "babel-plugin-polyfill-corejs3": "^0.13.0", - "babel-plugin-polyfill-regenerator": "^0.6.5", - "core-js-compat": "^3.43.0", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", "semver": "^6.3.1" }, "engines": { @@ -1784,18 +1802,18 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz", - "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.29.7.tgz", + "integrity": "sha512-C+PV1TFUPTmBQGoPBL8j2QmLpZ117YTCwxIZeJOM96GbYMFSc7/pOXU5lVykwnZxyTqQxRsvoRk6f2FktZgGHA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-transform-react-display-name": "^7.28.0", - "@babel/plugin-transform-react-jsx": "^7.27.1", - "@babel/plugin-transform-react-jsx-development": "^7.27.1", - "@babel/plugin-transform-react-pure-annotations": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-transform-react-display-name": "^7.29.7", + "@babel/plugin-transform-react-jsx": "^7.29.7", + "@babel/plugin-transform-react-jsx-development": "^7.29.7", + "@babel/plugin-transform-react-pure-annotations": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1805,17 +1823,17 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", - "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.29.7.tgz", + "integrity": "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@babel/plugin-transform-typescript": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-typescript": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1836,33 +1854,33 @@ } }, "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "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.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@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.28.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", - "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "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.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6", + "@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": { @@ -1870,14 +1888,14 @@ } }, "node_modules/@babel/types": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", - "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "version": "7.29.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.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -2516,13 +2534,6 @@ "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", "dev": true }, - "node_modules/@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/cors": { "version": "2.8.17", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", @@ -2533,28 +2544,10 @@ "@types/node": "*" } }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "license": "MIT" }, "node_modules/@types/hoist-non-react-statics": { @@ -2652,6 +2645,16 @@ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.59.7", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz", @@ -3436,14 +3439,14 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", - "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.7", - "@babel/helper-define-polyfill-provider": "^0.6.5", + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" }, "peerDependencies": { @@ -3451,27 +3454,27 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", - "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5", - "core-js-compat": "^3.43.0" + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", - "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5" + "@babel/helper-define-polyfill-provider": "^0.6.8" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -3541,10 +3544,11 @@ "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==" }, "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", "dev": true, + "license": "MIT", "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", @@ -3554,7 +3558,7 @@ "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", - "qs": "~6.14.0", + "qs": "~6.15.1", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" @@ -3667,11 +3671,12 @@ } }, "node_modules/browserify-sign": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", - "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.6.tgz", + "integrity": "sha512-sd+Q65fjlWCYWtZKXiKfrUc8d+4jtp/8f0W2NkwzLtoW4bI6UDnWusLWIurHnmurW0XShIRxpwiOX4EoPtXUAg==", + "license": "ISC", "dependencies": { - "bn.js": "^5.2.2", + "bn.js": "^5.2.3", "browserify-rsa": "^4.1.1", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", @@ -4162,13 +4167,13 @@ "hasInstallScript": true }, "node_modules/core-js-compat": { - "version": "3.46.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.46.0.tgz", - "integrity": "sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.26.3" + "browserslist": "^4.28.1" }, "funding": { "type": "opencollective", @@ -4861,22 +4866,22 @@ } }, "node_modules/engine.io": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", - "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "version": "6.6.8", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.8.tgz", + "integrity": "sha512-2agL3ueZhqxoVrfmntO8yuVj+uNSlIOnhykYHk3Cq0ShYPdUjjUiSJrQvXjq01I9jAuI0Zl2YO8Evv5Mqytm5g==", "dev": true, "license": "MIT", "dependencies": { - "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", + "@types/ws": "^8.5.12", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.7.2", "cors": "~2.8.5", - "debug": "~4.3.1", + "debug": "~4.4.1", "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" + "ws": "~8.20.1" }, "engines": { "node": ">=10.2.0" @@ -4902,14 +4907,39 @@ "node": ">= 0.6" } }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.1.tgz", + "integrity": "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.3" }, "engines": { "node": ">=10.13.0" @@ -5073,9 +5103,9 @@ } }, "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "license": "MIT" }, "node_modules/es-object-atoms": { @@ -5686,9 +5716,9 @@ "dev": true }, "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "funding": [ { "type": "github", @@ -5698,7 +5728,8 @@ "type": "opencollective", "url": "https://opencollective.com/fastify" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/fastest-levenshtein": { "version": "1.0.16", @@ -7165,7 +7196,8 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -7395,9 +7427,9 @@ } }, "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", "license": "MIT", "engines": { "node": ">=6.11.5" @@ -7595,6 +7627,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } @@ -7726,6 +7759,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -7734,6 +7768,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -7934,9 +7969,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.10.tgz", - "integrity": "sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "dev": true, "funding": [ { @@ -7944,6 +7979,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -8656,9 +8692,9 @@ } }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { @@ -8674,10 +8710,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -8844,10 +8881,11 @@ } }, "node_modules/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" }, @@ -9790,16 +9828,41 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", - "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.7.tgz", + "integrity": "sha512-e0LyK91f3cUxTmv95/KzoLg47+zF+s/sbxRGDNsyG4dmIP8ZSX8ax6byOxfJXeNNtS/8AZlfD+uP7gBeR7DLlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "~4.4.1", + "ws": "~8.20.1" + } + }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { - "debug": "~4.3.4", - "ws": "~8.17.1" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, + "node_modules/socket.io-adapter/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/socket.io-parser": { "version": "4.2.6", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", @@ -9845,10 +9908,11 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -10218,9 +10282,9 @@ } }, "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "license": "MIT", "engines": { "node": ">=6" @@ -10231,9 +10295,9 @@ } }, "node_modules/terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", + "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -10249,9 +10313,10 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", - "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", @@ -10269,21 +10334,48 @@ "webpack": "^5.1.0" }, "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, "@swc/core": { "optional": true }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, "esbuild": { "optional": true }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, "uglify-js": { "optional": true } } }, "node_modules/terser/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -10322,10 +10414,11 @@ } }, "node_modules/tmp": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.4.tgz", - "integrity": "sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.14" } @@ -10900,9 +10993,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", - "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", @@ -10913,36 +11006,34 @@ } }, "node_modules/webpack": { - "version": "5.104.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", - "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", + "version": "5.107.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.2.tgz", + "integrity": "sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==", "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.4", - "es-module-lexer": "^2.0.0", + "enhanced-resolve": "^5.22.0", + "es-module-lexer": "^2.1.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.4.4", - "webpack-sources": "^3.3.3" + "terser-webpack-plugin": "^5.5.0", + "watchpack": "^2.5.1", + "webpack-sources": "^3.5.0" }, "bin": { "webpack": "bin/webpack.js" @@ -11037,18 +11128,18 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", "license": "MIT", "engines": { "node": ">=10.13.0" } }, "node_modules/webpack/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -11069,6 +11160,15 @@ "acorn": "^8.14.0" } }, + "node_modules/webpack/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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/whatwg-fetch": { "version": "3.6.20", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", @@ -11320,9 +11420,9 @@ "dev": true }, "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "dev": true, "license": "MIT", "engines": { @@ -11362,7 +11462,8 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yargs": { "version": "16.2.0", @@ -11421,9 +11522,9 @@ }, "dependencies": { "@babel/cli": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.28.6.tgz", - "integrity": "sha512-6EUNcuBbNkj08Oj4gAZ+BUU8yLCgKzgVX4gaTh09Ya2C8ICM4P+G30g4m3akRxSYAp3A/gnWchrNst7px4/nUQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.29.7.tgz", + "integrity": "sha512-/75HwRbAYPqXv/Ax1h7Fg3IZfXgdU98jnA8H93/m/QBaPV3Hp5ICoLqzGYye1yHBCgpmXvtqgSUN8oOKX5tojQ==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.28", @@ -11457,37 +11558,37 @@ } }, "@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "@babel/compat-data": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", - "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true }, "@babel/core": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", - "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "requires": { + "@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", @@ -11497,77 +11598,77 @@ } }, "@babel/generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", - "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dev": true, "requires": { - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6", + "@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" } }, "@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", "dev": true, "requires": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.29.7" } }, "@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "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, "requires": { - "@babel/compat-data": "^7.28.6", - "@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" } }, "@babel/helper-create-class-features-plugin": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", - "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.6", + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", "semver": "^6.3.1" } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", - "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz", + "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-annotate-as-pure": "^7.29.7", "regexpu-core": "^6.3.1", "semver": "^6.3.1" } }, "@babel/helper-define-polyfill-provider": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", - "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", "dev": true, "requires": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "debug": "^4.4.1", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", "lodash.debounce": "^4.0.8", - "resolve": "^1.22.10" + "resolve": "^1.22.11" }, "dependencies": { "debug": { @@ -11588,184 +11689,194 @@ } }, "@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "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 }, "@babel/helper-member-expression-to-functions": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", - "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", "dev": true, "requires": { - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "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, "requires": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "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, "requires": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/helper-optimise-call-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", "dev": true, "requires": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.29.7" } }, "@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "dev": true }, "@babel/helper-remap-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", - "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz", + "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-wrap-function": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-wrap-function": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/helper-replace-supers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", - "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.28.6" + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", "dev": true, "requires": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@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 }, "@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "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 }, "@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 }, "@babel/helper-wrap-function": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", - "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz", + "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", "dev": true, "requires": { - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "requires": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@babel/parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", - "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "version": "7.29.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, "requires": { - "@babel/types": "^7.28.6" + "@babel/types": "^7.29.7" } }, "@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", - "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz", + "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz", + "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz", + "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.29.7" + } + }, + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz", + "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" } }, "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz", + "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7" } }, "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", - "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz", + "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-proposal-class-properties": { @@ -11786,39 +11897,39 @@ "requires": {} }, "@babel/plugin-syntax-import-assertions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", - "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz", + "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-syntax-import-attributes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", - "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz", + "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-syntax-unicode-sets-regex": { @@ -11832,389 +11943,389 @@ } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", - "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-async-generator-functions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.6.tgz", - "integrity": "sha512-9knsChgsMzBV5Yh3kkhrZNxH3oCYAfMBkNNaVN4cP2RVlFPe8wYdwwcnOsAbkdDoV9UjFtOXWrWB52M8W4jNeA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz", + "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", - "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz", + "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", - "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz", + "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", - "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz", + "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-class-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", - "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz", + "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-class-static-block": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", - "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz", + "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-classes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", - "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz", + "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-transform-computed-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", - "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.29.7.tgz", + "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/template": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/template": "^7.29.7" } }, "@babel/plugin-transform-destructuring": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", - "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz", + "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", - "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz", + "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", - "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz", + "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.28.6.tgz", - "integrity": "sha512-5suVoXjC14lUN6ZL9OLKIHCNVWCrqGqlmEp/ixdXjvgnEl/kauLvvMO/Xw9NyMc95Joj1AeLVPVMvibBgSoFlA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-dynamic-import": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz", + "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-explicit-resource-management": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", - "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz", + "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", - "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz", + "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-export-namespace-from": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz", + "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-for-of": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", - "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz", + "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" } }, "@babel/plugin-transform-function-name": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", - "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz", + "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==", "dev": true, "requires": { - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-transform-json-strings": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", - "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz", + "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", - "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz", + "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-logical-assignment-operators": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", - "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz", + "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", - "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz", + "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", - "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz", + "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", - "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz", + "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz", - "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz", + "integrity": "sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.5" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", - "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz", + "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-new-target": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", - "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz", + "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", - "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz", + "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-numeric-separator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", - "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz", + "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-object-rest-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", - "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz", + "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", "dev": true, "requires": { - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.6" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/traverse": "^7.29.7" } }, "@babel/plugin-transform-object-super": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", - "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz", + "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7" } }, "@babel/plugin-transform-optional-catch-binding": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", - "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz", + "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-optional-chaining": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", - "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz", + "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" } }, "@babel/plugin-transform-parameters": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", - "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz", + "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-private-methods": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", - "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz", + "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-private-property-in-object": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", - "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz", + "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-property-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", - "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz", + "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-react-constant-elements": { @@ -12227,170 +12338,170 @@ } }, "@babel/plugin-transform-react-display-name": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz", - "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.29.7.tgz", + "integrity": "sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-react-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", - "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.29.7.tgz", + "integrity": "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@babel/plugin-transform-react-jsx-development": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz", - "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.29.7.tgz", + "integrity": "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==", "dev": true, "requires": { - "@babel/plugin-transform-react-jsx": "^7.27.1" + "@babel/plugin-transform-react-jsx": "^7.29.7" } }, "@babel/plugin-transform-react-pure-annotations": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz", - "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.29.7.tgz", + "integrity": "sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-regenerator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.6.tgz", - "integrity": "sha512-eZhoEZHYQLL5uc1gS5e9/oTknS0sSSAtd5TkKMUp3J+S/CaUjagc0kOUPsEbDmMeva0nC3WWl4SxVY6+OBuxfw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.7.tgz", + "integrity": "sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-regexp-modifiers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", - "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz", + "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", - "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz", + "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", - "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.29.7.tgz", + "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", - "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.29.7.tgz", + "integrity": "sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", - "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.29.7.tgz", + "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-template-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", - "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.29.7.tgz", + "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", - "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz", + "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-typescript": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz", - "integrity": "sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.29.7.tgz", + "integrity": "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-syntax-typescript": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-syntax-typescript": "^7.29.7" } }, "@babel/plugin-transform-unicode-escapes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", - "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz", + "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-unicode-property-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", - "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz", + "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", - "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz", + "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/plugin-transform-unicode-sets-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", - "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz", + "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" } }, "@babel/polyfill": { @@ -12410,80 +12521,81 @@ } }, "@babel/preset-env": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.6.tgz", - "integrity": "sha512-GaTI4nXDrs7l0qaJ6Rg06dtOXTBCG6TMDB44zbqofCIC4PqC7SEvmFFtpxzCDw9W5aJ7RKVshgXTLvLdBFV/qw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.7.tgz", + "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.28.6", - "@babel/plugin-syntax-import-attributes": "^7.28.6", + "@babel/plugin-syntax-import-assertions": "^7.29.7", + "@babel/plugin-syntax-import-attributes": "^7.29.7", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.28.6", - "@babel/plugin-transform-async-to-generator": "^7.28.6", - "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.6", - "@babel/plugin-transform-class-properties": "^7.28.6", - "@babel/plugin-transform-class-static-block": "^7.28.6", - "@babel/plugin-transform-classes": "^7.28.6", - "@babel/plugin-transform-computed-properties": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-dotall-regex": "^7.28.6", - "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.28.6", - "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-explicit-resource-management": "^7.28.6", - "@babel/plugin-transform-exponentiation-operator": "^7.28.6", - "@babel/plugin-transform-export-namespace-from": "^7.27.1", - "@babel/plugin-transform-for-of": "^7.27.1", - "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.28.6", - "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", - "@babel/plugin-transform-member-expression-literals": "^7.27.1", - "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.28.6", - "@babel/plugin-transform-modules-systemjs": "^7.28.5", - "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", - "@babel/plugin-transform-numeric-separator": "^7.28.6", - "@babel/plugin-transform-object-rest-spread": "^7.28.6", - "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.28.6", - "@babel/plugin-transform-optional-chaining": "^7.28.6", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/plugin-transform-private-methods": "^7.28.6", - "@babel/plugin-transform-private-property-in-object": "^7.28.6", - "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.28.6", - "@babel/plugin-transform-regexp-modifiers": "^7.28.6", - "@babel/plugin-transform-reserved-words": "^7.27.1", - "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.28.6", - "@babel/plugin-transform-sticky-regex": "^7.27.1", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/plugin-transform-typeof-symbol": "^7.27.1", - "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.28.6", - "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", + "@babel/plugin-transform-arrow-functions": "^7.29.7", + "@babel/plugin-transform-async-generator-functions": "^7.29.7", + "@babel/plugin-transform-async-to-generator": "^7.29.7", + "@babel/plugin-transform-block-scoped-functions": "^7.29.7", + "@babel/plugin-transform-block-scoping": "^7.29.7", + "@babel/plugin-transform-class-properties": "^7.29.7", + "@babel/plugin-transform-class-static-block": "^7.29.7", + "@babel/plugin-transform-classes": "^7.29.7", + "@babel/plugin-transform-computed-properties": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-dotall-regex": "^7.29.7", + "@babel/plugin-transform-duplicate-keys": "^7.29.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-dynamic-import": "^7.29.7", + "@babel/plugin-transform-explicit-resource-management": "^7.29.7", + "@babel/plugin-transform-exponentiation-operator": "^7.29.7", + "@babel/plugin-transform-export-namespace-from": "^7.29.7", + "@babel/plugin-transform-for-of": "^7.29.7", + "@babel/plugin-transform-function-name": "^7.29.7", + "@babel/plugin-transform-json-strings": "^7.29.7", + "@babel/plugin-transform-literals": "^7.29.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.29.7", + "@babel/plugin-transform-member-expression-literals": "^7.29.7", + "@babel/plugin-transform-modules-amd": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-modules-systemjs": "^7.29.7", + "@babel/plugin-transform-modules-umd": "^7.29.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-new-target": "^7.29.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7", + "@babel/plugin-transform-numeric-separator": "^7.29.7", + "@babel/plugin-transform-object-rest-spread": "^7.29.7", + "@babel/plugin-transform-object-super": "^7.29.7", + "@babel/plugin-transform-optional-catch-binding": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/plugin-transform-private-methods": "^7.29.7", + "@babel/plugin-transform-private-property-in-object": "^7.29.7", + "@babel/plugin-transform-property-literals": "^7.29.7", + "@babel/plugin-transform-regenerator": "^7.29.7", + "@babel/plugin-transform-regexp-modifiers": "^7.29.7", + "@babel/plugin-transform-reserved-words": "^7.29.7", + "@babel/plugin-transform-shorthand-properties": "^7.29.7", + "@babel/plugin-transform-spread": "^7.29.7", + "@babel/plugin-transform-sticky-regex": "^7.29.7", + "@babel/plugin-transform-template-literals": "^7.29.7", + "@babel/plugin-transform-typeof-symbol": "^7.29.7", + "@babel/plugin-transform-unicode-escapes": "^7.29.7", + "@babel/plugin-transform-unicode-property-regex": "^7.29.7", + "@babel/plugin-transform-unicode-regex": "^7.29.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.29.7", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.14", - "babel-plugin-polyfill-corejs3": "^0.13.0", - "babel-plugin-polyfill-regenerator": "^0.6.5", - "core-js-compat": "^3.43.0", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", "semver": "^6.3.1" } }, @@ -12499,30 +12611,30 @@ } }, "@babel/preset-react": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz", - "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.29.7.tgz", + "integrity": "sha512-C+PV1TFUPTmBQGoPBL8j2QmLpZ117YTCwxIZeJOM96GbYMFSc7/pOXU5lVykwnZxyTqQxRsvoRk6f2FktZgGHA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-transform-react-display-name": "^7.28.0", - "@babel/plugin-transform-react-jsx": "^7.27.1", - "@babel/plugin-transform-react-jsx-development": "^7.27.1", - "@babel/plugin-transform-react-pure-annotations": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-transform-react-display-name": "^7.29.7", + "@babel/plugin-transform-react-jsx": "^7.29.7", + "@babel/plugin-transform-react-jsx-development": "^7.29.7", + "@babel/plugin-transform-react-pure-annotations": "^7.29.7" } }, "@babel/preset-typescript": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", - "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.29.7.tgz", + "integrity": "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@babel/plugin-transform-typescript": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-typescript": "^7.29.7" } }, "@babel/runtime": { @@ -12534,39 +12646,39 @@ } }, "@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "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, "requires": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" } }, "@babel/traverse": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", - "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "dev": true, "requires": { - "@babel/code-frame": "^7.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6", + "@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" } }, "@babel/types": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", - "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" } }, "@colors/colors": { @@ -12984,12 +13096,6 @@ "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", "dev": true }, - "@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", - "dev": true - }, "@types/cors": { "version": "2.8.17", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", @@ -12999,28 +13105,10 @@ "@types/node": "*" } }, - "@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==" }, "@types/hoist-non-react-statics": { "version": "3.3.1", @@ -13116,6 +13204,15 @@ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, + "@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@typescript-eslint/eslint-plugin": { "version": "5.59.7", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz", @@ -13686,33 +13783,33 @@ } }, "babel-plugin-polyfill-corejs2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", - "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", "dev": true, "requires": { - "@babel/compat-data": "^7.27.7", - "@babel/helper-define-polyfill-provider": "^0.6.5", + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" } }, "babel-plugin-polyfill-corejs3": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", - "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.6.5", - "core-js-compat": "^3.43.0" + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" } }, "babel-plugin-polyfill-regenerator": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", - "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.6.5" + "@babel/helper-define-polyfill-provider": "^0.6.8" } }, "balanced-match": { @@ -13754,9 +13851,9 @@ "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==" }, "body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", "dev": true, "requires": { "bytes": "~3.1.2", @@ -13767,7 +13864,7 @@ "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", - "qs": "~6.14.0", + "qs": "~6.15.1", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" @@ -13871,11 +13968,11 @@ } }, "browserify-sign": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", - "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.6.tgz", + "integrity": "sha512-sd+Q65fjlWCYWtZKXiKfrUc8d+4jtp/8f0W2NkwzLtoW4bI6UDnWusLWIurHnmurW0XShIRxpwiOX4EoPtXUAg==", "requires": { - "bn.js": "^5.2.2", + "bn.js": "^5.2.3", "browserify-rsa": "^4.1.1", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", @@ -14240,12 +14337,12 @@ "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" }, "core-js-compat": { - "version": "3.46.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.46.0.tgz", - "integrity": "sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", "dev": true, "requires": { - "browserslist": "^4.26.3" + "browserslist": "^4.28.1" } }, "core-util-is": { @@ -14775,21 +14872,21 @@ "dev": true }, "engine.io": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", - "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "version": "6.6.8", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.8.tgz", + "integrity": "sha512-2agL3ueZhqxoVrfmntO8yuVj+uNSlIOnhykYHk3Cq0ShYPdUjjUiSJrQvXjq01I9jAuI0Zl2YO8Evv5Mqytm5g==", "dev": true, "requires": { - "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", + "@types/ws": "^8.5.12", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.7.2", "cors": "~2.8.5", - "debug": "~4.3.1", + "debug": "~4.4.1", "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" + "ws": "~8.20.1" }, "dependencies": { "cookie": { @@ -14797,6 +14894,21 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true + }, + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true } } }, @@ -14807,12 +14919,12 @@ "dev": true }, "enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.1.tgz", + "integrity": "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==", "requires": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.3" } }, "ent": { @@ -14931,9 +15043,9 @@ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" }, "es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==" }, "es-object-atoms": { "version": "1.1.1", @@ -15402,9 +15514,9 @@ "dev": true }, "fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==" }, "fastest-levenshtein": { "version": "1.0.16", @@ -16424,7 +16536,8 @@ "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true }, "json-schema-traverse": { "version": "0.4.1", @@ -16615,9 +16728,9 @@ } }, "loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==" + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==" }, "locate-path": { "version": "6.0.0", @@ -16870,12 +16983,14 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "requires": { "mime-db": "1.52.0" } @@ -17024,9 +17139,9 @@ "dev": true }, "nanoid": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.10.tgz", - "integrity": "sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "dev": true }, "natural-compare": { @@ -17557,14 +17672,14 @@ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==" }, "postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "requires": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" } }, "postcss-modules-extract-imports": { @@ -17683,9 +17798,9 @@ "dev": true }, "qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "dev": true, "requires": { "side-channel": "^1.1.0" @@ -18354,13 +18469,30 @@ } }, "socket.io-adapter": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", - "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.7.tgz", + "integrity": "sha512-e0LyK91f3cUxTmv95/KzoLg47+zF+s/sbxRGDNsyG4dmIP8ZSX8ax6byOxfJXeNNtS/8AZlfD+uP7gBeR7DLlg==", "dev": true, "requires": { - "debug": "~4.3.4", - "ws": "~8.17.1" + "debug": "~4.4.1", + "ws": "~8.20.1" + }, + "dependencies": { + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } } }, "socket.io-parser": { @@ -18396,9 +18528,9 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true }, "source-map-support": { @@ -18681,14 +18813,14 @@ } }, "tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==" + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==" }, "terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", + "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", "requires": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", @@ -18697,9 +18829,9 @@ }, "dependencies": { "acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==" + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==" }, "commander": { "version": "2.20.3", @@ -18709,9 +18841,9 @@ } }, "terser-webpack-plugin": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", - "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", "requires": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", @@ -18740,9 +18872,9 @@ } }, "tmp": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.4.tgz", - "integrity": "sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", "dev": true }, "to-buffer": { @@ -19163,56 +19295,59 @@ "dev": true }, "watchpack": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", - "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "requires": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "webpack": { - "version": "5.104.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", - "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", + "version": "5.107.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.2.tgz", + "integrity": "sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==", "requires": { - "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.4", - "es-module-lexer": "^2.0.0", + "enhanced-resolve": "^5.22.0", + "es-module-lexer": "^2.1.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.4.4", - "webpack-sources": "^3.3.3" + "terser-webpack-plugin": "^5.5.0", + "watchpack": "^2.5.1", + "webpack-sources": "^3.5.0" }, "dependencies": { "acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==" + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==" }, "acorn-import-phases": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", "requires": {} + }, + "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==" } } }, @@ -19265,9 +19400,9 @@ } }, "webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==" + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==" }, "whatwg-fetch": { "version": "3.6.20", @@ -19466,9 +19601,9 @@ "dev": true }, "ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "dev": true, "requires": {} }, diff --git a/dash/dash-renderer/package.json b/dash/dash-renderer/package.json index a404fa2425..31547c684d 100644 --- a/dash/dash-renderer/package.json +++ b/dash/dash-renderer/package.json @@ -1,6 +1,6 @@ { "name": "dash-renderer", - "version": "3.1.0", + "version": "3.2.0", "description": "render dash components in react", "main": "build/dash_renderer.min.js", "scripts": { diff --git a/dash/version.py b/dash/version.py index d39d52c3b8..0fd7811c0d 100644 --- a/dash/version.py +++ b/dash/version.py @@ -1 +1 @@ -__version__ = "4.2.0rc3" +__version__ = "4.2.0" From 3b483d15c2f9222bd2d004c38ad2daa6d042d8e5 Mon Sep 17 00:00:00 2001 From: philippe Date: Mon, 1 Jun 2026 16:06:00 -0400 Subject: [PATCH 297/297] build artifacts for 4.2.0 --- dash/dash-renderer/build/dash-ws-worker.js | 1 + dash/dash-renderer/build/dash_renderer.dev.js | 151364 ++++++++------- dash/dash-renderer/build/dash_renderer.min.js | 2 +- dash/dash_table/async-export.js | 2 +- dash/dash_table/async-export.js.map | 2 +- dash/dash_table/async-highlight.js | 2 +- dash/dash_table/async-highlight.js.map | 2 +- dash/dash_table/async-table.js | 2 +- dash/dash_table/async-table.js.LICENSE.txt | 2 + dash/dash_table/async-table.js.map | 2 +- dash/dash_table/bundle.js | 2 +- dash/dash_table/bundle.js.map | 2 +- dash/dash_table/demo.js | 2 +- dash/dash_table/demo.js.map | 2 +- dash/dash_table/package-info.json | 4 +- dash/dcc/Dropdown.py | 9 + dash/dcc/Graph.py | 4 + dash/dcc/async-datepicker.js | 2 +- dash/dcc/async-datepicker.js.map | 2 +- dash/dcc/async-dropdown.js | 2 +- dash/dcc/async-dropdown.js.LICENSE.txt | 6 +- dash/dcc/async-dropdown.js.map | 2 +- dash/dcc/async-graph.js | 2 +- dash/dcc/async-graph.js.map | 2 +- dash/dcc/async-highlight.js | 2 +- dash/dcc/async-highlight.js.map | 2 +- dash/dcc/async-markdown.js | 2 +- dash/dcc/async-markdown.js.map | 2 +- dash/dcc/async-slider.js | 2 +- dash/dcc/async-slider.js.LICENSE.txt | 11 + dash/dcc/async-slider.js.map | 2 +- dash/dcc/async-upload.js | 3 +- dash/dcc/async-upload.js.map | 2 +- dash/dcc/dash_core_components-shared.js | 2 +- ...dash_core_components-shared.js.LICENSE.txt | 2 + dash/dcc/dash_core_components-shared.js.map | 2 +- dash/dcc/dash_core_components.js | 2 +- dash/dcc/dash_core_components.js.LICENSE.txt | 2 + dash/dcc/dash_core_components.js.map | 2 +- dash/dcc/metadata.json | 2 +- dash/dcc/package-info.json | 4 +- dash/dcc/proptypes.js | 1 + dash/html/dash_html_components.min.js.map | 2 +- dash/html/package-info.json | 2 +- 44 files changed, 76248 insertions(+), 75227 deletions(-) create mode 100644 dash/dash-renderer/build/dash-ws-worker.js create mode 100644 dash/dcc/async-slider.js.LICENSE.txt diff --git a/dash/dash-renderer/build/dash-ws-worker.js b/dash/dash-renderer/build/dash-ws-worker.js new file mode 100644 index 0000000000..79274d3b53 --- /dev/null +++ b/dash/dash-renderer/build/dash-ws-worker.js @@ -0,0 +1 @@ +(()=>{"use strict";const e={maxRetries:10,initialRetryDelay:1e3,maxRetryDelay:3e4,heartbeatInterval:3e4,heartbeatTimeout:1e4,inactivityTimeout:3e5};var t;!function(e){e.CONNECT="connect",e.DISCONNECT="disconnect",e.CALLBACK_REQUEST="callback_request",e.GET_PROPS_RESPONSE="get_props_response",e.TAB_VISIBLE="tab_visible",e.CONNECTED="connected",e.DISCONNECTED="disconnected",e.CALLBACK_RESPONSE="callback_response",e.SET_PROPS="set_props",e.SET_PROPS_BATCH="set_props_batch",e.GET_PROPS_REQUEST="get_props_request",e.ERROR="error",e.HEARTBEAT_ACK="heartbeat_ack"}(t||(t={}));const r=new class{constructor(t={}){this.ws=null,this.serverUrl=null,this.retryCount=0,this.retryTimeout=null,this.heartbeatInterval=null,this.heartbeatTimeout=null,this.lastActivityTime=Date.now(),this.messageQueue=[],this.isConnecting=!1,this.onOpen=null,this.onClose=null,this.onMessage=null,this.onError=null,this.config={...e,...t}}setConfig(e){this.config={...this.config,...e}}connect(e){this.ws&&this.ws.readyState===WebSocket.OPEN||this.isConnecting||(this.serverUrl=e,this.isConnecting=!0,this.retryCount=0,this.createConnection())}disconnect(){this.cleanup(),this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.close(1e3,"Client disconnect"),this.ws=null,this.serverUrl=null,this.retryCount=0}send(e){const t=JSON.stringify(e);"heartbeat"!==e.type&&(this.lastActivityTime=Date.now()),this.ws&&this.ws.readyState===WebSocket.OPEN?this.ws.send(t):(this.messageQueue.push(t),this.serverUrl&&!this.isConnecting&&(this.isConnecting=!0,this.retryCount=0,this.createConnection()))}get isConnected(){return null!==this.ws&&this.ws.readyState===WebSocket.OPEN}resetActivity(){this.lastActivityTime=Date.now()}createConnection(){if(this.serverUrl)try{this.ws=new WebSocket(this.serverUrl),this.ws.onopen=this.handleOpen.bind(this),this.ws.onclose=this.handleClose.bind(this),this.ws.onmessage=this.handleMessage.bind(this),this.ws.onerror=this.handleError.bind(this)}catch(e){this.isConnecting=!1,this.scheduleReconnect()}}handleOpen(){for(this.isConnecting=!1,this.retryCount=0,this.lastActivityTime=Date.now();this.messageQueue.length>0;){const e=this.messageQueue.shift();e&&this.ws&&this.ws.send(e)}this.startHeartbeat(),this.onOpen&&this.onOpen()}handleClose(e){this.isConnecting=!1,this.cleanup();const t=e.reason||"Connection closed";this.onClose&&this.onClose(t),this.serverUrl&&1e3!==e.code&&4001!==e.code&&this.scheduleReconnect()}handleMessage(e){try{const t=JSON.parse(e.data);if(Array.isArray(t)){let e=!1,r=!1;for(const s of t)"heartbeat_ack"===s.type?e=!0:r=!0;return e&&this.clearHeartbeatTimeout(),void(r&&(this.lastActivityTime=Date.now(),this.onMessage&&this.onMessage(t)))}if("heartbeat_ack"===t.type)return void this.clearHeartbeatTimeout();this.lastActivityTime=Date.now(),this.onMessage&&this.onMessage(t)}catch(e){this.onError&&this.onError(new Error("Failed to parse message"))}}handleError(){this.isConnecting=!1}scheduleReconnect(){if(this.retryTimeout&&clearTimeout(this.retryTimeout),this.retryCount>=this.config.maxRetries)return void(this.onError&&this.onError(new Error("Max reconnection attempts reached")));const e=Math.min(this.config.initialRetryDelay*Math.pow(2,this.retryCount)+1e3*Math.random(),this.config.maxRetryDelay);this.retryCount++,this.retryTimeout=setTimeout(()=>{this.createConnection()},e)}startHeartbeat(){this.stopHeartbeat(),this.heartbeatInterval=setInterval(()=>{if(this.ws&&this.ws.readyState===WebSocket.OPEN){if(this.config.inactivityTimeout>0&&Date.now()-this.lastActivityTime>=this.config.inactivityTimeout)return void this.ws.close(4001,"Inactivity timeout");this.ws.send(JSON.stringify({type:"heartbeat"})),this.setHeartbeatTimeout()}},this.config.heartbeatInterval)}stopHeartbeat(){this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null),this.clearHeartbeatTimeout()}setHeartbeatTimeout(){this.clearHeartbeatTimeout(),this.heartbeatTimeout=setTimeout(()=>{this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.close(4e3,"Heartbeat timeout")},this.config.heartbeatTimeout)}clearHeartbeatTimeout(){this.heartbeatTimeout&&(clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=null)}cleanup(){this.stopHeartbeat(),this.retryTimeout&&(clearTimeout(this.retryTimeout),this.retryTimeout=null)}},s=new class{constructor(){this.renderers=new Map,this.sendToServer=null}registerRenderer(e,t){this.renderers.set(e,t)}unregisterRenderer(e){this.renderers.delete(e)}get rendererCount(){return this.renderers.size}handleRendererMessage(e,r){switch(r.type){case t.CALLBACK_REQUEST:this.forwardCallbackRequest(e,r);break;case t.GET_PROPS_RESPONSE:this.forwardGetPropsResponse(e,r);break;default:console.warn(`Unknown message type from renderer: ${r.type}`)}}handleServerMessage(e){if(Array.isArray(e))return void this.handleBatchedMessages(e);const r=e,s=r.rendererId;switch(r.type){case t.CALLBACK_RESPONSE:this.forwardToRenderer(s,r);break;case t.SET_PROPS:this.forwardSetProps(s,r);break;case t.GET_PROPS_REQUEST:this.forwardGetPropsRequest(s,r);break;case t.ERROR:this.forwardToRenderer(s,r);break;default:console.warn(`Unknown message type from server: ${r.type}`)}}handleBatchedMessages(e){const r=new Map,s=[];for(const n of e)if(n.type!==t.HEARTBEAT_ACK)if(n.type===t.SET_PROPS){const e=n,t=e.rendererId,s=r.get(t);s?s.push(e.payload):r.set(t,[e.payload])}else s.push(n);for(const[e,s]of r){const r=this.renderers.get(e);if(r)try{r.postMessage({type:t.SET_PROPS_BATCH,rendererId:e,payload:s})}catch(t){console.warn(`Failed to forward batch to renderer ${e}, removing`),this.renderers.delete(e)}else console.warn(`Renderer ${e} not found for batch, skipping`)}for(const e of s)this.handleServerMessage(e)}broadcastToRenderers(e){for(const[t,r]of this.renderers)try{r.postMessage(e)}catch(e){console.warn(`Failed to send to renderer ${t}, removing`),this.renderers.delete(t)}}notifyConnected(e){const r=this.renderers.get(e);if(r)try{r.postMessage({type:t.CONNECTED,rendererId:e})}catch(t){console.warn(`Failed to notify renderer ${e}, removing`),this.renderers.delete(e)}}notifyDisconnected(e){this.broadcastToRenderers({type:t.DISCONNECTED,rendererId:"",payload:{reason:e}})}notifyError(e,r,s){const n=this.renderers.get(e);if(n)try{n.postMessage({type:t.ERROR,rendererId:e,payload:{message:r,code:s}})}catch(t){console.warn(`Failed to send error to renderer ${e}, removing`),this.renderers.delete(e)}}forwardCallbackRequest(e,r){this.sendToServer&&this.sendToServer({type:t.CALLBACK_REQUEST,rendererId:e,requestId:r.requestId,payload:r.payload})}forwardGetPropsResponse(e,r){this.sendToServer&&this.sendToServer({type:t.GET_PROPS_RESPONSE,rendererId:e,requestId:r.requestId,payload:r.payload})}forwardToRenderer(e,t){const r=this.renderers.get(e);if(r)try{r.postMessage(t)}catch(t){console.warn(`Failed to forward to renderer ${e}, removing`),this.renderers.delete(e)}else console.warn(`Renderer ${e} not found for message`)}forwardSetProps(e,t){this.forwardToRenderer(e,t)}forwardGetPropsRequest(e,t){this.forwardToRenderer(e,t)}};let n=null;r.onOpen=()=>{console.log("[DashWSWorker] WebSocket connected");for(const e of Array.from(o))s.notifyConnected(e)},r.onClose=e=>{console.log(`[DashWSWorker] WebSocket closed: ${e}`),s.notifyDisconnected(e)},r.onMessage=e=>{s.handleServerMessage(e)},r.onError=e=>{console.error("[DashWSWorker] WebSocket error:",e.message)},s.sendToServer=e=>{r.send(e)};const o=new Set;self.onconnect=e=>{const i=e.ports[0];i.onmessage=e=>{const a=e.data;switch(a.type){case t.CONNECT:{const e=a,t=e.rendererId,h=e.payload.serverUrl,c=e.payload.inactivityTimeout,d=e.payload.heartbeatInterval;s.registerRenderer(t,i),o.add(t),console.log(`[DashWSWorker] Renderer ${t} connected, inactivityTimeout: ${c}, heartbeatInterval: ${d}`);const l={};"number"==typeof c&&(l.inactivityTimeout=c),"number"==typeof d&&(l.heartbeatInterval=d),Object.keys(l).length>0&&r.setConfig(l),r.isConnected?s.notifyConnected(t):(n!==h&&(n=h),r.connect(n));break}case t.DISCONNECT:{const e=a.rendererId;s.unregisterRenderer(e),o.delete(e),console.log(`[DashWSWorker] Renderer ${e} disconnected`),0===s.rendererCount&&(r.disconnect(),n=null,console.log("[DashWSWorker] All renderers disconnected, closing WebSocket"));break}case t.TAB_VISIBLE:r.resetActivity();break;default:s.handleRendererMessage(a.rendererId,a)}},i.start()},console.log("[DashWSWorker] SharedWorker initialized")})(); \ No newline at end of file diff --git a/dash/dash-renderer/build/dash_renderer.dev.js b/dash/dash-renderer/build/dash_renderer.dev.js index 75d87fcfd2..4668ad0893 100644 --- a/dash/dash-renderer/build/dash_renderer.dev.js +++ b/dash/dash-renderer/build/dash_renderer.dev.js @@ -1,53395 +1,43481 @@ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ -/***/ "./node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js" -/*!*********************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js ***! - \*********************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _arrayLikeToArray) -/* harmony export */ }); -function _arrayLikeToArray(r, a) { - (null == a || a > r.length) && (a = r.length); - for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; - return n; -} +/***/ "./node_modules/@plotly/dash-component-plugins/dist/index.js" +/*!*******************************************************************!*\ + !*** ./node_modules/@plotly/dash-component-plugins/dist/index.js ***! + \*******************************************************************/ +(module, __unused_webpack_exports, __webpack_require__) { +!function(e,n){ true?module.exports=n(__webpack_require__(/*! react */ "react")):0}(window,(function(e){return function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=1)}([function(n,t){n.exports=e},function(e,n,t){"use strict";t.r(n),t.d(n,"asyncDecorator",(function(){return u})),t.d(n,"inheritAsyncDecorator",(function(){return a})),t.d(n,"isReady",(function(){return c})),t.d(n,"History",(function(){return d}));var r=t(0);function o(e,n,t,r,o,i,u){try{var a=e[i](u),c=a.value}catch(e){return void t(e)}a.done?n(c):Promise.resolve(c).then(r,o)}function i(e){return function(){var n=this,t=arguments;return new Promise((function(r,i){var u=e.apply(n,t);function a(e){o(u,r,i,a,c,"next",e)}function c(e){o(u,r,i,a,c,"throw",e)}a(void 0)}))}}var u=function(e,n){var t,o={isReady:new Promise((function(e){t=e})),get:Object(r.lazy)((function(){return Promise.resolve(n()).then((function(e){return setTimeout(i(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,t(!0);case 2:o.isReady=!0;case 3:case"end":return e.stop()}}),e)}))),0),e}))}))};return Object.defineProperty(e,"_dashprivate_isLazyComponentReady",{get:function(){return o.isReady}}),o.get},a=function(e,n){Object.defineProperty(e,"_dashprivate_isLazyComponentReady",{get:function(){return c(n)}})},c=function(e){return e&&e._dashprivate_isLazyComponentReady};function f(e,n){for(var t=0;t (/* binding */ _arrayWithHoles) -/* harmony export */ }); -function _arrayWithHoles(r) { - if (Array.isArray(r)) return r; -} +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react"); +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); +var _path; +function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } +var SvgCheckIcon = props => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("svg", _extends({ + xmlns: "http://www.w3.org/2000/svg", + width: 18, + height: 18, + fill: "none", + viewBox: "0 0 14 14" +}, props), _path || (_path = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", { + fill: "#06800A", + fillOpacity: 0.8, + d: "M9.854 5.146a.5.5 0 0 1 0 .708l-3.5 3.5a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L6 8.293l3.146-3.147a.5.5 0 0 1 .708 0M13.5 7A6.5 6.5 0 1 1 7 .5 6.507 6.507 0 0 1 13.5 7m-1 0A5.5 5.5 0 1 0 7 12.5 5.507 5.507 0 0 0 12.5 7" +}))); +/* harmony default export */ __webpack_exports__["default"] = (SvgCheckIcon); /***/ }, -/***/ "./node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js" -/*!**********************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js ***! - \**********************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { +/***/ "./src/components/error/icons/ClockIcon.svg" +/*!**************************************************!*\ + !*** ./src/components/error/icons/ClockIcon.svg ***! + \**************************************************/ +(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _arrayWithoutHoles) -/* harmony export */ }); -/* harmony import */ var _arrayLikeToArray_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./arrayLikeToArray.js */ "./node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js"); - -function _arrayWithoutHoles(r) { - if (Array.isArray(r)) return (0,_arrayLikeToArray_js__WEBPACK_IMPORTED_MODULE_0__["default"])(r); -} +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react"); +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); +var _path; +function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } +var SvgClockIcon = props => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("svg", _extends({ + xmlns: "http://www.w3.org/2000/svg", + viewBox: "0 0 54 24" +}, props), _path || (_path = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", { + fill: "none", + stroke: "#fff", + strokeWidth: 4, + d: "M27 0v22h22" +}))); +/* harmony default export */ __webpack_exports__["default"] = (SvgClockIcon); /***/ }, -/***/ "./node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js" -/*!**************************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js ***! - \**************************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { +/***/ "./src/components/error/icons/CloudSlashIcon.svg" +/*!*******************************************************!*\ + !*** ./src/components/error/icons/CloudSlashIcon.svg ***! + \*******************************************************/ +(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _assertThisInitialized) -/* harmony export */ }); -function _assertThisInitialized(e) { - if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - return e; -} +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react"); +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); +var _path; +function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } +var SvgCloudSlashIcon = props => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("svg", _extends({ + xmlns: "http://www.w3.org/2000/svg", + width: 32, + height: 32, + viewBox: "0 0 256 256" +}, props), _path || (_path = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", { + d: "M248 128.72A87.74 87.74 0 0 1 222.41 190a4 4 0 0 1-5.77-.16L103.78 65.67a4 4 0 0 1 .39-5.76A87.82 87.82 0 0 1 160.87 40c48.28.47 87.51 40.43 87.13 88.72M53.92 34.62a8 8 0 1 0-11.84 10.76l39.25 43.18-.06.11A64 64 0 0 0 8 153c.53 35.12 29.84 63 65 63h87a87.7 87.7 0 0 0 31.78-5.95l10.3 11.33a8 8 0 0 0 11.33.52 8.32 8.32 0 0 0 .29-11.52Z" +}))); +/* harmony default export */ __webpack_exports__["default"] = (SvgCloudSlashIcon); /***/ }, -/***/ "./node_modules/@babel/runtime/helpers/esm/classCallCheck.js" -/*!*******************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/classCallCheck.js ***! - \*******************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { +/***/ "./src/components/error/icons/CollapseIcon.svg" +/*!*****************************************************!*\ + !*** ./src/components/error/icons/CollapseIcon.svg ***! + \*****************************************************/ +(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _classCallCheck) -/* harmony export */ }); -function _classCallCheck(a, n) { - if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); -} +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react"); +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); +var _path; +function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } +var SvgCollapseIcon = props => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("svg", _extends({ + xmlns: "http://www.w3.org/2000/svg", + width: 10, + height: 6, + fill: "none" +}, props), _path || (_path = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", { + stroke: "#A2B1C6", + d: "m1 1 4 4 4-4" +}))); +/* harmony default export */ __webpack_exports__["default"] = (SvgCollapseIcon); /***/ }, -/***/ "./node_modules/@babel/runtime/helpers/esm/createClass.js" -/*!****************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/createClass.js ***! - \****************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { +/***/ "./src/components/error/icons/ErrorIcon.svg" +/*!**************************************************!*\ + !*** ./src/components/error/icons/ErrorIcon.svg ***! + \**************************************************/ +(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _createClass) -/* harmony export */ }); -/* harmony import */ var _toPropertyKey_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./toPropertyKey.js */ "./node_modules/@babel/runtime/helpers/esm/toPropertyKey.js"); - -function _defineProperties(e, r) { - for (var t = 0; t < r.length; t++) { - var o = r[t]; - o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, (0,_toPropertyKey_js__WEBPACK_IMPORTED_MODULE_0__["default"])(o.key), o); - } -} -function _createClass(e, r, t) { - return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { - writable: !1 - }), e; -} +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react"); +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); +var _path; +function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } +var SvgErrorIcon = props => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("svg", _extends({ + xmlns: "http://www.w3.org/2000/svg", + width: 32, + height: 32, + viewBox: "0 0 256 256" +}, props), _path || (_path = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", { + d: "M236.8 188.09 149.35 36.22a24.76 24.76 0 0 0-42.7 0L19.2 188.09a23.51 23.51 0 0 0 0 23.72A24.35 24.35 0 0 0 40.55 224h174.9a24.35 24.35 0 0 0 21.33-12.19 23.51 23.51 0 0 0 .02-23.72m-13.87 15.71a8.5 8.5 0 0 1-7.48 4.2H40.55a8.5 8.5 0 0 1-7.48-4.2 7.59 7.59 0 0 1 0-7.72l87.45-151.87a8.75 8.75 0 0 1 15 0l87.45 151.87a7.59 7.59 0 0 1-.04 7.72M120 144v-40a8 8 0 0 1 16 0v40a8 8 0 0 1-16 0m20 36a12 12 0 1 1-12-12 12 12 0 0 1 12 12" +}))); +/* harmony default export */ __webpack_exports__["default"] = (SvgErrorIcon); /***/ }, -/***/ "./node_modules/@babel/runtime/helpers/esm/defineProperty.js" -/*!*******************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/defineProperty.js ***! - \*******************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { +/***/ "./src/components/error/icons/Expand.svg" +/*!***********************************************!*\ + !*** ./src/components/error/icons/Expand.svg ***! + \***********************************************/ +(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _defineProperty) -/* harmony export */ }); -/* harmony import */ var _toPropertyKey_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./toPropertyKey.js */ "./node_modules/@babel/runtime/helpers/esm/toPropertyKey.js"); - -function _defineProperty(e, r, t) { - return (r = (0,_toPropertyKey_js__WEBPACK_IMPORTED_MODULE_0__["default"])(r)) in e ? Object.defineProperty(e, r, { - value: t, - enumerable: !0, - configurable: !0, - writable: !0 - }) : e[r] = t, e; -} +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react"); +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); +var _path; +function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } +var SvgExpand = props => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("svg", _extends({ + xmlns: "http://www.w3.org/2000/svg", + width: 30, + height: 30, + fill: "currentColor", + viewBox: "0 0 256 256" +}, props), _path || (_path = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", { + d: "M201.54 54.46A104 104 0 0 0 54.46 201.54 104 104 0 0 0 201.54 54.46m-11.31 135.77a88 88 0 1 1 0-124.46 88.11 88.11 0 0 1 0 124.46m-16.57-88.57L147.31 128l26.35 26.34a8 8 0 0 1-11.32 11.32l-32-32a8 8 0 0 1 0-11.32l32-32a8 8 0 0 1 11.32 11.32m-56 0L91.31 128l26.35 26.34a8 8 0 0 1-11.32 11.32l-32-32a8 8 0 0 1 0-11.32l32-32a8 8 0 0 1 11.32 11.32" +}))); +/* harmony default export */ __webpack_exports__["default"] = (SvgExpand); /***/ }, -/***/ "./node_modules/@babel/runtime/helpers/esm/extends.js" -/*!************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/extends.js ***! - \************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { +/***/ "./src/components/error/icons/GraphIcon.svg" +/*!**************************************************!*\ + !*** ./src/components/error/icons/GraphIcon.svg ***! + \**************************************************/ +(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _extends) -/* harmony export */ }); -function _extends() { - return _extends = Object.assign ? Object.assign.bind() : function (n) { - for (var e = 1; e < arguments.length; e++) { - var t = arguments[e]; - for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); - } - return n; - }, _extends.apply(null, arguments); -} +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react"); +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); +var _path; +function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } +var SvgGraphIcon = props => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("svg", _extends({ + xmlns: "http://www.w3.org/2000/svg", + width: 32, + height: 32, + viewBox: "0 0 256 256" +}, props), _path || (_path = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", { + d: "M200 152a31.84 31.84 0 0 0-19.53 6.68l-23.11-18A31.65 31.65 0 0 0 160 128c0-.74 0-1.48-.08-2.21l13.23-4.41A32 32 0 1 0 168 104c0 .74 0 1.48.08 2.21l-13.23 4.41A32 32 0 0 0 128 96a32.6 32.6 0 0 0-5.27.44L115.89 81A32 32 0 1 0 96 88a32.6 32.6 0 0 0 5.27-.44l6.84 15.4a31.92 31.92 0 0 0-8.57 39.64l-25.71 22.84a32.06 32.06 0 1 0 10.63 12l25.71-22.84a31.91 31.91 0 0 0 37.36-1.24l23.11 18A31.65 31.65 0 0 0 168 184a32 32 0 1 0 32-32m0-64a16 16 0 1 1-16 16 16 16 0 0 1 16-16M80 56a16 16 0 1 1 16 16 16 16 0 0 1-16-16M56 208a16 16 0 1 1 16-16 16 16 0 0 1-16 16m56-80a16 16 0 1 1 16 16 16 16 0 0 1-16-16m88 72a16 16 0 1 1 16-16 16 16 0 0 1-16 16" +}))); +/* harmony default export */ __webpack_exports__["default"] = (SvgGraphIcon); /***/ }, -/***/ "./node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js" -/*!*******************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js ***! - \*******************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { +/***/ "./src/components/error/icons/OffIcon.svg" +/*!************************************************!*\ + !*** ./src/components/error/icons/OffIcon.svg ***! + \************************************************/ +(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _getPrototypeOf) -/* harmony export */ }); -function _getPrototypeOf(t) { - return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { - return t.__proto__ || Object.getPrototypeOf(t); - }, _getPrototypeOf(t); -} +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react"); +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); +var _path; +function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } +var SvgOffIcon = props => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("svg", _extends({ + xmlns: "http://www.w3.org/2000/svg", + width: 18, + height: 18, + fill: "#C73A3A", + viewBox: "0 0 256 256" +}, props), _path || (_path = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", { + d: "M165.66 101.66 139.31 128l26.35 26.34a8 8 0 0 1-11.32 11.32L128 139.31l-26.34 26.35a8 8 0 0 1-11.32-11.32L116.69 128l-26.35-26.34a8 8 0 0 1 11.32-11.32L128 116.69l26.34-26.35a8 8 0 0 1 11.32 11.32M232 128A104 104 0 1 1 128 24a104.11 104.11 0 0 1 104 104m-16 0a88 88 0 1 0-88 88 88.1 88.1 0 0 0 88-88" +}))); +/* harmony default export */ __webpack_exports__["default"] = (SvgOffIcon); /***/ }, -/***/ "./node_modules/@babel/runtime/helpers/esm/inherits.js" -/*!*************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/inherits.js ***! - \*************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { +/***/ "./src/AppProvider.react.tsx" +/*!***********************************!*\ + !*** ./src/AppProvider.react.tsx ***! + \***********************************/ +(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _inherits) -/* harmony export */ }); -/* harmony import */ var _setPrototypeOf_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./setPrototypeOf.js */ "./node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js"); +/* harmony import */ var prop_types__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! prop-types */ "prop-types"); +/* harmony import */ var prop_types__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(prop_types__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ "react"); +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-redux */ "./node_modules/react-redux/es/index.js"); +/* harmony import */ var _store__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./store */ "./src/store.ts"); +/* harmony import */ var _AppContainer_react__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AppContainer.react */ "./src/AppContainer.react.js"); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./config */ "./src/config.ts"); +/* harmony import */ var _observers_websocketObserver__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./observers/websocketObserver */ "./src/observers/websocketObserver.ts"); +function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } +function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } +function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } +function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } +function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } +function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } +function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } -function _inherits(t, e) { - if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); - t.prototype = Object.create(e && e.prototype, { - constructor: { - value: t, - writable: !0, - configurable: !0 - } - }), Object.defineProperty(t, "prototype", { - writable: !1 - }), e && (0,_setPrototypeOf_js__WEBPACK_IMPORTED_MODULE_0__["default"])(t, e); -} -/***/ }, -/***/ "./node_modules/@babel/runtime/helpers/esm/iterableToArray.js" -/*!********************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/iterableToArray.js ***! - \********************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _iterableToArray) -/* harmony export */ }); -function _iterableToArray(r) { - if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); -} +var AppProvider = _ref => { + var _ref$hooks = _ref.hooks, + hooks = _ref$hooks === void 0 ? { + layout_pre: null, + layout_post: null, + request_pre: null, + request_post: null, + callback_resolved: null, + request_refresh_jwt: null + } : _ref$hooks; + var _useState = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(() => new _store__WEBPACK_IMPORTED_MODULE_3__["default"]()), + _useState2 = _slicedToArray(_useState, 1), + store = _useState2[0].store; + // Initialize WebSocket connection if enabled or if websocket config is available + // (for per-callback websocket=True) + (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => { + var _config$websocket, _config$websocket2, _config$websocket3; + var config = (0,_config__WEBPACK_IMPORTED_MODULE_5__["default"])(); + if ((_config$websocket = config.websocket) !== null && _config$websocket !== void 0 && _config$websocket.enabled || (_config$websocket2 = config.websocket) !== null && _config$websocket2 !== void 0 && _config$websocket2.url && (_config$websocket3 = config.websocket) !== null && _config$websocket3 !== void 0 && _config$websocket3.worker_url) { + // Add fetch config for consistency + var fullConfig = _objectSpread(_objectSpread({}, config), {}, { + fetch: { + credentials: 'same-origin', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json' + } + } + }); + (0,_observers_websocketObserver__WEBPACK_IMPORTED_MODULE_6__.initializeWebSocket)(store, fullConfig); + } + // Cleanup on unmount + return () => { + (0,_observers_websocketObserver__WEBPACK_IMPORTED_MODULE_6__.disconnectWebSocket)(); + }; + }, [store]); + return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(react_redux__WEBPACK_IMPORTED_MODULE_2__.Provider, { + store: store + }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_AppContainer_react__WEBPACK_IMPORTED_MODULE_4__["default"], { + hooks: hooks + })); +}; +AppProvider.propTypes = { + hooks: prop_types__WEBPACK_IMPORTED_MODULE_0___default().shape({ + layout_pre: (prop_types__WEBPACK_IMPORTED_MODULE_0___default().func), + layout_post: (prop_types__WEBPACK_IMPORTED_MODULE_0___default().func), + request_pre: (prop_types__WEBPACK_IMPORTED_MODULE_0___default().func), + request_post: (prop_types__WEBPACK_IMPORTED_MODULE_0___default().func), + callback_resolved: (prop_types__WEBPACK_IMPORTED_MODULE_0___default().func), + request_refresh_jwt: (prop_types__WEBPACK_IMPORTED_MODULE_0___default().func) + }) +}; +/* harmony default export */ __webpack_exports__["default"] = (AppProvider); + /***/ }, -/***/ "./node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js" -/*!*************************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js ***! - \*************************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { +/***/ "./src/StoreObserver.ts" +/*!******************************!*\ + !*** ./src/StoreObserver.ts ***! + \******************************/ +(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _iterableToArrayLimit) +/* harmony export */ "default": () => (/* binding */ StoreObserver) /* harmony export */ }); -function _iterableToArrayLimit(r, l) { - var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; - if (null != t) { - var e, - n, - i, - u, - a = [], - f = !0, - o = !1; - try { - if (i = (t = t.call(r)).next, 0 === l) { - if (Object(t) !== t) return; - f = !1; - } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); - } catch (r) { - o = !0, n = r; - } finally { - try { - if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; - } finally { - if (o) throw n; +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/any.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/filter.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/map.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/path.js"); +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } + +class StoreObserver { + constructor(_store) { + _defineProperty(this, "_store", void 0); + _defineProperty(this, "_unsubscribe", void 0); + _defineProperty(this, "_observers", []); + _defineProperty(this, "observe", (observer, inputs) => { + if (typeof observer === 'function') { + if (!Array.isArray(inputs)) { + throw new Error('inputs must be an array'); + } + this.add(observer, inputs); + return () => this.remove(observer); } - } - return a; + this.add(observer.observer, observer.inputs); + return () => this.remove(observer.observer); + }); + _defineProperty(this, "setStore", store => { + this.__finalize__(); + this.__init__(store); + }); + _defineProperty(this, "__finalize__", () => { + var _this$_unsubscribe; + return (_this$_unsubscribe = this._unsubscribe) === null || _this$_unsubscribe === void 0 ? void 0 : _this$_unsubscribe.call(this); + }); + _defineProperty(this, "__init__", store => { + this._store = store; + if (store) { + this._unsubscribe = store.subscribe(this.notify); + } + this._observers.forEach(o => { + o.lastState = null; + }); + }); + _defineProperty(this, "add", (observer, inputs) => this._observers.push({ + inputPaths: (0,ramda__WEBPACK_IMPORTED_MODULE_2__["default"])(p => p.split('.'), inputs), + lastState: null, + observer, + triggered: false + })); + _defineProperty(this, "notify", () => { + var store = this._store; + if (!store) { + return; + } + var state = store.getState(); + var triggered = (0,ramda__WEBPACK_IMPORTED_MODULE_1__["default"])(o => !o.triggered && (0,ramda__WEBPACK_IMPORTED_MODULE_0__["default"])(i => (0,ramda__WEBPACK_IMPORTED_MODULE_3__["default"])(i, state) !== (0,ramda__WEBPACK_IMPORTED_MODULE_3__["default"])(i, o.lastState), o.inputPaths), this._observers); + triggered.forEach(o => { + o.triggered = true; + }); + triggered.forEach(o => { + o.lastState = store.getState(); + o.observer(store); + o.triggered = false; + }); + }); + _defineProperty(this, "remove", observer => this._observers.splice(this._observers.findIndex(o => observer === o.observer, this._observers), 1)); + this.__init__(_store); } } - /***/ }, -/***/ "./node_modules/@babel/runtime/helpers/esm/nonIterableRest.js" -/*!********************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/nonIterableRest.js ***! - \********************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { +/***/ "./src/actions/callbacks.ts" +/*!**********************************!*\ + !*** ./src/actions/callbacks.ts ***! + \**********************************/ +(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _nonIterableRest) +/* harmony export */ addBlockedCallbacks: () => (/* binding */ addBlockedCallbacks), +/* harmony export */ addCompletedCallbacks: () => (/* binding */ addCompletedCallbacks), +/* harmony export */ addExecutedCallbacks: () => (/* binding */ addExecutedCallbacks), +/* harmony export */ addExecutingCallbacks: () => (/* binding */ addExecutingCallbacks), +/* harmony export */ addPrioritizedCallbacks: () => (/* binding */ addPrioritizedCallbacks), +/* harmony export */ addRequestedCallbacks: () => (/* binding */ addRequestedCallbacks), +/* harmony export */ addStoredCallbacks: () => (/* binding */ addStoredCallbacks), +/* harmony export */ addWatchedCallbacks: () => (/* binding */ addWatchedCallbacks), +/* harmony export */ aggregateCallbacks: () => (/* binding */ aggregateCallbacks), +/* harmony export */ executeCallback: () => (/* binding */ executeCallback), +/* harmony export */ removeBlockedCallbacks: () => (/* binding */ removeBlockedCallbacks), +/* harmony export */ removeExecutedCallbacks: () => (/* binding */ removeExecutedCallbacks), +/* harmony export */ removeExecutingCallbacks: () => (/* binding */ removeExecutingCallbacks), +/* harmony export */ removePrioritizedCallbacks: () => (/* binding */ removePrioritizedCallbacks), +/* harmony export */ removeRequestedCallbacks: () => (/* binding */ removeRequestedCallbacks), +/* harmony export */ removeStoredCallbacks: () => (/* binding */ removeStoredCallbacks), +/* harmony export */ removeWatchedCallbacks: () => (/* binding */ removeWatchedCallbacks) /* harmony export */ }); -function _nonIterableRest() { - throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); -} - - -/***/ }, - -/***/ "./node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js" -/*!**********************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js ***! - \**********************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _nonIterableSpread) -/* harmony export */ }); -function _nonIterableSpread() { - throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); -} - - -/***/ }, - -/***/ "./node_modules/@babel/runtime/helpers/esm/objectSpread2.js" -/*!******************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/objectSpread2.js ***! - \******************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _objectSpread2) -/* harmony export */ }); -/* harmony import */ var _defineProperty_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./defineProperty.js */ "./node_modules/@babel/runtime/helpers/esm/defineProperty.js"); - -function ownKeys(e, r) { - var t = Object.keys(e); - if (Object.getOwnPropertySymbols) { - var o = Object.getOwnPropertySymbols(e); - r && (o = o.filter(function (r) { - return Object.getOwnPropertyDescriptor(e, r).enumerable; - })), t.push.apply(t, o); - } - return t; -} -function _objectSpread2(e) { - for (var r = 1; r < arguments.length; r++) { - var t = null != arguments[r] ? arguments[r] : {}; - r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { - (0,_defineProperty_js__WEBPACK_IMPORTED_MODULE_0__["default"])(e, r, t[r]); - }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { - Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); - }); - } - return e; -} - - -/***/ }, - -/***/ "./node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js" -/*!****************************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js ***! - \****************************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _objectWithoutProperties) -/* harmony export */ }); -/* harmony import */ var _objectWithoutPropertiesLoose_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./objectWithoutPropertiesLoose.js */ "./node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js"); - -function _objectWithoutProperties(e, t) { - if (null == e) return {}; - var o, - r, - i = (0,_objectWithoutPropertiesLoose_js__WEBPACK_IMPORTED_MODULE_0__["default"])(e, t); - if (Object.getOwnPropertySymbols) { - var n = Object.getOwnPropertySymbols(e); - for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); - } - return i; -} - - -/***/ }, - -/***/ "./node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js" -/*!*********************************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js ***! - \*********************************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _objectWithoutPropertiesLoose) -/* harmony export */ }); -function _objectWithoutPropertiesLoose(r, e) { - if (null == r) return {}; - var t = {}; - for (var n in r) if ({}.hasOwnProperty.call(r, n)) { - if (-1 !== e.indexOf(n)) continue; - t[n] = r[n]; - } - return t; -} - - -/***/ }, - -/***/ "./node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js" -/*!******************************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js ***! - \******************************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _possibleConstructorReturn) -/* harmony export */ }); -/* harmony import */ var _typeof_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./typeof.js */ "./node_modules/@babel/runtime/helpers/esm/typeof.js"); -/* harmony import */ var _assertThisInitialized_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./assertThisInitialized.js */ "./node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js"); - - -function _possibleConstructorReturn(t, e) { - if (e && ("object" == (0,_typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(e) || "function" == typeof e)) return e; - if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); - return (0,_assertThisInitialized_js__WEBPACK_IMPORTED_MODULE_1__["default"])(t); -} - - -/***/ }, - -/***/ "./node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js" -/*!*******************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js ***! - \*******************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _setPrototypeOf) -/* harmony export */ }); -function _setPrototypeOf(t, e) { - return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { - return t.__proto__ = e, t; - }, _setPrototypeOf(t, e); -} - - -/***/ }, +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/assocPath.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/concat.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/flatten.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/intersection.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/keys.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/map.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/mergeDeepRight.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/path.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/pick.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/pluck.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/toPairs.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/values.js"); +/* harmony import */ var ramda__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ramda */ "./node_modules/ramda/es/zip.js"); +/* harmony import */ var _constants_constants__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../constants/constants */ "./src/constants/constants.js"); +/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./constants */ "./src/actions/constants.js"); +/* harmony import */ var _reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../reducers/callbacks */ "./src/reducers/callbacks.ts"); +/* harmony import */ var _dependencies__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./dependencies */ "./src/actions/dependencies.js"); +/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./utils */ "./src/actions/utils.js"); +/* harmony import */ var ___WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./index */ "./src/actions/index.js"); +/* harmony import */ var redux_actions__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! redux-actions */ "./node_modules/redux-actions/es/createAction.js"); +/* harmony import */ var _patch__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./patch */ "./src/actions/patch.ts"); +/* harmony import */ var _paths__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./paths */ "./src/actions/paths.js"); +/* harmony import */ var _requestDependencies__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./requestDependencies */ "./src/actions/requestDependencies.ts"); +/* harmony import */ var _utils_libraries__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../utils/libraries */ "./src/utils/libraries.ts"); +/* harmony import */ var _patternMatching__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./patternMatching */ "./src/actions/patternMatching.ts"); +/* harmony import */ var _loading__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./loading */ "./src/actions/loading.ts"); +/* harmony import */ var _wrapper_wrapping__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ../wrapper/wrapping */ "./src/wrapper/wrapping.ts"); +/* harmony import */ var _utils_workerClient__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../utils/workerClient */ "./src/utils/workerClient.ts"); +function _regeneratorValues(e) { if (null != e) { var t = e["function" == typeof Symbol && Symbol.iterator || "@@iterator"], r = 0; if (t) return t.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) return { next: function next() { return e && r >= e.length && (e = void 0), { value: e && e[r++], done: !e }; } }; } throw new TypeError(typeof e + " is not iterable"); } +function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); } +function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); } +function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); } +function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; } +function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } +function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } +function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } +function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } +function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } +function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } +function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } +function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } -/***/ "./node_modules/@babel/runtime/helpers/esm/slicedToArray.js" -/*!******************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/slicedToArray.js ***! - \******************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _slicedToArray) -/* harmony export */ }); -/* harmony import */ var _arrayWithHoles_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./arrayWithHoles.js */ "./node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js"); -/* harmony import */ var _iterableToArrayLimit_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./iterableToArrayLimit.js */ "./node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js"); -/* harmony import */ var _unsupportedIterableToArray_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./unsupportedIterableToArray.js */ "./node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js"); -/* harmony import */ var _nonIterableRest_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./nonIterableRest.js */ "./node_modules/@babel/runtime/helpers/esm/nonIterableRest.js"); -function _slicedToArray(r, e) { - return (0,_arrayWithHoles_js__WEBPACK_IMPORTED_MODULE_0__["default"])(r) || (0,_iterableToArrayLimit_js__WEBPACK_IMPORTED_MODULE_1__["default"])(r, e) || (0,_unsupportedIterableToArray_js__WEBPACK_IMPORTED_MODULE_2__["default"])(r, e) || (0,_nonIterableRest_js__WEBPACK_IMPORTED_MODULE_3__["default"])(); -} -/***/ }, -/***/ "./node_modules/@babel/runtime/helpers/esm/toConsumableArray.js" -/*!**********************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/toConsumableArray.js ***! - \**********************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _toConsumableArray) -/* harmony export */ }); -/* harmony import */ var _arrayWithoutHoles_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./arrayWithoutHoles.js */ "./node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js"); -/* harmony import */ var _iterableToArray_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./iterableToArray.js */ "./node_modules/@babel/runtime/helpers/esm/iterableToArray.js"); -/* harmony import */ var _unsupportedIterableToArray_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./unsupportedIterableToArray.js */ "./node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js"); -/* harmony import */ var _nonIterableSpread_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./nonIterableSpread.js */ "./node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js"); -function _toConsumableArray(r) { - return (0,_arrayWithoutHoles_js__WEBPACK_IMPORTED_MODULE_0__["default"])(r) || (0,_iterableToArray_js__WEBPACK_IMPORTED_MODULE_1__["default"])(r) || (0,_unsupportedIterableToArray_js__WEBPACK_IMPORTED_MODULE_2__["default"])(r) || (0,_nonIterableSpread_js__WEBPACK_IMPORTED_MODULE_3__["default"])(); -} -/***/ }, -/***/ "./node_modules/@babel/runtime/helpers/esm/toPrimitive.js" -/*!****************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/toPrimitive.js ***! - \****************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ toPrimitive) -/* harmony export */ }); -/* harmony import */ var _typeof_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./typeof.js */ "./node_modules/@babel/runtime/helpers/esm/typeof.js"); -function toPrimitive(t, r) { - if ("object" != (0,_typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(t) || !t) return t; - var e = t[Symbol.toPrimitive]; - if (void 0 !== e) { - var i = e.call(t, r || "default"); - if ("object" != (0,_typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(i)) return i; - throw new TypeError("@@toPrimitive must return a primitive value."); +var addBlockedCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.AddBlocked); +var addCompletedCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackAggregateActionType.AddCompleted); +var addExecutedCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.AddExecuted); +var addExecutingCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.AddExecuting); +var addPrioritizedCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.AddPrioritized); +var addRequestedCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.AddRequested); +var addStoredCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.AddStored); +var addWatchedCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.AddWatched); +var removeExecutedCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.RemoveExecuted); +var removeBlockedCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.RemoveBlocked); +var removeExecutingCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.RemoveExecuting); +var removePrioritizedCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.RemovePrioritized); +var removeRequestedCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.RemoveRequested); +var removeStoredCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.RemoveStored); +var removeWatchedCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackActionType.RemoveWatched); +var aggregateCallbacks = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])(_reducers_callbacks__WEBPACK_IMPORTED_MODULE_15__.CallbackAggregateActionType.Aggregate); +var updateResourceUsage = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])('UPDATE_RESOURCE_USAGE'); +var addCallbackJob = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])('ADD_CALLBACK_JOB'); +var removeCallbackJob = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])('REMOVE_CALLBACK_JOB'); +var setCallbackJobOutdated = (0,redux_actions__WEBPACK_IMPORTED_MODULE_19__["default"])('CALLBACK_JOB_OUTDATED'); +function unwrapIfNotMulti(paths, idProps, spec, anyVals, depType) { + var msg = ''; + if ((0,_dependencies__WEBPACK_IMPORTED_MODULE_16__.isMultiValued)(spec)) { + return [idProps, msg]; } - return ("string" === r ? String : Number)(t); -} - - -/***/ }, - -/***/ "./node_modules/@babel/runtime/helpers/esm/toPropertyKey.js" -/*!******************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/toPropertyKey.js ***! - \******************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ toPropertyKey) -/* harmony export */ }); -/* harmony import */ var _typeof_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./typeof.js */ "./node_modules/@babel/runtime/helpers/esm/typeof.js"); -/* harmony import */ var _toPrimitive_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./toPrimitive.js */ "./node_modules/@babel/runtime/helpers/esm/toPrimitive.js"); - - -function toPropertyKey(t) { - var i = (0,_toPrimitive_js__WEBPACK_IMPORTED_MODULE_1__["default"])(t, "string"); - return "symbol" == (0,_typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(i) ? i : i + ""; + if (idProps.length !== 1) { + if (!idProps.length) { + if (spec.allow_optional) { + idProps = [_objectSpread(_objectSpread({}, spec), {}, { + value: null + })]; + msg = ''; + } else { + var isStr = typeof spec.id === 'string'; + msg = 'A nonexistent object was used in an `' + depType + '` of a Dash callback. The id of this object is ' + (isStr ? '`' + spec.id + '`' : JSON.stringify(spec.id) + (anyVals ? ' with MATCH values ' + anyVals : '')) + ' and the property is `' + spec.property + (isStr ? '`. The string ids in the current layout are: [' + (0,ramda__WEBPACK_IMPORTED_MODULE_4__["default"])(paths.strs).join(', ') + ']' : '`. The wildcard ids currently available are logged above.'); + } + } else { + msg = 'Multiple objects were found for an `' + depType + '` of a callback that only takes one value. The id spec is ' + JSON.stringify(spec.id) + (anyVals ? ' with MATCH values ' + anyVals : '') + ' and the property is `' + spec.property + '`. The objects we found are: ' + JSON.stringify((0,ramda__WEBPACK_IMPORTED_MODULE_5__["default"])((0,ramda__WEBPACK_IMPORTED_MODULE_8__["default"])(['id', 'property']), idProps)); + } + } + return [idProps[0], msg]; } - - -/***/ }, - -/***/ "./node_modules/@babel/runtime/helpers/esm/typeof.js" -/*!***********************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/typeof.js ***! - \***********************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _typeof) -/* harmony export */ }); -function _typeof(o) { - "@babel/helpers - typeof"; - - return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { - return typeof o; - } : function (o) { - return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; - }, _typeof(o); +function fillVals(paths, layout, cb, specs, depType) { + var allowAllMissing = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; + var getter = depType === 'Input' ? cb.getInputs : cb.getState; + var errors = []; + var emptyMultiValues = 0; + var inputVals = getter(paths).map((inputList, i) => { + var _unwrapIfNotMulti = unwrapIfNotMulti(paths, inputList.map(_ref => { + var id = _ref.id, + property = _ref.property, + path_ = _ref.path; + return { + id, + property, + value: (0,ramda__WEBPACK_IMPORTED_MODULE_7__["default"])([...path_, 'props', property], layout) + }; + }), specs[i], cb.anyVals, depType), + _unwrapIfNotMulti2 = _slicedToArray(_unwrapIfNotMulti, 2), + inputs = _unwrapIfNotMulti2[0], + inputError = _unwrapIfNotMulti2[1]; + if ((0,_dependencies__WEBPACK_IMPORTED_MODULE_16__.isMultiValued)(specs[i]) && !inputs.length) { + emptyMultiValues++; + } + if (inputError) { + errors.push(inputError); + } + return inputs; + }); + if (errors.length) { + if (allowAllMissing && errors.length + emptyMultiValues === inputVals.length) { + // We have at least one non-multivalued input, but all simple and + // multi-valued inputs are missing. + // (if all inputs are multivalued and all missing we still return + // them as normal, and fire the callback.) + return null; + } + // If we get here we have some missing and some present inputs. + // Or all missing in a context that doesn't allow this. + // That's a real problem, so throw the first message as an error. + refErr(errors, paths); + } + return inputVals; } - - -/***/ }, - -/***/ "./node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js" -/*!*******************************************************************************!*\ - !*** ./node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js ***! - \*******************************************************************************/ -(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (/* binding */ _unsupportedIterableToArray) -/* harmony export */ }); -/* harmony import */ var _arrayLikeToArray_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./arrayLikeToArray.js */ "./node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js"); - -function _unsupportedIterableToArray(r, a) { - if (r) { - if ("string" == typeof r) return (0,_arrayLikeToArray_js__WEBPACK_IMPORTED_MODULE_0__["default"])(r, a); - var t = {}.toString.call(r).slice(8, -1); - return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? (0,_arrayLikeToArray_js__WEBPACK_IMPORTED_MODULE_0__["default"])(r, a) : void 0; +function refErr(errors, paths) { + var err = errors[0]; + if (err.indexOf('logged above') !== -1) { + // Wildcard reference errors mention a list of wildcard specs logged + // TODO: unwrapped list of wildcard ids? + // eslint-disable-next-line no-console + console.error(paths.objs); } + throw new ReferenceError(err); } - - -/***/ }, - -/***/ "./node_modules/@plotly/dash-component-plugins/dist/index.js" -/*!*******************************************************************!*\ - !*** ./node_modules/@plotly/dash-component-plugins/dist/index.js ***! - \*******************************************************************/ -(module, __unused_webpack_exports, __webpack_require__) { - -!function(e,n){ true?module.exports=n(__webpack_require__(/*! react */ "react")):0}(window,(function(e){return function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=1)}([function(n,t){n.exports=e},function(e,n,t){"use strict";t.r(n),t.d(n,"asyncDecorator",(function(){return u})),t.d(n,"inheritAsyncDecorator",(function(){return a})),t.d(n,"isReady",(function(){return c})),t.d(n,"History",(function(){return d}));var r=t(0);function o(e,n,t,r,o,i,u){try{var a=e[i](u),c=a.value}catch(e){return void t(e)}a.done?n(c):Promise.resolve(c).then(r,o)}function i(e){return function(){var n=this,t=arguments;return new Promise((function(r,i){var u=e.apply(n,t);function a(e){o(u,r,i,a,c,"next",e)}function c(e){o(u,r,i,a,c,"throw",e)}a(void 0)}))}}var u=function(e,n){var t,o={isReady:new Promise((function(e){t=e})),get:Object(r.lazy)((function(){return Promise.resolve(n()).then((function(e){return setTimeout(i(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,t(!0);case 2:o.isReady=!0;case 3:case"end":return e.stop()}}),e)}))),0),e}))}))};return Object.defineProperty(e,"_dashprivate_isLazyComponentReady",{get:function(){return o.isReady}}),o.get},a=function(e,n){Object.defineProperty(e,"_dashprivate_isLazyComponentReady",{get:function(){return c(n)}})},c=function(e){return e&&e._dashprivate_isLazyComponentReady};function f(e,n){for(var t=0;t Array.isArray(input) ? (0,ramda__WEBPACK_IMPORTED_MODULE_9__["default"])('value', input) : input.value; +var zipIfArray = (a, b) => { + if (Array.isArray(a)) { + // For client-side callbacks with multiple Outputs, only return a single dash_clientside.no_update + if (b === window.dash_clientside.no_update) { + return (0,ramda__WEBPACK_IMPORTED_MODULE_12__["default"])(a, [b]); + } + return (0,ramda__WEBPACK_IMPORTED_MODULE_12__["default"])(a, b); + } + return [[a, b]]; }; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/atelier-dune.js" -/*!*************************************************!*\ - !*** ./node_modules/base16/lib/atelier-dune.js ***! - \*************************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'atelier dune', - author: 'bram de haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune)', - base00: '#20201d', - base01: '#292824', - base02: '#6e6b5e', - base03: '#7d7a68', - base04: '#999580', - base05: '#a6a28c', - base06: '#e8e4cf', - base07: '#fefbec', - base08: '#d73737', - base09: '#b65611', - base0A: '#cfb017', - base0B: '#60ac39', - base0C: '#1fad83', - base0D: '#6684e1', - base0E: '#b854d4', - base0F: '#d43552' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/atelier-forest.js" -/*!***************************************************!*\ - !*** ./node_modules/base16/lib/atelier-forest.js ***! - \***************************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'atelier forest', - author: 'bram de haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/forest)', - base00: '#1b1918', - base01: '#2c2421', - base02: '#68615e', - base03: '#766e6b', - base04: '#9c9491', - base05: '#a8a19f', - base06: '#e6e2e0', - base07: '#f1efee', - base08: '#f22c40', - base09: '#df5320', - base0A: '#d5911a', - base0B: '#5ab738', - base0C: '#00ad9c', - base0D: '#407ee7', - base0E: '#6666ea', - base0F: '#c33ff3' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/atelier-heath.js" -/*!**************************************************!*\ - !*** ./node_modules/base16/lib/atelier-heath.js ***! - \**************************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'atelier heath', - author: 'bram de haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/heath)', - base00: '#1b181b', - base01: '#292329', - base02: '#695d69', - base03: '#776977', - base04: '#9e8f9e', - base05: '#ab9bab', - base06: '#d8cad8', - base07: '#f7f3f7', - base08: '#ca402b', - base09: '#a65926', - base0A: '#bb8a35', - base0B: '#379a37', - base0C: '#159393', - base0D: '#516aec', - base0E: '#7b59c0', - base0F: '#cc33cc' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/atelier-lakeside.js" -/*!*****************************************************!*\ - !*** ./node_modules/base16/lib/atelier-lakeside.js ***! - \*****************************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'atelier lakeside', - author: 'bram de haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/lakeside/)', - base00: '#161b1d', - base01: '#1f292e', - base02: '#516d7b', - base03: '#5a7b8c', - base04: '#7195a8', - base05: '#7ea2b4', - base06: '#c1e4f6', - base07: '#ebf8ff', - base08: '#d22d72', - base09: '#935c25', - base0A: '#8a8a0f', - base0B: '#568c3b', - base0C: '#2d8f6f', - base0D: '#257fad', - base0E: '#5d5db1', - base0F: '#b72dd2' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/atelier-seaside.js" -/*!****************************************************!*\ - !*** ./node_modules/base16/lib/atelier-seaside.js ***! - \****************************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'atelier seaside', - author: 'bram de haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/seaside/)', - base00: '#131513', - base01: '#242924', - base02: '#5e6e5e', - base03: '#687d68', - base04: '#809980', - base05: '#8ca68c', - base06: '#cfe8cf', - base07: '#f0fff0', - base08: '#e6193c', - base09: '#87711d', - base0A: '#c3c322', - base0B: '#29a329', - base0C: '#1999b3', - base0D: '#3d62f5', - base0E: '#ad2bee', - base0F: '#e619c3' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/bespin.js" -/*!*******************************************!*\ - !*** ./node_modules/base16/lib/bespin.js ***! - \*******************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'bespin', - author: 'jan t. sott', - base00: '#28211c', - base01: '#36312e', - base02: '#5e5d5c', - base03: '#666666', - base04: '#797977', - base05: '#8a8986', - base06: '#9d9b97', - base07: '#baae9e', - base08: '#cf6a4c', - base09: '#cf7d34', - base0A: '#f9ee98', - base0B: '#54be0d', - base0C: '#afc4db', - base0D: '#5ea6ea', - base0E: '#9b859d', - base0F: '#937121' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/brewer.js" -/*!*******************************************!*\ - !*** ./node_modules/base16/lib/brewer.js ***! - \*******************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'brewer', - author: 'timothée poisot (http://github.com/tpoisot)', - base00: '#0c0d0e', - base01: '#2e2f30', - base02: '#515253', - base03: '#737475', - base04: '#959697', - base05: '#b7b8b9', - base06: '#dadbdc', - base07: '#fcfdfe', - base08: '#e31a1c', - base09: '#e6550d', - base0A: '#dca060', - base0B: '#31a354', - base0C: '#80b1d3', - base0D: '#3182bd', - base0E: '#756bb1', - base0F: '#b15928' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/bright.js" -/*!*******************************************!*\ - !*** ./node_modules/base16/lib/bright.js ***! - \*******************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'bright', - author: 'chris kempson (http://chriskempson.com)', - base00: '#000000', - base01: '#303030', - base02: '#505050', - base03: '#b0b0b0', - base04: '#d0d0d0', - base05: '#e0e0e0', - base06: '#f5f5f5', - base07: '#ffffff', - base08: '#fb0120', - base09: '#fc6d24', - base0A: '#fda331', - base0B: '#a1c659', - base0C: '#76c7b7', - base0D: '#6fb3d2', - base0E: '#d381c3', - base0F: '#be643c' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/chalk.js" -/*!******************************************!*\ - !*** ./node_modules/base16/lib/chalk.js ***! - \******************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'chalk', - author: 'chris kempson (http://chriskempson.com)', - base00: '#151515', - base01: '#202020', - base02: '#303030', - base03: '#505050', - base04: '#b0b0b0', - base05: '#d0d0d0', - base06: '#e0e0e0', - base07: '#f5f5f5', - base08: '#fb9fb1', - base09: '#eda987', - base0A: '#ddb26f', - base0B: '#acc267', - base0C: '#12cfc0', - base0D: '#6fc2ef', - base0E: '#e1a3ee', - base0F: '#deaf8f' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/codeschool.js" -/*!***********************************************!*\ - !*** ./node_modules/base16/lib/codeschool.js ***! - \***********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'codeschool', - author: 'brettof86', - base00: '#232c31', - base01: '#1c3657', - base02: '#2a343a', - base03: '#3f4944', - base04: '#84898c', - base05: '#9ea7a6', - base06: '#a7cfa3', - base07: '#b5d8f6', - base08: '#2a5491', - base09: '#43820d', - base0A: '#a03b1e', - base0B: '#237986', - base0C: '#b02f30', - base0D: '#484d79', - base0E: '#c59820', - base0F: '#c98344' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/colors.js" -/*!*******************************************!*\ - !*** ./node_modules/base16/lib/colors.js ***! - \*******************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'colors', - author: 'mrmrs (http://clrs.cc)', - base00: '#111111', - base01: '#333333', - base02: '#555555', - base03: '#777777', - base04: '#999999', - base05: '#bbbbbb', - base06: '#dddddd', - base07: '#ffffff', - base08: '#ff4136', - base09: '#ff851b', - base0A: '#ffdc00', - base0B: '#2ecc40', - base0C: '#7fdbff', - base0D: '#0074d9', - base0E: '#b10dc9', - base0F: '#85144b' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/default.js" -/*!********************************************!*\ - !*** ./node_modules/base16/lib/default.js ***! - \********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'default', - author: 'chris kempson (http://chriskempson.com)', - base00: '#181818', - base01: '#282828', - base02: '#383838', - base03: '#585858', - base04: '#b8b8b8', - base05: '#d8d8d8', - base06: '#e8e8e8', - base07: '#f8f8f8', - base08: '#ab4642', - base09: '#dc9656', - base0A: '#f7ca88', - base0B: '#a1b56c', - base0C: '#86c1b9', - base0D: '#7cafc2', - base0E: '#ba8baf', - base0F: '#a16946' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/eighties.js" -/*!*********************************************!*\ - !*** ./node_modules/base16/lib/eighties.js ***! - \*********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'eighties', - author: 'chris kempson (http://chriskempson.com)', - base00: '#2d2d2d', - base01: '#393939', - base02: '#515151', - base03: '#747369', - base04: '#a09f93', - base05: '#d3d0c8', - base06: '#e8e6df', - base07: '#f2f0ec', - base08: '#f2777a', - base09: '#f99157', - base0A: '#ffcc66', - base0B: '#99cc99', - base0C: '#66cccc', - base0D: '#6699cc', - base0E: '#cc99cc', - base0F: '#d27b53' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/embers.js" -/*!*******************************************!*\ - !*** ./node_modules/base16/lib/embers.js ***! - \*******************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'embers', - author: 'jannik siebert (https://github.com/janniks)', - base00: '#16130F', - base01: '#2C2620', - base02: '#433B32', - base03: '#5A5047', - base04: '#8A8075', - base05: '#A39A90', - base06: '#BEB6AE', - base07: '#DBD6D1', - base08: '#826D57', - base09: '#828257', - base0A: '#6D8257', - base0B: '#57826D', - base0C: '#576D82', - base0D: '#6D5782', - base0E: '#82576D', - base0F: '#825757' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/flat.js" -/*!*****************************************!*\ - !*** ./node_modules/base16/lib/flat.js ***! - \*****************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'flat', - author: 'chris kempson (http://chriskempson.com)', - base00: '#2C3E50', - base01: '#34495E', - base02: '#7F8C8D', - base03: '#95A5A6', - base04: '#BDC3C7', - base05: '#e0e0e0', - base06: '#f5f5f5', - base07: '#ECF0F1', - base08: '#E74C3C', - base09: '#E67E22', - base0A: '#F1C40F', - base0B: '#2ECC71', - base0C: '#1ABC9C', - base0D: '#3498DB', - base0E: '#9B59B6', - base0F: '#be643c' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/google.js" -/*!*******************************************!*\ - !*** ./node_modules/base16/lib/google.js ***! - \*******************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'google', - author: 'seth wright (http://sethawright.com)', - base00: '#1d1f21', - base01: '#282a2e', - base02: '#373b41', - base03: '#969896', - base04: '#b4b7b4', - base05: '#c5c8c6', - base06: '#e0e0e0', - base07: '#ffffff', - base08: '#CC342B', - base09: '#F96A38', - base0A: '#FBA922', - base0B: '#198844', - base0C: '#3971ED', - base0D: '#3971ED', - base0E: '#A36AC7', - base0F: '#3971ED' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/grayscale.js" -/*!**********************************************!*\ - !*** ./node_modules/base16/lib/grayscale.js ***! - \**********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'grayscale', - author: 'alexandre gavioli (https://github.com/alexx2/)', - base00: '#101010', - base01: '#252525', - base02: '#464646', - base03: '#525252', - base04: '#ababab', - base05: '#b9b9b9', - base06: '#e3e3e3', - base07: '#f7f7f7', - base08: '#7c7c7c', - base09: '#999999', - base0A: '#a0a0a0', - base0B: '#8e8e8e', - base0C: '#868686', - base0D: '#686868', - base0E: '#747474', - base0F: '#5e5e5e' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/greenscreen.js" -/*!************************************************!*\ - !*** ./node_modules/base16/lib/greenscreen.js ***! - \************************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'green screen', - author: 'chris kempson (http://chriskempson.com)', - base00: '#001100', - base01: '#003300', - base02: '#005500', - base03: '#007700', - base04: '#009900', - base05: '#00bb00', - base06: '#00dd00', - base07: '#00ff00', - base08: '#007700', - base09: '#009900', - base0A: '#007700', - base0B: '#00bb00', - base0C: '#005500', - base0D: '#009900', - base0E: '#00bb00', - base0F: '#005500' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/harmonic.js" -/*!*********************************************!*\ - !*** ./node_modules/base16/lib/harmonic.js ***! - \*********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'harmonic16', - author: 'jannik siebert (https://github.com/janniks)', - base00: '#0b1c2c', - base01: '#223b54', - base02: '#405c79', - base03: '#627e99', - base04: '#aabcce', - base05: '#cbd6e2', - base06: '#e5ebf1', - base07: '#f7f9fb', - base08: '#bf8b56', - base09: '#bfbf56', - base0A: '#8bbf56', - base0B: '#56bf8b', - base0C: '#568bbf', - base0D: '#8b56bf', - base0E: '#bf568b', - base0F: '#bf5656' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/hopscotch.js" -/*!**********************************************!*\ - !*** ./node_modules/base16/lib/hopscotch.js ***! - \**********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'hopscotch', - author: 'jan t. sott', - base00: '#322931', - base01: '#433b42', - base02: '#5c545b', - base03: '#797379', - base04: '#989498', - base05: '#b9b5b8', - base06: '#d5d3d5', - base07: '#ffffff', - base08: '#dd464c', - base09: '#fd8b19', - base0A: '#fdcc59', - base0B: '#8fc13e', - base0C: '#149b93', - base0D: '#1290bf', - base0E: '#c85e7c', - base0F: '#b33508' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/index.js" -/*!******************************************!*\ - !*** ./node_modules/base16/lib/index.js ***! - \******************************************/ -(__unused_webpack_module, exports, __webpack_require__) { - -"use strict"; - - -exports.__esModule = true; - -function _interopRequire(obj) { return obj && obj.__esModule ? obj['default'] : obj; } - -var _threezerotwofour = __webpack_require__(/*! ./threezerotwofour */ "./node_modules/base16/lib/threezerotwofour.js"); - -exports.threezerotwofour = _interopRequire(_threezerotwofour); - -var _apathy = __webpack_require__(/*! ./apathy */ "./node_modules/base16/lib/apathy.js"); - -exports.apathy = _interopRequire(_apathy); - -var _ashes = __webpack_require__(/*! ./ashes */ "./node_modules/base16/lib/ashes.js"); - -exports.ashes = _interopRequire(_ashes); - -var _atelierDune = __webpack_require__(/*! ./atelier-dune */ "./node_modules/base16/lib/atelier-dune.js"); - -exports.atelierDune = _interopRequire(_atelierDune); - -var _atelierForest = __webpack_require__(/*! ./atelier-forest */ "./node_modules/base16/lib/atelier-forest.js"); - -exports.atelierForest = _interopRequire(_atelierForest); - -var _atelierHeath = __webpack_require__(/*! ./atelier-heath */ "./node_modules/base16/lib/atelier-heath.js"); - -exports.atelierHeath = _interopRequire(_atelierHeath); - -var _atelierLakeside = __webpack_require__(/*! ./atelier-lakeside */ "./node_modules/base16/lib/atelier-lakeside.js"); - -exports.atelierLakeside = _interopRequire(_atelierLakeside); - -var _atelierSeaside = __webpack_require__(/*! ./atelier-seaside */ "./node_modules/base16/lib/atelier-seaside.js"); - -exports.atelierSeaside = _interopRequire(_atelierSeaside); - -var _bespin = __webpack_require__(/*! ./bespin */ "./node_modules/base16/lib/bespin.js"); - -exports.bespin = _interopRequire(_bespin); - -var _brewer = __webpack_require__(/*! ./brewer */ "./node_modules/base16/lib/brewer.js"); - -exports.brewer = _interopRequire(_brewer); - -var _bright = __webpack_require__(/*! ./bright */ "./node_modules/base16/lib/bright.js"); - -exports.bright = _interopRequire(_bright); - -var _chalk = __webpack_require__(/*! ./chalk */ "./node_modules/base16/lib/chalk.js"); - -exports.chalk = _interopRequire(_chalk); - -var _codeschool = __webpack_require__(/*! ./codeschool */ "./node_modules/base16/lib/codeschool.js"); - -exports.codeschool = _interopRequire(_codeschool); - -var _colors = __webpack_require__(/*! ./colors */ "./node_modules/base16/lib/colors.js"); - -exports.colors = _interopRequire(_colors); - -var _default = __webpack_require__(/*! ./default */ "./node_modules/base16/lib/default.js"); - -exports["default"] = _interopRequire(_default); - -var _eighties = __webpack_require__(/*! ./eighties */ "./node_modules/base16/lib/eighties.js"); - -exports.eighties = _interopRequire(_eighties); - -var _embers = __webpack_require__(/*! ./embers */ "./node_modules/base16/lib/embers.js"); - -exports.embers = _interopRequire(_embers); - -var _flat = __webpack_require__(/*! ./flat */ "./node_modules/base16/lib/flat.js"); - -exports.flat = _interopRequire(_flat); - -var _google = __webpack_require__(/*! ./google */ "./node_modules/base16/lib/google.js"); - -exports.google = _interopRequire(_google); - -var _grayscale = __webpack_require__(/*! ./grayscale */ "./node_modules/base16/lib/grayscale.js"); - -exports.grayscale = _interopRequire(_grayscale); - -var _greenscreen = __webpack_require__(/*! ./greenscreen */ "./node_modules/base16/lib/greenscreen.js"); - -exports.greenscreen = _interopRequire(_greenscreen); - -var _harmonic = __webpack_require__(/*! ./harmonic */ "./node_modules/base16/lib/harmonic.js"); - -exports.harmonic = _interopRequire(_harmonic); - -var _hopscotch = __webpack_require__(/*! ./hopscotch */ "./node_modules/base16/lib/hopscotch.js"); - -exports.hopscotch = _interopRequire(_hopscotch); - -var _isotope = __webpack_require__(/*! ./isotope */ "./node_modules/base16/lib/isotope.js"); - -exports.isotope = _interopRequire(_isotope); - -var _marrakesh = __webpack_require__(/*! ./marrakesh */ "./node_modules/base16/lib/marrakesh.js"); - -exports.marrakesh = _interopRequire(_marrakesh); - -var _mocha = __webpack_require__(/*! ./mocha */ "./node_modules/base16/lib/mocha.js"); - -exports.mocha = _interopRequire(_mocha); - -var _monokai = __webpack_require__(/*! ./monokai */ "./node_modules/base16/lib/monokai.js"); - -exports.monokai = _interopRequire(_monokai); - -var _ocean = __webpack_require__(/*! ./ocean */ "./node_modules/base16/lib/ocean.js"); - -exports.ocean = _interopRequire(_ocean); - -var _paraiso = __webpack_require__(/*! ./paraiso */ "./node_modules/base16/lib/paraiso.js"); - -exports.paraiso = _interopRequire(_paraiso); - -var _pop = __webpack_require__(/*! ./pop */ "./node_modules/base16/lib/pop.js"); - -exports.pop = _interopRequire(_pop); - -var _railscasts = __webpack_require__(/*! ./railscasts */ "./node_modules/base16/lib/railscasts.js"); - -exports.railscasts = _interopRequire(_railscasts); - -var _shapeshifter = __webpack_require__(/*! ./shapeshifter */ "./node_modules/base16/lib/shapeshifter.js"); - -exports.shapeshifter = _interopRequire(_shapeshifter); - -var _solarized = __webpack_require__(/*! ./solarized */ "./node_modules/base16/lib/solarized.js"); - -exports.solarized = _interopRequire(_solarized); - -var _summerfruit = __webpack_require__(/*! ./summerfruit */ "./node_modules/base16/lib/summerfruit.js"); - -exports.summerfruit = _interopRequire(_summerfruit); - -var _tomorrow = __webpack_require__(/*! ./tomorrow */ "./node_modules/base16/lib/tomorrow.js"); - -exports.tomorrow = _interopRequire(_tomorrow); - -var _tube = __webpack_require__(/*! ./tube */ "./node_modules/base16/lib/tube.js"); - -exports.tube = _interopRequire(_tube); - -var _twilight = __webpack_require__(/*! ./twilight */ "./node_modules/base16/lib/twilight.js"); - -exports.twilight = _interopRequire(_twilight); - -/***/ }, - -/***/ "./node_modules/base16/lib/isotope.js" -/*!********************************************!*\ - !*** ./node_modules/base16/lib/isotope.js ***! - \********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'isotope', - author: 'jan t. sott', - base00: '#000000', - base01: '#404040', - base02: '#606060', - base03: '#808080', - base04: '#c0c0c0', - base05: '#d0d0d0', - base06: '#e0e0e0', - base07: '#ffffff', - base08: '#ff0000', - base09: '#ff9900', - base0A: '#ff0099', - base0B: '#33ff00', - base0C: '#00ffff', - base0D: '#0066ff', - base0E: '#cc00ff', - base0F: '#3300ff' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/marrakesh.js" -/*!**********************************************!*\ - !*** ./node_modules/base16/lib/marrakesh.js ***! - \**********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'marrakesh', - author: 'alexandre gavioli (http://github.com/alexx2/)', - base00: '#201602', - base01: '#302e00', - base02: '#5f5b17', - base03: '#6c6823', - base04: '#86813b', - base05: '#948e48', - base06: '#ccc37a', - base07: '#faf0a5', - base08: '#c35359', - base09: '#b36144', - base0A: '#a88339', - base0B: '#18974e', - base0C: '#75a738', - base0D: '#477ca1', - base0E: '#8868b3', - base0F: '#b3588e' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/mocha.js" -/*!******************************************!*\ - !*** ./node_modules/base16/lib/mocha.js ***! - \******************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'mocha', - author: 'chris kempson (http://chriskempson.com)', - base00: '#3B3228', - base01: '#534636', - base02: '#645240', - base03: '#7e705a', - base04: '#b8afad', - base05: '#d0c8c6', - base06: '#e9e1dd', - base07: '#f5eeeb', - base08: '#cb6077', - base09: '#d28b71', - base0A: '#f4bc87', - base0B: '#beb55b', - base0C: '#7bbda4', - base0D: '#8ab3b5', - base0E: '#a89bb9', - base0F: '#bb9584' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/monokai.js" -/*!********************************************!*\ - !*** ./node_modules/base16/lib/monokai.js ***! - \********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'monokai', - author: 'wimer hazenberg (http://www.monokai.nl)', - base00: '#272822', - base01: '#383830', - base02: '#49483e', - base03: '#75715e', - base04: '#a59f85', - base05: '#f8f8f2', - base06: '#f5f4f1', - base07: '#f9f8f5', - base08: '#f92672', - base09: '#fd971f', - base0A: '#f4bf75', - base0B: '#a6e22e', - base0C: '#a1efe4', - base0D: '#66d9ef', - base0E: '#ae81ff', - base0F: '#cc6633' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/ocean.js" -/*!******************************************!*\ - !*** ./node_modules/base16/lib/ocean.js ***! - \******************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'ocean', - author: 'chris kempson (http://chriskempson.com)', - base00: '#2b303b', - base01: '#343d46', - base02: '#4f5b66', - base03: '#65737e', - base04: '#a7adba', - base05: '#c0c5ce', - base06: '#dfe1e8', - base07: '#eff1f5', - base08: '#bf616a', - base09: '#d08770', - base0A: '#ebcb8b', - base0B: '#a3be8c', - base0C: '#96b5b4', - base0D: '#8fa1b3', - base0E: '#b48ead', - base0F: '#ab7967' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/paraiso.js" -/*!********************************************!*\ - !*** ./node_modules/base16/lib/paraiso.js ***! - \********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'paraiso', - author: 'jan t. sott', - base00: '#2f1e2e', - base01: '#41323f', - base02: '#4f424c', - base03: '#776e71', - base04: '#8d8687', - base05: '#a39e9b', - base06: '#b9b6b0', - base07: '#e7e9db', - base08: '#ef6155', - base09: '#f99b15', - base0A: '#fec418', - base0B: '#48b685', - base0C: '#5bc4bf', - base0D: '#06b6ef', - base0E: '#815ba4', - base0F: '#e96ba8' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/pop.js" -/*!****************************************!*\ - !*** ./node_modules/base16/lib/pop.js ***! - \****************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'pop', - author: 'chris kempson (http://chriskempson.com)', - base00: '#000000', - base01: '#202020', - base02: '#303030', - base03: '#505050', - base04: '#b0b0b0', - base05: '#d0d0d0', - base06: '#e0e0e0', - base07: '#ffffff', - base08: '#eb008a', - base09: '#f29333', - base0A: '#f8ca12', - base0B: '#37b349', - base0C: '#00aabb', - base0D: '#0e5a94', - base0E: '#b31e8d', - base0F: '#7a2d00' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/railscasts.js" -/*!***********************************************!*\ - !*** ./node_modules/base16/lib/railscasts.js ***! - \***********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'railscasts', - author: 'ryan bates (http://railscasts.com)', - base00: '#2b2b2b', - base01: '#272935', - base02: '#3a4055', - base03: '#5a647e', - base04: '#d4cfc9', - base05: '#e6e1dc', - base06: '#f4f1ed', - base07: '#f9f7f3', - base08: '#da4939', - base09: '#cc7833', - base0A: '#ffc66d', - base0B: '#a5c261', - base0C: '#519f50', - base0D: '#6d9cbe', - base0E: '#b6b3eb', - base0F: '#bc9458' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/shapeshifter.js" -/*!*************************************************!*\ - !*** ./node_modules/base16/lib/shapeshifter.js ***! - \*************************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'shapeshifter', - author: 'tyler benziger (http://tybenz.com)', - base00: '#000000', - base01: '#040404', - base02: '#102015', - base03: '#343434', - base04: '#555555', - base05: '#ababab', - base06: '#e0e0e0', - base07: '#f9f9f9', - base08: '#e92f2f', - base09: '#e09448', - base0A: '#dddd13', - base0B: '#0ed839', - base0C: '#23edda', - base0D: '#3b48e3', - base0E: '#f996e2', - base0F: '#69542d' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/solarized.js" -/*!**********************************************!*\ - !*** ./node_modules/base16/lib/solarized.js ***! - \**********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'solarized', - author: 'ethan schoonover (http://ethanschoonover.com/solarized)', - base00: '#002b36', - base01: '#073642', - base02: '#586e75', - base03: '#657b83', - base04: '#839496', - base05: '#93a1a1', - base06: '#eee8d5', - base07: '#fdf6e3', - base08: '#dc322f', - base09: '#cb4b16', - base0A: '#b58900', - base0B: '#859900', - base0C: '#2aa198', - base0D: '#268bd2', - base0E: '#6c71c4', - base0F: '#d33682' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/summerfruit.js" -/*!************************************************!*\ - !*** ./node_modules/base16/lib/summerfruit.js ***! - \************************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'summerfruit', - author: 'christopher corley (http://cscorley.github.io/)', - base00: '#151515', - base01: '#202020', - base02: '#303030', - base03: '#505050', - base04: '#B0B0B0', - base05: '#D0D0D0', - base06: '#E0E0E0', - base07: '#FFFFFF', - base08: '#FF0086', - base09: '#FD8900', - base0A: '#ABA800', - base0B: '#00C918', - base0C: '#1faaaa', - base0D: '#3777E6', - base0E: '#AD00A1', - base0F: '#cc6633' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/threezerotwofour.js" -/*!*****************************************************!*\ - !*** ./node_modules/base16/lib/threezerotwofour.js ***! - \*****************************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'threezerotwofour', - author: 'jan t. sott (http://github.com/idleberg)', - base00: '#090300', - base01: '#3a3432', - base02: '#4a4543', - base03: '#5c5855', - base04: '#807d7c', - base05: '#a5a2a2', - base06: '#d6d5d4', - base07: '#f7f7f7', - base08: '#db2d20', - base09: '#e8bbd0', - base0A: '#fded02', - base0B: '#01a252', - base0C: '#b5e4f4', - base0D: '#01a0e4', - base0E: '#a16a94', - base0F: '#cdab53' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/tomorrow.js" -/*!*********************************************!*\ - !*** ./node_modules/base16/lib/tomorrow.js ***! - \*********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'tomorrow', - author: 'chris kempson (http://chriskempson.com)', - base00: '#1d1f21', - base01: '#282a2e', - base02: '#373b41', - base03: '#969896', - base04: '#b4b7b4', - base05: '#c5c8c6', - base06: '#e0e0e0', - base07: '#ffffff', - base08: '#cc6666', - base09: '#de935f', - base0A: '#f0c674', - base0B: '#b5bd68', - base0C: '#8abeb7', - base0D: '#81a2be', - base0E: '#b294bb', - base0F: '#a3685a' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/tube.js" -/*!*****************************************!*\ - !*** ./node_modules/base16/lib/tube.js ***! - \*****************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'london tube', - author: 'jan t. sott', - base00: '#231f20', - base01: '#1c3f95', - base02: '#5a5758', - base03: '#737171', - base04: '#959ca1', - base05: '#d9d8d8', - base06: '#e7e7e8', - base07: '#ffffff', - base08: '#ee2e24', - base09: '#f386a1', - base0A: '#ffd204', - base0B: '#00853e', - base0C: '#85cebc', - base0D: '#009ddc', - base0E: '#98005d', - base0F: '#b06110' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/base16/lib/twilight.js" -/*!*********************************************!*\ - !*** ./node_modules/base16/lib/twilight.js ***! - \*********************************************/ -(module, exports) { - -"use strict"; - - -exports.__esModule = true; -exports["default"] = { - scheme: 'twilight', - author: 'david hart (http://hart-dev.com)', - base00: '#1e1e1e', - base01: '#323537', - base02: '#464b50', - base03: '#5f5a60', - base04: '#838184', - base05: '#a7a7a7', - base06: '#c3c3c3', - base07: '#ffffff', - base08: '#cf6a4c', - base09: '#cda869', - base0A: '#f9ee98', - base0B: '#8f9d6a', - base0C: '#afc4db', - base0D: '#7587a6', - base0E: '#9b859d', - base0F: '#9b703f' -}; -module.exports = exports['default']; - -/***/ }, - -/***/ "./node_modules/color-convert/conversions.js" -/*!***************************************************!*\ - !*** ./node_modules/color-convert/conversions.js ***! - \***************************************************/ -(module, __unused_webpack_exports, __webpack_require__) { - -/* MIT license */ -var cssKeywords = __webpack_require__(/*! color-name */ "./node_modules/color-name/index.js"); - -// NOTE: conversions should only return primitive values (i.e. arrays, or -// values that give correct `typeof` results). -// do not use box values types (i.e. Number(), String(), etc.) - -var reverseKeywords = {}; -for (var key in cssKeywords) { - if (cssKeywords.hasOwnProperty(key)) { - reverseKeywords[cssKeywords[key]] = key; - } -} - -var convert = module.exports = { - rgb: {channels: 3, labels: 'rgb'}, - hsl: {channels: 3, labels: 'hsl'}, - hsv: {channels: 3, labels: 'hsv'}, - hwb: {channels: 3, labels: 'hwb'}, - cmyk: {channels: 4, labels: 'cmyk'}, - xyz: {channels: 3, labels: 'xyz'}, - lab: {channels: 3, labels: 'lab'}, - lch: {channels: 3, labels: 'lch'}, - hex: {channels: 1, labels: ['hex']}, - keyword: {channels: 1, labels: ['keyword']}, - ansi16: {channels: 1, labels: ['ansi16']}, - ansi256: {channels: 1, labels: ['ansi256']}, - hcg: {channels: 3, labels: ['h', 'c', 'g']}, - apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, - gray: {channels: 1, labels: ['gray']} -}; - -// hide .channels and .labels properties -for (var model in convert) { - if (convert.hasOwnProperty(model)) { - if (!('channels' in convert[model])) { - throw new Error('missing channels property: ' + model); - } - - if (!('labels' in convert[model])) { - throw new Error('missing channel labels property: ' + model); - } - - if (convert[model].labels.length !== convert[model].channels) { - throw new Error('channel and label counts mismatch: ' + model); - } - - var channels = convert[model].channels; - var labels = convert[model].labels; - delete convert[model].channels; - delete convert[model].labels; - Object.defineProperty(convert[model], 'channels', {value: channels}); - Object.defineProperty(convert[model], 'labels', {value: labels}); - } -} - -convert.rgb.hsl = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var min = Math.min(r, g, b); - var max = Math.max(r, g, b); - var delta = max - min; - var h; - var s; - var l; - - if (max === min) { - h = 0; - } else if (r === max) { - h = (g - b) / delta; - } else if (g === max) { - h = 2 + (b - r) / delta; - } else if (b === max) { - h = 4 + (r - g) / delta; - } - - h = Math.min(h * 60, 360); - - if (h < 0) { - h += 360; - } - - l = (min + max) / 2; - - if (max === min) { - s = 0; - } else if (l <= 0.5) { - s = delta / (max + min); - } else { - s = delta / (2 - max - min); - } - - return [h, s * 100, l * 100]; -}; - -convert.rgb.hsv = function (rgb) { - var rdif; - var gdif; - var bdif; - var h; - var s; - - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var v = Math.max(r, g, b); - var diff = v - Math.min(r, g, b); - var diffc = function (c) { - return (v - c) / 6 / diff + 1 / 2; - }; - - if (diff === 0) { - h = s = 0; - } else { - s = diff / v; - rdif = diffc(r); - gdif = diffc(g); - bdif = diffc(b); - - if (r === v) { - h = bdif - gdif; - } else if (g === v) { - h = (1 / 3) + rdif - bdif; - } else if (b === v) { - h = (2 / 3) + gdif - rdif; - } - if (h < 0) { - h += 1; - } else if (h > 1) { - h -= 1; - } - } - - return [ - h * 360, - s * 100, - v * 100 - ]; -}; - -convert.rgb.hwb = function (rgb) { - var r = rgb[0]; - var g = rgb[1]; - var b = rgb[2]; - var h = convert.rgb.hsl(rgb)[0]; - var w = 1 / 255 * Math.min(r, Math.min(g, b)); - - b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); - - return [h, w * 100, b * 100]; -}; - -convert.rgb.cmyk = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var c; - var m; - var y; - var k; - - k = Math.min(1 - r, 1 - g, 1 - b); - c = (1 - r - k) / (1 - k) || 0; - m = (1 - g - k) / (1 - k) || 0; - y = (1 - b - k) / (1 - k) || 0; - - return [c * 100, m * 100, y * 100, k * 100]; -}; - -/** - * See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance - * */ -function comparativeDistance(x, y) { - return ( - Math.pow(x[0] - y[0], 2) + - Math.pow(x[1] - y[1], 2) + - Math.pow(x[2] - y[2], 2) - ); -} - -convert.rgb.keyword = function (rgb) { - var reversed = reverseKeywords[rgb]; - if (reversed) { - return reversed; - } - - var currentClosestDistance = Infinity; - var currentClosestKeyword; - - for (var keyword in cssKeywords) { - if (cssKeywords.hasOwnProperty(keyword)) { - var value = cssKeywords[keyword]; - - // Compute comparative distance - var distance = comparativeDistance(rgb, value); - - // Check if its less, if so set as closest - if (distance < currentClosestDistance) { - currentClosestDistance = distance; - currentClosestKeyword = keyword; - } - } - } - - return currentClosestKeyword; -}; - -convert.keyword.rgb = function (keyword) { - return cssKeywords[keyword]; -}; - -convert.rgb.xyz = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - - // assume sRGB - r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92); - g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92); - b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92); - - var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); - var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); - var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); - - return [x * 100, y * 100, z * 100]; -}; - -convert.rgb.lab = function (rgb) { - var xyz = convert.rgb.xyz(rgb); - var x = xyz[0]; - var y = xyz[1]; - var z = xyz[2]; - var l; - var a; - var b; - - x /= 95.047; - y /= 100; - z /= 108.883; - - x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); - - l = (116 * y) - 16; - a = 500 * (x - y); - b = 200 * (y - z); - - return [l, a, b]; -}; - -convert.hsl.rgb = function (hsl) { - var h = hsl[0] / 360; - var s = hsl[1] / 100; - var l = hsl[2] / 100; - var t1; - var t2; - var t3; - var rgb; - var val; - - if (s === 0) { - val = l * 255; - return [val, val, val]; - } - - if (l < 0.5) { - t2 = l * (1 + s); - } else { - t2 = l + s - l * s; - } - - t1 = 2 * l - t2; - - rgb = [0, 0, 0]; - for (var i = 0; i < 3; i++) { - t3 = h + 1 / 3 * -(i - 1); - if (t3 < 0) { - t3++; - } - if (t3 > 1) { - t3--; - } - - if (6 * t3 < 1) { - val = t1 + (t2 - t1) * 6 * t3; - } else if (2 * t3 < 1) { - val = t2; - } else if (3 * t3 < 2) { - val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; - } else { - val = t1; - } - - rgb[i] = val * 255; - } - - return rgb; -}; - -convert.hsl.hsv = function (hsl) { - var h = hsl[0]; - var s = hsl[1] / 100; - var l = hsl[2] / 100; - var smin = s; - var lmin = Math.max(l, 0.01); - var sv; - var v; - - l *= 2; - s *= (l <= 1) ? l : 2 - l; - smin *= lmin <= 1 ? lmin : 2 - lmin; - v = (l + s) / 2; - sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); - - return [h, sv * 100, v * 100]; -}; - -convert.hsv.rgb = function (hsv) { - var h = hsv[0] / 60; - var s = hsv[1] / 100; - var v = hsv[2] / 100; - var hi = Math.floor(h) % 6; - - var f = h - Math.floor(h); - var p = 255 * v * (1 - s); - var q = 255 * v * (1 - (s * f)); - var t = 255 * v * (1 - (s * (1 - f))); - v *= 255; - - switch (hi) { - case 0: - return [v, t, p]; - case 1: - return [q, v, p]; - case 2: - return [p, v, t]; - case 3: - return [p, q, v]; - case 4: - return [t, p, v]; - case 5: - return [v, p, q]; - } -}; - -convert.hsv.hsl = function (hsv) { - var h = hsv[0]; - var s = hsv[1] / 100; - var v = hsv[2] / 100; - var vmin = Math.max(v, 0.01); - var lmin; - var sl; - var l; - - l = (2 - s) * v; - lmin = (2 - s) * vmin; - sl = s * vmin; - sl /= (lmin <= 1) ? lmin : 2 - lmin; - sl = sl || 0; - l /= 2; - - return [h, sl * 100, l * 100]; -}; - -// http://dev.w3.org/csswg/css-color/#hwb-to-rgb -convert.hwb.rgb = function (hwb) { - var h = hwb[0] / 360; - var wh = hwb[1] / 100; - var bl = hwb[2] / 100; - var ratio = wh + bl; - var i; - var v; - var f; - var n; - - // wh + bl cant be > 1 - if (ratio > 1) { - wh /= ratio; - bl /= ratio; - } - - i = Math.floor(6 * h); - v = 1 - bl; - f = 6 * h - i; - - if ((i & 0x01) !== 0) { - f = 1 - f; - } - - n = wh + f * (v - wh); // linear interpolation - - var r; - var g; - var b; - switch (i) { - default: - case 6: - case 0: r = v; g = n; b = wh; break; - case 1: r = n; g = v; b = wh; break; - case 2: r = wh; g = v; b = n; break; - case 3: r = wh; g = n; b = v; break; - case 4: r = n; g = wh; b = v; break; - case 5: r = v; g = wh; b = n; break; - } - - return [r * 255, g * 255, b * 255]; -}; - -convert.cmyk.rgb = function (cmyk) { - var c = cmyk[0] / 100; - var m = cmyk[1] / 100; - var y = cmyk[2] / 100; - var k = cmyk[3] / 100; - var r; - var g; - var b; - - r = 1 - Math.min(1, c * (1 - k) + k); - g = 1 - Math.min(1, m * (1 - k) + k); - b = 1 - Math.min(1, y * (1 - k) + k); - - return [r * 255, g * 255, b * 255]; -}; - -convert.xyz.rgb = function (xyz) { - var x = xyz[0] / 100; - var y = xyz[1] / 100; - var z = xyz[2] / 100; - var r; - var g; - var b; - - r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); - g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); - b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); - - // assume sRGB - r = r > 0.0031308 - ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055) - : r * 12.92; - - g = g > 0.0031308 - ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055) - : g * 12.92; - - b = b > 0.0031308 - ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055) - : b * 12.92; - - r = Math.min(Math.max(0, r), 1); - g = Math.min(Math.max(0, g), 1); - b = Math.min(Math.max(0, b), 1); - - return [r * 255, g * 255, b * 255]; -}; - -convert.xyz.lab = function (xyz) { - var x = xyz[0]; - var y = xyz[1]; - var z = xyz[2]; - var l; - var a; - var b; - - x /= 95.047; - y /= 100; - z /= 108.883; - - x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); - - l = (116 * y) - 16; - a = 500 * (x - y); - b = 200 * (y - z); - - return [l, a, b]; -}; - -convert.lab.xyz = function (lab) { - var l = lab[0]; - var a = lab[1]; - var b = lab[2]; - var x; - var y; - var z; - - y = (l + 16) / 116; - x = a / 500 + y; - z = y - b / 200; - - var y2 = Math.pow(y, 3); - var x2 = Math.pow(x, 3); - var z2 = Math.pow(z, 3); - y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787; - x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787; - z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787; - - x *= 95.047; - y *= 100; - z *= 108.883; - - return [x, y, z]; -}; - -convert.lab.lch = function (lab) { - var l = lab[0]; - var a = lab[1]; - var b = lab[2]; - var hr; - var h; - var c; - - hr = Math.atan2(b, a); - h = hr * 360 / 2 / Math.PI; - - if (h < 0) { - h += 360; - } - - c = Math.sqrt(a * a + b * b); - - return [l, c, h]; -}; - -convert.lch.lab = function (lch) { - var l = lch[0]; - var c = lch[1]; - var h = lch[2]; - var a; - var b; - var hr; - - hr = h / 360 * 2 * Math.PI; - a = c * Math.cos(hr); - b = c * Math.sin(hr); - - return [l, a, b]; -}; - -convert.rgb.ansi16 = function (args) { - var r = args[0]; - var g = args[1]; - var b = args[2]; - var value = 1 in arguments ? arguments[1] : convert.rgb.hsv(args)[2]; // hsv -> ansi16 optimization - - value = Math.round(value / 50); - - if (value === 0) { - return 30; - } - - var ansi = 30 - + ((Math.round(b / 255) << 2) - | (Math.round(g / 255) << 1) - | Math.round(r / 255)); - - if (value === 2) { - ansi += 60; - } - - return ansi; -}; - -convert.hsv.ansi16 = function (args) { - // optimization here; we already know the value and don't need to get - // it converted for us. - return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]); -}; - -convert.rgb.ansi256 = function (args) { - var r = args[0]; - var g = args[1]; - var b = args[2]; - - // we use the extended greyscale palette here, with the exception of - // black and white. normal palette only has 4 greyscale shades. - if (r === g && g === b) { - if (r < 8) { - return 16; - } - - if (r > 248) { - return 231; - } - - return Math.round(((r - 8) / 247) * 24) + 232; - } - - var ansi = 16 - + (36 * Math.round(r / 255 * 5)) - + (6 * Math.round(g / 255 * 5)) - + Math.round(b / 255 * 5); - - return ansi; -}; - -convert.ansi16.rgb = function (args) { - var color = args % 10; - - // handle greyscale - if (color === 0 || color === 7) { - if (args > 50) { - color += 3.5; - } - - color = color / 10.5 * 255; - - return [color, color, color]; - } - - var mult = (~~(args > 50) + 1) * 0.5; - var r = ((color & 1) * mult) * 255; - var g = (((color >> 1) & 1) * mult) * 255; - var b = (((color >> 2) & 1) * mult) * 255; - - return [r, g, b]; -}; - -convert.ansi256.rgb = function (args) { - // handle greyscale - if (args >= 232) { - var c = (args - 232) * 10 + 8; - return [c, c, c]; - } - - args -= 16; - - var rem; - var r = Math.floor(args / 36) / 5 * 255; - var g = Math.floor((rem = args % 36) / 6) / 5 * 255; - var b = (rem % 6) / 5 * 255; - - return [r, g, b]; -}; - -convert.rgb.hex = function (args) { - var integer = ((Math.round(args[0]) & 0xFF) << 16) - + ((Math.round(args[1]) & 0xFF) << 8) - + (Math.round(args[2]) & 0xFF); - - var string = integer.toString(16).toUpperCase(); - return '000000'.substring(string.length) + string; -}; - -convert.hex.rgb = function (args) { - var match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); - if (!match) { - return [0, 0, 0]; - } - - var colorString = match[0]; - - if (match[0].length === 3) { - colorString = colorString.split('').map(function (char) { - return char + char; - }).join(''); - } - - var integer = parseInt(colorString, 16); - var r = (integer >> 16) & 0xFF; - var g = (integer >> 8) & 0xFF; - var b = integer & 0xFF; - - return [r, g, b]; -}; - -convert.rgb.hcg = function (rgb) { - var r = rgb[0] / 255; - var g = rgb[1] / 255; - var b = rgb[2] / 255; - var max = Math.max(Math.max(r, g), b); - var min = Math.min(Math.min(r, g), b); - var chroma = (max - min); - var grayscale; - var hue; - - if (chroma < 1) { - grayscale = min / (1 - chroma); - } else { - grayscale = 0; - } - - if (chroma <= 0) { - hue = 0; - } else - if (max === r) { - hue = ((g - b) / chroma) % 6; - } else - if (max === g) { - hue = 2 + (b - r) / chroma; - } else { - hue = 4 + (r - g) / chroma + 4; - } - - hue /= 6; - hue %= 1; - - return [hue * 360, chroma * 100, grayscale * 100]; -}; - -convert.hsl.hcg = function (hsl) { - var s = hsl[1] / 100; - var l = hsl[2] / 100; - var c = 1; - var f = 0; - - if (l < 0.5) { - c = 2.0 * s * l; - } else { - c = 2.0 * s * (1.0 - l); - } - - if (c < 1.0) { - f = (l - 0.5 * c) / (1.0 - c); - } - - return [hsl[0], c * 100, f * 100]; -}; - -convert.hsv.hcg = function (hsv) { - var s = hsv[1] / 100; - var v = hsv[2] / 100; - - var c = s * v; - var f = 0; - - if (c < 1.0) { - f = (v - c) / (1 - c); - } - - return [hsv[0], c * 100, f * 100]; -}; - -convert.hcg.rgb = function (hcg) { - var h = hcg[0] / 360; - var c = hcg[1] / 100; - var g = hcg[2] / 100; - - if (c === 0.0) { - return [g * 255, g * 255, g * 255]; - } - - var pure = [0, 0, 0]; - var hi = (h % 1) * 6; - var v = hi % 1; - var w = 1 - v; - var mg = 0; - - switch (Math.floor(hi)) { - case 0: - pure[0] = 1; pure[1] = v; pure[2] = 0; break; - case 1: - pure[0] = w; pure[1] = 1; pure[2] = 0; break; - case 2: - pure[0] = 0; pure[1] = 1; pure[2] = v; break; - case 3: - pure[0] = 0; pure[1] = w; pure[2] = 1; break; - case 4: - pure[0] = v; pure[1] = 0; pure[2] = 1; break; - default: - pure[0] = 1; pure[1] = 0; pure[2] = w; - } - - mg = (1.0 - c) * g; - - return [ - (c * pure[0] + mg) * 255, - (c * pure[1] + mg) * 255, - (c * pure[2] + mg) * 255 - ]; -}; - -convert.hcg.hsv = function (hcg) { - var c = hcg[1] / 100; - var g = hcg[2] / 100; - - var v = c + g * (1.0 - c); - var f = 0; - - if (v > 0.0) { - f = c / v; - } - - return [hcg[0], f * 100, v * 100]; -}; - -convert.hcg.hsl = function (hcg) { - var c = hcg[1] / 100; - var g = hcg[2] / 100; - - var l = g * (1.0 - c) + 0.5 * c; - var s = 0; - - if (l > 0.0 && l < 0.5) { - s = c / (2 * l); - } else - if (l >= 0.5 && l < 1.0) { - s = c / (2 * (1 - l)); - } - - return [hcg[0], s * 100, l * 100]; -}; - -convert.hcg.hwb = function (hcg) { - var c = hcg[1] / 100; - var g = hcg[2] / 100; - var v = c + g * (1.0 - c); - return [hcg[0], (v - c) * 100, (1 - v) * 100]; -}; - -convert.hwb.hcg = function (hwb) { - var w = hwb[1] / 100; - var b = hwb[2] / 100; - var v = 1 - b; - var c = v - w; - var g = 0; - - if (c < 1) { - g = (v - c) / (1 - c); - } - - return [hwb[0], c * 100, g * 100]; -}; - -convert.apple.rgb = function (apple) { - return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255]; -}; - -convert.rgb.apple = function (rgb) { - return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535]; -}; - -convert.gray.rgb = function (args) { - return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; -}; - -convert.gray.hsl = convert.gray.hsv = function (args) { - return [0, 0, args[0]]; -}; - -convert.gray.hwb = function (gray) { - return [0, 100, gray[0]]; -}; - -convert.gray.cmyk = function (gray) { - return [0, 0, 0, gray[0]]; -}; - -convert.gray.lab = function (gray) { - return [gray[0], 0, 0]; -}; - -convert.gray.hex = function (gray) { - var val = Math.round(gray[0] / 100 * 255) & 0xFF; - var integer = (val << 16) + (val << 8) + val; - - var string = integer.toString(16).toUpperCase(); - return '000000'.substring(string.length) + string; -}; - -convert.rgb.gray = function (rgb) { - var val = (rgb[0] + rgb[1] + rgb[2]) / 3; - return [val / 255 * 100]; -}; - - -/***/ }, - -/***/ "./node_modules/color-convert/index.js" -/*!*********************************************!*\ - !*** ./node_modules/color-convert/index.js ***! - \*********************************************/ -(module, __unused_webpack_exports, __webpack_require__) { - -var conversions = __webpack_require__(/*! ./conversions */ "./node_modules/color-convert/conversions.js"); -var route = __webpack_require__(/*! ./route */ "./node_modules/color-convert/route.js"); - -var convert = {}; - -var models = Object.keys(conversions); - -function wrapRaw(fn) { - var wrappedFn = function (args) { - if (args === undefined || args === null) { - return args; - } - - if (arguments.length > 1) { - args = Array.prototype.slice.call(arguments); - } - - return fn(args); - }; - - // preserve .conversion property if there is one - if ('conversion' in fn) { - wrappedFn.conversion = fn.conversion; - } - - return wrappedFn; -} - -function wrapRounded(fn) { - var wrappedFn = function (args) { - if (args === undefined || args === null) { - return args; - } - - if (arguments.length > 1) { - args = Array.prototype.slice.call(arguments); - } - - var result = fn(args); - - // we're assuming the result is an array here. - // see notice in conversions.js; don't use box types - // in conversion functions. - if (typeof result === 'object') { - for (var len = result.length, i = 0; i < len; i++) { - result[i] = Math.round(result[i]); - } - } - - return result; - }; - - // preserve .conversion property if there is one - if ('conversion' in fn) { - wrappedFn.conversion = fn.conversion; - } - - return wrappedFn; -} - -models.forEach(function (fromModel) { - convert[fromModel] = {}; - - Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels}); - Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels}); - - var routes = route(fromModel); - var routeModels = Object.keys(routes); - - routeModels.forEach(function (toModel) { - var fn = routes[toModel]; - - convert[fromModel][toModel] = wrapRounded(fn); - convert[fromModel][toModel].raw = wrapRaw(fn); - }); -}); - -module.exports = convert; - - -/***/ }, - -/***/ "./node_modules/color-convert/route.js" -/*!*********************************************!*\ - !*** ./node_modules/color-convert/route.js ***! - \*********************************************/ -(module, __unused_webpack_exports, __webpack_require__) { - -var conversions = __webpack_require__(/*! ./conversions */ "./node_modules/color-convert/conversions.js"); - -/* - this function routes a model to all other models. - - all functions that are routed have a property `.conversion` attached - to the returned synthetic function. This property is an array - of strings, each with the steps in between the 'from' and 'to' - color models (inclusive). - - conversions that are not possible simply are not included. -*/ - -function buildGraph() { - var graph = {}; - // https://jsperf.com/object-keys-vs-for-in-with-closure/3 - var models = Object.keys(conversions); - - for (var len = models.length, i = 0; i < len; i++) { - graph[models[i]] = { - // http://jsperf.com/1-vs-infinity - // micro-opt, but this is simple. - distance: -1, - parent: null - }; - } - - return graph; -} - -// https://en.wikipedia.org/wiki/Breadth-first_search -function deriveBFS(fromModel) { - var graph = buildGraph(); - var queue = [fromModel]; // unshift -> queue -> pop - - graph[fromModel].distance = 0; - - while (queue.length) { - var current = queue.pop(); - var adjacents = Object.keys(conversions[current]); - - for (var len = adjacents.length, i = 0; i < len; i++) { - var adjacent = adjacents[i]; - var node = graph[adjacent]; - - if (node.distance === -1) { - node.distance = graph[current].distance + 1; - node.parent = current; - queue.unshift(adjacent); - } - } - } - - return graph; -} - -function link(from, to) { - return function (args) { - return to(from(args)); - }; -} - -function wrapConversion(toModel, graph) { - var path = [graph[toModel].parent, toModel]; - var fn = conversions[graph[toModel].parent][toModel]; - - var cur = graph[toModel].parent; - while (graph[cur].parent) { - path.unshift(graph[cur].parent); - fn = link(conversions[graph[cur].parent][cur], fn); - cur = graph[cur].parent; - } - - fn.conversion = path; - return fn; -} - -module.exports = function (fromModel) { - var graph = deriveBFS(fromModel); - var conversion = {}; - - var models = Object.keys(graph); - for (var len = models.length, i = 0; i < len; i++) { - var toModel = models[i]; - var node = graph[toModel]; - - if (node.parent === null) { - // no possible conversion, or this node is the source model. - continue; - } - - conversion[toModel] = wrapConversion(toModel, graph); - } - - return conversion; -}; - - - -/***/ }, - -/***/ "./node_modules/color-name/index.js" -/*!******************************************!*\ - !*** ./node_modules/color-name/index.js ***! - \******************************************/ -(module) { - -"use strict"; - - -module.exports = { - "aliceblue": [240, 248, 255], - "antiquewhite": [250, 235, 215], - "aqua": [0, 255, 255], - "aquamarine": [127, 255, 212], - "azure": [240, 255, 255], - "beige": [245, 245, 220], - "bisque": [255, 228, 196], - "black": [0, 0, 0], - "blanchedalmond": [255, 235, 205], - "blue": [0, 0, 255], - "blueviolet": [138, 43, 226], - "brown": [165, 42, 42], - "burlywood": [222, 184, 135], - "cadetblue": [95, 158, 160], - "chartreuse": [127, 255, 0], - "chocolate": [210, 105, 30], - "coral": [255, 127, 80], - "cornflowerblue": [100, 149, 237], - "cornsilk": [255, 248, 220], - "crimson": [220, 20, 60], - "cyan": [0, 255, 255], - "darkblue": [0, 0, 139], - "darkcyan": [0, 139, 139], - "darkgoldenrod": [184, 134, 11], - "darkgray": [169, 169, 169], - "darkgreen": [0, 100, 0], - "darkgrey": [169, 169, 169], - "darkkhaki": [189, 183, 107], - "darkmagenta": [139, 0, 139], - "darkolivegreen": [85, 107, 47], - "darkorange": [255, 140, 0], - "darkorchid": [153, 50, 204], - "darkred": [139, 0, 0], - "darksalmon": [233, 150, 122], - "darkseagreen": [143, 188, 143], - "darkslateblue": [72, 61, 139], - "darkslategray": [47, 79, 79], - "darkslategrey": [47, 79, 79], - "darkturquoise": [0, 206, 209], - "darkviolet": [148, 0, 211], - "deeppink": [255, 20, 147], - "deepskyblue": [0, 191, 255], - "dimgray": [105, 105, 105], - "dimgrey": [105, 105, 105], - "dodgerblue": [30, 144, 255], - "firebrick": [178, 34, 34], - "floralwhite": [255, 250, 240], - "forestgreen": [34, 139, 34], - "fuchsia": [255, 0, 255], - "gainsboro": [220, 220, 220], - "ghostwhite": [248, 248, 255], - "gold": [255, 215, 0], - "goldenrod": [218, 165, 32], - "gray": [128, 128, 128], - "green": [0, 128, 0], - "greenyellow": [173, 255, 47], - "grey": [128, 128, 128], - "honeydew": [240, 255, 240], - "hotpink": [255, 105, 180], - "indianred": [205, 92, 92], - "indigo": [75, 0, 130], - "ivory": [255, 255, 240], - "khaki": [240, 230, 140], - "lavender": [230, 230, 250], - "lavenderblush": [255, 240, 245], - "lawngreen": [124, 252, 0], - "lemonchiffon": [255, 250, 205], - "lightblue": [173, 216, 230], - "lightcoral": [240, 128, 128], - "lightcyan": [224, 255, 255], - "lightgoldenrodyellow": [250, 250, 210], - "lightgray": [211, 211, 211], - "lightgreen": [144, 238, 144], - "lightgrey": [211, 211, 211], - "lightpink": [255, 182, 193], - "lightsalmon": [255, 160, 122], - "lightseagreen": [32, 178, 170], - "lightskyblue": [135, 206, 250], - "lightslategray": [119, 136, 153], - "lightslategrey": [119, 136, 153], - "lightsteelblue": [176, 196, 222], - "lightyellow": [255, 255, 224], - "lime": [0, 255, 0], - "limegreen": [50, 205, 50], - "linen": [250, 240, 230], - "magenta": [255, 0, 255], - "maroon": [128, 0, 0], - "mediumaquamarine": [102, 205, 170], - "mediumblue": [0, 0, 205], - "mediumorchid": [186, 85, 211], - "mediumpurple": [147, 112, 219], - "mediumseagreen": [60, 179, 113], - "mediumslateblue": [123, 104, 238], - "mediumspringgreen": [0, 250, 154], - "mediumturquoise": [72, 209, 204], - "mediumvioletred": [199, 21, 133], - "midnightblue": [25, 25, 112], - "mintcream": [245, 255, 250], - "mistyrose": [255, 228, 225], - "moccasin": [255, 228, 181], - "navajowhite": [255, 222, 173], - "navy": [0, 0, 128], - "oldlace": [253, 245, 230], - "olive": [128, 128, 0], - "olivedrab": [107, 142, 35], - "orange": [255, 165, 0], - "orangered": [255, 69, 0], - "orchid": [218, 112, 214], - "palegoldenrod": [238, 232, 170], - "palegreen": [152, 251, 152], - "paleturquoise": [175, 238, 238], - "palevioletred": [219, 112, 147], - "papayawhip": [255, 239, 213], - "peachpuff": [255, 218, 185], - "peru": [205, 133, 63], - "pink": [255, 192, 203], - "plum": [221, 160, 221], - "powderblue": [176, 224, 230], - "purple": [128, 0, 128], - "rebeccapurple": [102, 51, 153], - "red": [255, 0, 0], - "rosybrown": [188, 143, 143], - "royalblue": [65, 105, 225], - "saddlebrown": [139, 69, 19], - "salmon": [250, 128, 114], - "sandybrown": [244, 164, 96], - "seagreen": [46, 139, 87], - "seashell": [255, 245, 238], - "sienna": [160, 82, 45], - "silver": [192, 192, 192], - "skyblue": [135, 206, 235], - "slateblue": [106, 90, 205], - "slategray": [112, 128, 144], - "slategrey": [112, 128, 144], - "snow": [255, 250, 250], - "springgreen": [0, 255, 127], - "steelblue": [70, 130, 180], - "tan": [210, 180, 140], - "teal": [0, 128, 128], - "thistle": [216, 191, 216], - "tomato": [255, 99, 71], - "turquoise": [64, 224, 208], - "violet": [238, 130, 238], - "wheat": [245, 222, 179], - "white": [255, 255, 255], - "whitesmoke": [245, 245, 245], - "yellow": [255, 255, 0], - "yellowgreen": [154, 205, 50] -}; - - -/***/ }, - -/***/ "./node_modules/color-string/index.js" -/*!********************************************!*\ - !*** ./node_modules/color-string/index.js ***! - \********************************************/ -(module, __unused_webpack_exports, __webpack_require__) { - -/* MIT license */ -var colorNames = __webpack_require__(/*! color-name */ "./node_modules/color-name/index.js"); -var swizzle = __webpack_require__(/*! simple-swizzle */ "./node_modules/simple-swizzle/index.js"); -var hasOwnProperty = Object.hasOwnProperty; - -var reverseNames = Object.create(null); - -// create a list of reverse color names -for (var name in colorNames) { - if (hasOwnProperty.call(colorNames, name)) { - reverseNames[colorNames[name]] = name; - } -} - -var cs = module.exports = { - to: {}, - get: {} -}; - -cs.get = function (string) { - var prefix = string.substring(0, 3).toLowerCase(); - var val; - var model; - switch (prefix) { - case 'hsl': - val = cs.get.hsl(string); - model = 'hsl'; - break; - case 'hwb': - val = cs.get.hwb(string); - model = 'hwb'; - break; - default: - val = cs.get.rgb(string); - model = 'rgb'; - break; - } - - if (!val) { - return null; - } - - return {model: model, value: val}; -}; - -cs.get.rgb = function (string) { - if (!string) { - return null; - } - - var abbr = /^#([a-f0-9]{3,4})$/i; - var hex = /^#([a-f0-9]{6})([a-f0-9]{2})?$/i; - var rgba = /^rgba?\(\s*([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)\s*(?:[,|\/]\s*([+-]?[\d\.]+)(%?)\s*)?\)$/; - var per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,?\s*([+-]?[\d\.]+)\%\s*,?\s*([+-]?[\d\.]+)\%\s*(?:[,|\/]\s*([+-]?[\d\.]+)(%?)\s*)?\)$/; - var keyword = /^(\w+)$/; - - var rgb = [0, 0, 0, 1]; - var match; - var i; - var hexAlpha; - - if (match = string.match(hex)) { - hexAlpha = match[2]; - match = match[1]; - - for (i = 0; i < 3; i++) { - // https://jsperf.com/slice-vs-substr-vs-substring-methods-long-string/19 - var i2 = i * 2; - rgb[i] = parseInt(match.slice(i2, i2 + 2), 16); - } - - if (hexAlpha) { - rgb[3] = parseInt(hexAlpha, 16) / 255; - } - } else if (match = string.match(abbr)) { - match = match[1]; - hexAlpha = match[3]; - - for (i = 0; i < 3; i++) { - rgb[i] = parseInt(match[i] + match[i], 16); - } - - if (hexAlpha) { - rgb[3] = parseInt(hexAlpha + hexAlpha, 16) / 255; - } - } else if (match = string.match(rgba)) { - for (i = 0; i < 3; i++) { - rgb[i] = parseInt(match[i + 1], 0); - } - - if (match[4]) { - if (match[5]) { - rgb[3] = parseFloat(match[4]) * 0.01; - } else { - rgb[3] = parseFloat(match[4]); - } - } - } else if (match = string.match(per)) { - for (i = 0; i < 3; i++) { - rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55); - } - - if (match[4]) { - if (match[5]) { - rgb[3] = parseFloat(match[4]) * 0.01; - } else { - rgb[3] = parseFloat(match[4]); - } - } - } else if (match = string.match(keyword)) { - if (match[1] === 'transparent') { - return [0, 0, 0, 0]; - } - - if (!hasOwnProperty.call(colorNames, match[1])) { - return null; - } - - rgb = colorNames[match[1]]; - rgb[3] = 1; - - return rgb; - } else { - return null; - } - - for (i = 0; i < 3; i++) { - rgb[i] = clamp(rgb[i], 0, 255); - } - rgb[3] = clamp(rgb[3], 0, 1); - - return rgb; -}; - -cs.get.hsl = function (string) { - if (!string) { - return null; - } - - var hsl = /^hsla?\(\s*([+-]?(?:\d{0,3}\.)?\d+)(?:deg)?\s*,?\s*([+-]?[\d\.]+)%\s*,?\s*([+-]?[\d\.]+)%\s*(?:[,|\/]\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/; - var match = string.match(hsl); - - if (match) { - var alpha = parseFloat(match[4]); - var h = ((parseFloat(match[1]) % 360) + 360) % 360; - var s = clamp(parseFloat(match[2]), 0, 100); - var l = clamp(parseFloat(match[3]), 0, 100); - var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1); - - return [h, s, l, a]; - } - - return null; -}; - -cs.get.hwb = function (string) { - if (!string) { - return null; - } - - var hwb = /^hwb\(\s*([+-]?\d{0,3}(?:\.\d+)?)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/; - var match = string.match(hwb); - - if (match) { - var alpha = parseFloat(match[4]); - var h = ((parseFloat(match[1]) % 360) + 360) % 360; - var w = clamp(parseFloat(match[2]), 0, 100); - var b = clamp(parseFloat(match[3]), 0, 100); - var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1); - return [h, w, b, a]; - } - - return null; -}; - -cs.to.hex = function () { - var rgba = swizzle(arguments); - - return ( - '#' + - hexDouble(rgba[0]) + - hexDouble(rgba[1]) + - hexDouble(rgba[2]) + - (rgba[3] < 1 - ? (hexDouble(Math.round(rgba[3] * 255))) - : '') - ); -}; - -cs.to.rgb = function () { - var rgba = swizzle(arguments); - - return rgba.length < 4 || rgba[3] === 1 - ? 'rgb(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ')' - : 'rgba(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ', ' + rgba[3] + ')'; -}; - -cs.to.rgb.percent = function () { - var rgba = swizzle(arguments); - - var r = Math.round(rgba[0] / 255 * 100); - var g = Math.round(rgba[1] / 255 * 100); - var b = Math.round(rgba[2] / 255 * 100); - - return rgba.length < 4 || rgba[3] === 1 - ? 'rgb(' + r + '%, ' + g + '%, ' + b + '%)' - : 'rgba(' + r + '%, ' + g + '%, ' + b + '%, ' + rgba[3] + ')'; -}; - -cs.to.hsl = function () { - var hsla = swizzle(arguments); - return hsla.length < 4 || hsla[3] === 1 - ? 'hsl(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%)' - : 'hsla(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%, ' + hsla[3] + ')'; -}; - -// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax -// (hwb have alpha optional & 1 is default value) -cs.to.hwb = function () { - var hwba = swizzle(arguments); - - var a = ''; - if (hwba.length >= 4 && hwba[3] !== 1) { - a = ', ' + hwba[3]; - } - - return 'hwb(' + hwba[0] + ', ' + hwba[1] + '%, ' + hwba[2] + '%' + a + ')'; -}; - -cs.to.keyword = function (rgb) { - return reverseNames[rgb.slice(0, 3)]; -}; - -// helpers -function clamp(num, min, max) { - return Math.min(Math.max(min, num), max); -} - -function hexDouble(num) { - var str = Math.round(num).toString(16).toUpperCase(); - return (str.length < 2) ? '0' + str : str; -} - - -/***/ }, - -/***/ "./node_modules/color/index.js" -/*!*************************************!*\ - !*** ./node_modules/color/index.js ***! - \*************************************/ -(module, __unused_webpack_exports, __webpack_require__) { - -"use strict"; - - -var colorString = __webpack_require__(/*! color-string */ "./node_modules/color-string/index.js"); -var convert = __webpack_require__(/*! color-convert */ "./node_modules/color-convert/index.js"); - -var _slice = [].slice; - -var skippedModels = [ - // to be honest, I don't really feel like keyword belongs in color convert, but eh. - 'keyword', - - // gray conflicts with some method names, and has its own method defined. - 'gray', - - // shouldn't really be in color-convert either... - 'hex' -]; - -var hashedModelKeys = {}; -Object.keys(convert).forEach(function (model) { - hashedModelKeys[_slice.call(convert[model].labels).sort().join('')] = model; -}); - -var limiters = {}; - -function Color(obj, model) { - if (!(this instanceof Color)) { - return new Color(obj, model); - } - - if (model && model in skippedModels) { - model = null; - } - - if (model && !(model in convert)) { - throw new Error('Unknown model: ' + model); - } - - var i; - var channels; - - if (obj == null) { // eslint-disable-line no-eq-null,eqeqeq - this.model = 'rgb'; - this.color = [0, 0, 0]; - this.valpha = 1; - } else if (obj instanceof Color) { - this.model = obj.model; - this.color = obj.color.slice(); - this.valpha = obj.valpha; - } else if (typeof obj === 'string') { - var result = colorString.get(obj); - if (result === null) { - throw new Error('Unable to parse color from string: ' + obj); - } - - this.model = result.model; - channels = convert[this.model].channels; - this.color = result.value.slice(0, channels); - this.valpha = typeof result.value[channels] === 'number' ? result.value[channels] : 1; - } else if (obj.length) { - this.model = model || 'rgb'; - channels = convert[this.model].channels; - var newArr = _slice.call(obj, 0, channels); - this.color = zeroArray(newArr, channels); - this.valpha = typeof obj[channels] === 'number' ? obj[channels] : 1; - } else if (typeof obj === 'number') { - // this is always RGB - can be converted later on. - obj &= 0xFFFFFF; - this.model = 'rgb'; - this.color = [ - (obj >> 16) & 0xFF, - (obj >> 8) & 0xFF, - obj & 0xFF - ]; - this.valpha = 1; - } else { - this.valpha = 1; - - var keys = Object.keys(obj); - if ('alpha' in obj) { - keys.splice(keys.indexOf('alpha'), 1); - this.valpha = typeof obj.alpha === 'number' ? obj.alpha : 0; - } - - var hashedKeys = keys.sort().join(''); - if (!(hashedKeys in hashedModelKeys)) { - throw new Error('Unable to parse color from object: ' + JSON.stringify(obj)); - } - - this.model = hashedModelKeys[hashedKeys]; - - var labels = convert[this.model].labels; - var color = []; - for (i = 0; i < labels.length; i++) { - color.push(obj[labels[i]]); - } - - this.color = zeroArray(color); - } - - // perform limitations (clamping, etc.) - if (limiters[this.model]) { - channels = convert[this.model].channels; - for (i = 0; i < channels; i++) { - var limit = limiters[this.model][i]; - if (limit) { - this.color[i] = limit(this.color[i]); - } - } - } - - this.valpha = Math.max(0, Math.min(1, this.valpha)); - - if (Object.freeze) { - Object.freeze(this); - } -} - -Color.prototype = { - toString: function () { - return this.string(); - }, - - toJSON: function () { - return this[this.model](); - }, - - string: function (places) { - var self = this.model in colorString.to ? this : this.rgb(); - self = self.round(typeof places === 'number' ? places : 1); - var args = self.valpha === 1 ? self.color : self.color.concat(this.valpha); - return colorString.to[self.model](args); - }, - - percentString: function (places) { - var self = this.rgb().round(typeof places === 'number' ? places : 1); - var args = self.valpha === 1 ? self.color : self.color.concat(this.valpha); - return colorString.to.rgb.percent(args); - }, - - array: function () { - return this.valpha === 1 ? this.color.slice() : this.color.concat(this.valpha); - }, - - object: function () { - var result = {}; - var channels = convert[this.model].channels; - var labels = convert[this.model].labels; - - for (var i = 0; i < channels; i++) { - result[labels[i]] = this.color[i]; - } - - if (this.valpha !== 1) { - result.alpha = this.valpha; - } - - return result; - }, - - unitArray: function () { - var rgb = this.rgb().color; - rgb[0] /= 255; - rgb[1] /= 255; - rgb[2] /= 255; - - if (this.valpha !== 1) { - rgb.push(this.valpha); - } - - return rgb; - }, - - unitObject: function () { - var rgb = this.rgb().object(); - rgb.r /= 255; - rgb.g /= 255; - rgb.b /= 255; - - if (this.valpha !== 1) { - rgb.alpha = this.valpha; - } - - return rgb; - }, - - round: function (places) { - places = Math.max(places || 0, 0); - return new Color(this.color.map(roundToPlace(places)).concat(this.valpha), this.model); - }, - - alpha: function (val) { - if (arguments.length) { - return new Color(this.color.concat(Math.max(0, Math.min(1, val))), this.model); - } - - return this.valpha; - }, - - // rgb - red: getset('rgb', 0, maxfn(255)), - green: getset('rgb', 1, maxfn(255)), - blue: getset('rgb', 2, maxfn(255)), - - hue: getset(['hsl', 'hsv', 'hsl', 'hwb', 'hcg'], 0, function (val) { return ((val % 360) + 360) % 360; }), // eslint-disable-line brace-style - - saturationl: getset('hsl', 1, maxfn(100)), - lightness: getset('hsl', 2, maxfn(100)), - - saturationv: getset('hsv', 1, maxfn(100)), - value: getset('hsv', 2, maxfn(100)), - - chroma: getset('hcg', 1, maxfn(100)), - gray: getset('hcg', 2, maxfn(100)), - - white: getset('hwb', 1, maxfn(100)), - wblack: getset('hwb', 2, maxfn(100)), - - cyan: getset('cmyk', 0, maxfn(100)), - magenta: getset('cmyk', 1, maxfn(100)), - yellow: getset('cmyk', 2, maxfn(100)), - black: getset('cmyk', 3, maxfn(100)), - - x: getset('xyz', 0, maxfn(100)), - y: getset('xyz', 1, maxfn(100)), - z: getset('xyz', 2, maxfn(100)), - - l: getset('lab', 0, maxfn(100)), - a: getset('lab', 1), - b: getset('lab', 2), - - keyword: function (val) { - if (arguments.length) { - return new Color(val); - } - - return convert[this.model].keyword(this.color); - }, - - hex: function (val) { - if (arguments.length) { - return new Color(val); - } - - return colorString.to.hex(this.rgb().round().color); - }, - - rgbNumber: function () { - var rgb = this.rgb().color; - return ((rgb[0] & 0xFF) << 16) | ((rgb[1] & 0xFF) << 8) | (rgb[2] & 0xFF); - }, - - luminosity: function () { - // http://www.w3.org/TR/WCAG20/#relativeluminancedef - var rgb = this.rgb().color; - - var lum = []; - for (var i = 0; i < rgb.length; i++) { - var chan = rgb[i] / 255; - lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4); - } - - return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2]; - }, - - contrast: function (color2) { - // http://www.w3.org/TR/WCAG20/#contrast-ratiodef - var lum1 = this.luminosity(); - var lum2 = color2.luminosity(); - - if (lum1 > lum2) { - return (lum1 + 0.05) / (lum2 + 0.05); - } - - return (lum2 + 0.05) / (lum1 + 0.05); - }, - - level: function (color2) { - var contrastRatio = this.contrast(color2); - if (contrastRatio >= 7.1) { - return 'AAA'; - } - - return (contrastRatio >= 4.5) ? 'AA' : ''; - }, - - isDark: function () { - // YIQ equation from http://24ways.org/2010/calculating-color-contrast - var rgb = this.rgb().color; - var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; - return yiq < 128; - }, - - isLight: function () { - return !this.isDark(); - }, - - negate: function () { - var rgb = this.rgb(); - for (var i = 0; i < 3; i++) { - rgb.color[i] = 255 - rgb.color[i]; - } - return rgb; - }, - - lighten: function (ratio) { - var hsl = this.hsl(); - hsl.color[2] += hsl.color[2] * ratio; - return hsl; - }, - - darken: function (ratio) { - var hsl = this.hsl(); - hsl.color[2] -= hsl.color[2] * ratio; - return hsl; - }, - - saturate: function (ratio) { - var hsl = this.hsl(); - hsl.color[1] += hsl.color[1] * ratio; - return hsl; - }, - - desaturate: function (ratio) { - var hsl = this.hsl(); - hsl.color[1] -= hsl.color[1] * ratio; - return hsl; - }, - - whiten: function (ratio) { - var hwb = this.hwb(); - hwb.color[1] += hwb.color[1] * ratio; - return hwb; - }, - - blacken: function (ratio) { - var hwb = this.hwb(); - hwb.color[2] += hwb.color[2] * ratio; - return hwb; - }, - - grayscale: function () { - // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale - var rgb = this.rgb().color; - var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11; - return Color.rgb(val, val, val); - }, - - fade: function (ratio) { - return this.alpha(this.valpha - (this.valpha * ratio)); - }, - - opaquer: function (ratio) { - return this.alpha(this.valpha + (this.valpha * ratio)); - }, - - rotate: function (degrees) { - var hsl = this.hsl(); - var hue = hsl.color[0]; - hue = (hue + degrees) % 360; - hue = hue < 0 ? 360 + hue : hue; - hsl.color[0] = hue; - return hsl; - }, - - mix: function (mixinColor, weight) { - // ported from sass implementation in C - // https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209 - if (!mixinColor || !mixinColor.rgb) { - throw new Error('Argument to "mix" was not a Color instance, but rather an instance of ' + typeof mixinColor); - } - var color1 = mixinColor.rgb(); - var color2 = this.rgb(); - var p = weight === undefined ? 0.5 : weight; - - var w = 2 * p - 1; - var a = color1.alpha() - color2.alpha(); - - var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - return Color.rgb( - w1 * color1.red() + w2 * color2.red(), - w1 * color1.green() + w2 * color2.green(), - w1 * color1.blue() + w2 * color2.blue(), - color1.alpha() * p + color2.alpha() * (1 - p)); - } -}; - -// model conversion methods and static constructors -Object.keys(convert).forEach(function (model) { - if (skippedModels.indexOf(model) !== -1) { - return; - } - - var channels = convert[model].channels; - - // conversion methods - Color.prototype[model] = function () { - if (this.model === model) { - return new Color(this); - } - - if (arguments.length) { - return new Color(arguments, model); - } - - var newAlpha = typeof arguments[channels] === 'number' ? channels : this.valpha; - return new Color(assertArray(convert[this.model][model].raw(this.color)).concat(newAlpha), model); - }; - - // 'static' construction methods - Color[model] = function (color) { - if (typeof color === 'number') { - color = zeroArray(_slice.call(arguments), channels); - } - return new Color(color, model); - }; -}); - -function roundTo(num, places) { - return Number(num.toFixed(places)); -} - -function roundToPlace(places) { - return function (num) { - return roundTo(num, places); - }; -} - -function getset(model, channel, modifier) { - model = Array.isArray(model) ? model : [model]; - - model.forEach(function (m) { - (limiters[m] || (limiters[m] = []))[channel] = modifier; - }); - - model = model[0]; - - return function (val) { - var result; - - if (arguments.length) { - if (modifier) { - val = modifier(val); - } - - result = this[model](); - result.color[channel] = val; - return result; - } - - result = this[model]().color[channel]; - if (modifier) { - result = modifier(result); - } - - return result; - }; -} - -function maxfn(max) { - return function (v) { - return Math.max(0, Math.min(max, v)); - }; -} - -function assertArray(val) { - return Array.isArray(val) ? val : [val]; -} - -function zeroArray(arr, length) { - for (var i = 0; i < length; i++) { - if (typeof arr[i] !== 'number') { - arr[i] = 0; - } - } - - return arr; -} - -module.exports = Color; - - -/***/ }, - -/***/ "./node_modules/cookie/dist/index.js" -/*!*******************************************!*\ - !*** ./node_modules/cookie/dist/index.js ***! - \*******************************************/ -(__unused_webpack_module, exports) { - -"use strict"; - - -function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } -function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } -function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } -function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } -function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.parseCookie = parseCookie; -exports.parse = parseCookie; -exports.stringifyCookie = stringifyCookie; -exports.stringifySetCookie = stringifySetCookie; -exports.serialize = stringifySetCookie; -exports.parseSetCookie = parseSetCookie; -exports.stringifySetCookie = stringifySetCookie; -exports.serialize = stringifySetCookie; -/** - * RegExp to match cookie-name in RFC 6265 sec 4.1.1 - * This refers out to the obsoleted definition of token in RFC 2616 sec 2.2 - * which has been replaced by the token definition in RFC 7230 appendix B. - * - * cookie-name = token - * token = 1*tchar - * tchar = "!" / "#" / "$" / "%" / "&" / "'" / - * "*" / "+" / "-" / "." / "^" / "_" / - * "`" / "|" / "~" / DIGIT / ALPHA - * - * Note: Allowing more characters - https://github.com/jshttp/cookie/issues/191 - * Allow same range as cookie value, except `=`, which delimits end of name. - */ -var cookieNameRegExp = /^[\u0021-\u003A\u003C\u003E-\u007E]+$/; -/** - * RegExp to match cookie-value in RFC 6265 sec 4.1.1 - * - * cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) - * cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E - * ; US-ASCII characters excluding CTLs, - * ; whitespace DQUOTE, comma, semicolon, - * ; and backslash - * - * Allowing more characters: https://github.com/jshttp/cookie/issues/191 - * Comma, backslash, and DQUOTE are not part of the parsing algorithm. - */ -var cookieValueRegExp = /^[\u0021-\u003A\u003C-\u007E]*$/; -/** - * RegExp to match domain-value in RFC 6265 sec 4.1.1 - * - * domain-value = - * ; defined in [RFC1034], Section 3.5, as - * ; enhanced by [RFC1123], Section 2.1 - * =