From 8d968a3315dccc095e14f732f2888519866d7169 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 7 Nov 2022 13:26:46 +0100 Subject: [PATCH 01/30] Fix: Fix multiple maps issue (#33) --- src/views/map-view.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/views/map-view.ts b/src/views/map-view.ts index efd3e6d..24a6269 100644 --- a/src/views/map-view.ts +++ b/src/views/map-view.ts @@ -30,9 +30,11 @@ const osmAttribution = 'Leaflet | ' + 'Map data © OpenStreetMap contributors'; -const DEFAULT_MAP_TILE: ILeafletMapTile = { - instance: new L.TileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'), - attribution: osmAttribution, +const getDefaultMapTile = () => { + return { + instance: new L.TileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'), + attribution: osmAttribution, + }; }; const DEFAULT_ZOOM_LEVEL = 2; @@ -82,7 +84,7 @@ export class MapView implements IOrbVi ...settings, map: { zoomLevel: settings.map?.zoomLevel ?? DEFAULT_ZOOM_LEVEL, - tile: settings.map?.tile ?? DEFAULT_MAP_TILE, + tile: settings.map?.tile ?? getDefaultMapTile(), }, render: { type: RendererType.CANVAS, From 60d0721e68ec90ad92c2417de283536218ff602d Mon Sep 17 00:00:00 2001 From: Toni Lastre Date: Mon, 7 Nov 2022 13:28:20 +0100 Subject: [PATCH 02/30] Chore: Update package.json version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cc1d340..70928e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@memgraph/orb", - "version": "0.1.4", + "version": "0.2.0", "description": "Graph visualization library", "engines": { "node": ">=16.0.0" From ab9ba316cee355f8683d92dfc437c9d415181898 Mon Sep 17 00:00:00 2001 From: Toni Date: Wed, 9 Nov 2022 17:23:44 +0100 Subject: [PATCH 03/30] New: Change the API to handle OrbView and OrbMapView (#34) * New: Change the API to handle OrbView and OrbMapView * New: Change the API for select/hover strategies --- README.md | 14 +- docs/data.md | 20 +- docs/events.md | 90 ++++---- docs/styles.md | 36 ++-- docs/view-default.md | 146 ++++++++----- docs/view-map.md | 163 ++++++++++----- examples/example-custom-styled-graph.html | 6 +- examples/example-fixed-coordinates-graph.html | 9 +- examples/example-graph-data-changes.html | 10 +- examples/example-graph-events.html | 6 +- examples/example-graph-on-map.html | 9 +- examples/example-simple-graph.html | 6 +- examples/playground.html | 111 ++++++---- examples/simulator-scenarios.html | 47 +++-- src/events.ts | 87 +++++--- src/index.ts | 28 ++- src/models/strategy.ts | 51 +++-- src/orb.ts | 71 ------- src/views/index.ts | 6 +- src/views/{map-view.ts => orb-map-view.ts} | 193 +++++++++++------- src/views/{default-view.ts => orb-view.ts} | 190 ++++++++++------- src/views/shared.ts | 17 +- 22 files changed, 752 insertions(+), 564 deletions(-) delete mode 100644 src/orb.ts rename src/views/{map-view.ts => orb-map-view.ts} (65%) rename src/views/{default-view.ts => orb-view.ts} (73%) diff --git a/README.md b/README.md index f7c4b2f..0043168 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Below you can find a simple Typescript example using Orb to visualize a small gr free to check other Javascript examples in `examples/` directory. ```typescript -import { Orb } from '@memgraph/orb'; +import { OrbView } from '@memgraph/orb'; const container = document.getElementById('graph'); const nodes: MyNode[] = [ @@ -56,14 +56,14 @@ const edges: MyEdge[] = [ { id: 2, start: 2, end: 3, label: 'ON' }, ]; -const orb = new Orb(container); +const orb = new OrbView(container); // Initialize nodes and edges orb.data.setup({ nodes, edges }); // Render and recenter the view -orb.view.render(() => { - orb.view.recenter(); +orb.render(() => { + orb.recenter(); }); ``` @@ -118,14 +118,14 @@ free to check other Javascript examples in `examples/` directory. ]; // First `Orb` is just a namespace of the JS package - const orb = new Orb.Orb(container); + const orb = new Orb.OrbView(container); // Initialize nodes and edges orb.data.setup({ nodes, edges }); // Render and recenter the view - orb.view.render(() => { - orb.view.recenter(); + orb.render(() => { + orb.recenter(); }); diff --git a/docs/data.md b/docs/data.md index d0c15c5..f694692 100644 --- a/docs/data.md +++ b/docs/data.md @@ -15,7 +15,9 @@ To initialize graph data structure use `orb.data.setup` function that receives ` `edges`. Here is a simple example of it: ```typescript -const orb = new Orb(container); +import { OrbView } from "@memgraph/orb"; + +const orb = new OrbView(container); const nodes: MyNode[] = [ { id: 0, text: "Node A", myField: 12 }, @@ -65,7 +67,9 @@ There are some useful node functions that you can use such as: Check the example to get to know node handling better: ```typescript -const orb = new Orb(container); +import { OrbView } from "@memgraph/orb"; + +const orb = new OrbView(container); const nodes: MyNode[] = [ { id: 0, text: "Node A", myField: 12 }, @@ -116,7 +120,9 @@ There are some useful node functions that you can use such as: Check the example to get to know edge handling better: ```typescript -const orb = new Orb(container); +import { OrbView } from "@memgraph/orb"; + +const orb = new OrbView(container); const nodes: MyNode[] = [ { id: 0, text: "Node A", myField: 12 }, @@ -148,7 +154,9 @@ ones. An update of a node or edge will happen if a node or edge with the same un exists in the graph structure. Check the example below: ```typescript -const orb = new Orb(container); +import { OrbView } from "@memgraph/orb"; + +const orb = new OrbView(container); const nodes: MyNode[] = [ { id: 0, text: "Node A", myField: 12 }, @@ -191,7 +199,9 @@ To remove nodes or edges from a graph, you just need the `id`. Removing a node w remove all inbound and outbound edges to that node. Removing an edge will just remove that edge. ```typescript -const orb = new Orb(container); +import { OrbView } from "@memgraph/orb"; + +const orb = new OrbView(container); const nodes: MyNode[] = [ { id: 0, text: "Node A" }, diff --git a/docs/events.md b/docs/events.md index af5bff4..996395a 100644 --- a/docs/events.md +++ b/docs/events.md @@ -75,9 +75,9 @@ Event data for `OrbEventType.RENDER_START` is undefined. Event is emitted on each render call after the renderer completes drawing the graph on canvas. ```typescript -import { OrbEventType } from '@memgraph/orb'; +import { OrbEventType, IOrbEventRenderEnd } from '@memgraph/orb'; -orb.events.on(OrbEventType.RENDER_END, (event) => { +orb.events.on(OrbEventType.RENDER_END, (event: IOrbEventRenderEnd) => { console.log(`Render ended in ${event.durationMs} ms`); }); ``` @@ -85,7 +85,7 @@ orb.events.on(OrbEventType.RENDER_END, (event) => { Event data for `OrbEventType.RENDER_END` has the following properties: ```typescript -interface Event { +interface IOrbEventRenderEnd { durationMs: number; } ``` @@ -116,9 +116,9 @@ Event `OrbEventType.SIMULATION_STEP` is emitted on each simulation step. `d3` si node positioning in iterations where each iteration is one simulation step. ```typescript -import { OrbEventType } from '@memgraph/orb'; +import { OrbEventType, IOrbEventSimulationStep } from '@memgraph/orb'; -orb.events.on(OrbEventType.SIMULATION_STEP, (event) => { +orb.events.on(OrbEventType.SIMULATION_STEP, (event: IOrbEventSimulationStep) => { console.log(`Simulation progress: ${event.progress}`); // If you want to see each step of the simulation, add render here orb.view.render(); @@ -128,7 +128,7 @@ orb.events.on(OrbEventType.SIMULATION_STEP, (event) => { Event data for `OrbEventType.SIMULATION_STEP` has the following properties: ```typescript -interface Event { +interface IOrbEventSimulationStep { progress: number; } ``` @@ -138,9 +138,9 @@ interface Event { Event `OrbEventType.SIMULATION_END` is emitted once the simulator ends with the final node positions. ```typescript -import { OrbEventType } from '@memgraph/orb'; +import { OrbEventType, IOrbEventSimulationEnd } from '@memgraph/orb'; -orb.events.on(OrbEventType.SIMULATION_END, (event) => { +orb.events.on(OrbEventType.SIMULATION_END, (event: IOrbEventSimulationEnd) => { console.log(`Simulation ended in ${event.durationMs} ms`); }); ``` @@ -148,7 +148,7 @@ orb.events.on(OrbEventType.SIMULATION_END, (event) => { Event data for `OrbEventType.SIMULATION_END` has the following properties: ```typescript -interface Event { +interface IOrbEventSimulationEnd { durationMs: number; } ``` @@ -161,9 +161,9 @@ Event is emitted on mouse click that selects the node. The event `OrbEventType.M triggered. ```typescript -import { OrbEventType } from '@memgraph/orb'; +import { OrbEventType, IOrbEventNodeClick } from '@memgraph/orb'; -orb.events.on(OrbEventType.NODE_CLICK, (event) => { +orb.events.on(OrbEventType.NODE_CLICK, (event: IOrbEventNodeClick) => { console.log(`Node clicked`, event.node); }); ``` @@ -171,7 +171,7 @@ orb.events.on(OrbEventType.NODE_CLICK, (event) => { Event data for `OrbEventType.NODE_CLICK` has the following properties: ```typescript -interface Event { +interface IOrbEventNodeClick { node: INode; event: PointerEvent; localPoint: { x: number; y: number }; @@ -188,9 +188,9 @@ Event is emitted on mouse move that hovers the node. The event `OrbEventType.MOU triggered. ```typescript -import { OrbEventType } from '@memgraph/orb'; +import { OrbEventType, IOrbEventNodeHover } from '@memgraph/orb'; -orb.events.on(OrbEventType.NODE_HOVER, (event) => { +orb.events.on(OrbEventType.NODE_HOVER, (event: IOrbEventNodeHover) => { console.log(`Node hovered`, event.node); }); ``` @@ -198,7 +198,7 @@ orb.events.on(OrbEventType.NODE_HOVER, (event) => { Event data for `OrbEventType.NODE_HOVER` has the following properties: ```typescript -interface Event { +interface IOrbEventNodeHover { node: INode; event: MouseEvent; localPoint: { x: number; y: number }; @@ -215,9 +215,9 @@ Event is emitted on mouse click that selects the edge. The event `OrbEventType.M triggered. ```typescript -import { OrbEventType } from '@memgraph/orb'; +import { OrbEventType, IOrbEventEdgeClick } from '@memgraph/orb'; -orb.events.on(OrbEventType.EDGE_CLICK, (event) => { +orb.events.on(OrbEventType.EDGE_CLICK, (event: IOrbEventEdgeClick) => { console.log(`Edge clicked`, event.edge); }); ``` @@ -225,7 +225,7 @@ orb.events.on(OrbEventType.EDGE_CLICK, (event) => { Event data for `OrbEventType.EDGE_CLICK` has the following properties: ```typescript -interface Event { +interface IOrbEventEdgeClick { edge: IEdge; event: PointerEvent; localPoint: { x: number; y: number }; @@ -245,9 +245,9 @@ triggered. > the distance to the closest edge to hover it. ```typescript -import { OrbEventType } from '@memgraph/orb'; +import { OrbEventType, IOrbEventEdgeHover } from '@memgraph/orb'; -orb.events.on(OrbEventType.EDGE_HOVER, (event) => { +orb.events.on(OrbEventType.EDGE_HOVER, (event: IOrbEventEdgeHover) => { console.log(`Edge hovered`, event.node); }); ``` @@ -255,7 +255,7 @@ orb.events.on(OrbEventType.EDGE_HOVER, (event) => { Event data for `OrbEventType.EDGE_HOVER` has the following properties: ```typescript -interface Event { +interface IOrbEventEdgeHover { edge: IEdge; event: MouseEvent; localPoint: { x: number; y: number }; @@ -273,9 +273,9 @@ edge) at the mouse click position, `OrbEventType.NODE_CLICK` and `OrbEventType.E will be triggered too. ```typescript -import { OrbEventType } from '@memgraph/orb'; +import { OrbEventType, IOrbEventMouseClick } from '@memgraph/orb'; -orb.events.on(OrbEventType.MOUSE_CLICK, (event) => { +orb.events.on(OrbEventType.MOUSE_CLICK, (event: IOrbEventMouseClick) => { console.log(`Mouse clicked`, event); }); ``` @@ -283,7 +283,7 @@ orb.events.on(OrbEventType.MOUSE_CLICK, (event) => { Event data for `OrbEventType.MOUSE_CLICK` has the following properties: ```typescript -interface Event { +interface IOrbEventMouseClick { subject?: INode | IEdge; event: PointerEvent; localPoint: { x: number; y: number }; @@ -299,9 +299,9 @@ the events `OrbEventType.NODE_CLICK` and `OrbEventType.EDGE_CLICK`. If you need to check if `subject` is a `INode` or `IEdge` use type check functions from orb: ```typescript -import { isNode, isEdge, OrbEventType } from '@memgraph/orb'; +import { isNode, isEdge, OrbEventType, IOrbEventMouseClick } from '@memgraph/orb'; -orb.events.on(OrbEventType.MOUSE_CLICK, (event) => { +orb.events.on(OrbEventType.MOUSE_CLICK, (event: IOrbEventMouseClick) => { if (event.subject && isNode(event.subject)) { console.log(`Mouse clicked on top of the node`, event.subject); } @@ -318,7 +318,9 @@ edge) at the mouse position, `OrbEventType.NODE_HOVER` and `OrbEventType.EDGE_HO be triggered too. ```typescript -orb.events.on(OrbEventType.MOUSE_MOVE, (event) => { +import { OrbEventType, IOrbEventMouseMove } from '@memgraph/orb'; + +orb.events.on(OrbEventType.MOUSE_MOVE, (event: IOrbEventMouseMove) => { console.log(`Mouse moved`, event); }); ``` @@ -326,7 +328,7 @@ orb.events.on(OrbEventType.MOUSE_MOVE, (event) => { Event data for `OrbEventType.MOUSE_MOVE` has the following properties: ```typescript -interface Event { +interface IOrbEventMouseMove { subject?: INode | IEdge; event: MouseEvent; localPoint: { x: number; y: number }; @@ -342,9 +344,9 @@ events `OrbEventType.NODE_CLICK` and `OrbEventType.EDGE_CLICK`. If you need to check if `subject` is a `INode` or `IEdge` use type check functions from orb: ```typescript -import { isNode, isEdge, OrbEventType } from '@memgraph/orb'; +import { isNode, isEdge, OrbEventType, IOrbEventMouseMove } from '@memgraph/orb'; -orb.events.on(OrbEventType.MOUSE_MOVE, (event) => { +orb.events.on(OrbEventType.MOUSE_MOVE, (event: IOrbEventMouseMove) => { if (event.subject && isNode(event.subject)) { console.log(`Mouse moved over the node`, event.subject); } @@ -361,9 +363,9 @@ orb.events.on(OrbEventType.MOUSE_MOVE, (event) => { Event is emitted on any zoom or pan event. ```typescript -import { OrbEventType } from '@memgraph/orb'; +import { OrbEventType, IOrbEventTransform } from '@memgraph/orb'; -orb.events.on(OrbEventType.TRANSFORM, (event) => { +orb.events.on(OrbEventType.TRANSFORM, (event: IOrbEventTransform) => { console.log(`Zoom or pan event`, event); }); ``` @@ -371,12 +373,12 @@ orb.events.on(OrbEventType.TRANSFORM, (event) => { Event data for `OrbEventType.TRANSFORM` has the following properties: ```typescript -interface Event { +interface IOrbEventTransform { transform: { x: number; y: number, k: number }; } ``` -Properties `x` and `y` are translation coordinates while `k` stands for zoom scale. If `DefaultView` +Properties `x` and `y` are translation coordinates while `k` stands for zoom scale. If `OrbView` is used, `transform` data is actually same as `ZoomTransform` type from `d3` library. ## Node dragging events @@ -384,7 +386,7 @@ is used, `transform` data is actually same as `ZoomTransform` type from `d3` lib Node dragging events are events that are emitted on node dragging which starts with a mouse click and hold, mouse movement, and ends with mouse click release. -> Note: Node dragging events might not be enabled on some views, e.g. `MapView` which currently +> Note: Node dragging events might not be enabled on some views, e.g. `OrbMapView` which currently > has a fixed position for each node by `latitude` and `longitude` values. ### Event `OrbEventType.NODE_DRAG_START` @@ -395,9 +397,9 @@ and `OrbEventType.MOUSE_CLICK`. If you want to listen just for drag then combine with `OrbEventType.NODE_DRAG_(START|END)`. ```typescript -import { OrbEventType } from '@memgraph/orb'; +import { OrbEventType, IOrbEventNodeDragStart } from '@memgraph/orb'; -orb.events.on(OrbEventType.NODE_DRAG_START, (event) => { +orb.events.on(OrbEventType.NODE_DRAG_START, (event: IOrbEventNodeDragStart) => { console.log(`Node drag started`, event); }); ``` @@ -405,7 +407,7 @@ orb.events.on(OrbEventType.NODE_DRAG_START, (event) => { Event data for `OrbEventType.NODE_DRAG_START` has the following properties: ```typescript -interface Event { +interface IOrbEventNodeDragStart { node: INode; event: MouseEvent; localPoint: { x: number; y: number }; @@ -422,9 +424,9 @@ Event is emitted on every mouse movement which is dragging a node with it. Event will also be triggered. ```typescript -import { OrbEventType } from '@memgraph/orb'; +import { OrbEventType, IOrbEventNodeDrag } from '@memgraph/orb'; -orb.events.on(OrbEventType.NODE_DRAG, (event) => { +orb.events.on(OrbEventType.NODE_DRAG, (event: IOrbEventNodeDrag) => { console.log(`Node dragged`, event); }); ``` @@ -432,7 +434,7 @@ orb.events.on(OrbEventType.NODE_DRAG, (event) => { Event data for `OrbEventType.NODE_DRAG` has the following properties: ```typescript -interface Event { +interface IOrbEventNodeDrag { node: INode; event: MouseEvent; localPoint: { x: number; y: number }; @@ -451,9 +453,9 @@ and `OrbEventType.MOUSE_CLICK`. If you want to listen just for drag then combine with `OrbEventType.NODE_DRAG_(START|END)`. ```typescript -import { OrbEventType } from '@memgraph/orb'; +import { OrbEventType, IOrbEventNodeDragEnd } from '@memgraph/orb'; -orb.events.on(OrbEventType.NODE_DRAG_END, (event) => { +orb.events.on(OrbEventType.NODE_DRAG_END, (event: IOrbEventNodeDragEnd) => { console.log(`Node drag ended`, event); }); ``` @@ -461,7 +463,7 @@ orb.events.on(OrbEventType.NODE_DRAG_END, (event) => { Event data for `OrbEventType.NODE_DRAG_END` has the following properties: ```typescript -interface Event { +interface IOrbEventNodeDragEnd { node: INode; event: MouseEvent; localPoint: { x: number; y: number }; diff --git a/docs/styles.md b/docs/styles.md index 98358d6..83648cf 100644 --- a/docs/styles.md +++ b/docs/styles.md @@ -84,13 +84,16 @@ const DEFAULT_NODE_STYLE: INodeStyle = { > below: ```typescript +import { OrbView } from "@memgraph/orb"; + const nodes: MyNode[] = [ { id: 1, name: "First" }, { id: 1, name: "Second" }, ]; -const orb = new Orb(container); -orb.setDefaultStyle({ +const orb = new OrbView(container); + +orb.data.setDefaultStyle({ getNodeStyle: (node) => { return { ...node.style, @@ -98,6 +101,7 @@ orb.setDefaultStyle({ }; }, }); + orb.data.setup({ nodes }); ``` @@ -269,9 +273,9 @@ node (`INode`) or edge (`IEdge`) object. Using those objects, you can change the any time: ```typescript -import { OrbEventType } from '@memgraph/orb'; +import { OrbView, OrbEventType } from '@memgraph/orb'; -const orb = new Orb(container); +const orb = new OrbView(container); orb.data.setup({ nodes, edges }); const node = orb.data.getNodeById(0); @@ -308,16 +312,18 @@ without setting `(node|edge).style.label = ""` or `(node|edge).style.fontSize = each node/edge, you can use the view settings to enable/disable labels globally: ```typescript +import { OrbView } from '@memgraph/orb'; + // Change on view init -orb.setView((context) => new DefaultView(context, { +const orb = new OrbView(container, { render: { labelsIsEnabled: true, labelsOnEventIsEnabled: true, }, -})); +}); // Change anytime for the current view -orb.view.setSettings({ +orb.setSettings({ render: { labelsIsEnabled: true, labelsOnEventIsEnabled: true, @@ -336,16 +342,18 @@ for the large number of nodes/edges. To simplify the way to disable/enable shado whole graph you can use the view settings to enable/disable shadows globally: ```typescript +import { OrbView } from '@memgraph/orb'; + // Change on view init -orb.setView((context) => new DefaultView(context, { +const orb = new OrbView(container, { render: { shadowsIsEnabled: true, shadowsOnEventIsEnabled: true, }, -})); +}); // Change anytime for the current view -orb.view.setSettings({ +orb.setSettings({ render: { shadowsIsEnabled: true, shadowsOnEventIsEnabled: true, @@ -371,16 +379,18 @@ You can configure the transparency with the following two properties: The default is `true`. ```typescript +import { OrbView } from '@memgraph/orb'; + // Change on view init -orb.setView((context) => new DefaultView(context, { +const orb = new OrbView(container, { render: { contextAlphaOnEvent: 0.3, contextAlphaOnEventIsEnabled: true, }, -})); +}); // Change anytime for the current view -orb.view.setSettings({ +orb.setSettings({ render: { contextAlphaOnEvent: 0.3, contextAlphaOnEventIsEnabled: true, diff --git a/docs/view-default.md b/docs/view-default.md index ddf9171..6f2be30 100644 --- a/docs/view-default.md +++ b/docs/view-default.md @@ -4,26 +4,20 @@ This is the default view that Orb uses to render a basic graph. ## Initialization -The `DefaultView` is assigned to every instance of Orb by default. You don't need to -provide any additional configuration to use it. - -You can, however, explicitly provide it in the factory function as you would any -other type of `IOrbView`. This will be necessary if you want to assign fixed node -coordinates, which you can read about further below. +The `OrbView` doesn't need any additional configuration. You can, however, explicitly provide +if you want to assign fixed node coordinates, which you can read about further below. ```typescript -import { DefaultView } from "@memgraph/orb"; - -const orb = new Orb(container); +import { OrbView } from "@memgraph/orb"; -orb.setView((context) => new DefaultView(context, optionalSettings)); +const orb = new OrbView(container, optionalSettings); ``` -You can set settings on view initialization or afterward with `orb.view.setSettings`. Below +You can set settings on view initialization or afterward with `orb.setSettings`. Below you can see the list of all settings' parameters: ```typescript -interface IDefaultViewSettings { +interface IOrbViewSettings { // For custom node positions getPosition(node: INode): { x: number; y: number } | undefined; // For node positioning simulation (d3-force parameters) @@ -80,6 +74,11 @@ interface IDefaultViewSettings { contextAlphaOnEvent: number; contextAlphaOnEventIsEnabled: boolean; }; + // For select and hover look-and-feel + strategy: { + isDefaultSelectEnabled: boolean; + isDefaultHoverEnabled: boolean; + }; // Other default view parameters zoomFitTransitionMs: number; isOutOfBoundsDragEnabled: boolean; @@ -89,7 +88,7 @@ interface IDefaultViewSettings { } ``` -The default settings that `DefaultView` uses is: +The default settings that `OrbView` uses is: ```typescript const defaultSettings = { @@ -144,6 +143,10 @@ const defaultSettings = { contextAlphaOnEvent: 0.3, contextAlphaOnEventIsEnabled: true, }, + strategy: { + isDefaultSelectEnabled: true, + isDefaultHoverEnabled: true, + }, zoomFitTransitionMs: 200, isOutOfBoundsDragEnabled: false, areCoordinatesRounded: true, @@ -156,7 +159,7 @@ You can read more about each property down below and on [Styles guide](./styles. ### Property `getPosition` -There are two basic ways to use the `DefaultView` API based on the node positions: +There are two basic ways to use the `OrbView` API based on the node positions: - **Simulated node positions** - Orb internally calculates and assigns coordinates to your nodes. @@ -165,7 +168,7 @@ There are two basic ways to use the `DefaultView` API based on the node position #### Simulated node positions -In this mode, the `DefaultView` arranges node positions by internally calculating their +In this mode, the `OrbView` arranges node positions by internally calculating their coordinates using the [D3.js](https://d3js.org/) library, or more specifically, [`d3-force`](https://github.com/d3/d3-force). This method is applied by default - you don't need to initialize Orb with any additional configuration. @@ -173,6 +176,8 @@ need to initialize Orb with any additional configuration. ![](./assets/view-default-simulated.png) ```typescript +import { OrbView } from "@memgraph/orb"; + const nodes: MyNode[] = [ { id: 0, label: "Node A" }, { id: 1, label: "Node B" }, @@ -187,14 +192,14 @@ const edges: MyEdge[] = [ { id: 5, start: 0, end: 1, label: "Edge V" }, ]; -const orb = new Orb(container); +const orb = new OrbView(container); // Initialize nodes and edges orb.data.setup({ nodes, edges }); // Render and recenter the view -orb.view.render(() => { - orb.view.recenter(); +orb.render(() => { + orb.recenter(); }); ``` @@ -208,7 +213,7 @@ that allows Orb to position the nodes. ![](./assets/view-default-fixed.png) ```typescript -import { DefaultView } from "@memgraph/orb"; +import { OrbView } from "@memgraph/orb"; const container = document.getElementById("graph"); const nodes: MyNode[] = [ @@ -225,20 +230,16 @@ const edges: MyEdge[] = [ { id: 5, start: 0, end: 1, label: "Edge V" }, ]; -const orb = new Orb(container); -orb.setView( - (context) => - new DefaultView(context, { - getPosition: (node) => ({ x: node.data.posX, y: node.data.posY }), - }) -); +const orb = new OrbView(container, { + getPosition: (node) => ({ x: node.data.posX, y: node.data.posY }), +}); // Initialize nodes and edges orb.data.setup({ nodes, edges }); // Render and recenter the view -orb.view.render(() => { - orb.view.recenter(); +orb.render(() => { + orb.recenter(); }); ``` @@ -257,6 +258,58 @@ Here you can use your original properties to indicate which ones represent your Optional property `render` has several rendering options that you can tweak. Read more about them on [Styling guide](./styles.md). +### Property `strategy` + +The optional property `strategy` has two properties that you can enable/disable: + +* `isDefaultSelectEnabled` - when `true`, the default selection strategy is used on mouse click: + * If there is a node at the mouse click point, the node, its edges, and adjacent nodes will change + its state to `GraphObjectState.SELECTED`. Style properties that end with `...Selected` will be + applied to all the selected objects (e.g. `borderColorSelected`). + * If there is an edge at the mouse click point, the edge and its starting and ending nodes will change + its state to `GraphObjectState.SELECTED`. +* `isDefaultHoverEnabled` - when `true`, the default hover strategy is used on mouse move: + * If there is a node at the mouse pointer, the node, its edges, and adjacent nodes will change its state to + `GraphObjectState.HOVERED`. Style properties that end with `...Hovered` will be applied to all the + hovered objects (e.g. `borderColorHovered`). + +With property `strategy` you can disable the above behavior and implement your select/hover strategy on +top of events `OrbEventType.MOUSE_CLICK` and `OrbEventType.MOUSE_MOVE`, e.g: + +```typescript +import { isNode, OrbEventType, GraphObjectState } from '@memgraph/orb'; + +// Disable default select and hover strategy +orb.setSettings({ + strategy: { + isDefaultSelectEnabled: false, + isDefaultHoverEnabled: false, + }, +}); + +// Create custom select strategy which selects just clicked node +orb.events.on(OrbEventType.MOUSE_CLICK, (event) => { + // Clicked on blank canvas + if (!event.subject) { + // Deselect the previously selected nodes and render if there are changes + const selectedNodes = orb.data.getNodes((node) => node.isSelected()); + if (selectedNodes) { + selectedNodes.forEach((node) => node.clearState()); + orb.render(); + } + } + + // Clicked on unselected node + if (event.subject && isNode(event.subject) && !event.subject.isSelected()) { + // Deselect the previously selected nodes + orb.data.getNodes((node) => node.isSelected()).forEach((node) => node.clearState()); + // Select the new node + event.subject.state = GraphObjectState.SELECTED; + orb.render(); + } +}); +``` + ### Property `simulation` Fine-grained D3 simulation engine settings. They include `isPhysicsEnabled`, `alpha`, @@ -294,38 +347,33 @@ Disabled by default (`false`). ## Settings -The above settings of the `DefaultView` can be defined on view initialization, but also anytime +The above settings of the `OrbView` can be defined on view initialization, but also anytime after the initialization with a view function `setSettings`: ```typescript -import { DefaultView } from "@memgraph/orb"; - -const orb = new Orb(container); - -orb.setView( - (context) => - new DefaultView(context, { - getPosition: (node) => ({ x: node.data.posY, y: node.data.posX }), - zoomFitTransformMs: 1000, - render: { - shadowIsEnabled: false, - shadowOnEventIsEnabled: false, - }, - }) -); +import { OrbView } from "@memgraph/orb"; + +const orb = new OrbView(container, { + getPosition: (node) => ({ x: node.data.posY, y: node.data.posX }), + zoomFitTransformMs: 1000, + render: { + shadowIsEnabled: false, + shadowOnEventIsEnabled: false, + }, +}); ``` ```typescript // If you want to see all the current view settings -const settings = orb.view.getSettings(); +const settings = orb.getSettings(); // Change the x and y axis -orb.view.setSettings({ +orb.setSettings({ getPosition: (node) => ({ x: node.data.posY, y: node.data.posX }), }); // Change the zoom fit and transform time while recentering and disable shadows -orb.view.setSettings({ +orb.setSettings({ zoomFitTransformMs: 1000, render: { shadowIsEnabled: false, @@ -340,7 +388,7 @@ Just like other Orb views, use `render` to render the view and `recenter` to fit the rendered graph. ```typescript -orb.view.render(() => { - orb.view.recenter(); +orb.render(() => { + orb.recenter(); }); ``` diff --git a/docs/view-map.md b/docs/view-map.md index 721962d..6383447 100644 --- a/docs/view-map.md +++ b/docs/view-map.md @@ -1,6 +1,6 @@ # Orb views: Map view -By default, Orb offers a `MapView` which is a graph view with a map as a background. Map rendering is +By default, Orb offers a `OrbMapView` which is a graph view with a map as a background. Map rendering is done with a library [leaflet](https://leafletjs.com/). To render maps, make sure to add the following CSS to your project: @@ -11,12 +11,13 @@ following CSS to your project: /> ``` -Here is a simple example of `MapView` usage: +Here is a simple example of `OrbMapView` usage: ![](./assets/view-map-example.png) ```typescript -import { MapView } from "@memgraph/orb"; +import { OrbMapView } from "@memgraph/orb"; + const container = document.getElementById(""); const nodes: MyNode[] = [ @@ -30,13 +31,9 @@ const edges: MyEdge[] = [ { id: 2, start: "hamilton", end: "miami" }, ]; -const orb = new Orb(container); -orb.setView( - (context) => - new MapView(context, { - getGeoPosition: (node) => ({ lat: node.data.lat, lng: node.data.lng }), - }) -); +const orb = new OrbMapView(container, { + getGeoPosition: (node) => ({ lat: node.data.lat, lng: node.data.lng }), +}); // Assign a default style orb.data.setDefaultStyle({ @@ -63,61 +60,58 @@ orb.data.setDefaultStyle({ orb.data.setup({ nodes, edges }); // Render and recenter the view -orb.view.render(() => { - orb.view.recenter(); +orb.render(() => { + orb.recenter(); }); ``` ## Initialization -On `MapView` initialization, you must provide an implementation for `getGeoPosition` which is used +On `OrbMapView` initialization, you must provide an implementation for `getGeoPosition` which is used to get `latitude` and `longitude` for each node. Here is the example of settings (required and optional) -initialized on the new `MapView`: +initialized on the new `OrbMapView`: ```typescript import * as L from "leaflet"; -import { MapView } from "@memgraph/orb"; +import { OrbMapView } from "@memgraph/orb"; const mapAttribution = 'Leaflet | ' + 'Map data © OpenStreetMap contributors'; -orb.setView( - (context) => - new MapView(context, { - getGeoPosition: (node) => ({ - lat: node.data.latitude, - lng: node.data.longitude, - }), - map: { - zoomLevel: 5, - tile: { - instance: new L.TileLayer( - "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" - ), - attribution: mapAttribution, - }, - render: { - labelsIsEnabled: true, - labelsOnEventIsEnabled: true, - shadowIsEnabled: true, - shadowOnEventIsEnabled: true, - contextAlphaOnEvent: 0.3, - contextAlphaOnEventIsEnabled: true, - }, - }, - areCollapsedContainerDimensionsAllowed: false; - }) -); +const orb = new OrbMapView(container, { + getGeoPosition: (node) => ({ + lat: node.data.latitude, + lng: node.data.longitude, + }), + map: { + zoomLevel: 5, + tile: { + instance: new L.TileLayer( + "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" + ), + attribution: mapAttribution, + }, + }, + render: { + labelsIsEnabled: true, + labelsOnEventIsEnabled: true, + shadowIsEnabled: true, + shadowOnEventIsEnabled: true, + contextAlphaOnEvent: 0.3, + contextAlphaOnEventIsEnabled: true, + }, + areCollapsedContainerDimensionsAllowed: false, +}); ``` -You can set settings on view initialization or afterward with `orb.view.setSettings`. Below +You can set settings on view initialization or afterward with `orb.setSettings`. Below you can see the list of all settings' parameters: ```typescript import * as L from "leaflet"; -interface IMapViewSettings { +interface IOrbMapViewSettings { // For map node positions getGeoPosition(node: INode): { lat: number; lng: number } | undefined; // For canvas rendering and events @@ -133,6 +127,11 @@ interface IMapViewSettings { contextAlphaOnEvent: number; contextAlphaOnEventIsEnabled: boolean; }; + // For select and hover look-and-feel + strategy: { + isDefaultSelectEnabled: boolean; + isDefaultHoverEnabled: boolean; + }; // Other map view parameters map: { zoomLevel: number; @@ -142,7 +141,7 @@ interface IMapViewSettings { } ``` -The default settings that `MapView` uses is: +The default settings that `OrbMapView` uses is: ```typescript const defaultSettings = { @@ -158,6 +157,10 @@ const defaultSettings = { contextAlphaOnEvent: 0.3, contextAlphaOnEventIsEnabled: true, }, + strategy: { + isDefaultSelectEnabled: true, + isDefaultHoverEnabled: true, + }, map: { zoomLevel: 2, // Default map zoom level tile: new L.TileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"), // OpenStreetMaps @@ -186,6 +189,58 @@ Optional property `map` has two properties that you can set which are: Optional property `render` has several rendering options that you can tweak. Read more about them on [Styling guide](./styles.md). +### Property `strategy` + +The optional property `strategy` has two properties that you can enable/disable: + +* `isDefaultSelectEnabled` - when `true`, the default selection strategy is used on mouse click: + * If there is a node at the mouse click point, the node, its edges, and adjacent nodes will change + its state to `GraphObjectState.SELECTED`. Style properties that end with `...Selected` will be + applied to all the selected objects (e.g. `borderColorSelected`). + * If there is an edge at the mouse click point, the edge and its starting and ending nodes will change + its state to `GraphObjectState.SELECTED`. +* `isDefaultHoverEnabled` - when `true`, the default hover strategy is used on mouse move: + * If there is a node at the mouse pointer, the node, its edges, and adjacent nodes will change its state to + `GraphObjectState.HOVERED`. Style properties that end with `...Hovered` will be applied to all the + hovered objects (e.g. `borderColorHovered`). + +With property `strategy` you can disable the above behavior and implement your select/hover strategy on +top of events `OrbEventType.MOUSE_CLICK` and `OrbEventType.MOUSE_MOVE`, e.g: + +```typescript +import { isNode, OrbEventType, GraphObjectState } from '@memgraph/orb'; + +// Disable default select and hover strategy +orb.setSettings({ + strategy: { + isDefaultSelectEnabled: false, + isDefaultHoverEnabled: false, + }, +}); + +// Create custom select strategy which selects just clicked node +orb.events.on(OrbEventType.MOUSE_CLICK, (event) => { + // Clicked on blank canvas + if (!event.subject) { + // Deselect the previously selected nodes and render if there are changes + const selectedNodes = orb.data.getNodes((node) => node.isSelected()); + if (selectedNodes) { + selectedNodes.forEach((node) => node.clearState()); + orb.render(); + } + } + + // Clicked on unselected node + if (event.subject && isNode(event.subject) && !event.subject.isSelected()) { + // Deselect the previously selected nodes + orb.data.getNodes((node) => node.isSelected()).forEach((node) => node.clearState()); + // Select the new node + event.subject.state = GraphObjectState.SELECTED; + orb.render(); + } +}); +``` + ### Property `areCollapsedContainerDimensionsAllowed` Enables setting the dimensions of the Orb container element to zero. @@ -197,20 +252,20 @@ Disabled by default (`false`). ## Settings -The above settings of `MapView` can be defined on view initialization, but also anytime after the +The above settings of `OrbMapView` can be defined on view initialization, but also anytime after the initialization with a view function `setSettings`: ```typescript // If you want to see all the current view settings -const settings = orb.view.getSettings(); +const settings = orb.getSettings(); // Change the way how geo coordinates are defined on nodes -orb.view.setSettings({ +orb.setSettings({ getGeoPosition: (node) => ({ lat: node.data.lat, lng: node.data.lng }), }); // Change the zoom level and disable shadows -orb.view.setSettings({ +orb.setSettings({ map: { zoomLevel: 7, }, @@ -227,8 +282,8 @@ Just like other Orb views, use `render` to render the view and `recenter` to fit the rendered graph. ```typescript -orb.view.render(() => { - orb.view.recenter(); +orb.render(() => { + orb.recenter(); }); ``` @@ -238,8 +293,8 @@ If you need a reference to the internal map reference from `leaflet` library, ju following example: ```typescript -import { MapView } from "@memgraph/orb"; +import { OrbMapView } from "@memgraph/orb"; -// It will only work on MapView -const leaflet = (orb.view as MapView).leaflet; +// It will only work on OrbMapView +const leaflet = (orb.view as OrbMapView).leaflet; ``` diff --git a/examples/example-custom-styled-graph.html b/examples/example-custom-styled-graph.html index d7678d0..8e4c8c3 100644 --- a/examples/example-custom-styled-graph.html +++ b/examples/example-custom-styled-graph.html @@ -42,7 +42,7 @@

Example 2 - Basic + Custom default style

{ id: 5, start: 0, end: 1, label: 'A -> B' }, ] - const orb = new Orb.Orb(container); + const orb = new Orb.OrbView(container); // Assign a basic style orb.data.setDefaultStyle({ @@ -87,8 +87,8 @@

Example 2 - Basic + Custom default style

// Initialize nodes and edges orb.data.setup({ nodes, edges }); - orb.view.render(() => { - orb.view.recenter(); + orb.render(() => { + orb.recenter(); }); diff --git a/examples/example-fixed-coordinates-graph.html b/examples/example-fixed-coordinates-graph.html index 0819d27..55998c7 100644 --- a/examples/example-fixed-coordinates-graph.html +++ b/examples/example-fixed-coordinates-graph.html @@ -42,10 +42,9 @@

Example 3 - Fixed coordinates

{ id: 5, start: 0, end: 1, label: 'A -> B' }, ]; - const orb = new Orb.Orb(container); - orb.setView((context) => new Orb.DefaultView(context, { + const orb = new Orb.OrbView(container, { getPosition: (node) => ({ x: node.data.x, y: node.data.y }) - })) + }); // Initialize nodes and edges orb.data.setup({ nodes, edges }); @@ -78,8 +77,8 @@

Example 3 - Fixed coordinates

}, }); - orb.view.render(() => { - orb.view.recenter(); + orb.render(() => { + orb.recenter(); }); diff --git a/examples/example-graph-data-changes.html b/examples/example-graph-data-changes.html index a80d95b..6537bbd 100644 --- a/examples/example-graph-data-changes.html +++ b/examples/example-graph-data-changes.html @@ -46,7 +46,7 @@

Example 5 - Dynamics

}; } - const orb = new Orb.Orb(container); + const orb = new Orb.OrbView(container); orb.data.setDefaultStyle({ getNodeStyle(node) { @@ -106,7 +106,7 @@

Example 5 - Dynamics

n += 1; orb.data.merge(graphUpdates); - orb.view.render(); + orb.render(); randomlyExpandGraph(); }, 3000); }; @@ -116,12 +116,12 @@

Example 5 - Dynamics

orb.events.on(Orb.OrbEventType.NODE_CLICK, (event) => { console.log('Node clicked: ', event.node); orb.data.remove({ nodeIds: [event.node.id] }); - orb.view.render(); + orb.render(); }); // Render and recenter the view - orb.view.render(() => { - orb.view.recenter(); + orb.render(() => { + orb.recenter(); }); diff --git a/examples/example-graph-events.html b/examples/example-graph-events.html index bf40ae0..0a0d2d9 100644 --- a/examples/example-graph-events.html +++ b/examples/example-graph-events.html @@ -53,7 +53,7 @@

Example 4 - Events

}; } - const orb = new Orb.Orb(container); + const orb = new Orb.OrbView(container); // Assign a basic style orb.data.setDefaultStyle({ @@ -87,8 +87,8 @@

Example 4 - Events

orb.data.setup({ nodes, edges }); // Render and recenter the view - orb.view.render(() => { - orb.view.recenter(() => { + orb.render(() => { + orb.recenter(() => { output.innerHTML = '< Click on any of the nodes or edges >'; }); }); diff --git a/examples/example-graph-on-map.html b/examples/example-graph-on-map.html index 0e45ddb..db11d4d 100644 --- a/examples/example-graph-on-map.html +++ b/examples/example-graph-on-map.html @@ -44,10 +44,9 @@

Example 6 - Map

{ id: 5, start: 0, end: 1 }, ]; - const orb = new Orb.Orb(container); - orb.setView((context) => new Orb.MapView(context, { + const orb = new Orb.OrbMapView(container, { getGeoPosition: (node) => ({ lat: node.data.lat, lng: node.data.lng, }), - })); + }); // Assign a basic style orb.data.setDefaultStyle({ @@ -81,8 +80,8 @@

Example 6 - Map

orb.data.setup({ nodes, edges }); // Render and recenter the view - orb.view.render(() => { - orb.view.recenter(); + orb.render(() => { + orb.recenter(); }); diff --git a/examples/example-simple-graph.html b/examples/example-simple-graph.html index 6607610..b1cf701 100644 --- a/examples/example-simple-graph.html +++ b/examples/example-simple-graph.html @@ -40,13 +40,13 @@

Example 1 - Basic

{ id: 5, start: 0, end: 1, label: 'A -> B' }, ]; - const orb = new Orb.Orb(container); + const orb = new Orb.OrbView(container); // Initialize nodes and edges orb.data.setup({ nodes, edges }); - orb.view.render(() => { - orb.view.recenter(); + orb.render(() => { + orb.recenter(); }); diff --git a/examples/playground.html b/examples/playground.html index 1905d4b..9bb17b5 100644 --- a/examples/playground.html +++ b/examples/playground.html @@ -31,63 +31,84 @@ { id: 15, start: 0, end: 1, label: 'Edge V', properties: { test: 3 } }, ]; - const orb = new Orb.Orb(container); - orb.setView((context) => new Orb.MapView(context, { - getGeoPosition: (node) => ({ lat: node.data.lat, lng: node.data.lng, }), - })); + const getDefaultStyle = () => { + return { + getNodeStyle(node) { + return { + borderColor: '#1d1d1d', + borderWidth: 0.6, + color: '#DD2222', + colorHover: '#e7644e', + colorSelected: '#e7644e', + fontSize: 3, + label: node.data.labels[0], + size: 6, + }; + }, + getEdgeStyle(edge) { + return { + color: '#999999', + colorHover: '#1d1d1d', + colorSelected: '#1d1d1d', + fontSize: 3, + width: 0.3, + widthHover: 0.9, + widthSelected: 0.9, + label: edge.data.label, + }; + }, + }; + }; - // Initialize nodes and edges - orb.data.setup({ nodes, edges }); + const getOrbMapView = (container) => { + const view = new Orb.OrbMapView(container, { + getGeoPosition: (node) => ({ lat: node.data.lat, lng: node.data.lng, }), + }); - // Assign a basic style - orb.data.setStyle({ - getNodeStyle(node) { - return { - borderColor: '#1d1d1d', - borderWidth: 0.6, - color: '#DD2222', - colorHover: '#e7644e', - colorSelected: '#e7644e', - fontSize: 3, - label: node.data.labels[0], - size: 6, - }; - }, - getEdgeStyle(edge) { - return { - color: '#999999', - colorHover: '#1d1d1d', - colorSelected: '#1d1d1d', - fontSize: 3, - width: 0.3, - widthHover: 0.9, - widthSelected: 0.9, - label: edge.data.label, - }; - }, - }); + // Assign a basic style + view.data.setDefaultStyle(getDefaultStyle()); + + // Initialize nodes and edges + view.data.setup({ nodes, edges }); + return view; + } + + const getOrbView = (container) => { + const view = new Orb.OrbView(container); + + // Assign a basic style + view.data.setDefaultStyle(getDefaultStyle()); + + // Initialize nodes and edges + view.data.setup({ nodes, edges }); + return view; + } + + const orb1 = getOrbMapView(container); // Render and recenter the view - orb.view.render(() => { - orb.view.recenter(); + orb1.render(() => { + orb1.recenter(); }); setTimeout(() => { - orb.setView((context) => new Orb.DefaultView(context)); - orb.view.render(() => { + orb1.destroy(); + const orb2 = getOrbView(container); + + orb2.render(() => { setTimeout(() => { - orb.data.clearPositions(); - orb.view.render(() => { - orb.view.recenter(); + orb2.data.clearPositions(); + orb2.render(() => { + orb2.recenter(); }); setTimeout(() => { - orb.setView((context) => new Orb.MapView(context, { - getGeoPosition: (node) => ({ lat: node.data.lat, lng: node.data.lng, }), - })); - orb.view.render(() => { - orb.view.recenter(); + orb2.destroy(); + + const orb3 = getOrbMapView(container); + orb3.render(() => { + orb3.recenter(); }); }, 2000); }, 2000); diff --git a/examples/simulator-scenarios.html b/examples/simulator-scenarios.html index dbbacee..81ba062 100644 --- a/examples/simulator-scenarios.html +++ b/examples/simulator-scenarios.html @@ -159,13 +159,9 @@

Simulator Scenarios

const initialSetup = (graphContainerId, nodes, edges, callback) => { const container = document.getElementById(graphContainerId); - const orb = new Orb.Orb(container); - orb.setView((context) => new Orb.DefaultView(context, { + const orb = new Orb.OrbView(container, { getPosition: (node) => ({ x: node.data.x, y: node.data.y }) - })) - - // Initialize nodes and edges - orb.data.setup({ nodes, edges }); + }); // Assign a basic style orb.data.setDefaultStyle({ @@ -199,10 +195,13 @@

Simulator Scenarios

}, }); + // Initialize nodes and edges + orb.data.setup({ nodes, edges }); + // Render and recenter the view - orb.view.render(() => { + orb.render(() => { setTimeout(() => { - orb.view.recenter(); + orb.recenter(); }, 1000); if (callback) { callback(orb); @@ -221,12 +220,12 @@

Simulator Scenarios

const globalPhysicsCheckbox = document.getElementById('globalPhysicsCheckbox'); globalPhysicsCheckbox.addEventListener('click', () => { - orb.view.setSettings({ simulation: { isPhysicsEnabled: globalPhysicsCheckbox.checked } }); + orb.setSettings({ simulation: { isPhysicsEnabled: globalPhysicsCheckbox.checked } }); }); const containerPhysicsCheckbox = container.getElementsByClassName('checkbox')[0]; containerPhysicsCheckbox.addEventListener('click', () => { - orb.view.setSettings({ simulation: { isPhysicsEnabled: containerPhysicsCheckbox.checked } }); + orb.setSettings({ simulation: { isPhysicsEnabled: containerPhysicsCheckbox.checked } }); }); } @@ -270,7 +269,7 @@

Simulator Scenarios

initialSetupFree('oldNodesFixedNewNodesFree1', (orb) => { setTimeout(() => { - orb.view.fixNodes(); + orb.fixNodes(); orb.data.merge({ nodes: [ { id: 4, labels: ['Node E'] }, @@ -279,9 +278,9 @@

Simulator Scenarios

{ id: 14, start: 0, end: 4, label: 'Edge R' } ] }); - orb.view.render(() => { + orb.render(() => { setTimeout(() => { - orb.view.recenter(); + orb.recenter(); }, 1000); }); }, 2000); @@ -297,9 +296,9 @@

Simulator Scenarios

{ id: 14, start: 0, end: 4, label: 'Edge R' } ] }); - orb.view.render(() => { + orb.render(() => { setTimeout(() => { - orb.view.recenter(); + orb.recenter(); }, 1000); }); }, 2000); @@ -315,9 +314,9 @@

Simulator Scenarios

{ id: 14, start: 0, end: 4, label: 'Edge R' } ] }); - orb.view.render(() => { + orb.render(() => { setTimeout(() => { - orb.view.recenter(); + orb.recenter(); }, 1000); }); }, 2000); @@ -333,9 +332,9 @@

Simulator Scenarios

{ id: 14, start: 0, end: 4, label: 'Edge R' } ] }); - orb.view.render(() => { + orb.render(() => { setTimeout(() => { - orb.view.recenter(); + orb.recenter(); }, 1000); }); }, 2000); @@ -351,9 +350,9 @@

Simulator Scenarios

{ id: 14, start: 0, end: 4, label: 'Edge R' } ] }); - orb.view.render(() => { + orb.render(() => { setTimeout(() => { - orb.view.recenter(); + orb.recenter(); }, 1000); }); }, 2000); @@ -361,7 +360,7 @@

Simulator Scenarios

initialSetupFixed('oldNodesFreeNewNodesFixed2', (orb) => { setTimeout(() => { - orb.view.releaseNodes(); + orb.releaseNodes(); orb.data.merge({ nodes: [ { id: 4, labels: ['Node E'], x: -100, y: -50 }, @@ -372,9 +371,9 @@

Simulator Scenarios

{ id: 15, start: 0, end: 5, label: 'Edge T' } ] }); - orb.view.render(() => { + orb.render(() => { setTimeout(() => { - orb.view.recenter(); + orb.recenter(); }, 1000); }); }, 2000); diff --git a/src/events.ts b/src/events.ts index 4240f7d..5d1b1ef 100644 --- a/src/events.ts +++ b/src/events.ts @@ -26,61 +26,94 @@ export enum OrbEventType { NODE_DRAG_END = 'node-drag-end', } -export interface IOrbEventDuration { +interface IOrbEventDuration { durationMs: number; } -export interface IOrbEventProgress { +interface IOrbEventProgress { progress: number; } -export interface IOrbEventTransform { - transform: { - x: number; - y: number; - k: number; - }; -} - interface IOrbEventMousePosition { localPoint: IPosition; globalPoint: IPosition; } -export interface IOrbEventMouseClickEvent extends IOrbEventMousePosition { +interface IOrbEventMouseClickEvent extends IOrbEventMousePosition { event: PointerEvent; } -export interface IOrbEventMouseMoveEvent extends IOrbEventMousePosition { +interface IOrbEventMouseMoveEvent extends IOrbEventMousePosition { event: MouseEvent; } -export interface IOrbEventMouseEvent extends IOrbEventMousePosition { +interface IOrbEventMouseEvent extends IOrbEventMousePosition { subject?: INode | IEdge; } -export interface IOrbEventMouseNodeEvent { +interface IOrbEventMouseNodeEvent { node: INode; } -export interface IOrbEventMouseEdgeEvent { +interface IOrbEventMouseEdgeEvent { edge: IEdge; } +export type IOrbEventRenderEnd = IOrbEventDuration; + +export type IOrbEventSimulationStep = IOrbEventProgress; + +export type IOrbEventSimulationEnd = IOrbEventDuration; + +export type IOrbEventNodeClick = IOrbEventMouseNodeEvent & + IOrbEventMouseClickEvent; + +export type IOrbEventNodeHover = IOrbEventMouseNodeEvent & + IOrbEventMouseMoveEvent; + +export type IOrbEventEdgeClick = IOrbEventMouseEdgeEvent & + IOrbEventMouseClickEvent; + +export type IOrbEventEdgeHover = IOrbEventMouseEdgeEvent & + IOrbEventMouseMoveEvent; + +export type IOrbEventMouseClick = IOrbEventMouseEvent & + IOrbEventMouseClickEvent; + +export type IOrbEventMouseMove = IOrbEventMouseEvent & + IOrbEventMouseMoveEvent; + +export interface IOrbEventTransform { + transform: { + x: number; + y: number; + k: number; + }; +} + +export type IOrbEventNodeDragStart = IOrbEventMouseNodeEvent & + IOrbEventMouseMoveEvent; + +export type IOrbEventNodeDrag = IOrbEventMouseNodeEvent & + IOrbEventMouseMoveEvent; + +export type IOrbEventNodeDragEnd = IOrbEventMouseNodeEvent & + IOrbEventMouseMoveEvent; + export class OrbEmitter extends Emitter<{ [OrbEventType.RENDER_START]: undefined; - [OrbEventType.RENDER_END]: IOrbEventDuration; + [OrbEventType.RENDER_END]: IOrbEventRenderEnd; [OrbEventType.SIMULATION_START]: undefined; - [OrbEventType.SIMULATION_STEP]: IOrbEventProgress; - [OrbEventType.SIMULATION_END]: IOrbEventDuration; - [OrbEventType.NODE_CLICK]: IOrbEventMouseNodeEvent & IOrbEventMouseClickEvent; - [OrbEventType.NODE_HOVER]: IOrbEventMouseNodeEvent & IOrbEventMouseMoveEvent; - [OrbEventType.EDGE_CLICK]: IOrbEventMouseEdgeEvent & IOrbEventMouseClickEvent; - [OrbEventType.EDGE_HOVER]: IOrbEventMouseEdgeEvent & IOrbEventMouseMoveEvent; - [OrbEventType.MOUSE_CLICK]: IOrbEventMouseEvent & IOrbEventMouseClickEvent; - [OrbEventType.MOUSE_MOVE]: IOrbEventMouseEvent & IOrbEventMouseMoveEvent; + [OrbEventType.SIMULATION_STEP]: IOrbEventSimulationStep; + [OrbEventType.SIMULATION_END]: IOrbEventSimulationEnd; + [OrbEventType.NODE_CLICK]: IOrbEventNodeClick; + [OrbEventType.NODE_HOVER]: IOrbEventNodeHover; + [OrbEventType.EDGE_CLICK]: IOrbEventEdgeClick; + [OrbEventType.EDGE_HOVER]: IOrbEventEdgeHover; + [OrbEventType.MOUSE_CLICK]: IOrbEventMouseClick; + [OrbEventType.MOUSE_MOVE]: IOrbEventMouseMove; [OrbEventType.TRANSFORM]: IOrbEventTransform; - [OrbEventType.NODE_DRAG_START]: IOrbEventMouseNodeEvent & IOrbEventMouseMoveEvent; - [OrbEventType.NODE_DRAG]: IOrbEventMouseNodeEvent & IOrbEventMouseMoveEvent; - [OrbEventType.NODE_DRAG_END]: IOrbEventMouseNodeEvent & IOrbEventMouseMoveEvent; + [OrbEventType.NODE_DRAG_START]: IOrbEventNodeDragStart; + [OrbEventType.NODE_DRAG]: IOrbEventNodeDrag; + [OrbEventType.NODE_DRAG_END]: IOrbEventNodeDragEnd; }> {} diff --git a/src/index.ts b/src/index.ts index 30e61bf..b81444b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,18 +1,24 @@ -export { Orb, IOrbSettings } from './orb'; -export { OrbEventType } from './events'; -export { OrbError } from './exceptions'; export { - DefaultView, - MapView, - IOrbView, - IOrbViewContext, - IOrbViewFactory, - IMapViewSettings, - IDefaultViewSettings, -} from './views'; + OrbEventType, + IOrbEventRenderEnd, + IOrbEventSimulationStep, + IOrbEventSimulationEnd, + IOrbEventNodeClick, + IOrbEventNodeHover, + IOrbEventEdgeClick, + IOrbEventEdgeHover, + IOrbEventMouseClick, + IOrbEventMouseMove, + IOrbEventTransform, + IOrbEventNodeDragStart, + IOrbEventNodeDrag, + IOrbEventNodeDragEnd, +} from './events'; +export { OrbError } from './exceptions'; export { IGraph, IGraphData, INodeFilter, IEdgeFilter } from './models/graph'; export { GraphObjectState } from './models/state'; export { INode, INodeBase, INodePosition, INodeStyle, isNode, NodeShapeType } from './models/node'; export { IEdge, IEdgeBase, IEdgePosition, IEdgeStyle, isEdge, EdgeType } from './models/edge'; export { IGraphStyle, getDefaultGraphStyle } from './models/style'; export { ICircle, IPosition, IRectangle, Color, IColorRGB } from './common'; +export { OrbView, OrbMapView, IOrbView, IOrbMapViewSettings, IOrbViewSettings } from './views'; diff --git a/src/models/strategy.ts b/src/models/strategy.ts index dbd951f..c24f58a 100644 --- a/src/models/strategy.ts +++ b/src/models/strategy.ts @@ -4,27 +4,39 @@ import { IGraph } from './graph'; import { IPosition } from '../common'; import { GraphObjectState } from './state'; +export interface IEventStrategySettings { + isDefaultSelectEnabled: boolean; + isDefaultHoverEnabled: boolean; +} + export interface IEventStrategyResponse { isStateChanged: boolean; changedSubject?: INode | IEdge; } export interface IEventStrategy { - onMouseClick: ((graph: IGraph, point: IPosition) => IEventStrategyResponse) | null; - onMouseMove: ((graph: IGraph, point: IPosition) => IEventStrategyResponse) | null; + isSelectEnabled: boolean; + isHoverEnabled: boolean; + onMouseClick: (graph: IGraph, point: IPosition) => IEventStrategyResponse; + onMouseMove: (graph: IGraph, point: IPosition) => IEventStrategyResponse; } -export const getDefaultEventStrategy = (): IEventStrategy => { - return new DefaultEventStrategy(); -}; +export class DefaultEventStrategy implements IEventStrategy { + private _lastHoveredNode?: INode; + public isSelectEnabled: boolean; + public isHoverEnabled: boolean; -class DefaultEventStrategy implements IEventStrategy { - lastHoveredNode?: INode; + constructor(settings: IEventStrategySettings) { + this.isSelectEnabled = settings.isDefaultSelectEnabled; + this.isHoverEnabled = settings.isDefaultHoverEnabled; + } onMouseClick(graph: IGraph, point: IPosition): IEventStrategyResponse { const node = graph.getNearestNode(point); if (node) { - selectNode(graph, node); + if (this.isSelectEnabled) { + selectNode(graph, node); + } return { isStateChanged: true, changedSubject: node, @@ -33,13 +45,19 @@ class DefaultEventStrategy implements const edge = graph.getNearestEdge(point); if (edge) { - selectEdge(graph, edge); + if (this.isSelectEnabled) { + selectEdge(graph, edge); + } return { isStateChanged: true, changedSubject: edge, }; } + if (!this.isSelectEnabled) { + return { isStateChanged: false }; + } + const { changedCount } = unselectAll(graph); return { isStateChanged: changedCount > 0, @@ -48,24 +66,27 @@ class DefaultEventStrategy implements onMouseMove(graph: IGraph, point: IPosition): IEventStrategyResponse { const node = graph.getNearestNode(point); - if (node && !node.isSelected()) { - if (node === this.lastHoveredNode) { + if (node && (!this.isSelectEnabled || (this.isSelectEnabled && !node.isSelected()))) { + if (node === this._lastHoveredNode) { return { changedSubject: node, isStateChanged: false, }; } - hoverNode(graph, node); - this.lastHoveredNode = node; + if (this.isHoverEnabled) { + hoverNode(graph, node); + } + + this._lastHoveredNode = node; return { isStateChanged: true, changedSubject: node, }; } - this.lastHoveredNode = undefined; - if (!node) { + this._lastHoveredNode = undefined; + if (!node && this.isHoverEnabled) { const { changedCount } = unhoverAll(graph); return { isStateChanged: changedCount > 0, diff --git a/src/orb.ts b/src/orb.ts deleted file mode 100644 index 5b8cb29..0000000 --- a/src/orb.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { Graph, IGraph } from './models/graph'; -import { INodeBase } from './models/node'; -import { IEdgeBase } from './models/edge'; -import { DefaultView, IOrbViewFactory, IOrbView, IOrbViewContext } from './views'; -import { getDefaultEventStrategy, IEventStrategy } from './models/strategy'; -import { OrbEmitter } from './events'; -import { getDefaultGraphStyle } from './models/style'; - -export interface IOrbSettings { - view: IOrbViewFactory; - strategy: IEventStrategy; -} - -// TODO: Change the Orb API to be a single view instance to support non-any -// @see: https://stackoverflow.com/questions/73429628/how-to-setup-typescript-generics-in-class-constructors-and-functions -export class Orb { - private _view: IOrbView; - private readonly _events: OrbEmitter; - private readonly _graph: IGraph; - private readonly _context: IOrbViewContext; - - constructor(private container: HTMLElement, settings?: Partial>) { - this._events = new OrbEmitter(); - this._graph = new Graph(undefined, { - onLoadedImages: () => { - // Not to call render() before user's .render() - if (this._view.isInitiallyRendered()) { - this._view.render(); - } - }, - }); - this._graph.setDefaultStyle(getDefaultGraphStyle()); - - this._context = { - container: this.container, - graph: this._graph, - events: this._events, - strategy: settings?.strategy ?? getDefaultEventStrategy(), - }; - - if (settings?.view) { - this._view = settings.view(this._context); - } else { - this._view = new DefaultView(this._context); - } - } - - get data(): IGraph { - return this._graph; - } - - get view(): IOrbView { - return this._view; - } - - get events(): OrbEmitter { - return this._events; - } - - setView(factory: IOrbViewFactory) { - // Reset the existing graph in case of switching between different view types. - if (this._graph.getNodeCount() > 0) { - this._graph.clearPositions(); - } - - if (this._view) { - this._view.destroy(); - } - this._view = factory(this._context); - } -} diff --git a/src/views/index.ts b/src/views/index.ts index 146209d..cefda53 100644 --- a/src/views/index.ts +++ b/src/views/index.ts @@ -1,3 +1,3 @@ -export { DefaultView, IDefaultViewSettings } from './default-view'; -export { MapView, IMapViewSettings } from './map-view'; -export { IOrbView, IOrbViewFactory, IOrbViewContext } from './shared'; +export { OrbView, IOrbViewSettings } from './orb-view'; +export { OrbMapView, IOrbMapViewSettings } from './orb-map-view'; +export { IOrbView } from './shared'; diff --git a/src/views/map-view.ts b/src/views/orb-map-view.ts similarity index 65% rename from src/views/map-view.ts rename to src/views/orb-map-view.ts index 24a6269..2838ba5 100644 --- a/src/views/map-view.ts +++ b/src/views/orb-map-view.ts @@ -1,15 +1,17 @@ import * as L from 'leaflet'; import { IEdgeBase, isEdge } from '../models/edge'; import { INode, INodeBase, isNode } from '../models/node'; -import { IGraph } from '../models/graph'; -import { IOrbView, IOrbViewContext } from './shared'; +import { Graph, IGraph } from '../models/graph'; +import { IOrbView } from './shared'; import { IPosition } from '../common'; -import { IEventStrategy } from '../models/strategy'; +import { DefaultEventStrategy, IEventStrategy, IEventStrategySettings } from '../models/strategy'; import { copyObject } from '../utils/object.utils'; import { OrbEmitter, OrbEventType } from '../events'; import { IRenderer, RendererType, RenderEventType, IRendererSettingsInit, IRendererSettings } from '../renderer/shared'; import { RendererFactory } from '../renderer/factory'; import { setupContainer } from '../utils/html.utils'; +import { getDefaultGraphStyle } from '../models/style'; +import { isBoolean } from '../utils/type.utils'; export interface ILeafletMapTile { instance: L.TileLayer; @@ -44,28 +46,32 @@ export interface IMapSettings { tile: ILeafletMapTile; } -export interface IMapViewSettings { +export interface IOrbMapViewSettings { getGeoPosition(node: INode): { lat: number; lng: number } | undefined; map: IMapSettings; render: Partial; + strategy: Partial; areCollapsedContainerDimensionsAllowed: boolean; } -export interface IMapViewSettingsInit { +export interface IOrbMapViewSettingsInit { getGeoPosition(node: INode): { lat: number; lng: number } | undefined; map?: Partial; render?: Partial; + strategy?: Partial; } -export type IMapViewSettingsUpdate = Partial>; +export type IOrbMapViewSettingsUpdate = Partial< + IOrbMapViewSettingsInit +>; -export class MapView implements IOrbView> { +export class OrbMapView implements IOrbView> { private _container: HTMLElement; private _graph: IGraph; private _events: OrbEmitter; private _strategy: IEventStrategy; - private _settings: IMapViewSettings; + private _settings: IOrbMapViewSettings; private _canvas: HTMLCanvasElement; private _map: HTMLDivElement; @@ -73,11 +79,18 @@ export class MapView implements IOrbVi private readonly _renderer: IRenderer; private readonly _leaflet: L.Map; - constructor(context: IOrbViewContext, settings: IMapViewSettingsInit) { - this._container = context.container; - this._graph = context.graph; - this._events = context.events; - this._strategy = context.strategy; + constructor(container: HTMLElement, settings: IOrbMapViewSettingsInit) { + this._container = container; + this._graph = new Graph(undefined, { + onLoadedImages: () => { + // Not to call render() before user's .render() + if (this._renderer.isInitiallyRendered) { + this.render(); + } + }, + }); + this._graph.setDefaultStyle(getDefaultGraphStyle()); + this._events = new OrbEmitter(); this._settings = { areCollapsedContainerDimensionsAllowed: false, @@ -90,8 +103,18 @@ export class MapView implements IOrbVi type: RendererType.CANVAS, ...settings.render, }, + strategy: { + isDefaultHoverEnabled: true, + isDefaultSelectEnabled: true, + ...settings?.strategy, + }, }; + this._strategy = new DefaultEventStrategy({ + isDefaultSelectEnabled: this._settings.strategy.isDefaultSelectEnabled ?? false, + isDefaultHoverEnabled: this._settings.strategy.isDefaultHoverEnabled ?? false, + }); + setupContainer(this._container); this._canvas = this._initCanvas(); this._map = this._initMap(); @@ -117,19 +140,23 @@ export class MapView implements IOrbVi this._handleTileChange(); } - get leaflet(): L.Map { - return this._leaflet; + get data(): IGraph { + return this._graph; + } + + get events(): OrbEmitter { + return this._events; } - isInitiallyRendered(): boolean { - return this._renderer.isInitiallyRendered; + get leaflet(): L.Map { + return this._leaflet; } - getSettings(): IMapViewSettings { + getSettings(): IOrbMapViewSettings { return copyObject(this._settings); } - setSettings(settings: IMapViewSettingsUpdate) { + setSettings(settings: IOrbMapViewSettingsUpdate) { if (settings.getGeoPosition) { this._settings.getGeoPosition = settings.getGeoPosition; this._updateGraphPositions(); @@ -151,6 +178,18 @@ export class MapView implements IOrbVi this._renderer.setSettings(settings.render); this._settings.render = this._renderer.getSettings(); } + + if (settings.strategy) { + if (isBoolean(settings.strategy.isDefaultHoverEnabled)) { + this._settings.strategy.isDefaultHoverEnabled = settings.strategy.isDefaultHoverEnabled; + this._strategy.isHoverEnabled = this._settings.strategy.isDefaultHoverEnabled; + } + + if (isBoolean(settings.strategy.isDefaultSelectEnabled)) { + this._settings.strategy.isDefaultSelectEnabled = settings.strategy.isDefaultSelectEnabled; + this._strategy.isSelectEnabled = this._settings.strategy.isDefaultSelectEnabled; + } + } } render(onRendered?: () => void) { @@ -216,39 +255,37 @@ export class MapView implements IOrbVi const point: IPosition = { x: event.layerPoint.x, y: event.layerPoint.y }; const containerPoint: IPosition = { x: event.containerPoint.x, y: event.containerPoint.y }; - if (this._strategy.onMouseMove) { - const response = this._strategy.onMouseMove(this._graph, point); - const subject = response.changedSubject; - - if (subject && response.isStateChanged) { - if (isNode(subject)) { - this._events.emit(OrbEventType.NODE_HOVER, { - node: subject, - event: event.originalEvent, - localPoint: point, - globalPoint: containerPoint, - }); - } - if (isEdge(subject)) { - this._events.emit(OrbEventType.EDGE_HOVER, { - edge: subject, - event: event.originalEvent, - localPoint: point, - globalPoint: containerPoint, - }); - } + const response = this._strategy.onMouseMove(this._graph, point); + const subject = response.changedSubject; + + if (subject && response.isStateChanged) { + if (isNode(subject)) { + this._events.emit(OrbEventType.NODE_HOVER, { + node: subject, + event: event.originalEvent, + localPoint: point, + globalPoint: containerPoint, + }); + } + if (isEdge(subject)) { + this._events.emit(OrbEventType.EDGE_HOVER, { + edge: subject, + event: event.originalEvent, + localPoint: point, + globalPoint: containerPoint, + }); } + } - this._events.emit(OrbEventType.MOUSE_MOVE, { - subject, - event: event.originalEvent, - localPoint: point, - globalPoint: containerPoint, - }); + this._events.emit(OrbEventType.MOUSE_MOVE, { + subject, + event: event.originalEvent, + localPoint: point, + globalPoint: containerPoint, + }); - if (response.isStateChanged) { - this._renderer.render(this._graph); - } + if (response.isStateChanged) { + this._renderer.render(this._graph); } }); @@ -258,39 +295,37 @@ export class MapView implements IOrbVi const point: IPosition = { x: event.layerPoint.x, y: event.layerPoint.y }; const containerPoint: IPosition = { x: event.containerPoint.x, y: event.containerPoint.y }; - if (this._strategy.onMouseClick) { - const response = this._strategy.onMouseClick(this._graph, point); - const subject = response.changedSubject; - - if (subject) { - if (isNode(subject)) { - this._events.emit(OrbEventType.NODE_CLICK, { - node: subject, - event: event.originalEvent, - localPoint: point, - globalPoint: containerPoint, - }); - } - if (isEdge(subject)) { - this._events.emit(OrbEventType.EDGE_CLICK, { - edge: subject, - event: event.originalEvent, - localPoint: point, - globalPoint: containerPoint, - }); - } + const response = this._strategy.onMouseClick(this._graph, point); + const subject = response.changedSubject; + + if (subject) { + if (isNode(subject)) { + this._events.emit(OrbEventType.NODE_CLICK, { + node: subject, + event: event.originalEvent, + localPoint: point, + globalPoint: containerPoint, + }); + } + if (isEdge(subject)) { + this._events.emit(OrbEventType.EDGE_CLICK, { + edge: subject, + event: event.originalEvent, + localPoint: point, + globalPoint: containerPoint, + }); } + } - this._events.emit(OrbEventType.MOUSE_CLICK, { - subject, - event: event.originalEvent, - localPoint: point, - globalPoint: containerPoint, - }); + this._events.emit(OrbEventType.MOUSE_CLICK, { + subject, + event: event.originalEvent, + localPoint: point, + globalPoint: containerPoint, + }); - if (response.isStateChanged || response.changedSubject) { - this._renderer.render(this._graph); - } + if (response.isStateChanged || response.changedSubject) { + this._renderer.render(this._graph); } }); diff --git a/src/views/default-view.ts b/src/views/orb-view.ts similarity index 73% rename from src/views/default-view.ts rename to src/views/orb-view.ts index 3a7b5ca..c146a72 100644 --- a/src/views/default-view.ts +++ b/src/views/orb-view.ts @@ -8,23 +8,26 @@ import { D3ZoomEvent, zoom, ZoomBehavior } from 'd3-zoom'; import { select } from 'd3-selection'; import { IPosition, isEqualPosition } from '../common'; import { ISimulator, SimulatorFactory } from '../simulator'; -import { IGraph } from '../models/graph'; +import { Graph, IGraph } from '../models/graph'; import { INode, INodeBase, isNode } from '../models/node'; import { IEdgeBase, isEdge } from '../models/edge'; -import { IOrbView, IOrbViewContext } from './shared'; -import { IEventStrategy } from '../models/strategy'; -import { ID3SimulatorEngineSettingsUpdate } from '../simulator/engine/d3-simulator-engine'; +import { IOrbView } from './shared'; +import { DefaultEventStrategy, IEventStrategy, IEventStrategySettings } from '../models/strategy'; +import { ID3SimulatorEngineSettings } from '../simulator/engine/d3-simulator-engine'; import { copyObject } from '../utils/object.utils'; import { OrbEmitter, OrbEventType } from '../events'; import { IRenderer, RenderEventType, IRendererSettingsInit, IRendererSettings } from '../renderer/shared'; import { RendererFactory } from '../renderer/factory'; import { setupContainer } from '../utils/html.utils'; import { SimulatorEventType } from '../simulator/shared'; +import { getDefaultGraphStyle } from '../models/style'; +import { isBoolean } from '../utils/type.utils'; -export interface IDefaultViewSettings { +export interface IOrbViewSettings { getPosition?(node: INode): IPosition | undefined; - simulation: ID3SimulatorEngineSettingsUpdate; + simulation: Partial; render: Partial; + strategy: Partial; zoomFitTransitionMs: number; isOutOfBoundsDragEnabled: boolean; areCoordinatesRounded: boolean; @@ -32,17 +35,17 @@ export interface IDefaultViewSettings areCollapsedContainerDimensionsAllowed: boolean; } -export type IDefaultViewSettingsInit = Omit< - Partial>, +export type IOrbViewSettingsInit = Omit< + Partial>, 'render' > & { render?: Partial }; -export class DefaultView implements IOrbView> { +export class OrbView implements IOrbView> { private _container: HTMLElement; private _graph: IGraph; private _events: OrbEmitter; private _strategy: IEventStrategy; - private _settings: IDefaultViewSettings; + private _settings: IOrbViewSettings; private _canvas: HTMLCanvasElement; private readonly _renderer: IRenderer; @@ -54,11 +57,18 @@ export class DefaultView implements IO private _d3Zoom: ZoomBehavior; private _dragStartPosition: IPosition | undefined; - constructor(context: IOrbViewContext, settings?: Partial>) { - this._container = context.container; - this._graph = context.graph; - this._events = context.events; - this._strategy = context.strategy; + constructor(container: HTMLElement, settings?: Partial>) { + this._container = container; + this._graph = new Graph(undefined, { + onLoadedImages: () => { + // Not to call render() before user's .render() + if (this._renderer.isInitiallyRendered) { + this.render(); + } + }, + }); + this._graph.setDefaultStyle(getDefaultGraphStyle()); + this._events = new OrbEmitter(); this._settings = { getPosition: settings?.getPosition, @@ -75,8 +85,18 @@ export class DefaultView implements IO render: { ...settings?.render, }, + strategy: { + isDefaultHoverEnabled: true, + isDefaultSelectEnabled: true, + ...settings?.strategy, + }, }; + this._strategy = new DefaultEventStrategy({ + isDefaultSelectEnabled: this._settings.strategy.isDefaultSelectEnabled ?? false, + isDefaultHoverEnabled: this._settings.strategy.isDefaultHoverEnabled ?? false, + }); + setupContainer(this._container, this._settings.areCollapsedContainerDimensionsAllowed); this._canvas = this._initCanvas(); @@ -149,15 +169,19 @@ export class DefaultView implements IO this._simulator.setSettings(this._settings.simulation); } - isInitiallyRendered(): boolean { - return this._renderer.isInitiallyRendered; + get data(): IGraph { + return this._graph; + } + + get events(): OrbEmitter { + return this._events; } - getSettings(): IDefaultViewSettings { + getSettings(): IOrbViewSettings { return copyObject(this._settings); } - setSettings(settings: Partial>) { + setSettings(settings: Partial>) { if (settings.getPosition) { this._settings.getPosition = settings.getPosition; } @@ -174,6 +198,18 @@ export class DefaultView implements IO this._renderer.setSettings(settings.render); this._settings.render = this._renderer.getSettings(); } + + if (settings.strategy) { + if (isBoolean(settings.strategy.isDefaultHoverEnabled)) { + this._settings.strategy.isDefaultHoverEnabled = settings.strategy.isDefaultHoverEnabled; + this._strategy.isHoverEnabled = this._settings.strategy.isDefaultHoverEnabled; + } + + if (isBoolean(settings.strategy.isDefaultSelectEnabled)) { + this._settings.strategy.isDefaultSelectEnabled = settings.strategy.isDefaultSelectEnabled; + this._strategy.isSelectEnabled = this._settings.strategy.isDefaultSelectEnabled; + } + } } render(onRendered?: () => void) { @@ -309,39 +345,37 @@ export class DefaultView implements IO const mousePoint = this.getCanvasMousePosition(event); const simulationPoint = this._renderer.getSimulationPosition(mousePoint); - if (this._strategy.onMouseMove) { - const response = this._strategy.onMouseMove(this._graph, simulationPoint); - const subject = response.changedSubject; - - if (subject && response.isStateChanged) { - if (isNode(subject)) { - this._events.emit(OrbEventType.NODE_HOVER, { - node: subject, - event, - localPoint: simulationPoint, - globalPoint: mousePoint, - }); - } - if (isEdge(subject)) { - this._events.emit(OrbEventType.EDGE_HOVER, { - edge: subject, - event, - localPoint: simulationPoint, - globalPoint: mousePoint, - }); - } + const response = this._strategy.onMouseMove(this._graph, simulationPoint); + const subject = response.changedSubject; + + if (subject && response.isStateChanged) { + if (isNode(subject)) { + this._events.emit(OrbEventType.NODE_HOVER, { + node: subject, + event, + localPoint: simulationPoint, + globalPoint: mousePoint, + }); + } + if (isEdge(subject)) { + this._events.emit(OrbEventType.EDGE_HOVER, { + edge: subject, + event, + localPoint: simulationPoint, + globalPoint: mousePoint, + }); } + } - this._events.emit(OrbEventType.MOUSE_MOVE, { - subject, - event, - localPoint: simulationPoint, - globalPoint: mousePoint, - }); + this._events.emit(OrbEventType.MOUSE_MOVE, { + subject, + event, + localPoint: simulationPoint, + globalPoint: mousePoint, + }); - if (response.isStateChanged) { - this._renderer.render(this._graph); - } + if (response.isStateChanged) { + this._renderer.render(this._graph); } }; @@ -349,39 +383,37 @@ export class DefaultView implements IO const mousePoint = this.getCanvasMousePosition(event); const simulationPoint = this._renderer.getSimulationPosition(mousePoint); - if (this._strategy.onMouseClick) { - const response = this._strategy.onMouseClick(this._graph, simulationPoint); - const subject = response.changedSubject; - - if (subject) { - if (isNode(subject)) { - this._events.emit(OrbEventType.NODE_CLICK, { - node: subject, - event, - localPoint: simulationPoint, - globalPoint: mousePoint, - }); - } - if (isEdge(subject)) { - this._events.emit(OrbEventType.EDGE_CLICK, { - edge: subject, - event, - localPoint: simulationPoint, - globalPoint: mousePoint, - }); - } + const response = this._strategy.onMouseClick(this._graph, simulationPoint); + const subject = response.changedSubject; + + if (subject) { + if (isNode(subject)) { + this._events.emit(OrbEventType.NODE_CLICK, { + node: subject, + event, + localPoint: simulationPoint, + globalPoint: mousePoint, + }); + } + if (isEdge(subject)) { + this._events.emit(OrbEventType.EDGE_CLICK, { + edge: subject, + event, + localPoint: simulationPoint, + globalPoint: mousePoint, + }); } + } - this._events.emit(OrbEventType.MOUSE_CLICK, { - subject, - event, - localPoint: simulationPoint, - globalPoint: mousePoint, - }); + this._events.emit(OrbEventType.MOUSE_CLICK, { + subject, + event, + localPoint: simulationPoint, + globalPoint: mousePoint, + }); - if (response.isStateChanged || response.changedSubject) { - this._renderer.render(this._graph); - } + if (response.isStateChanged || response.changedSubject) { + this._renderer.render(this._graph); } }; diff --git a/src/views/shared.ts b/src/views/shared.ts index 88b771e..98c28aa 100644 --- a/src/views/shared.ts +++ b/src/views/shared.ts @@ -2,24 +2,13 @@ import { INodeBase } from '../models/node'; import { IEdgeBase } from '../models/edge'; import { IGraph } from '../models/graph'; import { OrbEmitter } from '../events'; -import { IEventStrategy } from '../models/strategy'; -export interface IOrbView { - isInitiallyRendered(): boolean; +export interface IOrbView { + data: IGraph; + events: OrbEmitter; getSettings(): S; setSettings(settings: Partial): void; render(onRendered?: () => void): void; recenter(onRendered?: () => void): void; destroy(): void; } - -export interface IOrbViewContext { - container: HTMLElement; - graph: IGraph; - events: OrbEmitter; - strategy: IEventStrategy; -} - -export type IOrbViewFactory = ( - context: IOrbViewContext, -) => IOrbView; From 2cfe2bb82c0e8c51e140dcb9e3d9adba2dba8d81 Mon Sep 17 00:00:00 2001 From: Toni Lastre Date: Tue, 4 Apr 2023 16:53:06 +0200 Subject: [PATCH 04/30] Chore: Release/1.0.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index ddae81f..69050ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@memgraph/orb", - "version": "0.1.4", + "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@memgraph/orb", - "version": "0.1.4", + "version": "1.0.0", "license": "Apache-2.0", "dependencies": { "d3-drag": "3.0.0", diff --git a/package.json b/package.json index 70928e0..38c2c04 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@memgraph/orb", - "version": "0.2.0", + "version": "1.0.0", "description": "Graph visualization library", "engines": { "node": ">=16.0.0" From 0e9ffb63871142d68219f852d1b126c415708caa Mon Sep 17 00:00:00 2001 From: Abhinv Singh Parmar Date: Fri, 9 Jun 2023 21:26:36 +0530 Subject: [PATCH 05/30] New: Add support to get selected/hovered nodes and edges (#61) * New: Added support to get selected nodes and edges * New: Added support to get hovered nodes and edges --------- Co-authored-by: Abhinav Singh Parmar --- src/models/graph.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/models/graph.ts b/src/models/graph.ts index 97e03ff..ff9c9ea 100644 --- a/src/models/graph.ts +++ b/src/models/graph.ts @@ -22,6 +22,10 @@ export interface IGraph { getEdgeCount(): number; getNodeById(id: any): INode | undefined; getEdgeById(id: any): IEdge | undefined; + getSelectedNodes(): INode[]; + getSelectedEdges(): IEdge[]; + getHoveredNodes(): INode[]; + getHoveredEdges(): IEdge[]; getNodePositions(): INodePosition[]; setNodePositions(positions: INodePosition[]): void; getEdgePositions(): IEdgePosition[]; @@ -118,6 +122,42 @@ export class Graph implements IGraph[] { + return this.getNodes((node) => node.isSelected()); + } + + /** + * Returns a list of selected edges. + * + * @return {IEdge[]} List of selected edges + */ + getSelectedEdges(): IEdge[] { + return this.getEdges((edge) => edge.isSelected()); + } + + /** + * Returns a list of hovered nodes. + * + * @return {INode[]} List of hovered nodes + */ + getHoveredNodes(): INode[] { + return this.getNodes((node) => node.isHovered()); + } + + /** + * Returns a list of hovered edges. + * + * @return {IEdge[]} List of hovered edges + */ + getHoveredEdges(): IEdge[] { + return this.getEdges((edge) => edge.isHovered()); + } + /** * Returns a list of current node positions (x, y). * From 21e18b4dadd01dbf2ee61fe391bc8f169452aa00 Mon Sep 17 00:00:00 2001 From: Abhinv Singh Parmar Date: Tue, 18 Jul 2023 21:09:01 +0530 Subject: [PATCH 06/30] New: Add support for enabling and disabling dragging of nodes (fixes #62) (#69) * New: Add feature to enable/disable node dragging (fixes #62) * New: Added support to modify interaction from setSettings * New: Updated documentation for interaction property --- docs/view-default.md | 20 ++++++++++++++++++++ src/views/orb-view.ts | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/docs/view-default.md b/docs/view-default.md index fc8f96a..e9abed0 100644 --- a/docs/view-default.md +++ b/docs/view-default.md @@ -80,6 +80,10 @@ interface IOrbViewSettings { isDefaultSelectEnabled: boolean; isDefaultHoverEnabled: boolean; }; + // For graph interaction + interaction: { + isDragEnabled: boolean; + }; // Other default view parameters zoomFitTransitionMs: number; isOutOfBoundsDragEnabled: boolean; @@ -149,6 +153,9 @@ const defaultSettings = { isDefaultSelectEnabled: true, isDefaultHoverEnabled: true, }, + interaction: { + isDragEnabled: true; + }, zoomFitTransitionMs: 200, isOutOfBoundsDragEnabled: false, areCoordinatesRounded: true, @@ -312,6 +319,19 @@ orb.events.on(OrbEventType.MOUSE_CLICK, (event) => { }); ``` +### Property `interaction` + +The optional property `interaction` has one property that you can enable/disable: + +* `isDragEnabled` - property controls the dragging behavior within the application. When it is set to `true`, dragging is enabled, allowing users to interact with nodes and edges by dragging them to different positions within the graph. On the other hand, when `isDragEnabled`` is set to false, dragging functionality is disabled, preventing users from moving or repositioning nodes and edges through dragging interactions. + +This property provides a straightforward way to enable or disable the dragging feature based on the needs and requirements of your application. By toggling the value of `isDragEnabled`, you can easily control whether users are allowed to interactively reposition elements within the graph by dragging them. e.g: + +```typescript +// Disable default drag interaction +orb.setSettings({ interaction: { isDragEnabled: false } }); +``` + ### Property `simulation` Fine-grained D3 simulation engine settings. They include `isPhysicsEnabled`, `alpha`, diff --git a/src/views/orb-view.ts b/src/views/orb-view.ts index 5d311f8..76b27d9 100644 --- a/src/views/orb-view.ts +++ b/src/views/orb-view.ts @@ -23,11 +23,16 @@ import { SimulatorEventType } from '../simulator/shared'; import { getDefaultGraphStyle } from '../models/style'; import { isBoolean } from '../utils/type.utils'; +export interface IGraphInteractionSettings { + isDragEnabled: boolean; +} + export interface IOrbViewSettings { getPosition?(node: INode): IPosition | undefined; simulation: Partial; render: Partial; strategy: Partial; + interaction: Partial; zoomFitTransitionMs: number; isOutOfBoundsDragEnabled: boolean; areCoordinatesRounded: boolean; @@ -90,6 +95,10 @@ export class OrbView implements IOrbVi isDefaultSelectEnabled: true, ...settings?.strategy, }, + interaction: { + isDragEnabled: true, + ...settings?.interaction + } }; this._strategy = new DefaultEventStrategy({ @@ -212,6 +221,16 @@ export class OrbView implements IOrbVi this._strategy.isSelectEnabled = this._settings.strategy.isDefaultSelectEnabled; } } + + // Check if interaction settings are provided + if (settings.interaction) { + // Check if isDragEnabled is a boolean value + if (isBoolean(settings.interaction.isDragEnabled)) { + // Update the internal isDragEnabled setting based on the provided value + this._settings.interaction.isDragEnabled = + settings.interaction.isDragEnabled; + } + } } render(onRendered?: () => void) { @@ -263,6 +282,11 @@ export class OrbView implements IOrbVi }; dragStarted = (event: D3DragEvent>) => { + // If drag is disabled then return + if(!this._settings.interaction.isDragEnabled) { + return; + } + const mousePoint = this.getCanvasMousePosition(event.sourceEvent); const simulationPoint = this._renderer.getSimulationPosition(mousePoint); @@ -278,6 +302,11 @@ export class OrbView implements IOrbVi }; dragged = (event: D3DragEvent>) => { + // If drag is disabled then return + if(!this._settings.interaction.isDragEnabled) { + return; + } + const mousePoint = this.getCanvasMousePosition(event.sourceEvent); const simulationPoint = this._renderer.getSimulationPosition(mousePoint); @@ -296,6 +325,11 @@ export class OrbView implements IOrbVi }; dragEnded = (event: D3DragEvent>) => { + // If drag is disabled then return + if(!this._settings.interaction.isDragEnabled) { + return; + } + const mousePoint = this.getCanvasMousePosition(event.sourceEvent); const simulationPoint = this._renderer.getSimulationPosition(mousePoint); From 985295931ae36b80a04ac12726f2e9e60f05f289 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Parmar Date: Tue, 18 Jul 2023 22:43:37 +0530 Subject: [PATCH 07/30] New: Add feature to enable/disable zoom (fixes memgraph#62) --- src/views/orb-view.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/views/orb-view.ts b/src/views/orb-view.ts index 76b27d9..f935b34 100644 --- a/src/views/orb-view.ts +++ b/src/views/orb-view.ts @@ -25,6 +25,7 @@ import { isBoolean } from '../utils/type.utils'; export interface IGraphInteractionSettings { isDragEnabled: boolean; + isZoomEnabled: boolean; } export interface IOrbViewSettings { @@ -97,6 +98,7 @@ export class OrbView implements IOrbVi }, interaction: { isDragEnabled: true, + isZoomEnabled: true, ...settings?.interaction } }; @@ -230,6 +232,13 @@ export class OrbView implements IOrbVi this._settings.interaction.isDragEnabled = settings.interaction.isDragEnabled; } + + // Check if isZoomEnabled is a boolean value + if (isBoolean(settings.interaction.isZoomEnabled)) { + // Update the internal isZoomEnabled setting based on the provided value + this._settings.interaction.isZoomEnabled = + settings.interaction.isZoomEnabled; + } } } @@ -346,6 +355,10 @@ export class OrbView implements IOrbVi }; zoomed = (event: D3ZoomEvent) => { + // If zoom is disabled then return + if(!this._settings.interaction.isZoomEnabled) { + return; + } this._renderer.transform = event.transform; setTimeout(() => { this._renderer.render(this._graph); From cceb75686ccbf067383853d4874aeef0231c8774 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Parmar Date: Tue, 18 Jul 2023 22:53:26 +0530 Subject: [PATCH 08/30] NEW: Updated documentation for interaction property --- docs/view-default.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/view-default.md b/docs/view-default.md index e9abed0..178efbb 100644 --- a/docs/view-default.md +++ b/docs/view-default.md @@ -321,15 +321,17 @@ orb.events.on(OrbEventType.MOUSE_CLICK, (event) => { ### Property `interaction` -The optional property `interaction` has one property that you can enable/disable: +The optional property `interaction` has two properties that you can enable/disable: * `isDragEnabled` - property controls the dragging behavior within the application. When it is set to `true`, dragging is enabled, allowing users to interact with nodes and edges by dragging them to different positions within the graph. On the other hand, when `isDragEnabled`` is set to false, dragging functionality is disabled, preventing users from moving or repositioning nodes and edges through dragging interactions. -This property provides a straightforward way to enable or disable the dragging feature based on the needs and requirements of your application. By toggling the value of `isDragEnabled`, you can easily control whether users are allowed to interactively reposition elements within the graph by dragging them. e.g: +* `isZoomEnabled` - This property controls the zooming behavior within the application. Setting it to `true` enables zooming, allowing users to interactively zoom in and out of the graph. Setting it to `false` disables zooming, restricting the user's ability to change the zoom level. + +These properties provide a straightforward way to enable or disable dragging and zooming features based on the needs and requirements of your application. By toggling the values of isDragEnabled and isZoomEnabled, you can easily control the interactivity options available to users. e.g: ```typescript -// Disable default drag interaction -orb.setSettings({ interaction: { isDragEnabled: false } }); +// Disable default drag interaction and enable zooming +orb.setSettings({ interaction: { isDragEnabled: false, isZoomEnabled: true } }); ``` ### Property `simulation` From e3a1f2461c99e967c8273064ec079dfff8728a4a Mon Sep 17 00:00:00 2001 From: Abhinav Singh Parmar Date: Fri, 21 Jul 2023 17:33:52 +0530 Subject: [PATCH 09/30] NEW: Updated documentation to include isDragEnabled --- docs/view-default.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/view-default.md b/docs/view-default.md index 178efbb..e564205 100644 --- a/docs/view-default.md +++ b/docs/view-default.md @@ -83,6 +83,7 @@ interface IOrbViewSettings { // For graph interaction interaction: { isDragEnabled: boolean; + isZoomEnabled: boolean; }; // Other default view parameters zoomFitTransitionMs: number; @@ -155,6 +156,7 @@ const defaultSettings = { }, interaction: { isDragEnabled: true; + isZoomEnabled: true; }, zoomFitTransitionMs: 200, isOutOfBoundsDragEnabled: false, From 900f989663bc72a25e5d4bf84ff2c2f6a88d5798 Mon Sep 17 00:00:00 2001 From: Abhinv Singh Parmar Date: Mon, 4 Sep 2023 19:08:42 +0530 Subject: [PATCH 10/30] New: Add support for custom edge line style (#77) * New Added support for custom edges * Refactor: Streamline edge rendering code and optimize line style handling --- docs/styles.md | 1 + src/models/edge.ts | 37 +++++++++++++++++++ src/renderer/canvas/edge/types/edge-curved.ts | 4 ++ .../canvas/edge/types/edge-loopback.ts | 4 ++ .../canvas/edge/types/edge-straight.ts | 4 ++ src/utils/type.utils.ts | 13 +++++++ 6 files changed, 63 insertions(+) diff --git a/docs/styles.md b/docs/styles.md index 9846ea3..b44e4e9 100644 --- a/docs/styles.md +++ b/docs/styles.md @@ -142,6 +142,7 @@ style properties: | `widthHover` | number | Edge line width on mouse hover event. If not defined `width` is used. | | `widthSelected` | number | Edge line width on mouse click event. If not defined `width` is used. | | `zIndex` | number | Specifies the stack order of an element during rendering. The default is `0`. | +| `lineStyle` | object | Allows to customize the style of edges in the graph visualization. The default is `{type: 'solid'}` | ## Default style values diff --git a/src/models/edge.ts b/src/models/edge.ts index 8fda65e..cb818b6 100644 --- a/src/models/edge.ts +++ b/src/models/edge.ts @@ -1,9 +1,12 @@ import { INodeBase, INode } from './node'; import { GraphObjectState } from './state'; import { Color, IPosition, ICircle, getDistanceToLine } from '../common'; +import { isArrayOfNumbers } from '../utils/type.utils'; const CURVED_CONTROL_POINT_OFFSET_MIN_SIZE = 4; const CURVED_CONTROL_POINT_OFFSET_MULTIPLIER = 4; +const DEFAULT_DASHED_LINE_PATTERN: number[] = [5, 5]; +const DEFAULT_DOTTED_LINE_PATTERN: number[] = [1, 1]; /** * Edge baseline object with required fields @@ -25,6 +28,19 @@ export interface IEdgePosition { target: any; } +export enum EdgeLineStyleType { + SOLID = 'solid', + DASHED = 'dashed', + DOTTED = 'dotted', + CUSTOM = 'custom', +} + +export type IEdgeLineStyle = + | { type: EdgeLineStyleType.SOLID } + | { type: EdgeLineStyleType.DASHED } + | { type: EdgeLineStyleType.DOTTED } + | { type: EdgeLineStyleType.CUSTOM; pattern: number[] }; + /** * Edge style properties used to style the edge (color, width, label, etc.). */ @@ -46,6 +62,7 @@ export type IEdgeStyle = Partial<{ widthHover: number; widthSelected: number; zIndex: number; + lineStyle: IEdgeLineStyle; }>; export interface IEdgeData { @@ -89,6 +106,7 @@ export interface IEdge { hasShadow(): boolean; getWidth(): number; getColor(): Color | string | undefined; + getLineDashPattern(): number[] | null; } export class EdgeFactory { @@ -256,6 +274,25 @@ abstract class Edge implements IEdge(data: IEdgeData): EdgeType => { diff --git a/src/renderer/canvas/edge/types/edge-curved.ts b/src/renderer/canvas/edge/types/edge-curved.ts index 184d1e8..5da1859 100644 --- a/src/renderer/canvas/edge/types/edge-curved.ts +++ b/src/renderer/canvas/edge/types/edge-curved.ts @@ -18,6 +18,10 @@ export const drawCurvedLine = ( context.beginPath(); context.moveTo(sourcePoint.x, sourcePoint.y); context.quadraticCurveTo(controlPoint.x, controlPoint.y, targetPoint.x, targetPoint.y); + + const lineDashPattern = edge.getLineDashPattern(); + context.setLineDash(lineDashPattern ?? []); + context.stroke(); }; diff --git a/src/renderer/canvas/edge/types/edge-loopback.ts b/src/renderer/canvas/edge/types/edge-loopback.ts index a283be8..6aaaaaa 100644 --- a/src/renderer/canvas/edge/types/edge-loopback.ts +++ b/src/renderer/canvas/edge/types/edge-loopback.ts @@ -13,6 +13,10 @@ export const drawLoopbackLine = ( context.beginPath(); context.arc(x, y, radius, 0, 2 * Math.PI, false); context.closePath(); + + const lineDashPattern = edge.getLineDashPattern(); + context.setLineDash(lineDashPattern ?? []); + context.stroke(); }; diff --git a/src/renderer/canvas/edge/types/edge-straight.ts b/src/renderer/canvas/edge/types/edge-straight.ts index 353e504..67cafdc 100644 --- a/src/renderer/canvas/edge/types/edge-straight.ts +++ b/src/renderer/canvas/edge/types/edge-straight.ts @@ -17,6 +17,10 @@ export const drawStraightLine = ( context.beginPath(); context.moveTo(sourcePoint.x, sourcePoint.y); context.lineTo(targetPoint.x, targetPoint.y); + + const lineDashPattern = edge.getLineDashPattern(); + context.setLineDash(lineDashPattern ?? []); + context.stroke(); }; diff --git a/src/utils/type.utils.ts b/src/utils/type.utils.ts index aea6dbc..8289cb7 100644 --- a/src/utils/type.utils.ts +++ b/src/utils/type.utils.ts @@ -87,3 +87,16 @@ export const isNull = (value: any): value is null => { export const isFunction = (value: any): value is Function => { return typeof value === 'function'; }; + +/** + * Type check for an array of numbers + * + * @param {any} value Any value + * @return {boolean} True if it is an array of numbers, false otherwise + */ +export const isArrayOfNumbers = (value: any): value is number[] => { + if (!isArray(value)) { + return false; + } + return value.every((element) => isNumber(element)); +}; From cdb3a6d49b9cdeb60a94f33587d24eebeb7ae2b7 Mon Sep 17 00:00:00 2001 From: Toni Date: Tue, 20 Feb 2024 11:48:29 +0100 Subject: [PATCH 11/30] New: Add support for handling device pixel ratio (#45) * Chore: Move container and canvas creation from the view to the renderer * New: Add devicePixelRatio render property and handler * Fix: Add default DPR for older browsers * Chore: Remove useless check for automatic DPR --- docs/view-default.md | 35 +++++--- docs/view-map.md | 31 +++++-- src/renderer/canvas/canvas-renderer.ts | 117 +++++++++++++++++++++---- src/renderer/factory.ts | 16 +--- src/renderer/shared.ts | 20 +++-- src/renderer/webgl/webgl-renderer.ts | 49 +++++++++-- src/utils/html.utils.ts | 35 ++++++++ src/views/orb-map-view.ts | 55 ++++-------- src/views/orb-view.ts | 58 ++++-------- 9 files changed, 272 insertions(+), 144 deletions(-) diff --git a/docs/view-default.md b/docs/view-default.md index 598dae6..12ea901 100644 --- a/docs/view-default.md +++ b/docs/view-default.md @@ -63,6 +63,7 @@ interface IOrbViewSettings { }; // For canvas rendering and events render: { + devicePixelRatio: number | null; fps: number; minZoom: number; maxZoom: number; @@ -74,6 +75,7 @@ interface IOrbViewSettings { contextAlphaOnEvent: number; contextAlphaOnEventIsEnabled: boolean; backgroundColor: Color | string | null; + areCollapsedContainerDimensionsAllowed: boolean; }; // For select and hover look-and-feel strategy: { @@ -90,7 +92,6 @@ interface IOrbViewSettings { isOutOfBoundsDragEnabled: boolean; areCoordinatesRounded: boolean; isSimulationAnimated: boolean; - areCollapsedContainerDimensionsAllowed: boolean; } ``` @@ -138,6 +139,7 @@ const defaultSettings = { }, }, render: { + devicePixelRatio: window.devicePixelRatio, fps: 60, minZoom: 0.25, maxZoom: 8, @@ -149,6 +151,7 @@ const defaultSettings = { contextAlphaOnEvent: 0.3, contextAlphaOnEventIsEnabled: true, backgroundColor: null, + areCollapsedContainerDimensionsAllowed: false, }, strategy: { isDefaultSelectEnabled: true, @@ -162,7 +165,6 @@ const defaultSettings = { isOutOfBoundsDragEnabled: false, areCoordinatesRounded: true, isSimulationAnimated: true, - areCollapsedContainerDimensionsAllowed: false; } ``` @@ -269,6 +271,26 @@ Here you can use your original properties to indicate which ones represent your Optional property `render` has several rendering options that you can tweak. Read more about them on [Styling guide](./styles.md). +#### Property `render.devicePixelRatio` + +`devicePixelRatio` is useful when dealing with the difference between rendering on a standard +display versus a HiDPI or Retina display, which uses more screen pixels to draw the same +objects, resulting in a sharper image. ([Reference: MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio)). +Orb will listen for `devicePixelRatio` changes and handles them by default. You can override the +value with a settings property `render.devicePixelRatio`. Once a custom value is provided, Orb will +stop listening for `devicePixelRatio` changes. +If you want to return automatic `devicePixelRatio` handling, just set `render.devicePixelRatio` +to `null`. + +#### Property `render.areCollapsedContainerDimensionsAllowed` + +Enables setting the dimensions of the Orb container element to zero. +If the container element of Orb has collapsed dimensions (`width: 0;` or `height: 0;`), +Orb will expand the container by setting the values to `100%`. +If that doesn't work (the parent of the container also has collapsed dimensions), +Orb will set an arbitrary fixed dimension to the container. +Disabled by default (`false`). + ### Property `strategy` The optional property `strategy` has two properties that you can enable/disable: @@ -362,15 +384,6 @@ Shows the process of simulation where the nodes are moved by the physics engine converge to a stable position. If disabled, the graph will suddenly appear in its final position. Enabled by default (`true`). -### Property `areCollapsedContainerDimensionsAllowed` - -Enables setting the dimensions of the Orb container element to zero. -If the container element of Orb has collapsed dimensions (`width: 0;` or `height: 0;`), -Orb will expand the container by setting the values to `100%`. -If that doesn't work (the parent of the container also has collapsed dimensions), -Orb will set an arbitrary fixed dimension to the container. -Disabled by default (`false`). - ## Settings The above settings of the `OrbView` can be defined on view initialization, but also anytime diff --git a/docs/view-map.md b/docs/view-map.md index f5dc6c9..26c1cb8 100644 --- a/docs/view-map.md +++ b/docs/view-map.md @@ -116,6 +116,7 @@ interface IOrbMapViewSettings { getGeoPosition(node: INode): { lat: number; lng: number } | undefined; // For canvas rendering and events render: { + devicePixelRatio: number | null; fps: number; minZoom: number; maxZoom: number; @@ -147,6 +148,7 @@ The default settings that `OrbMapView` uses is: ```typescript const defaultSettings = { render: { + devicePixelRatio: window.devicePixelRatio, fps: 60, minZoom: 0.25, maxZoom: 8, @@ -191,6 +193,26 @@ Optional property `map` has two properties that you can set which are: Optional property `render` has several rendering options that you can tweak. Read more about them on [Styling guide](./styles.md). +#### Property `render.devicePixelRatio` + +`devicePixelRatio` is useful when dealing with the difference between rendering on a standard +display versus a HiDPI or Retina display, which uses more screen pixels to draw the same +objects, resulting in a sharper image. ([Reference: MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio)). +Orb will listen for `devicePixelRatio` changes and handles them by default. You can override the +value with a settings property `render.devicePixelRatio`. Once a custom value is provided, Orb will +stop listening for `devicePixelRatio` changes. +If you want to return automatic `devicePixelRatio` handling, just set `render.devicePixelRatio` +to `null`. + +#### Property `render.areCollapsedContainerDimensionsAllowed` + +Enables setting the dimensions of the Orb container element to zero. +If the container element of Orb has collapsed dimensions (`width: 0;` or `height: 0;`), +Orb will expand the container by setting the values to `100%`. +If that doesn't work (the parent of the container also has collapsed dimensions), +Orb will set an arbitrary fixed dimension to the container. +Disabled by default (`false`). + ### Property `strategy` The optional property `strategy` has two properties that you can enable/disable: @@ -243,15 +265,6 @@ orb.events.on(OrbEventType.MOUSE_CLICK, (event) => { }); ``` -### Property `areCollapsedContainerDimensionsAllowed` - -Enables setting the dimensions of the Orb container element to zero. -If the container element of Orb has collapsed dimensions (`width: 0;` or `height: 0;`), -Orb will expand the container by setting the values to `100%`. -If that doesn't work (the parent of the container also has collapsed dimensions), -Orb will set an arbitrary fixed dimension to the container. -Disabled by default (`false`). - ## Settings The above settings of `OrbMapView` can be defined on view initialization, but also anytime after the diff --git a/src/renderer/canvas/canvas-renderer.ts b/src/renderer/canvas/canvas-renderer.ts index 0625c9b..9265d93 100644 --- a/src/renderer/canvas/canvas-renderer.ts +++ b/src/renderer/canvas/canvas-renderer.ts @@ -18,6 +18,14 @@ import { import { throttle } from '../../utils/function.utils'; import { getThrottleMsFromFPS } from '../../utils/math.utils'; import { copyObject } from '../../utils/object.utils'; +import { + appendCanvas, + IObserveDPRUnsubscribe, + observeDevicePixelRatioChanges, + setupContainer, +} from '../../utils/html.utils'; +import { OrbError } from '../../exceptions'; +import { isNumber } from '../../utils/type.utils'; const DEBUG = false; const DEBUG_RED = '#FF5733'; @@ -26,12 +34,16 @@ const DEBUG_BLUE = '#3383FF'; const DEBUG_PINK = '#F333FF'; export class CanvasRenderer extends Emitter implements IRenderer { + private readonly _container: HTMLElement; + private readonly _canvas: HTMLCanvasElement; + private _resizeObs: ResizeObserver; + // Contains the HTML5 Canvas element which is used for drawing nodes and edges. private readonly _context: CanvasRenderingContext2D; // Width and height of the canvas. Used for clearing - public width: number; - public height: number; + private _width: number; + private _height: number; private _settings: IRendererSettings; // Includes translation (pan) in the x and y direction @@ -45,23 +57,58 @@ export class CanvasRenderer extends Em private _isInitiallyRendered = false; private _throttleRender: (graph: IGraph) => void; + private _dprObserveUnsubscribe?: IObserveDPRUnsubscribe; - constructor(context: CanvasRenderingContext2D, settings?: Partial) { + constructor(container: HTMLElement, settings?: Partial) { super(); + setupContainer(container, settings?.areCollapsedContainerDimensionsAllowed); + this._container = container; + this._canvas = appendCanvas(container); + + const context = this._canvas.getContext('2d'); + if (!context) { + throw new OrbError('Failed to create Canvas context.'); + } + this._context = context; - this.width = DEFAULT_RENDERER_WIDTH; - this.height = DEFAULT_RENDERER_HEIGHT; + this._width = DEFAULT_RENDERER_WIDTH; + this._height = DEFAULT_RENDERER_HEIGHT; this.transform = zoomIdentity; this._settings = { ...DEFAULT_RENDERER_SETTINGS, ...settings, }; + // Resize the canvas based on the dimensions of its parent container
. + this._resizeObs = new ResizeObserver(() => this._resize()); + this._resizeObs.observe(this._container); + this._resize(); + + if (!isNumber(settings?.devicePixelRatio)) { + this._dprObserveUnsubscribe = observeDevicePixelRatioChanges(() => this._resize()); + } + this._throttleRender = throttle((graph: IGraph) => { this._render(graph); }, getThrottleMsFromFPS(this._settings.fps)); } + get width(): number { + return this._width; + } + + get height(): number { + return this._height; + } + + get container(): HTMLElement { + return this._container; + } + + get canvas(): HTMLCanvasElement { + return this._canvas; + } + get isInitiallyRendered(): boolean { return this._isInitiallyRendered; } @@ -72,6 +119,9 @@ export class CanvasRenderer extends Em setSettings(settings: Partial) { const isFpsChanged = settings.fps && settings.fps !== this._settings.fps; + const previousDprValue = this._settings.devicePixelRatio; + const newDprValue = settings.devicePixelRatio; + this._settings = { ...this._settings, ...settings, @@ -82,6 +132,17 @@ export class CanvasRenderer extends Em this._render(graph); }, getThrottleMsFromFPS(this._settings.fps)); } + + // Change DPR from automatic to manual handling or change DPR value manually + if (!isNumber(previousDprValue) && isNumber(newDprValue)) { + this._dprObserveUnsubscribe?.(); + this._resize(); + } + + // Change DPR from manual to automatic handling + if (isNumber(previousDprValue) && newDprValue === null) { + this._dprObserveUnsubscribe = observeDevicePixelRatioChanges(() => this._resize()); + } } render(graph: IGraph) { @@ -97,30 +158,30 @@ export class CanvasRenderer extends Em const renderStartedAt = Date.now(); // Clear drawing. - this._context.clearRect(0, 0, this.width, this.height); + this._context.clearRect(0, 0, this._width, this._height); if (this._settings.backgroundColor) { this._context.fillStyle = this._settings.backgroundColor.toString(); - this._context.fillRect(0, 0, this.width, this.height); + this._context.fillRect(0, 0, this._width, this._height); } this._context.save(); if (DEBUG) { this._context.lineWidth = 3; this._context.fillStyle = DEBUG_RED; - this._context.fillRect(0, 0, this.width, this.height); + this._context.fillRect(0, 0, this._width, this._height); } // Apply any scaling (zoom) or translation (pan) transformations. this._context.translate(this.transform.x, this.transform.y); if (DEBUG) { this._context.fillStyle = DEBUG_BLUE; - this._context.fillRect(0, 0, this.width, this.height); + this._context.fillRect(0, 0, this._width, this._height); } this._context.scale(this.transform.k, this.transform.k); if (DEBUG) { this._context.fillStyle = DEBUG_GREEN; - this._context.fillRect(0, 0, this.width, this.height); + this._context.fillRect(0, 0, this._width, this._height); } // Move coordinates (0, 0) to canvas center. @@ -129,11 +190,11 @@ export class CanvasRenderer extends Em // relative to (0, 0), so any source mouse event position needs to take this // offset into account. (Handled in getMousePos()) if (this._isOriginCentered) { - this._context.translate(this.width / 2, this.height / 2); + this._context.translate(this._width / 2, this._height / 2); } if (DEBUG) { this._context.fillStyle = DEBUG_PINK; - this._context.fillRect(0, 0, this.width, this.height); + this._context.fillRect(0, 0, this._width, this._height); } this.drawObjects(graph.getEdges()); @@ -195,6 +256,23 @@ export class CanvasRenderer extends Em } } + private _resize() { + const dpr = this._settings.devicePixelRatio || window.devicePixelRatio || 1; + + const containerSize = this._container.getBoundingClientRect(); + this._canvas.style.width = `${containerSize.width}px`; + this._canvas.style.height = `${containerSize.height}px`; + this._canvas.width = containerSize.width * dpr; + this._canvas.height = containerSize.height * dpr; + + // Normalize coordinate system to use CSS pixels + this._context.scale(dpr, dpr); + + this._width = containerSize.width; + this._height = containerSize.height; + this.emit(RenderEventType.RESIZE, undefined); + } + private drawObject(obj: INode | IEdge, options?: Partial | Partial) { if (isNode(obj)) { drawNode(this._context, obj, options); @@ -207,7 +285,7 @@ export class CanvasRenderer extends Em this.transform = zoomIdentity; // Clear drawing. - this._context.clearRect(0, 0, this.width, this.height); + this._context.clearRect(0, 0, this._width, this._height); this._context.save(); } @@ -252,8 +330,8 @@ export class CanvasRenderer extends Em // simulation coordinates (O) when dragging and hovering nodes. const [x, y] = this.transform.invert([canvasPoint.x, canvasPoint.y]); return { - x: x - this.width / 2, - y: y - this.height / 2, + x: x - this._width / 2, + y: y - this._height / 2, }; } @@ -264,7 +342,7 @@ export class CanvasRenderer extends Em */ getSimulationViewRectangle(): IRectangle { const topLeftPosition = this.getSimulationPosition({ x: 0, y: 0 }); - const bottomRightPosition = this.getSimulationPosition({ x: this.width, y: this.height }); + const bottomRightPosition = this.getSimulationPosition({ x: this._width, y: this._height }); return { x: topLeftPosition.x, y: topLeftPosition.y, @@ -276,4 +354,11 @@ export class CanvasRenderer extends Em translateOriginToCenter() { this._isOriginCentered = true; } + + destroy(): void { + this._resizeObs.unobserve(this._container); + this._dprObserveUnsubscribe?.(); + this.removeAllListeners(); + this._canvas.outerHTML = ''; + } } diff --git a/src/renderer/factory.ts b/src/renderer/factory.ts index 9cc76a9..4fd245c 100644 --- a/src/renderer/factory.ts +++ b/src/renderer/factory.ts @@ -1,28 +1,18 @@ import { CanvasRenderer } from './canvas/canvas-renderer'; import { IRenderer, IRendererSettings, RendererType } from './shared'; import { WebGLRenderer } from './webgl/webgl-renderer'; -import { OrbError } from '../exceptions'; import { INodeBase } from '../models/node'; import { IEdgeBase } from '../models/edge'; export class RendererFactory { static getRenderer( - canvas: HTMLCanvasElement, + container: HTMLElement, type: RendererType = RendererType.CANVAS, settings?: Partial, ): IRenderer { if (type === RendererType.WEBGL) { - const context = canvas.getContext('webgl2'); - if (!context) { - throw new OrbError('Failed to create WebGL context.'); - } - return new WebGLRenderer(context, settings); + return new WebGLRenderer(container, settings); } - - const context = canvas.getContext('2d'); - if (!context) { - throw new OrbError('Failed to create Canvas context.'); - } - return new CanvasRenderer(context, settings); + return new CanvasRenderer(container, settings); } } diff --git a/src/renderer/shared.ts b/src/renderer/shared.ts index fe945b0..a5719bc 100644 --- a/src/renderer/shared.ts +++ b/src/renderer/shared.ts @@ -11,11 +11,13 @@ export enum RendererType { } export enum RenderEventType { + RESIZE = 'resize', RENDER_START = 'render-start', RENDER_END = 'render-end', } export interface IRendererSettings { + devicePixelRatio: number | null; fps: number; minZoom: number; maxZoom: number; @@ -27,6 +29,7 @@ export interface IRendererSettings { contextAlphaOnEvent: number; contextAlphaOnEventIsEnabled: boolean; backgroundColor: Color | string | null; + areCollapsedContainerDimensionsAllowed: boolean; } export interface IRendererSettingsInit extends IRendererSettings { @@ -34,31 +37,30 @@ export interface IRendererSettingsInit extends IRendererSettings { } export type RendererEvents = { + [RenderEventType.RESIZE]: undefined; [RenderEventType.RENDER_START]: undefined; [RenderEventType.RENDER_END]: { durationMs: number }; }; export interface IRenderer extends IEmitter { - // Width and height of the canvas. Used for clearing. - width: number; - height: number; - // Includes translation (pan) in the x and y direction // as well as scaling (level of zoom). transform: ZoomTransform; + // Width and height of the canvas + get width(): number; + get height(): number; + get container(): HTMLElement; + get canvas(): HTMLCanvasElement; get isInitiallyRendered(): boolean; getSettings(): IRendererSettings; - setSettings(settings: Partial): void; render(graph: IGraph): void; - reset(): void; getFitZoomTransform(graph: IGraph): ZoomTransform; - getSimulationPosition(canvasPoint: IPosition): IPosition; /** @@ -69,9 +71,12 @@ export interface IRenderer extends IEm getSimulationViewRectangle(): IRectangle; translateOriginToCenter(): void; + + destroy(): void; } export const DEFAULT_RENDERER_SETTINGS: IRendererSettings = { + devicePixelRatio: null, fps: 60, minZoom: 0.25, maxZoom: 8, @@ -83,6 +88,7 @@ export const DEFAULT_RENDERER_SETTINGS: IRendererSettings = { contextAlphaOnEvent: 0.3, contextAlphaOnEventIsEnabled: true, backgroundColor: null, + areCollapsedContainerDimensionsAllowed: false, }; export const DEFAULT_RENDERER_WIDTH = 640; diff --git a/src/renderer/webgl/webgl-renderer.ts b/src/renderer/webgl/webgl-renderer.ts index 9f7115f..52ba3a1 100644 --- a/src/renderer/webgl/webgl-renderer.ts +++ b/src/renderer/webgl/webgl-renderer.ts @@ -13,28 +13,58 @@ import { IRendererSettings, } from '../shared'; import { copyObject } from '../../utils/object.utils'; +import { appendCanvas, setupContainer } from '../../utils/html.utils'; +import { OrbError } from '../../exceptions'; export class WebGLRenderer extends Emitter implements IRenderer { + private readonly _container: HTMLElement; + private readonly _canvas: HTMLCanvasElement; + // Contains the HTML5 Canvas element which is used for drawing nodes and edges. private readonly _context: WebGL2RenderingContext; - width: number; - height: number; + private _width: number; + private _height: number; private _settings: IRendererSettings; transform: ZoomTransform; - constructor(context: WebGL2RenderingContext, settings?: Partial) { + constructor(container: HTMLElement, settings?: Partial) { super(); - this._context = context; - console.log('context', this._context); + setupContainer(container, settings?.areCollapsedContainerDimensionsAllowed); + this._container = container; + this._canvas = appendCanvas(container); + const context = this._canvas.getContext('webgl2'); - this.width = DEFAULT_RENDERER_WIDTH; - this.height = DEFAULT_RENDERER_HEIGHT; + if (!context) { + throw new OrbError('Failed to create WebGL context.'); + } + + this._context = context; + this._width = DEFAULT_RENDERER_WIDTH; + this._height = DEFAULT_RENDERER_HEIGHT; this.transform = zoomIdentity; this._settings = { ...DEFAULT_RENDERER_SETTINGS, ...settings, }; + + console.log('context', this._context); + } + + get width(): number { + return this._width; + } + + get height(): number { + return this._height; + } + + get container(): HTMLElement { + return this._container; + } + + get canvas(): HTMLCanvasElement { + return this._canvas; } get isInitiallyRendered(): boolean { @@ -78,4 +108,9 @@ export class WebGLRenderer extends Emi translateOriginToCenter(): void { throw new Error('Method not implemented.'); } + + destroy(): void { + this.removeAllListeners(); + this._canvas.outerHTML = ''; + } } diff --git a/src/utils/html.utils.ts b/src/utils/html.utils.ts index 0b02415..deef5b1 100644 --- a/src/utils/html.utils.ts +++ b/src/utils/html.utils.ts @@ -48,3 +48,38 @@ export const isCollapsedDimension = (dimension: string | null | undefined) => { return collapsedDimensionRegex.test(dimension); }; + +export const appendCanvas = (container: HTMLElement): HTMLCanvasElement => { + const canvas = document.createElement('canvas'); + canvas.style.position = 'absolute'; + canvas.style.top = '0'; + canvas.style.left = '0'; + container.appendChild(canvas); + return canvas; +}; + +export type IObserveDPRCallback = (devicePixelRatio: number) => void; +export type IObserveDPRUnsubscribe = () => void; + +export const observeDevicePixelRatioChanges = (callback: IObserveDPRCallback): IObserveDPRUnsubscribe => { + let currentDpr = window.devicePixelRatio; + let unsubscribe: IObserveDPRUnsubscribe = () => { + return; + }; + + const listenForDPRChanges = () => { + unsubscribe(); + + const media = matchMedia(`(resolution: ${currentDpr}dppx)`); + media.addEventListener('change', listenForDPRChanges); + unsubscribe = () => media.removeEventListener('change', listenForDPRChanges); + + if (window.devicePixelRatio !== currentDpr) { + currentDpr = window.devicePixelRatio; + callback(currentDpr); + } + }; + + listenForDPRChanges(); + return () => unsubscribe(); +}; diff --git a/src/views/orb-map-view.ts b/src/views/orb-map-view.ts index 83f994a..01211ab 100644 --- a/src/views/orb-map-view.ts +++ b/src/views/orb-map-view.ts @@ -9,7 +9,6 @@ import { copyObject } from '../utils/object.utils'; import { OrbEmitter, OrbEventType } from '../events'; import { IRenderer, RendererType, RenderEventType, IRendererSettingsInit, IRendererSettings } from '../renderer/shared'; import { RendererFactory } from '../renderer/factory'; -import { setupContainer } from '../utils/html.utils'; import { getDefaultGraphStyle } from '../models/style'; import { isBoolean } from '../utils/type.utils'; @@ -67,14 +66,11 @@ export type IOrbMapViewSettingsUpdate export class OrbMapView implements IOrbView> { private _container: HTMLElement; - private _resizeObs: ResizeObserver; private _graph: IGraph; private _events: OrbEmitter; private _strategy: IEventStrategy; private _settings: IOrbMapViewSettings; - - private _canvas: HTMLCanvasElement; private _map: HTMLDivElement; private readonly _renderer: IRenderer; @@ -116,12 +112,12 @@ export class OrbMapView implements IOr isDefaultHoverEnabled: this._settings.strategy.isDefaultHoverEnabled ?? false, }); - setupContainer(this._container); - this._canvas = this._initCanvas(); - this._map = this._initMap(); - try { - this._renderer = RendererFactory.getRenderer(this._canvas, settings?.render?.type, this._settings.render); + this._renderer = RendererFactory.getRenderer( + this._container, + settings?.render?.type, + this._settings.render, + ); } catch (error: any) { this._container.textContent = error.message; throw error; @@ -129,12 +125,18 @@ export class OrbMapView implements IOr this._renderer.on(RenderEventType.RENDER_END, (data) => { this._events.emit(OrbEventType.RENDER_END, data); }); + this._renderer.on(RenderEventType.RESIZE, () => { + if (this._renderer.isInitiallyRendered) { + this._leaflet.invalidateSize(false); + this._renderer.render(this._graph); + } + }); + this._settings.render = this._renderer.getSettings(); + this._renderer.canvas.style.zIndex = '2'; + this._renderer.canvas.style.pointerEvents = 'none'; - // Resize the canvas based on the dimensions of it's parent container
. - this._resizeObs = new ResizeObserver(() => this._handleResize()); - this._resizeObs.observe(this._container); - this._handleResize(); + this._map = this._initMap(); this._leaflet = this._initLeaflet(); // Setting up leaflet map tile @@ -208,23 +210,10 @@ export class OrbMapView implements IOr } destroy() { - this._resizeObs.unobserve(this._container); - this._renderer.removeAllListeners(); + this._renderer.destroy(); this._leaflet.off(); this._leaflet.remove(); this._leaflet.getContainer().outerHTML = ''; - this._canvas.outerHTML = ''; - } - - private _initCanvas() { - const canvas = document.createElement('canvas'); - canvas.style.position = 'absolute'; - canvas.style.width = '100%'; - canvas.style.zIndex = '2'; - canvas.style.pointerEvents = 'none'; - - this._container.appendChild(canvas); - return canvas; } private _initMap() { @@ -442,18 +431,6 @@ export class OrbMapView implements IOr } } - private _handleResize() { - const containerSize = this._container.getBoundingClientRect(); - this._canvas.width = containerSize.width; - this._canvas.height = containerSize.height; - this._renderer.width = containerSize.width; - this._renderer.height = containerSize.height; - if (this._renderer.isInitiallyRendered) { - this._leaflet.invalidateSize(false); - this._renderer.render(this._graph); - } - } - private _handleTileChange() { const newTile: ILeafletMapTile = this._settings.map.tile; diff --git a/src/views/orb-view.ts b/src/views/orb-view.ts index 932cb6a..d4832b6 100644 --- a/src/views/orb-view.ts +++ b/src/views/orb-view.ts @@ -18,7 +18,6 @@ import { copyObject } from '../utils/object.utils'; import { OrbEmitter, OrbEventType } from '../events'; import { IRenderer, RenderEventType, IRendererSettingsInit, IRendererSettings } from '../renderer/shared'; import { RendererFactory } from '../renderer/factory'; -import { setupContainer } from '../utils/html.utils'; import { SimulatorEventType } from '../simulator/shared'; import { getDefaultGraphStyle } from '../models/style'; import { isBoolean } from '../utils/type.utils'; @@ -38,7 +37,6 @@ export interface IOrbViewSettings { isOutOfBoundsDragEnabled: boolean; areCoordinatesRounded: boolean; isSimulationAnimated: boolean; - areCollapsedContainerDimensionsAllowed: boolean; } export type IOrbViewSettingsInit = Omit< @@ -48,12 +46,10 @@ export type IOrbViewSettingsInit = Omi export class OrbView implements IOrbView> { private _container: HTMLElement; - private _resizeObs: ResizeObserver; private _graph: IGraph; private _events: OrbEmitter; private _strategy: IEventStrategy; private _settings: IOrbViewSettings; - private _canvas: HTMLCanvasElement; private readonly _renderer: IRenderer; private readonly _simulator: ISimulator; @@ -83,7 +79,6 @@ export class OrbView implements IOrbVi isOutOfBoundsDragEnabled: false, areCoordinatesRounded: true, isSimulationAnimated: true, - areCollapsedContainerDimensionsAllowed: false, ...settings, simulation: { isPhysicsEnabled: false, @@ -109,11 +104,12 @@ export class OrbView implements IOrbVi isDefaultHoverEnabled: this._settings.strategy.isDefaultHoverEnabled ?? false, }); - setupContainer(this._container, this._settings.areCollapsedContainerDimensionsAllowed); - this._canvas = this._initCanvas(); - try { - this._renderer = RendererFactory.getRenderer(this._canvas, settings?.render?.type, this._settings.render); + this._renderer = RendererFactory.getRenderer( + this._container, + settings?.render?.type, + this._settings.render, + ); } catch (error: any) { this._container.textContent = error.message; throw error; @@ -124,22 +120,23 @@ export class OrbView implements IOrbVi this._renderer.on(RenderEventType.RENDER_END, (data) => { this._events.emit(OrbEventType.RENDER_END, data); }); + this._renderer.on(RenderEventType.RESIZE, () => { + if (this._renderer.isInitiallyRendered) { + this._renderer.render(this._graph); + } + }); + this._renderer.translateOriginToCenter(); this._settings.render = this._renderer.getSettings(); - // Resize the canvas based on the dimensions of its parent container
. - this._resizeObs = new ResizeObserver(() => this._handleResize()); - this._resizeObs.observe(this._container); - this._handleResize(); - this._d3Zoom = zoom() .scaleExtent([this._renderer.getSettings().minZoom, this._renderer.getSettings().maxZoom]) .on('zoom', this.zoomed); - select(this._canvas) + select(this._renderer.canvas) .call( drag() - .container(this._canvas) + .container(this._renderer.canvas) .subject(this.dragSubject) .on('start', this.dragStarted) .on('drag', this.dragged) @@ -266,7 +263,7 @@ export class OrbView implements IOrbVi recenter(onRendered?: () => void) { const fitZoomTransform = this._renderer.getFitZoomTransform(this._graph); - select(this._canvas) + select(this._renderer.canvas) .transition() .duration(this._settings.zoomFitTransitionMs) .ease(easeLinear) @@ -278,10 +275,8 @@ export class OrbView implements IOrbVi } destroy() { - this._resizeObs.unobserve(this._container); - this._renderer.removeAllListeners(); + this._renderer.destroy(); this._simulator.terminate(); - this._canvas.outerHTML = ''; } dragSubject = (event: D3DragEvent>) => { @@ -367,7 +362,7 @@ export class OrbView implements IOrbVi }; getCanvasMousePosition(event: MouseEvent): IPosition { - const rect = this._canvas.getBoundingClientRect(); + const rect = this._renderer.canvas.getBoundingClientRect(); let x = event.clientX ?? event.pageX ?? event.x; let y = event.clientY ?? event.pageY ?? event.y; @@ -542,27 +537,6 @@ export class OrbView implements IOrbVi } }; - private _initCanvas(): HTMLCanvasElement { - const canvas = document.createElement('canvas'); - canvas.style.position = 'absolute'; - canvas.style.top = '0'; - canvas.style.left = '0'; - - this._container.appendChild(canvas); - return canvas; - } - - private _handleResize() { - const containerSize = this._container.getBoundingClientRect(); - this._canvas.width = containerSize.width; - this._canvas.height = containerSize.height; - this._renderer.width = containerSize.width; - this._renderer.height = containerSize.height; - if (this._renderer.isInitiallyRendered) { - this._renderer.render(this._graph); - } - } - private _startSimulation() { const nodePositions = this._graph.getNodePositions(); const edgePositions = this._graph.getEdgePositions(); From 2530739140b3053566bbc21b5cd00fbfbe69140f Mon Sep 17 00:00:00 2001 From: Toni Date: Wed, 27 Mar 2024 12:43:18 +0100 Subject: [PATCH 12/30] New: Add new simulator (#56) (#57) * New: Add new simulator (#56) * New: Add simulator scenarios for manual testing * New: Refactor simulator (WIP) * New: Add progress overlay, Update descriptions * Fix: Introduce new simulator event, Fix main-thread behavior * Fix: Rearrange class methods based on visibility * Fix: Improve naming * Chore(release): 0.2.0 * Fix: Tweak simulator, adjust API slightly * Fix: Temporarily patch some physics behavior * Fix: Adjust re-heating parameters * Fix: tweak physics behavior -> immediately stop sim when disabling * Chore: Remove the beta from release branches --------- Co-authored-by: dlozic * New: Add zoom and recenter functions (#74) * New: Add zoom and recenter functions * Fix: Reduce excessive recentering (#75) * Fix: Remove excessive recenterings * Fix: Remove unused code * Fix: New simulator (#92) * Chore: Refactor naming * New: Add new events * Chore: Refactor code styling * Docs: Remove unused flags * Chore: Remove unused simulation functions * Chore: Refactor view render function calls * Chore: Add missing tests * New: Add removal functions (#96) * New: Add removal functions * Fix: Add missing callback data * Chore: Refactor remove return values * Chore: Refactor remove function type usage * Fix: Default settings for node placement (#98) * New: Add properties setters and getters (#93) * New: Add node properties setters * New: Add edge properties setters * New: Add properties getters * New: Add patch for nodes and edges * Fix: Make getters return copies * Fix: Edge factory listeners copying * Fix: Jest outdated tests * Fix: Github actions node version * Chore: Refactor observer interface * Chore: Refactor node/edge constructor settings * Chore: Refactor node/edge function grouping * Chore: Refactor node/edge function grouping * Fix: Listeners behaviour * Chore: Refactor property copying * Chore: Refactor subject implementation * Fix: Set position behaviour on node drag * Chore: Upgrade node version * Chore: Refactor function type check * Fix: Remove listener behaviour * Chore: Refactor util naming * Chore: Remove unused type assertion * Chore: Refactor position setter options * Chore: Refactor property patch function * Fix: Set map node position behaviour * Chore: Refactor simulator data patching * Chore: Change observers to callbacks * New: Add state setters with options (#95) * New: Add state setters with options * Chore: Remove leftover comments * Chore: Refactor state setter logic * Chore: Refactor state types * Fix: Rename merged function usage * Fix: Merged variable naming * Chore: Fix tests --------- Co-authored-by: dlozic Co-authored-by: Oleksandr Ichenskyi <55350107+AlexIchenskiy@users.noreply.github.com> Co-authored-by: AlexIchenskiy --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 2 +- .releaserc | 6 +- README.md | 12 +- docs/view-default.md | 35 +- examples/example-custom-styled-graph.html | 6 +- examples/example-fixed-coordinates-graph.html | 6 +- examples/example-graph-data-changes.html | 8 +- examples/example-graph-events.html | 18 +- examples/example-graph-on-map.html | 6 +- examples/playground.html | 6 +- examples/simulator-scenarios.html | 3077 +++- package-lock.json | 12973 ++-------------- package.json | 19 +- src/events.ts | 16 +- src/models/edge.ts | 245 +- src/models/graph.ts | 233 +- src/models/node.ts | 304 +- src/models/state.ts | 18 + src/models/strategy.ts | 18 +- src/models/style.ts | 3 +- src/renderer/canvas/canvas-renderer.ts | 4 - src/renderer/canvas/edge/base.ts | 40 +- src/renderer/canvas/edge/types/edge-curved.ts | 4 +- .../canvas/edge/types/edge-loopback.ts | 2 +- .../canvas/edge/types/edge-straight.ts | 4 +- src/renderer/canvas/node.ts | 40 +- src/simulator/engine/d3-simulator-engine.ts | 560 +- src/simulator/factory.ts | 3 +- src/simulator/layout/layout.ts | 29 + src/simulator/layout/layouts/circle.ts | 11 + src/simulator/shared.ts | 44 +- src/simulator/types/main-thread-simulator.ts | 82 +- .../types/web-worker-simulator/index.ts | 2 +- .../message/worker-input.ts | 51 +- .../message/worker-output.ts | 11 + ...{process.worker.ts => simulator.worker.ts} | 48 +- .../{simulator.ts => web-worker-simulator.ts} | 67 +- src/utils/array.utils.ts | 5 + src/utils/object.utils.ts | 8 + src/utils/observer.utils.ts | 50 + src/views/orb-map-view.ts | 20 +- src/views/orb-view.ts | 141 +- test/models/graph.spec.ts | 236 +- webpack.config.js | 4 +- 45 files changed, 5722 insertions(+), 12757 deletions(-) create mode 100644 src/simulator/layout/layout.ts create mode 100644 src/simulator/layout/layouts/circle.ts rename src/simulator/types/web-worker-simulator/{process.worker.ts => simulator.worker.ts} (68%) rename src/simulator/types/web-worker-simulator/{simulator.ts => web-worker-simulator.ts} (63%) create mode 100644 src/utils/observer.utils.ts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9a57469..6ce3f17 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ jobs: - uses: actions/checkout@v1 - uses: actions/setup-node@v1 with: - node-version: "16.x" + node-version: "18.x" - name: 'Install' run: npm ci diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ae29e61..1954f5f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v1 - uses: actions/setup-node@v1 with: - node-version: "16.x" + node-version: "18.x" - name: 'Install' run: npm ci diff --git a/.releaserc b/.releaserc index 657424e..036ab65 100644 --- a/.releaserc +++ b/.releaserc @@ -8,10 +8,10 @@ }], "@semantic-release/changelog", "@semantic-release/npm", - '@semantic-release/github', + "@semantic-release/github", ["@semantic-release/git", { "assets": ["package.json", "CHANGELOG.md"], "message": "Chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" - }], - ], + }] + ] } diff --git a/README.md b/README.md index 991cc2a..2d5cd1a 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Orb is a graph visualization library. Read more about Orb in the following guide * [Styling nodes and edges](./docs/styles.md) * [Handling events](./docs/events.md) * Using different views - * [Default view](./docs/view-default.md) + * [Default view](./docs/view-default.md) * [Map view](./docs/view-map.md) ## Install @@ -106,7 +106,7 @@ free to check other JavaScript examples in `examples/` directory.
diff --git a/package-lock.json b/package-lock.json index 47222a8..97f8586 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,7 @@ { "name": "@memgraph/orb", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -28,7 +28,7 @@ "@types/d3-selection": "3.0.1", "@types/d3-transition": "3.0.1", "@types/d3-zoom": "3.0.1", - "@types/jest": "27.4.1", + "@types/jest": "29.5.12", "@types/leaflet": "1.7.9", "@types/resize-observer-browser": "^0.1.7", "@typescript-eslint/eslint-plugin": "5.24.0", @@ -42,10 +42,10 @@ "eslint-plugin-prettier": "4.0.0", "http-server": "^14.1.1", "husky": "^8.0.1", - "jest": "27.5.1", + "jest": "29.7.0", "prettier": "^2.7.1", "semantic-release": "19.0.3", - "ts-jest": "27.1.4", + "ts-jest": "29.1.2", "ts-loader": "^9.3.1", "ts-node": "10.8.0", "typescript": "4.6.3", @@ -54,16 +54,16 @@ "webpack-dev-server": "^4.9.3" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { @@ -71,47 +71,119 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", - "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.9.tgz", - "integrity": "sha512-1LIb1eL8APMy91/IMW+31ckrfBM4yCoLaVzoDhZUKSM4cu1L1nIidyxkCgzPAgrC5WEz36IPEr/eSeSF9pIn+g==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.9", - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-module-transforms": "^7.18.9", - "@babel/helpers": "^7.18.9", - "@babel/parser": "^7.18.9", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.9", - "@babel/types": "^7.18.9", - "convert-source-map": "^1.7.0", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -131,49 +203,43 @@ } }, "node_modules/@babel/generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.9.tgz", - "integrity": "sha512-wt5Naw6lJrL1/SGkipMiFxJjtyczUWTP38deiP1PO60HsBjDeKk08CGC3S8iVuvf0FmTdgKwU1KIXzSKL1G0Ug==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dev": true, "dependencies": { - "@babel/types": "^7.18.9", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz", - "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==", + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.18.8", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.20.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "yallist": "^3.0.2" } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { @@ -185,144 +251,159 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz", - "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.18.6", - "@babel/types": "^7.18.9" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz", - "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.9", - "@babel/types": "^7.18.9" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz", - "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", - "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", + "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", "dev": true, "dependencies": { - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.9", - "@babel/types": "^7.18.9" + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -401,9 +482,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz", - "integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -472,6 +553,21 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", @@ -560,12 +656,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", - "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -575,34 +671,34 @@ } }, "node_modules/@babel/template": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", - "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/types": "^7.18.6" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz", - "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.9", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.18.9", - "@babel/types": "^7.18.9", - "debug": "^4.1.0", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -619,12 +715,13 @@ } }, "node_modules/@babel/types": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.9.tgz", - "integrity": "sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1148,59 +1245,59 @@ } }, "node_modules/@jest/console": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", - "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", - "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "dependencies": { - "@jest/console": "^27.5.1", - "@jest/reporters": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "emittery": "^0.8.1", + "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^27.5.1", - "jest-config": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-resolve-dependencies": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "jest-watcher": "^27.5.1", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", "micromatch": "^4.0.4", - "rimraf": "^3.0.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -1211,101 +1308,111 @@ } } }, - "node_modules/@jest/core/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "dependencies": { - "glob": "^7.1.3" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/environment": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", - "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "dependencies": { - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1" + "jest-get-type": "^29.6.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", - "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", - "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", - "glob": "^7.1.2", + "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-haste-map": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "slash": "^3.0.0", - "source-map": "^0.6.0", "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -1316,100 +1423,144 @@ } } }, + "node_modules/@jest/reporters/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/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, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jest/source-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", - "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", - "graceful-fs": "^4.2.9", - "source-map": "^0.6.0" + "graceful-fs": "^4.2.9" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-result": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", - "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "dependencies": { - "@jest/console": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-sequencer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", - "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "dependencies": { - "@jest/test-result": "^27.5.1", + "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-runtime": "^27.5.1" + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", - "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "dependencies": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.5.1", + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-util": "^27.5.1", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" + "write-file-atomic": "^4.0.2" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "dependencies": { + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "@types/yargs": "^16.0.0", + "@types/yargs": "^17.0.8", "chalk": "^4.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz", + "integrity": "sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" @@ -1443,20 +1594,6 @@ "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", @@ -1929,31 +2066,28 @@ "semantic-release": ">=18.0.0-beta.1" } }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" + "@sinonjs/commons": "^3.0.0" } }, "node_modules/@tsconfig/node10": { @@ -1981,31 +2115,31 @@ "dev": true }, "node_modules/@types/babel__core": { - "version": "7.1.19", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", - "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "node_modules/@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dev": true, "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", @@ -2013,12 +2147,12 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.17.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", - "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", "dev": true, "dependencies": { - "@babel/types": "^7.3.0" + "@babel/types": "^7.20.7" } }, "node_modules/@types/body-parser": { @@ -2176,9 +2310,9 @@ "dev": true }, "node_modules/@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, "dependencies": { "@types/node": "*" @@ -2194,37 +2328,37 @@ } }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/jest": { - "version": "27.4.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", - "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", "dev": true, "dependencies": { - "jest-matcher-utils": "^27.0.0", - "pretty-format": "^27.0.0" + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, "node_modules/@types/json-schema": { @@ -2272,12 +2406,6 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, - "node_modules/@types/prettier": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.3.tgz", - "integrity": "sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg==", - "dev": true - }, "node_modules/@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", @@ -2331,9 +2459,9 @@ } }, "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, "node_modules/@types/ws": { @@ -2346,18 +2474,18 @@ } }, "node_modules/@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -2738,12 +2866,6 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2769,28 +2891,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/acorn-import-assertions": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", @@ -2809,15 +2909,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -3027,12 +3118,6 @@ "lodash": "^4.17.14" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -3043,22 +3128,21 @@ } }, "node_modules/babel-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", - "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "dependencies": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.8.0" @@ -3080,25 +3164,50 @@ "node": ">=8" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=8" } }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", @@ -3119,16 +3228,16 @@ } }, "node_modules/babel-preset-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", - "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^27.5.1", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -3276,16 +3385,10 @@ "node": ">=8" } }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, "node_modules/browserslist": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.2.tgz", - "integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -3295,13 +3398,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "caniuse-lite": "^1.0.30001366", - "electron-to-chromium": "^1.4.188", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.4" + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -3395,9 +3502,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001368", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001368.tgz", - "integrity": "sha512-wgfRYa9DenEomLG/SdWgQxpIyvdtH3NW8Vq+tB6AwR9e56iOIcu1im5F/wNdDf04XlKHXqIx4N8Jo0PemeBenQ==", + "version": "1.0.30001591", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz", + "integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==", "dev": true, "funding": [ { @@ -3407,6 +3514,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -3497,15 +3608,24 @@ } }, "node_modules/ci-info": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", - "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", - "dev": true + "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/cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, "node_modules/clean-stack": { @@ -3580,9 +3700,9 @@ } }, "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, "node_modules/color-convert": { @@ -3609,18 +3729,6 @@ "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", "dev": true }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -3853,13 +3961,10 @@ } }, "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true }, "node_modules/cookie": { "version": "0.5.0", @@ -3978,6 +4083,27 @@ "typescript": ">=3" } }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -4007,30 +4133,6 @@ "node": ">=8" } }, - "node_modules/cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, "node_modules/d3-color": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", @@ -4157,20 +4259,6 @@ "node": ">=8" } }, - "node_modules/data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", @@ -4228,17 +4316,19 @@ "node": ">=0.10.0" } }, - "node_modules/decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", - "dev": true - }, "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } }, "node_modules/deep-extend": { "version": "0.6.0", @@ -4256,9 +4346,9 @@ "dev": true }, "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, "engines": { "node": ">=0.10.0" @@ -4322,30 +4412,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/del/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -4396,12 +4462,12 @@ } }, "node_modules/diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/dir-glob": { @@ -4446,27 +4512,6 @@ "node": ">=6.0.0" } }, - "node_modules/domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "dependencies": { - "webidl-conversions": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -4495,18 +4540,18 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.196", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.196.tgz", - "integrity": "sha512-uxMa/Dt7PQsLBVXwH+t6JvpHJnrsYBaxWKi/J6HE+/nBtoHENhwBoNkgkm226/Kfxeg0z1eMQLBRPPKcDH8xWA==", + "version": "1.4.685", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.685.tgz", + "integrity": "sha512-yDYeobbTEe4TNooEzOQO6xFqg9XnAkVy2Lod1C1B2it8u47JNLYvl9nLDWBamqUakWB8Jc1hhS1uHUNYTNQdfw==", "dev": true }, "node_modules/emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sindresorhus/emittery?sponsor=1" @@ -4608,88 +4653,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/estraverse": { - "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" - } - }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/eslint": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz", @@ -5048,18 +5011,19 @@ } }, "node_modules/expect": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", - "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/express": { @@ -5243,9 +5207,9 @@ } }, "node_modules/fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, "dependencies": { "bser": "2.1.1" @@ -5376,21 +5340,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/flatted": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", @@ -5417,20 +5366,6 @@ } } }, - "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -5826,24 +5761,6 @@ "node": ">=10" } }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hosted-git-info/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -5856,18 +5773,6 @@ "wbuf": "^1.1.0" } }, - "node_modules/html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^1.0.5" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/html-entities": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", @@ -5922,20 +5827,6 @@ "node": ">=8.0.0" } }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/http-proxy-middleware": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", @@ -6410,12 +6301,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -6440,12 +6325,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -6496,75 +6375,57 @@ } }, "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-instrument": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", - "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", "dev": true, "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "semver": "^7.5.4" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/istanbul-lib-report/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "node": ">=10" } }, "node_modules/istanbul-lib-source-maps": { @@ -6582,9 +6443,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -6604,20 +6465,21 @@ } }, "node_modules/jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", - "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "dependencies": { - "@jest/core": "^27.5.1", + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^27.5.1" + "jest-cli": "^29.7.0" }, "bin": { "jest": "bin/jest.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -6629,73 +6491,103 @@ } }, "node_modules/jest-changed-files": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", - "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", "execa": "^5.0.0", - "throat": "^6.0.1" + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/jest-circus": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", - "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", - "expect": "^27.5.1", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/jest-cli": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", - "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, "dependencies": { - "@jest/core": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", + "create-jest": "^29.7.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "prompts": "^2.0.1", - "yargs": "^16.2.0" + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" }, "bin": { "jest": "bin/jest.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -6706,282 +6598,241 @@ } } }, - "node_modules/jest-cli/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-cli/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/jest-config": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", - "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "dependencies": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", - "glob": "^7.1.1", + "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { + "@types/node": "*", "ts-node": ">=9.0.0" }, "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, "ts-node": { "optional": true } } }, "node_modules/jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", - "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", - "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-environment-jsdom": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", - "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1", - "jsdom": "^16.6.0" + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", - "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", - "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", - "@types/graceful-fs": "^4.1.2", + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^27.5.1", - "jest-serializer": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, - "node_modules/jest-jasmine2": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", - "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "node_modules/jest-haste-map/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "throat": "^6.0.1" + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map/node_modules/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, + "dependencies": { + "has-flag": "^4.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/jest-leak-detector": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", - "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, "dependencies": { - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", - "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-mock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "engines": { "node": ">=6" @@ -6996,167 +6847,220 @@ } }, "node_modules/jest-regex-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", - "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", - "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", + "jest-haste-map": "^29.7.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", + "resolve.exports": "^2.0.0", "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve-dependencies": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", - "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-snapshot": "^27.5.1" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", - "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "dependencies": { - "@jest/console": "^27.5.1", - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "emittery": "^0.8.1", + "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-leak-detector": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "node_modules/jest-runner/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-serializer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", - "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "node_modules/jest-runner/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runner/node_modules/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, "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "graceful-fs": "^4.2.9" + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", - "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "dependencies": { - "@babel/core": "^7.7.2", + "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^27.5.1", + "expect": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "natural-compare": "^1.4.0", - "pretty-format": "^27.5.1", - "semver": "^7.3.2" + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=10" } }, "node_modules/jest-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", - "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -7164,24 +7068,24 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-validate": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", - "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^27.5.1" + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-validate/node_modules/camelcase": { @@ -7197,21 +7101,22 @@ } }, "node_modules/jest-watcher": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", - "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "dependencies": { - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-util": "^27.5.1", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", "string-length": "^4.0.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-worker": { @@ -7261,52 +7166,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -7585,24 +7444,66 @@ "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", "dev": true }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "tmpl": "1.0.5" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "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-dir/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true, "engines": { @@ -8007,9 +7908,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/normalize-package-data": { @@ -10626,12 +10527,6 @@ "inBundle": true, "license": "ISC" }, - "node_modules/nwsapi": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.1.tgz", - "integrity": "sha512-JYOWTeFoS0Z93587vRJgASD5Ut11fYl5NyihP3KrYBvMe1FRRs6RN7m20SA/16GM4P6hTnZjT+UmDOt38UeXNg==", - "dev": true - }, "node_modules/object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -10883,12 +10778,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -10965,9 +10854,9 @@ } }, "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true, "engines": { "node": ">= 6" @@ -11113,17 +11002,17 @@ } }, "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "react-is": "^18.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/pretty-format/node_modules/ansi-styles": { @@ -11185,12 +11074,6 @@ "node": ">= 0.10" } }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -11200,6 +11083,22 @@ "node": ">=6" } }, + "node_modules/pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, "node_modules/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -11225,12 +11124,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -11327,9 +11220,9 @@ } }, "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/read-pkg": { @@ -11606,9 +11499,9 @@ } }, "node_modules/resolve.exports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", - "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true, "engines": { "node": ">=10" @@ -11633,6 +11526,21 @@ "node": ">=0.10.0" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -11668,18 +11576,6 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "node_modules/saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/schema-utils": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", @@ -11840,24 +11736,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -12330,9 +12208,9 @@ "dev": true }, "node_modules/stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "dependencies": { "escape-string-regexp": "^2.0.0" @@ -12496,12 +12374,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -12551,22 +12423,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/terser": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.1.tgz", @@ -12697,12 +12553,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/throat": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", - "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", - "dev": true - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -12774,42 +12624,6 @@ "node": ">=0.6" } }, - "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/traverse": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", @@ -12826,38 +12640,38 @@ } }, "node_modules/ts-jest": { - "version": "27.1.4", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.4.tgz", - "integrity": "sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", + "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", "dev": true, "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", - "jest-util": "^27.0.0", - "json5": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "20.x" + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" }, "bin": { "ts-jest": "cli.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", - "@types/jest": "^27.0.0", - "babel-jest": ">=27.0.0 <28", - "jest": "^27.0.0", - "typescript": ">=3.8 <5.0" + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" }, "peerDependenciesMeta": { "@babel/core": { "optional": true }, - "@types/jest": { + "@jest/types": { "optional": true }, "babel-jest": { @@ -12868,6 +12682,30 @@ } } }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/ts-loader": { "version": "9.3.1", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.3.1.tgz", @@ -13006,15 +12844,6 @@ "node": ">= 0.6" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, "node_modules/typescript": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", @@ -13090,9 +12919,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", - "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "funding": [ { @@ -13102,6 +12931,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { @@ -13109,7 +12942,7 @@ "picocolors": "^1.0.0" }, "bin": { - "browserslist-lint": "cli.js" + "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" @@ -13130,16 +12963,6 @@ "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "dev": true }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -13177,28 +13000,19 @@ "dev": true }, "node_modules/v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" + "convert-source-map": "^2.0.0" }, "engines": { "node": ">=10.12.0" } }, - "node_modules/v8-to-istanbul/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -13218,27 +13032,6 @@ "node": ">= 0.8" } }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "dependencies": { - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -13270,15 +13063,6 @@ "minimalistic-assert": "^1.0.0" } }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true, - "engines": { - "node": ">=10.4" - } - }, "node_modules/webpack": { "version": "5.80.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.80.0.tgz", @@ -13460,21 +13244,6 @@ } } }, - "node_modules/webpack-dev-server/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/webpack-dev-server/node_modules/ws": { "version": "8.8.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", @@ -13590,35 +13359,6 @@ "node": ">=0.8.0" } }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "dependencies": { - "iconv-lite": "0.4.24" - } - }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, - "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -13679,59 +13419,33 @@ "dev": true }, "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true, "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "node": ">=0.4" } }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", @@ -13807,10324 +13521,5 @@ "url": "https://github.com/sponsors/sindresorhus" } } - }, - "dependencies": { - "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@babel/compat-data": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", - "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", - "dev": true - }, - "@babel/core": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.9.tgz", - "integrity": "sha512-1LIb1eL8APMy91/IMW+31ckrfBM4yCoLaVzoDhZUKSM4cu1L1nIidyxkCgzPAgrC5WEz36IPEr/eSeSF9pIn+g==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.9", - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-module-transforms": "^7.18.9", - "@babel/helpers": "^7.18.9", - "@babel/parser": "^7.18.9", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.9", - "@babel/types": "^7.18.9", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.9.tgz", - "integrity": "sha512-wt5Naw6lJrL1/SGkipMiFxJjtyczUWTP38deiP1PO60HsBjDeKk08CGC3S8iVuvf0FmTdgKwU1KIXzSKL1G0Ug==", - "dev": true, - "requires": { - "@babel/types": "^7.18.9", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@babel/helper-compilation-targets": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz", - "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.18.8", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.20.2", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true - }, - "@babel/helper-function-name": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz", - "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==", - "dev": true, - "requires": { - "@babel/template": "^7.18.6", - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-transforms": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz", - "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.9", - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz", - "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==", - "dev": true - }, - "@babel/helper-simple-access": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", - "dev": true - }, - "@babel/helpers": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", - "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", - "dev": true, - "requires": { - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.9", - "@babel/types": "^7.18.9" - } - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz", - "integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==", - "dev": true - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", - "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/template": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", - "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/types": "^7.18.6" - } - }, - "@babel/traverse": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz", - "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.9", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.18.9", - "@babel/types": "^7.18.9", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.9.tgz", - "integrity": "sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "to-fast-properties": "^2.0.0" - } - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "optional": true - }, - "@commitlint/cli": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.0.0.tgz", - "integrity": "sha512-Np6slCdVVG1XwMvwbZrXIzS1INPAD5QmN4L6al04AmCd4nAPU63gxgxC5Mz0Fmx7va23Uvb0S7yEFV1JPhvPUQ==", - "dev": true, - "requires": { - "@commitlint/format": "^17.0.0", - "@commitlint/lint": "^17.0.0", - "@commitlint/load": "^17.0.0", - "@commitlint/read": "^17.0.0", - "@commitlint/types": "^17.0.0", - "lodash": "^4.17.19", - "resolve-from": "5.0.0", - "resolve-global": "1.0.0", - "yargs": "^17.0.0" - } - }, - "@commitlint/config-conventional": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.0.0.tgz", - "integrity": "sha512-jttJXBIq3AuQCvUVwxSctCwKfHxxbALE0IB9OIHYCu/eQdOzPxN72pugeZsWDo1VK/T9iFx+MZoPb6Rb1/ylsw==", - "dev": true, - "requires": { - "conventional-changelog-conventionalcommits": "^4.3.1" - } - }, - "@commitlint/config-validator": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.4.4.tgz", - "integrity": "sha512-bi0+TstqMiqoBAQDvdEP4AFh0GaKyLFlPPEObgI29utoKEYoPQTvF0EYqIwYYLEoJYhj5GfMIhPHJkTJhagfeg==", - "dev": true, - "requires": { - "@commitlint/types": "^17.4.4", - "ajv": "^8.11.0" - } - }, - "@commitlint/ensure": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.0.0.tgz", - "integrity": "sha512-M2hkJnNXvEni59S0QPOnqCKIK52G1XyXBGw51mvh7OXDudCmZ9tZiIPpU882p475Mhx48Ien1MbWjCP1zlyC0A==", - "dev": true, - "requires": { - "@commitlint/types": "^17.0.0", - "lodash": "^4.17.19" - } - }, - "@commitlint/execute-rule": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.4.0.tgz", - "integrity": "sha512-LIgYXuCSO5Gvtc0t9bebAMSwd68ewzmqLypqI2Kke1rqOqqDbMpYcYfoPfFlv9eyLIh4jocHWwCK5FS7z9icUA==", - "dev": true - }, - "@commitlint/format": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.0.0.tgz", - "integrity": "sha512-MZzJv7rBp/r6ZQJDEodoZvdRM0vXu1PfQvMTNWFb8jFraxnISMTnPBWMMjr2G/puoMashwaNM//fl7j8gGV5lA==", - "dev": true, - "requires": { - "@commitlint/types": "^17.0.0", - "chalk": "^4.1.0" - } - }, - "@commitlint/is-ignored": { - "version": "17.6.7", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.6.7.tgz", - "integrity": "sha512-vqyNRqtbq72P2JadaoWiuoLtXIs9SaAWDqdtef6G2zsoXqKFc7vqj1f+thzVgosXG3X/5K9jNp+iYijmvOfc/g==", - "dev": true, - "requires": { - "@commitlint/types": "^17.4.4", - "semver": "7.5.2" - } - }, - "@commitlint/lint": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.0.3.tgz", - "integrity": "sha512-2o1fk7JUdxBUgszyt41sHC/8Nd5PXNpkmuOo9jvGIjDHzOwXyV0PSdbEVTH3xGz9NEmjohFHr5l+N+T9fcxong==", - "dev": true, - "requires": { - "@commitlint/is-ignored": "^17.0.3", - "@commitlint/parse": "^17.0.0", - "@commitlint/rules": "^17.0.0", - "@commitlint/types": "^17.0.0" - } - }, - "@commitlint/load": { - "version": "17.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.5.0.tgz", - "integrity": "sha512-l+4W8Sx4CD5rYFsrhHH8HP01/8jEP7kKf33Xlx2Uk2out/UKoKPYMOIRcDH5ppT8UXLMV+x6Wm5osdRKKgaD1Q==", - "dev": true, - "requires": { - "@commitlint/config-validator": "^17.4.4", - "@commitlint/execute-rule": "^17.4.0", - "@commitlint/resolve-extends": "^17.4.4", - "@commitlint/types": "^17.4.4", - "@types/node": "*", - "chalk": "^4.1.0", - "cosmiconfig": "^8.0.0", - "cosmiconfig-typescript-loader": "^4.0.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "lodash.uniq": "^4.5.0", - "resolve-from": "^5.0.0", - "ts-node": "^10.8.1", - "typescript": "^4.6.4 || ^5.0.0" - }, - "dependencies": { - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - }, - "cosmiconfig": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", - "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", - "dev": true, - "requires": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" - } - }, - "ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - } - }, - "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", - "dev": true - } - } - }, - "@commitlint/message": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.0.0.tgz", - "integrity": "sha512-LpcwYtN+lBlfZijHUdVr8aNFTVpHjuHI52BnfoV01TF7iSLnia0jttzpLkrLmI8HNQz6Vhr9UrxDWtKZiMGsBw==", - "dev": true - }, - "@commitlint/parse": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.0.0.tgz", - "integrity": "sha512-cKcpfTIQYDG1ywTIr5AG0RAiLBr1gudqEsmAGCTtj8ffDChbBRxm6xXs2nv7GvmJN7msOt7vOKleLvcMmRa1+A==", - "dev": true, - "requires": { - "@commitlint/types": "^17.0.0", - "conventional-changelog-angular": "^5.0.11", - "conventional-commits-parser": "^3.2.2" - } - }, - "@commitlint/read": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.0.0.tgz", - "integrity": "sha512-zkuOdZayKX3J6F6mPnVMzohK3OBrsEdOByIqp4zQjA9VLw1hMsDEFQ18rKgUc2adkZar+4S01QrFreDCfZgbxA==", - "dev": true, - "requires": { - "@commitlint/top-level": "^17.0.0", - "@commitlint/types": "^17.0.0", - "fs-extra": "^10.0.0", - "git-raw-commits": "^2.0.0" - } - }, - "@commitlint/resolve-extends": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.4.4.tgz", - "integrity": "sha512-znXr1S0Rr8adInptHw0JeLgumS11lWbk5xAWFVno+HUFVN45875kUtqjrI6AppmD3JI+4s0uZlqqlkepjJd99A==", - "dev": true, - "requires": { - "@commitlint/config-validator": "^17.4.4", - "@commitlint/types": "^17.4.4", - "import-fresh": "^3.0.0", - "lodash.mergewith": "^4.6.2", - "resolve-from": "^5.0.0", - "resolve-global": "^1.0.0" - } - }, - "@commitlint/rules": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.0.0.tgz", - "integrity": "sha512-45nIy3dERKXWpnwX9HeBzK5SepHwlDxdGBfmedXhL30fmFCkJOdxHyOJsh0+B0RaVsLGT01NELpfzJUmtpDwdQ==", - "dev": true, - "requires": { - "@commitlint/ensure": "^17.0.0", - "@commitlint/message": "^17.0.0", - "@commitlint/to-lines": "^17.0.0", - "@commitlint/types": "^17.0.0", - "execa": "^5.0.0" - } - }, - "@commitlint/to-lines": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.0.0.tgz", - "integrity": "sha512-nEi4YEz04Rf2upFbpnEorG8iymyH7o9jYIVFBG1QdzebbIFET3ir+8kQvCZuBE5pKCtViE4XBUsRZz139uFrRQ==", - "dev": true - }, - "@commitlint/top-level": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.0.0.tgz", - "integrity": "sha512-dZrEP1PBJvodNWYPOYiLWf6XZergdksKQaT6i1KSROLdjf5Ai0brLOv5/P+CPxBeoj3vBxK4Ax8H1Pg9t7sHIQ==", - "dev": true, - "requires": { - "find-up": "^5.0.0" - } - }, - "@commitlint/types": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.4.4.tgz", - "integrity": "sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==", - "dev": true, - "requires": { - "chalk": "^4.1.0" - } - }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "dependencies": { - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - } - } - }, - "@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - } - } - }, - "@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jest/console": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", - "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0" - } - }, - "@jest/core": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", - "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", - "dev": true, - "requires": { - "@jest/console": "^27.5.1", - "@jest/reporters": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^27.5.1", - "jest-config": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-resolve-dependencies": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "jest-watcher": "^27.5.1", - "micromatch": "^4.0.4", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "@jest/environment": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", - "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", - "dev": true, - "requires": { - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1" - } - }, - "@jest/fake-timers": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", - "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", - "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - } - }, - "@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" - } - }, - "@jest/reporters": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", - "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-haste-map": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" - } - }, - "@jest/source-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", - "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", - "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", - "dev": true, - "requires": { - "@jest/console": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", - "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", - "dev": true, - "requires": { - "@jest/test-result": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-runtime": "^27.5.1" - } - }, - "@jest/transform": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", - "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.5.1", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-util": "^27.5.1", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - } - }, - "@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - } - }, - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@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 - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/source-map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", - "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@octokit/auth-token": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.0.tgz", - "integrity": "sha512-MDNFUBcJIptB9At7HiV7VCvU3NcL4GnfCQaP8C5lrxWrRPMJBnemYtehaKSOlaM7AYxeRyj9etenu8LVpSpVaQ==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3" - } - }, - "@octokit/core": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.0.4.tgz", - "integrity": "sha512-sUpR/hc4Gc7K34o60bWC7WUH6Q7T6ftZ2dUmepSyJr9PRF76/qqkWjE2SOEzCqLA5W83SaISymwKtxks+96hPQ==", - "dev": true, - "requires": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/endpoint": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.0.tgz", - "integrity": "sha512-Kz/mIkOTjs9rV50hf/JK9pIDl4aGwAtT8pry6Rpy+hVXkAPhXanNQRxMoq6AeRgDCZR6t/A1zKniY2V1YhrzlQ==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/graphql": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.0.tgz", - "integrity": "sha512-1ZZ8tX4lUEcLPvHagfIVu5S2xpHYXAmgN0+95eAOPoaVPzCfUXJtA5vASafcpWcO86ze0Pzn30TAx72aB2aguQ==", - "dev": true, - "requires": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/openapi-types": { - "version": "12.10.1", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.10.1.tgz", - "integrity": "sha512-P+SukKanjFY0ZhsK6wSVnQmxTP2eVPPE8OPSNuxaMYtgVzwJZgfGdwlYjf4RlRU4vLEw4ts2fsE2icG4nZ5ddQ==", - "dev": true - }, - "@octokit/plugin-paginate-rest": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-3.0.0.tgz", - "integrity": "sha512-fvw0Q5IXnn60D32sKeLIxgXCEZ7BTSAjJd8cFAE6QU5qUp0xo7LjFUjjX1J5D7HgN355CN4EXE4+Q1/96JaNUA==", - "dev": true, - "requires": { - "@octokit/types": "^6.39.0" - } - }, - "@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "dev": true, - "requires": {} - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.1.2.tgz", - "integrity": "sha512-sAfSKtLHNq0UQ2iFuI41I6m5SK6bnKFRJ5kUjDRVbmQXiRVi4aQiIcgG4cM7bt+bhSiWL4HwnTxDkWFlKeKClA==", - "dev": true, - "requires": { - "@octokit/types": "^6.40.0", - "deprecation": "^2.3.1" - } - }, - "@octokit/request": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.0.tgz", - "integrity": "sha512-7IAmHnaezZrgUqtRShMlByJK33MT9ZDnMRgZjnRrRV9a/jzzFwKGz0vxhFU6i7VMLraYcQ1qmcAOin37Kryq+Q==", - "dev": true, - "requires": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.0.tgz", - "integrity": "sha512-WBtpzm9lR8z4IHIMtOqr6XwfkGvMOOILNLxsWvDwtzm/n7f5AWuqJTXQXdDtOvPfTDrH4TPhEvW2qMlR4JFA2w==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/rest": { - "version": "19.0.3", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.3.tgz", - "integrity": "sha512-5arkTsnnRT7/sbI4fqgSJ35KiFaN7zQm0uQiQtivNQLI8RQx8EHwJCajcTUwmaCMNDg7tdCvqAnc7uvHHPxrtQ==", - "dev": true, - "requires": { - "@octokit/core": "^4.0.0", - "@octokit/plugin-paginate-rest": "^3.0.0", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^6.0.0" - } - }, - "@octokit/types": { - "version": "6.40.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.40.0.tgz", - "integrity": "sha512-MFZOU5r8SwgJWDMhrLUSvyJPtVsqA6VnbVI3TNbsmw+Jnvrktzvq2fYES/6RiJA/5Ykdwq4mJmtlYUfW7CGjmw==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^12.10.0" - } - }, - "@pnpm/config.env-replace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", - "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", - "dev": true - }, - "@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", - "dev": true, - "requires": { - "graceful-fs": "4.2.10" - } - }, - "@pnpm/npm-conf": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", - "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", - "dev": true, - "requires": { - "@pnpm/config.env-replace": "^1.1.0", - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" - } - }, - "@semantic-release/changelog": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@semantic-release/changelog/-/changelog-6.0.1.tgz", - "integrity": "sha512-FT+tAGdWHr0RCM3EpWegWnvXJ05LQtBkQUaQRIExONoXjVjLuOILNm4DEKNaV+GAQyJjbLRVs57ti//GypH6PA==", - "dev": true, - "requires": { - "@semantic-release/error": "^3.0.0", - "aggregate-error": "^3.0.0", - "fs-extra": "^9.0.0", - "lodash": "^4.17.4" - }, - "dependencies": { - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - } - } - }, - "@semantic-release/commit-analyzer": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-9.0.2.tgz", - "integrity": "sha512-E+dr6L+xIHZkX4zNMe6Rnwg4YQrWNXK+rNsvwOPpdFppvZO1olE2fIgWhv89TkQErygevbjsZFSIxp+u6w2e5g==", - "dev": true, - "requires": { - "conventional-changelog-angular": "^5.0.0", - "conventional-commits-filter": "^2.0.0", - "conventional-commits-parser": "^3.2.3", - "debug": "^4.0.0", - "import-from": "^4.0.0", - "lodash": "^4.17.4", - "micromatch": "^4.0.2" - } - }, - "@semantic-release/error": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-3.0.0.tgz", - "integrity": "sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==", - "dev": true - }, - "@semantic-release/git": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@semantic-release/git/-/git-10.0.1.tgz", - "integrity": "sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==", - "dev": true, - "requires": { - "@semantic-release/error": "^3.0.0", - "aggregate-error": "^3.0.0", - "debug": "^4.0.0", - "dir-glob": "^3.0.0", - "execa": "^5.0.0", - "lodash": "^4.17.4", - "micromatch": "^4.0.0", - "p-reduce": "^2.0.0" - } - }, - "@semantic-release/github": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-8.0.5.tgz", - "integrity": "sha512-9pGxRM3gv1hgoZ/muyd4pWnykdIUVfCiev6MXE9lOyGQof4FQy95GFE26nDcifs9ZG7bBzV8ue87bo/y1zVf0g==", - "dev": true, - "requires": { - "@octokit/rest": "^19.0.0", - "@semantic-release/error": "^2.2.0", - "aggregate-error": "^3.0.0", - "bottleneck": "^2.18.1", - "debug": "^4.0.0", - "dir-glob": "^3.0.0", - "fs-extra": "^10.0.0", - "globby": "^11.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "issue-parser": "^6.0.0", - "lodash": "^4.17.4", - "mime": "^3.0.0", - "p-filter": "^2.0.0", - "p-retry": "^4.0.0", - "url-join": "^4.0.0" - }, - "dependencies": { - "@semantic-release/error": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-2.2.0.tgz", - "integrity": "sha512-9Tj/qn+y2j+sjCI3Jd+qseGtHjOAeg7dU2/lVcqIQ9TV3QDaDXDYXcoOHU+7o2Hwh8L8ymL4gfuO7KxDs3q2zg==", - "dev": true - }, - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true - } - } - }, - "@semantic-release/npm": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-9.0.2.tgz", - "integrity": "sha512-zgsynF6McdzxPnFet+a4iO9HpAlARXOM5adz7VGVCvj0ne8wtL2ZOQoDV2wZPDmdEotDIbVeJjafhelZjs9j6g==", - "dev": true, - "requires": { - "@semantic-release/error": "^3.0.0", - "aggregate-error": "^3.0.0", - "execa": "^5.0.0", - "fs-extra": "^11.0.0", - "lodash": "^4.17.15", - "nerf-dart": "^1.0.0", - "normalize-url": "^6.0.0", - "npm": "^8.3.0", - "rc": "^1.2.8", - "read-pkg": "^5.0.0", - "registry-auth-token": "^5.0.0", - "semver": "^7.1.2", - "tempy": "^1.0.0" - }, - "dependencies": { - "fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - } - } - }, - "@semantic-release/release-notes-generator": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-10.0.3.tgz", - "integrity": "sha512-k4x4VhIKneOWoBGHkx0qZogNjCldLPRiAjnIpMnlUh6PtaWXp/T+C9U7/TaNDDtgDa5HMbHl4WlREdxHio6/3w==", - "dev": true, - "requires": { - "conventional-changelog-angular": "^5.0.0", - "conventional-changelog-writer": "^5.0.0", - "conventional-commits-filter": "^2.0.0", - "conventional-commits-parser": "^3.2.3", - "debug": "^4.0.0", - "get-stream": "^6.0.0", - "import-from": "^4.0.0", - "into-stream": "^6.0.0", - "lodash": "^4.17.4", - "read-pkg-up": "^7.0.0" - } - }, - "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true - }, - "@types/babel__core": { - "version": "7.1.19", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", - "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.17.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", - "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", - "dev": true, - "requires": { - "@babel/types": "^7.3.0" - } - }, - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/bonjour": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", - "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect-history-api-fallback": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", - "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", - "dev": true, - "requires": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "@types/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==", - "dev": true - }, - "@types/d3-drag": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.1.tgz", - "integrity": "sha512-o1Va7bLwwk6h03+nSM8dpaGEYnoIG19P0lKqlic8Un36ymh9NSkNFX1yiXMKNMx8rJ0Kfnn2eovuFaL6Jvj0zA==", - "dev": true, - "requires": { - "@types/d3-selection": "*" - } - }, - "@types/d3-ease": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.0.tgz", - "integrity": "sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==", - "dev": true - }, - "@types/d3-force": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.3.tgz", - "integrity": "sha512-z8GteGVfkWJMKsx6hwC3SiTSLspL98VNpmvLpEFJQpZPq6xpA1I8HNBDNSpukfK0Vb0l64zGFhzunLgEAcBWSA==", - "dev": true - }, - "@types/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==", - "dev": true, - "requires": { - "@types/d3-color": "*" - } - }, - "@types/d3-selection": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.1.tgz", - "integrity": "sha512-aJ1d1SCUtERHH65bB8NNoLpUOI3z8kVcfg2BGm4rMMUwuZF4x6qnIEKjT60Vt0o7gP/a/xkRVs4D9CpDifbyRA==", - "dev": true - }, - "@types/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-Sv4qEI9uq3bnZwlOANvYK853zvpdKEm1yz9rcc8ZTsxvRklcs9Fx4YFuGA3gXoQN/c/1T6QkVNjhaRO/cWj94g==", - "dev": true, - "requires": { - "@types/d3-selection": "*" - } - }, - "@types/d3-zoom": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.1.tgz", - "integrity": "sha512-7s5L9TjfqIYQmQQEUcpMAcBOahem7TRoSO/+Gkz02GbMVuULiZzjF2BOdw291dbO2aNon4m2OdFsRGaCq2caLQ==", - "dev": true, - "requires": { - "@types/d3-interpolate": "*", - "@types/d3-selection": "*" - } - }, - "@types/eslint": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.5.tgz", - "integrity": "sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", - "dev": true - }, - "@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.29", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.29.tgz", - "integrity": "sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/geojson": { - "version": "7946.0.10", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz", - "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==", - "dev": true - }, - "@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/http-proxy": { - "version": "1.17.9", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", - "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/jest": { - "version": "27.4.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", - "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", - "dev": true, - "requires": { - "jest-matcher-utils": "^27.0.0", - "pretty-format": "^27.0.0" - } - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/leaflet": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.9.tgz", - "integrity": "sha512-H8vPgD49HKzqM41ArHGZM70g/tfhp8W+JcPxfnF+5H/Xvp+xiP+KQOUNWU8U89fqS1Jj3cpRY/+nbnaHFzwnFA==", - "dev": true, - "requires": { - "@types/geojson": "*" - } - }, - "@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true - }, - "@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "@types/node": { - "version": "18.0.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.6.tgz", - "integrity": "sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==", - "dev": true - }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "@types/prettier": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.3.tgz", - "integrity": "sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg==", - "dev": true - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true - }, - "@types/resize-observer-browser": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@types/resize-observer-browser/-/resize-observer-browser-0.1.7.tgz", - "integrity": "sha512-G9eN0Sn0ii9PWQ3Vl72jDPgeJwRWhv2Qk/nQkJuWmRmOB4HX3/BhD5SE1dZs/hzPZL/WKnvF0RHdTSG54QJFyg==", - "dev": true - }, - "@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "dev": true - }, - "@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", - "dev": true, - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.24.0.tgz", - "integrity": "sha512-6bqFGk6wa9+6RrU++eLknKyDqXU1Oc8nyoLu5a1fU17PNRJd9UBr56rMF7c4DRaRtnarlkQ4jwxUbvBo8cNlpw==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.24.0", - "@typescript-eslint/type-utils": "5.24.0", - "@typescript-eslint/utils": "5.24.0", - "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.24.0.tgz", - "integrity": "sha512-4q29C6xFYZ5B2CXqSBBdcS0lPyfM9M09DoQLtHS5kf+WbpV8pBBhHDLNhXfgyVwFnhrhYzOu7xmg02DzxeF2Uw==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.24.0", - "@typescript-eslint/types": "5.24.0", - "@typescript-eslint/typescript-estree": "5.24.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.24.0.tgz", - "integrity": "sha512-WpMWipcDzGmMzdT7NtTjRXFabx10WleLUGrJpuJLGaxSqpcyq5ACpKSD5VE40h2nz3melQ91aP4Du7lh9FliCA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.24.0", - "@typescript-eslint/visitor-keys": "5.24.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.24.0.tgz", - "integrity": "sha512-uGi+sQiM6E5CeCZYBXiaIvIChBXru4LZ1tMoeKbh1Lze+8BO9syUG07594C4lvN2YPT4KVeIupOJkVI+9/DAmQ==", - "dev": true, - "requires": { - "@typescript-eslint/utils": "5.24.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.24.0.tgz", - "integrity": "sha512-Tpg1c3shTDgTmZd3qdUyd+16r/pGmVaVEbLs+ufuWP0EruVbUiEOmpBBQxBb9a8iPRxi8Rb2oiwOxuZJzSq11A==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.24.0.tgz", - "integrity": "sha512-zcor6vQkQmZAQfebSPVwUk/FD+CvnsnlfKXYeQDsWXRF+t7SBPmIfNia/wQxCSeu1h1JIjwV2i9f5/DdSp/uDw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.24.0", - "@typescript-eslint/visitor-keys": "5.24.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.24.0.tgz", - "integrity": "sha512-K05sbWoeCBJH8KXu6hetBJ+ukG0k2u2KlgD3bN+v+oBKm8adJqVHpSSLHNzqyuv0Lh4GVSAUgZ5lB4icmPmWLw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.24.0", - "@typescript-eslint/types": "5.24.0", - "@typescript-eslint/typescript-estree": "5.24.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.24.0.tgz", - "integrity": "sha512-qzGwSXMyMnogcAo+/2fU+jhlPPVMXlIH2PeAonIKjJSoDKl1+lJVvG5Z5Oud36yU0TWK2cs1p/FaSN5J2OUFYA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.24.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@webassemblyjs/ast": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.5.tgz", - "integrity": "sha512-LHY/GSAZZRpsNQH+/oHqhRQ5FT7eoULcBqgfyTB5nQHogFnK3/7QoN7dLnwSE/JkUAF0SrRuclT7ODqMFtWxxQ==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.5.tgz", - "integrity": "sha512-1j1zTIC5EZOtCplMBG/IEwLtUojtwFVwdyVMbL/hwWqbzlQoJsWCOavrdnLkemwNoC/EOwtUFch3fuo+cbcXYQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.5.tgz", - "integrity": "sha512-L65bDPmfpY0+yFrsgz8b6LhXmbbs38OnwDCf6NpnMUYqa+ENfE5Dq9E42ny0qz/PdR0LJyq/T5YijPnU8AXEpA==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.5.tgz", - "integrity": "sha512-fDKo1gstwFFSfacIeH5KfwzjykIE6ldh1iH9Y/8YkAZrhmu4TctqYjSh7t0K2VyDSXOZJ1MLhht/k9IvYGcIxg==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.5.tgz", - "integrity": "sha512-DhykHXM0ZABqfIGYNv93A5KKDw/+ywBFnuWybZZWcuzWHfbp21wUfRkbtz7dMGwGgT4iXjWuhRMA2Mzod6W4WA==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.5", - "@webassemblyjs/helper-api-error": "1.11.5", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.5.tgz", - "integrity": "sha512-oC4Qa0bNcqnjAowFn7MPCETQgDYytpsfvz4ujZz63Zu/a/v71HeCAAmZsgZ3YVKec3zSPYytG3/PrRCqbtcAvA==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.5.tgz", - "integrity": "sha512-uEoThA1LN2NA+K3B9wDo3yKlBfVtC6rh0i4/6hvbz071E8gTNZD/pT0MsBf7MeD6KbApMSkaAK0XeKyOZC7CIA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.5.tgz", - "integrity": "sha512-37aGq6qVL8A8oPbPrSGMBcp38YZFXcHfiROflJn9jxSdSMMM5dS5P/9e2/TpaJuhE+wFrbukN2WI6Hw9MH5acg==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.5.tgz", - "integrity": "sha512-ajqrRSXaTJoPW+xmkfYN6l8VIeNnR4vBOTQO9HzR7IygoCcKWkICbKFbVTNMjMgMREqXEr0+2M6zukzM47ZUfQ==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.5.tgz", - "integrity": "sha512-WiOhulHKTZU5UPlRl53gHR8OxdGsSOxqfpqWeA2FmcwBMaoEdz6b2x2si3IwC9/fSPLfe8pBMRTHVMk5nlwnFQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.5.tgz", - "integrity": "sha512-C0p9D2fAu3Twwqvygvf42iGCQ4av8MFBLiTb+08SZ4cEdwzWx9QeAHDo1E2k+9s/0w1DM40oflJOpkZ8jW4HCQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/helper-wasm-section": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5", - "@webassemblyjs/wasm-opt": "1.11.5", - "@webassemblyjs/wasm-parser": "1.11.5", - "@webassemblyjs/wast-printer": "1.11.5" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.5.tgz", - "integrity": "sha512-14vteRlRjxLK9eSyYFvw1K8Vv+iPdZU0Aebk3j6oB8TQiQYuO6hj9s4d7qf6f2HJr2khzvNldAFG13CgdkAIfA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/ieee754": "1.11.5", - "@webassemblyjs/leb128": "1.11.5", - "@webassemblyjs/utf8": "1.11.5" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.5.tgz", - "integrity": "sha512-tcKwlIXstBQgbKy1MlbDMlXaxpucn42eb17H29rawYLxm5+MsEmgPzeCP8B1Cl69hCice8LeKgZpRUAPtqYPgw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5", - "@webassemblyjs/wasm-parser": "1.11.5" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.5.tgz", - "integrity": "sha512-SVXUIwsLQlc8srSD7jejsfTU83g7pIGr2YYNb9oHdtldSxaOhvA5xwvIiWIfcX8PlSakgqMXsLpLfbbJ4cBYew==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-api-error": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/ieee754": "1.11.5", - "@webassemblyjs/leb128": "1.11.5", - "@webassemblyjs/utf8": "1.11.5" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.5.tgz", - "integrity": "sha512-f7Pq3wvg3GSPUPzR0F6bmI89Hdb+u9WXrSKc4v+N0aV0q6r42WoF92Jp2jEorBEBRoRNXgjp53nBniDXcqZYPA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.5", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-cli/configtest": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", - "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", - "dev": true, - "requires": {} - }, - "@webpack-cli/info": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", - "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", - "dev": true, - "requires": { - "envinfo": "^7.7.3" - } - }, - "@webpack-cli/serve": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", - "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", - "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 - }, - "@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 - }, - "abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true - }, - "acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - } - } - }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "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" - } - }, - "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" - } - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } - } - }, - "ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "ansicolors": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", - "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", - "dev": true - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "argv-formatter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/argv-formatter/-/argv-formatter-1.0.0.tgz", - "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", - "dev": true - }, - "array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true - }, - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, - "babel-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", - "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", - "dev": true, - "requires": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - } - }, - "babel-preset-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", - "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^27.5.1", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "before-after-hook": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", - "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "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.10.3", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - } - } - }, - "bonjour-service": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.13.tgz", - "integrity": "sha512-LWKRU/7EqDUC9CTAQtuZl5HzBALoCYwtLhffW3et7vZMwv3bWLpJf8bRYlMD5OCcDpTfnPgNCV4yo9ZIaJGMiA==", - "dev": true, - "requires": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "bottleneck": { - "version": "2.19.5", - "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", - "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, - "browserslist": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.2.tgz", - "integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001366", - "electron-to-chromium": "^1.4.188", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.4" - } - }, - "bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "requires": { - "fast-json-stable-stringify": "2.x" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "requires": { - "node-int64": "^0.4.0" - } - }, - "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 - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - } - }, - "caniuse-lite": { - "version": "1.0.30001368", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001368.tgz", - "integrity": "sha512-wgfRYa9DenEomLG/SdWgQxpIyvdtH3NW8Vq+tB6AwR9e56iOIcu1im5F/wNdDf04XlKHXqIx4N8Jo0PemeBenQ==", - "dev": true - }, - "cardinal": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", - "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", - "dev": true, - "requires": { - "ansicolors": "~0.3.2", - "redeyed": "~2.1.0" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "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 - }, - "ci-info": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", - "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", - "dev": true - }, - "cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-table3": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz", - "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==", - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "string-width": "^4.2.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true - }, - "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "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 - }, - "compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "requires": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "requires": { - "safe-buffer": "5.2.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, - "conventional-changelog-angular": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", - "dev": true, - "requires": { - "compare-func": "^2.0.0", - "q": "^1.5.1" - } - }, - "conventional-changelog-conventionalcommits": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz", - "integrity": "sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==", - "dev": true, - "requires": { - "compare-func": "^2.0.0", - "lodash": "^4.17.15", - "q": "^1.5.1" - } - }, - "conventional-changelog-eslint": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", - "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", - "dev": true, - "requires": { - "q": "^1.5.1" - } - }, - "conventional-changelog-writer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", - "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", - "dev": true, - "requires": { - "conventional-commits-filter": "^2.0.7", - "dateformat": "^3.0.0", - "handlebars": "^4.7.7", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "semver": "^6.0.0", - "split": "^1.0.0", - "through2": "^4.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "conventional-commits-filter": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", - "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", - "dev": true, - "requires": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.0" - } - }, - "conventional-commits-parser": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", - "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", - "dev": true, - "requires": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - } - }, - "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "copy-webpack-plugin": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", - "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", - "dev": true, - "requires": { - "fast-glob": "^3.2.11", - "glob-parent": "^6.0.1", - "globby": "^13.1.1", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" - }, - "dependencies": { - "globby": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz", - "integrity": "sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==", - "dev": true, - "requires": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^4.0.0" - } - }, - "slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true - } - } - }, - "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 - }, - "corser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", - "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", - "dev": true - }, - "cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - } - }, - "cosmiconfig-typescript-loader": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.3.0.tgz", - "integrity": "sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q==", - "dev": true, - "requires": {} - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true - }, - "cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } - } - }, - "d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==" - }, - "d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==" - }, - "d3-drag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", - "requires": { - "d3-dispatch": "1 - 3", - "d3-selection": "3" - } - }, - "d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==" - }, - "d3-force": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", - "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", - "requires": { - "d3-dispatch": "1 - 3", - "d3-quadtree": "1 - 3", - "d3-timer": "1 - 3" - } - }, - "d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "requires": { - "d3-color": "1 - 3" - } - }, - "d3-quadtree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", - "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==" - }, - "d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==" - }, - "d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==" - }, - "d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", - "requires": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" - } - }, - "d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "requires": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" - } - }, - "dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "dev": true - }, - "data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "requires": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - } - }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true - }, - "decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==", - "dev": true, - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true - } - } - }, - "decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", - "dev": true - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true - }, - "default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "requires": { - "execa": "^5.0.0" - } - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true - }, - "del": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", - "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", - "dev": true, - "requires": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "dependencies": { - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", - "dev": true - }, - "dns-packet": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.4.0.tgz", - "integrity": "sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==", - "dev": true, - "requires": { - "@leichtgewicht/ip-codec": "^2.0.1" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "requires": { - "webidl-conversions": "^5.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } - } - }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.4.196", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.196.tgz", - "integrity": "sha512-uxMa/Dt7PQsLBVXwH+t6JvpHJnrsYBaxWKi/J6HE+/nBtoHENhwBoNkgkm226/Kfxeg0z1eMQLBRPPKcDH8xWA==", - "dev": true - }, - "emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true - }, - "enhanced-resolve": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.13.0.tgz", - "integrity": "sha512-eyV8f0y1+bzyfh8xAwW/WTSZpLbjhqc4ne9eGSH4Zo2ejdyiNG9pU6mf9DG8a7+Auk6MFTlNOT4Y2y/9k8GKVg==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "env-ci": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-5.5.0.tgz", - "integrity": "sha512-o0JdWIbOLP+WJKIUt36hz1ImQQFuN92nhsfTkHHap+J8CiI8WgGpH/a9jEGHh4/TU5BUUGjlnKXNoDb57+ne+A==", - "dev": true, - "requires": { - "execa": "^5.0.0", - "fromentries": "^1.3.2", - "java-properties": "^1.0.0" - } - }, - "envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-module-lexer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", - "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - } - } - }, - "eslint": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz", - "integrity": "sha512-GG5USZ1jhCu8HJkzGgeK8/+RGnHaNYZGrGDzUtigK3BsGESW/rs2az23XqE0WVwDxy1VRvvjSSGu5nB0Bu+6SA==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.2.3", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - } - } - }, - "eslint-config-google": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", - "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", - "dev": true, - "requires": {} - }, - "eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "requires": {} - }, - "eslint-plugin-jest": { - "version": "26.2.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.2.2.tgz", - "integrity": "sha512-etSFZ8VIFX470aA6kTqDPhIq7YWe0tjBcboFNV3WeiC18PJ/AVonGhuTwlmuz2fBkH8FJHA7JQ4k7GsQIj1Gew==", - "dev": true, - "requires": { - "@typescript-eslint/utils": "^5.10.0" - } - }, - "eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-scope": { - "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" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", - "dev": true, - "requires": { - "acorn": "^8.7.1", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "esrecurse": { - "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" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "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" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true - }, - "expect": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", - "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1" - } - }, - "express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", - "dev": true, - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.0", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.10.3", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "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 - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastest-levenshtein": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.14.tgz", - "integrity": "sha512-tFfWHjnuUfKE186Tfgr+jtaFc0mZTApEgKDOeyN+FwOqRkO/zK/3h1AiRd8u8CY53owL3CUmGr/oI9p/RdyLTA==", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", - "dev": true, - "requires": { - "bser": "2.1.1" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - } - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "find-versions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", - "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", - "dev": true, - "requires": { - "semver-regex": "^3.1.2" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "flatted": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", - "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", - "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", - "dev": true - }, - "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "dev": true - }, - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", - "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "git-log-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", - "integrity": "sha512-rnCVNfkTL8tdNryFuaY0fYiBWEBcgF748O6ZI61rslBvr2o7U65c2/6npCRqH40vuAhtgtDiqLTJjBVdrejCzA==", - "dev": true, - "requires": { - "argv-formatter": "~1.0.0", - "spawn-error-forwarder": "~1.0.0", - "split2": "~1.0.0", - "stream-combiner2": "~1.1.1", - "through2": "~2.0.0", - "traverse": "~0.6.6" - }, - "dependencies": { - "split2": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", - "integrity": "sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==", - "dev": true, - "requires": { - "through2": "~2.0.0" - } - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - } - } - }, - "git-raw-commits": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", - "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", - "dev": true, - "requires": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "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 - }, - "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", - "dev": true, - "requires": { - "ini": "^1.3.4" - } - }, - "globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - } - }, - "hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "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 - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "hook-std": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-2.0.0.tgz", - "integrity": "sha512-zZ6T5WcuBMIUVh49iPQS9t977t7C0l7OtHrpeMb5uk48JdflRX0NSFvCekfYNmGQETnLq9W/isMyHl69kxGi8g==", - "dev": true - }, - "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.5" - } - }, - "html-entities": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", - "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "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==", - "dev": true, - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, - "requires": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "dependencies": { - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true - } - } - }, - "http-server": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", - "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", - "dev": true, - "requires": { - "basic-auth": "^2.0.1", - "chalk": "^4.1.2", - "corser": "^2.0.1", - "he": "^1.2.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy": "^1.18.1", - "mime": "^1.6.0", - "minimist": "^1.2.6", - "opener": "^1.5.1", - "portfinder": "^1.0.28", - "secure-compare": "3.0.1", - "union": "~0.5.0", - "url-join": "^4.0.1" - }, - "dependencies": { - "html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "requires": { - "whatwg-encoding": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "requires": { - "iconv-lite": "0.6.3" - } - } - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "husky": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", - "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "import-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-4.0.0.tgz", - "integrity": "sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==", - "dev": true - }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true - }, - "into-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-6.0.0.tgz", - "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==", - "dev": true, - "requires": { - "from2": "^2.3.0", - "p-is-promise": "^3.0.0" - } - }, - "ipaddr.js": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", - "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true - }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - }, - "is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", - "dev": true, - "requires": { - "text-extensions": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - }, - "issue-parser": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz", - "integrity": "sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==", - "dev": true, - "requires": { - "lodash.capitalize": "^4.2.1", - "lodash.escaperegexp": "^4.1.2", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.uniqby": "^4.7.0" - } - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", - "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "java-properties": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-1.0.2.tgz", - "integrity": "sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==", - "dev": true - }, - "jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", - "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", - "dev": true, - "requires": { - "@jest/core": "^27.5.1", - "import-local": "^3.0.2", - "jest-cli": "^27.5.1" - } - }, - "jest-changed-files": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", - "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "execa": "^5.0.0", - "throat": "^6.0.1" - } - }, - "jest-circus": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", - "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" - } - }, - "jest-cli": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", - "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", - "dev": true, - "requires": { - "@jest/core": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "prompts": "^2.0.1", - "yargs": "^16.2.0" - }, - "dependencies": { - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - } - } - }, - "jest-config": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", - "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", - "dev": true, - "requires": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, - "jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - } - }, - "jest-docblock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", - "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", - "dev": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", - "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1" - } - }, - "jest-environment-jsdom": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", - "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1", - "jsdom": "^16.6.0" - } - }, - "jest-environment-node": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", - "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - } - }, - "jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", - "dev": true - }, - "jest-haste-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", - "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/graceful-fs": "^4.1.2", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^27.5.1", - "jest-serializer": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "micromatch": "^4.0.4", - "walker": "^1.0.7" - } - }, - "jest-jasmine2": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", - "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "throat": "^6.0.1" - } - }, - "jest-leak-detector": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", - "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", - "dev": true, - "requires": { - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - } - }, - "jest-matcher-utils": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", - "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - } - }, - "jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-mock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/node": "*" - } - }, - "jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true, - "requires": {} - }, - "jest-regex-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", - "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", - "dev": true - }, - "jest-resolve": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", - "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" - } - }, - "jest-resolve-dependencies": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", - "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-snapshot": "^27.5.1" - } - }, - "jest-runner": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", - "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", - "dev": true, - "requires": { - "@jest/console": "^27.5.1", - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-leak-detector": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" - } - }, - "jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - } - }, - "jest-serializer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", - "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", - "dev": true, - "requires": { - "@types/node": "*", - "graceful-fs": "^4.2.9" - } - }, - "jest-snapshot": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", - "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", - "dev": true, - "requires": { - "@babel/core": "^7.7.2", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^27.5.1", - "semver": "^7.3.2" - } - }, - "jest-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", - "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", - "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "leven": "^3.1.0", - "pretty-format": "^27.5.1" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - } - } - }, - "jest-watcher": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", - "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", - "dev": true, - "requires": { - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^27.5.1", - "string-length": "^4.0.1" - } - }, - "jest-worker": { - "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", - "supports-color": "^8.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "requires": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "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": "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 - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - }, - "leaflet": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.8.0.tgz", - "integrity": "sha512-gwhMjFCQiYs3x/Sf+d49f10ERXaEFCPr+nVTryhAW8DWbMGqJqt9G4XuIaHmFW08zYvhgdzqXGr8AlW8v8dQkA==" - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - } - } - }, - "loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.capitalize": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", - "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", - "dev": true - }, - "lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", - "dev": true - }, - "lodash.ismatch": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", - "dev": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "lodash.uniqby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", - "dev": true - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "requires": { - "tmpl": "1.0.5" - } - }, - "map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true - }, - "marked": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.18.tgz", - "integrity": "sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==", - "dev": true - }, - "marked-terminal": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.1.1.tgz", - "integrity": "sha512-+cKTOx9P4l7HwINYhzbrBSyzgxO2HaHKGZGuB1orZsMIgXYaJyfidT81VXRdpelW/PcHEWxywscePVgI/oUF6g==", - "dev": true, - "requires": { - "ansi-escapes": "^5.0.0", - "cardinal": "^2.1.1", - "chalk": "^5.0.0", - "cli-table3": "^0.6.1", - "node-emoji": "^1.11.0", - "supports-hyperlinks": "^2.2.0" - }, - "dependencies": { - "ansi-escapes": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", - "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", - "dev": true, - "requires": { - "type-fest": "^1.0.2" - } - }, - "chalk": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", - "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", - "dev": true - }, - "type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true - } - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true - }, - "memfs": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz", - "integrity": "sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw==", - "dev": true, - "requires": { - "fs-monkey": "^1.0.3" - } - }, - "meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "dev": true, - "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "dependencies": { - "type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true - } - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "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 - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "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 - }, - "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" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "modify-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "requires": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - } - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true - }, - "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 - }, - "nerf-dart": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", - "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", - "dev": true - }, - "node-emoji": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", - "dev": true, - "requires": { - "lodash": "^4.17.21" - } - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - }, - "dependencies": { - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - } - }, - "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true - }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true - }, - "npm": { - "version": "8.19.4", - "resolved": "https://registry.npmjs.org/npm/-/npm-8.19.4.tgz", - "integrity": "sha512-3HANl8i9DKnUA89P4KEgVNN28EjSeDCmvEqbzOAuxCFDzdBZzjUl99zgnGpOUumvW5lvJo2HKcjrsc+tfyv1Hw==", - "dev": true, - "requires": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^5.6.3", - "@npmcli/ci-detect": "^2.0.0", - "@npmcli/config": "^4.2.1", - "@npmcli/fs": "^2.1.0", - "@npmcli/map-workspaces": "^2.0.3", - "@npmcli/package-json": "^2.0.0", - "@npmcli/run-script": "^4.2.1", - "abbrev": "~1.1.1", - "archy": "~1.0.0", - "cacache": "^16.1.3", - "chalk": "^4.1.2", - "chownr": "^2.0.0", - "cli-columns": "^4.0.0", - "cli-table3": "^0.6.2", - "columnify": "^1.6.0", - "fastest-levenshtein": "^1.0.12", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "graceful-fs": "^4.2.10", - "hosted-git-info": "^5.2.1", - "ini": "^3.0.1", - "init-package-json": "^3.0.2", - "is-cidr": "^4.0.2", - "json-parse-even-better-errors": "^2.3.1", - "libnpmaccess": "^6.0.4", - "libnpmdiff": "^4.0.5", - "libnpmexec": "^4.0.14", - "libnpmfund": "^3.0.5", - "libnpmhook": "^8.0.4", - "libnpmorg": "^4.0.4", - "libnpmpack": "^4.1.3", - "libnpmpublish": "^6.0.5", - "libnpmsearch": "^5.0.4", - "libnpmteam": "^4.0.4", - "libnpmversion": "^3.0.7", - "make-fetch-happen": "^10.2.0", - "minimatch": "^5.1.0", - "minipass": "^3.1.6", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "mkdirp-infer-owner": "^2.0.0", - "ms": "^2.1.2", - "node-gyp": "^9.1.0", - "nopt": "^6.0.0", - "npm-audit-report": "^3.0.0", - "npm-install-checks": "^5.0.0", - "npm-package-arg": "^9.1.0", - "npm-pick-manifest": "^7.0.2", - "npm-profile": "^6.2.0", - "npm-registry-fetch": "^13.3.1", - "npm-user-validate": "^1.0.1", - "npmlog": "^6.0.2", - "opener": "^1.5.2", - "p-map": "^4.0.0", - "pacote": "^13.6.2", - "parse-conflict-json": "^2.0.2", - "proc-log": "^2.0.1", - "qrcode-terminal": "^0.12.0", - "read": "~1.0.7", - "read-package-json": "^5.0.2", - "read-package-json-fast": "^2.0.3", - "readdir-scoped-modules": "^1.1.0", - "rimraf": "^3.0.2", - "semver": "^7.3.7", - "ssri": "^9.0.1", - "tar": "^6.1.11", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "treeverse": "^2.0.0", - "validate-npm-package-name": "^4.0.0", - "which": "^2.0.2", - "write-file-atomic": "^4.0.1" - }, - "dependencies": { - "@colors/colors": { - "version": "1.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "@gar/promisify": { - "version": "1.1.3", - "bundled": true, - "dev": true - }, - "@isaacs/string-locale-compare": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "@npmcli/arborist": { - "version": "5.6.3", - "bundled": true, - "dev": true, - "requires": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/map-workspaces": "^2.0.3", - "@npmcli/metavuln-calculator": "^3.0.1", - "@npmcli/move-file": "^2.0.0", - "@npmcli/name-from-folder": "^1.0.1", - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/package-json": "^2.0.0", - "@npmcli/query": "^1.2.0", - "@npmcli/run-script": "^4.1.3", - "bin-links": "^3.0.3", - "cacache": "^16.1.3", - "common-ancestor-path": "^1.0.1", - "hosted-git-info": "^5.2.1", - "json-parse-even-better-errors": "^2.3.1", - "json-stringify-nice": "^1.1.4", - "minimatch": "^5.1.0", - "mkdirp": "^1.0.4", - "mkdirp-infer-owner": "^2.0.0", - "nopt": "^6.0.0", - "npm-install-checks": "^5.0.0", - "npm-package-arg": "^9.0.0", - "npm-pick-manifest": "^7.0.2", - "npm-registry-fetch": "^13.0.0", - "npmlog": "^6.0.2", - "pacote": "^13.6.1", - "parse-conflict-json": "^2.0.1", - "proc-log": "^2.0.0", - "promise-all-reject-late": "^1.0.0", - "promise-call-limit": "^1.0.1", - "read-package-json-fast": "^2.0.2", - "readdir-scoped-modules": "^1.1.0", - "rimraf": "^3.0.2", - "semver": "^7.3.7", - "ssri": "^9.0.0", - "treeverse": "^2.0.0", - "walk-up-path": "^1.0.0" - } - }, - "@npmcli/ci-detect": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "@npmcli/config": { - "version": "4.2.2", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/map-workspaces": "^2.0.2", - "ini": "^3.0.0", - "mkdirp-infer-owner": "^2.0.0", - "nopt": "^6.0.0", - "proc-log": "^2.0.0", - "read-package-json-fast": "^2.0.3", - "semver": "^7.3.5", - "walk-up-path": "^1.0.0" - } - }, - "@npmcli/disparity-colors": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-styles": "^4.3.0" - } - }, - "@npmcli/fs": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "requires": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - } - }, - "@npmcli/git": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/promise-spawn": "^3.0.0", - "lru-cache": "^7.4.4", - "mkdirp": "^1.0.4", - "npm-pick-manifest": "^7.0.0", - "proc-log": "^2.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^2.0.2" - } - }, - "@npmcli/installed-package-contents": { - "version": "1.0.7", - "bundled": true, - "dev": true, - "requires": { - "npm-bundled": "^1.1.1", - "npm-normalize-package-bin": "^1.0.1" - }, - "dependencies": { - "npm-bundled": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - } - } - }, - "@npmcli/map-workspaces": { - "version": "2.0.4", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/name-from-folder": "^1.0.1", - "glob": "^8.0.1", - "minimatch": "^5.0.1", - "read-package-json-fast": "^2.0.3" - } - }, - "@npmcli/metavuln-calculator": { - "version": "3.1.1", - "bundled": true, - "dev": true, - "requires": { - "cacache": "^16.0.0", - "json-parse-even-better-errors": "^2.3.1", - "pacote": "^13.0.3", - "semver": "^7.3.5" - } - }, - "@npmcli/move-file": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "@npmcli/name-from-folder": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "@npmcli/node-gyp": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "@npmcli/package-json": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "json-parse-even-better-errors": "^2.3.1" - } - }, - "@npmcli/promise-spawn": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "infer-owner": "^1.0.4" - } - }, - "@npmcli/query": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "requires": { - "npm-package-arg": "^9.1.0", - "postcss-selector-parser": "^6.0.10", - "semver": "^7.3.7" - } - }, - "@npmcli/run-script": { - "version": "4.2.1", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/promise-spawn": "^3.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^2.0.3", - "which": "^2.0.2" - } - }, - "@tootallnate/once": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "bundled": true, - "dev": true, - "requires": { - "debug": "4" - } - }, - "agentkeepalive": { - "version": "4.2.1", - "bundled": true, - "dev": true, - "requires": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" - } - }, - "aggregate-error": { - "version": "3.1.0", - "bundled": true, - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ansi-regex": { - "version": "5.0.1", - "bundled": true, - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "bundled": true, - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "aproba": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "archy": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "are-we-there-yet": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "asap": { - "version": "2.0.6", - "bundled": true, - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "bin-links": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "requires": { - "cmd-shim": "^5.0.0", - "mkdirp-infer-owner": "^2.0.0", - "npm-normalize-package-bin": "^2.0.0", - "read-cmd-shim": "^3.0.0", - "rimraf": "^3.0.0", - "write-file-atomic": "^4.0.0" - }, - "dependencies": { - "npm-normalize-package-bin": { - "version": "2.0.0", - "bundled": true, - "dev": true - } - } - }, - "binary-extensions": { - "version": "2.2.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "builtins": { - "version": "5.0.1", - "bundled": true, - "dev": true, - "requires": { - "semver": "^7.0.0" - } - }, - "cacache": { - "version": "16.1.3", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - } - }, - "chalk": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "chownr": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "cidr-regex": { - "version": "3.1.1", - "bundled": true, - "dev": true, - "requires": { - "ip-regex": "^4.1.0" - } - }, - "clean-stack": { - "version": "2.2.0", - "bundled": true, - "dev": true - }, - "cli-columns": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - } - }, - "cli-table3": { - "version": "0.6.2", - "bundled": true, - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "string-width": "^4.2.0" - } - }, - "clone": { - "version": "1.0.4", - "bundled": true, - "dev": true - }, - "cmd-shim": { - "version": "5.0.0", - "bundled": true, - "dev": true, - "requires": { - "mkdirp-infer-owner": "^2.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "bundled": true, - "dev": true - }, - "color-support": { - "version": "1.1.3", - "bundled": true, - "dev": true - }, - "columnify": { - "version": "1.6.0", - "bundled": true, - "dev": true, - "requires": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" - } - }, - "common-ancestor-path": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "debug": { - "version": "4.3.4", - "bundled": true, - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "bundled": true, - "dev": true - } - } - }, - "debuglog": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "defaults": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "depd": { - "version": "1.1.2", - "bundled": true, - "dev": true - }, - "dezalgo": { - "version": "1.0.4", - "bundled": true, - "dev": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "diff": { - "version": "5.1.0", - "bundled": true, - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "bundled": true, - "dev": true - }, - "encoding": { - "version": "0.1.13", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "iconv-lite": "^0.6.2" - } - }, - "env-paths": { - "version": "2.2.1", - "bundled": true, - "dev": true - }, - "err-code": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "fastest-levenshtein": { - "version": "1.0.12", - "bundled": true, - "dev": true - }, - "fs-minipass": { - "version": "2.1.0", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "bundled": true, - "dev": true - }, - "gauge": { - "version": "4.0.4", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "glob": { - "version": "8.0.3", - "bundled": true, - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "bundled": true, - "dev": true - }, - "has": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "hosted-git-info": { - "version": "5.2.1", - "bundled": true, - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "http-cache-semantics": { - "version": "4.1.1", - "bundled": true, - "dev": true - }, - "http-proxy-agent": { - "version": "5.0.0", - "bundled": true, - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "bundled": true, - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "humanize-ms": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "ignore-walk": { - "version": "5.0.1", - "bundled": true, - "dev": true, - "requires": { - "minimatch": "^5.0.1" - } - }, - "imurmurhash": { - "version": "0.1.4", - "bundled": true, - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "bundled": true, - "dev": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true, - "dev": true - }, - "ini": { - "version": "3.0.1", - "bundled": true, - "dev": true - }, - "init-package-json": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "requires": { - "npm-package-arg": "^9.0.1", - "promzard": "^0.3.0", - "read": "^1.0.7", - "read-package-json": "^5.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^4.0.0" - } - }, - "ip": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "ip-regex": { - "version": "4.3.0", - "bundled": true, - "dev": true - }, - "is-cidr": { - "version": "4.0.2", - "bundled": true, - "dev": true, - "requires": { - "cidr-regex": "^3.1.1" - } - }, - "is-core-module": { - "version": "2.10.0", - "bundled": true, - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "is-lambda": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "isexe": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "bundled": true, - "dev": true - }, - "json-stringify-nice": { - "version": "1.1.4", - "bundled": true, - "dev": true - }, - "jsonparse": { - "version": "1.3.1", - "bundled": true, - "dev": true - }, - "just-diff": { - "version": "5.1.1", - "bundled": true, - "dev": true - }, - "just-diff-apply": { - "version": "5.4.1", - "bundled": true, - "dev": true - }, - "libnpmaccess": { - "version": "6.0.4", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^2.0.0", - "minipass": "^3.1.1", - "npm-package-arg": "^9.0.1", - "npm-registry-fetch": "^13.0.0" - } - }, - "libnpmdiff": { - "version": "4.0.5", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/disparity-colors": "^2.0.0", - "@npmcli/installed-package-contents": "^1.0.7", - "binary-extensions": "^2.2.0", - "diff": "^5.1.0", - "minimatch": "^5.0.1", - "npm-package-arg": "^9.0.1", - "pacote": "^13.6.1", - "tar": "^6.1.0" - } - }, - "libnpmexec": { - "version": "4.0.14", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/arborist": "^5.6.3", - "@npmcli/ci-detect": "^2.0.0", - "@npmcli/fs": "^2.1.1", - "@npmcli/run-script": "^4.2.0", - "chalk": "^4.1.0", - "mkdirp-infer-owner": "^2.0.0", - "npm-package-arg": "^9.0.1", - "npmlog": "^6.0.2", - "pacote": "^13.6.1", - "proc-log": "^2.0.0", - "read": "^1.0.7", - "read-package-json-fast": "^2.0.2", - "semver": "^7.3.7", - "walk-up-path": "^1.0.0" - } - }, - "libnpmfund": { - "version": "3.0.5", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/arborist": "^5.6.3" - } - }, - "libnpmhook": { - "version": "8.0.4", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^13.0.0" - } - }, - "libnpmorg": { - "version": "4.0.4", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^13.0.0" - } - }, - "libnpmpack": { - "version": "4.1.3", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/run-script": "^4.1.3", - "npm-package-arg": "^9.0.1", - "pacote": "^13.6.1" - } - }, - "libnpmpublish": { - "version": "6.0.5", - "bundled": true, - "dev": true, - "requires": { - "normalize-package-data": "^4.0.0", - "npm-package-arg": "^9.0.1", - "npm-registry-fetch": "^13.0.0", - "semver": "^7.3.7", - "ssri": "^9.0.0" - } - }, - "libnpmsearch": { - "version": "5.0.4", - "bundled": true, - "dev": true, - "requires": { - "npm-registry-fetch": "^13.0.0" - } - }, - "libnpmteam": { - "version": "4.0.4", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^13.0.0" - } - }, - "libnpmversion": { - "version": "3.0.7", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/git": "^3.0.0", - "@npmcli/run-script": "^4.1.3", - "json-parse-even-better-errors": "^2.3.1", - "proc-log": "^2.0.0", - "semver": "^7.3.7" - } - }, - "lru-cache": { - "version": "7.13.2", - "bundled": true, - "dev": true - }, - "make-fetch-happen": { - "version": "10.2.1", - "bundled": true, - "dev": true, - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - } - }, - "minimatch": { - "version": "5.1.0", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "3.3.4", - "bundled": true, - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-fetch": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - }, - "minipass-flush": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-json-stream": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-sized": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "bundled": true, - "dev": true - }, - "mkdirp-infer-owner": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "chownr": "^2.0.0", - "infer-owner": "^1.0.4", - "mkdirp": "^1.0.3" - } - }, - "ms": { - "version": "2.1.3", - "bundled": true, - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "bundled": true, - "dev": true - }, - "node-gyp": { - "version": "9.1.0", - "bundled": true, - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "glob": { - "version": "7.2.3", - "bundled": true, - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "nopt": { - "version": "5.0.0", - "bundled": true, - "dev": true, - "requires": { - "abbrev": "1" - } - } - } - }, - "nopt": { - "version": "6.0.0", - "bundled": true, - "dev": true, - "requires": { - "abbrev": "^1.0.0" - } - }, - "normalize-package-data": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "requires": { - "hosted-git-info": "^5.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - } - }, - "npm-audit-report": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "chalk": "^4.0.0" - } - }, - "npm-bundled": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "npm-normalize-package-bin": "^2.0.0" - }, - "dependencies": { - "npm-normalize-package-bin": { - "version": "2.0.0", - "bundled": true, - "dev": true - } - } - }, - "npm-install-checks": { - "version": "5.0.0", - "bundled": true, - "dev": true, - "requires": { - "semver": "^7.1.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "npm-package-arg": { - "version": "9.1.0", - "bundled": true, - "dev": true, - "requires": { - "hosted-git-info": "^5.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "validate-npm-package-name": "^4.0.0" - } - }, - "npm-packlist": { - "version": "5.1.3", - "bundled": true, - "dev": true, - "requires": { - "glob": "^8.0.1", - "ignore-walk": "^5.0.1", - "npm-bundled": "^2.0.0", - "npm-normalize-package-bin": "^2.0.0" - }, - "dependencies": { - "npm-normalize-package-bin": { - "version": "2.0.0", - "bundled": true, - "dev": true - } - } - }, - "npm-pick-manifest": { - "version": "7.0.2", - "bundled": true, - "dev": true, - "requires": { - "npm-install-checks": "^5.0.0", - "npm-normalize-package-bin": "^2.0.0", - "npm-package-arg": "^9.0.0", - "semver": "^7.3.5" - }, - "dependencies": { - "npm-normalize-package-bin": { - "version": "2.0.0", - "bundled": true, - "dev": true - } - } - }, - "npm-profile": { - "version": "6.2.1", - "bundled": true, - "dev": true, - "requires": { - "npm-registry-fetch": "^13.0.1", - "proc-log": "^2.0.0" - } - }, - "npm-registry-fetch": { - "version": "13.3.1", - "bundled": true, - "dev": true, - "requires": { - "make-fetch-happen": "^10.0.6", - "minipass": "^3.1.6", - "minipass-fetch": "^2.0.3", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^9.0.1", - "proc-log": "^2.0.0" - } - }, - "npm-user-validate": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "npmlog": { - "version": "6.0.2", - "bundled": true, - "dev": true, - "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - } - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "opener": { - "version": "1.5.2", - "bundled": true, - "dev": true - }, - "p-map": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "pacote": { - "version": "13.6.2", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/git": "^3.0.0", - "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/promise-spawn": "^3.0.0", - "@npmcli/run-script": "^4.1.0", - "cacache": "^16.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "infer-owner": "^1.0.4", - "minipass": "^3.1.6", - "mkdirp": "^1.0.4", - "npm-package-arg": "^9.0.0", - "npm-packlist": "^5.1.0", - "npm-pick-manifest": "^7.0.0", - "npm-registry-fetch": "^13.0.1", - "proc-log": "^2.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^5.0.0", - "read-package-json-fast": "^2.0.3", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11" - } - }, - "parse-conflict-json": { - "version": "2.0.2", - "bundled": true, - "dev": true, - "requires": { - "json-parse-even-better-errors": "^2.3.1", - "just-diff": "^5.0.1", - "just-diff-apply": "^5.2.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "postcss-selector-parser": { - "version": "6.0.10", - "bundled": true, - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "proc-log": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "promise-all-reject-late": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "promise-call-limit": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "promise-retry": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - } - }, - "promzard": { - "version": "0.3.0", - "bundled": true, - "dev": true, - "requires": { - "read": "1" - } - }, - "qrcode-terminal": { - "version": "0.12.0", - "bundled": true, - "dev": true - }, - "read": { - "version": "1.0.7", - "bundled": true, - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-cmd-shim": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "read-package-json": { - "version": "5.0.2", - "bundled": true, - "dev": true, - "requires": { - "glob": "^8.0.1", - "json-parse-even-better-errors": "^2.3.1", - "normalize-package-data": "^4.0.0", - "npm-normalize-package-bin": "^2.0.0" - }, - "dependencies": { - "npm-normalize-package-bin": { - "version": "2.0.0", - "bundled": true, - "dev": true - } - } - }, - "read-package-json-fast": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "requires": { - "json-parse-even-better-errors": "^2.3.0", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "readable-stream": { - "version": "3.6.0", - "bundled": true, - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdir-scoped-modules": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "retry": { - "version": "0.12.0", - "bundled": true, - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "glob": { - "version": "7.2.3", - "bundled": true, - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "safe-buffer": { - "version": "5.2.1", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "7.3.7", - "bundled": true, - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "bundled": true, - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "signal-exit": { - "version": "3.0.7", - "bundled": true, - "dev": true - }, - "smart-buffer": { - "version": "4.2.0", - "bundled": true, - "dev": true - }, - "socks": { - "version": "2.7.0", - "bundled": true, - "dev": true, - "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - } - }, - "socks-proxy-agent": { - "version": "7.0.0", - "bundled": true, - "dev": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - } - }, - "spdx-correct": { - "version": "3.1.1", - "bundled": true, - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "bundled": true, - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.11", - "bundled": true, - "dev": true - }, - "ssri": { - "version": "9.0.1", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-width": { - "version": "4.2.3", - "bundled": true, - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "supports-color": { - "version": "7.2.0", - "bundled": true, - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "tar": { - "version": "6.1.11", - "bundled": true, - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - }, - "text-table": { - "version": "0.2.0", - "bundled": true, - "dev": true - }, - "tiny-relative-date": { - "version": "1.3.0", - "bundled": true, - "dev": true - }, - "treeverse": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "unique-filename": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "unique-slug": "^3.0.0" - } - }, - "unique-slug": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validate-npm-package-name": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "builtins": "^5.0.0" - } - }, - "walk-up-path": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "wcwidth": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "which": { - "version": "2.0.2", - "bundled": true, - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wide-align": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "write-file-atomic": { - "version": "4.0.2", - "bundled": true, - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - } - }, - "yallist": { - "version": "4.0.0", - "bundled": true, - "dev": true - } - } - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "nwsapi": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.1.tgz", - "integrity": "sha512-JYOWTeFoS0Z93587vRJgASD5Ut11fYl5NyihP3KrYBvMe1FRRs6RN7m20SA/16GM4P6hTnZjT+UmDOt38UeXNg==", - "dev": true - }, - "object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", - "dev": true - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", - "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "p-each-series": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", - "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", - "dev": true - }, - "p-filter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", - "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", - "dev": true, - "requires": { - "p-map": "^2.0.0" - } - }, - "p-is-promise": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", - "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - }, - "dependencies": { - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - } - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - }, - "p-reduce": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz", - "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", - "dev": true - }, - "p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dev": true, - "requires": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true - }, - "pkg-conf": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", - "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "load-json-file": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true - } - } - }, - "portfinder": { - "version": "1.0.28", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", - "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", - "dev": true, - "requires": { - "async": "^2.6.2", - "debug": "^3.1.1", - "mkdirp": "^0.5.5" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "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 - }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "dependencies": { - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true - } - } - }, - "psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "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" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - } - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true - } - } - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "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" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "rechoir": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", - "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", - "dev": true, - "requires": { - "resolve": "^1.9.0" - } - }, - "redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "requires": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - } - }, - "redeyed": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", - "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", - "dev": true, - "requires": { - "esprima": "~4.0.0" - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "registry-auth-token": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", - "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", - "dev": true, - "requires": { - "@pnpm/npm-conf": "^2.1.0" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "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 - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "resolve-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", - "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", - "dev": true, - "requires": { - "global-dirs": "^0.1.1" - } - }, - "resolve.exports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", - "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", - "dev": true - }, - "retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "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 - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - }, - "secure-compare": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", - "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", - "dev": true - }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "selfsigned": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.1.tgz", - "integrity": "sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==", - "dev": true, - "requires": { - "node-forge": "^1" - } - }, - "semantic-release": { - "version": "19.0.3", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-19.0.3.tgz", - "integrity": "sha512-HaFbydST1cDKZHuFZxB8DTrBLJVK/AnDExpK0s3EqLIAAUAHUgnd+VSJCUtTYQKkAkauL8G9CucODrVCc7BuAA==", - "dev": true, - "requires": { - "@semantic-release/commit-analyzer": "^9.0.2", - "@semantic-release/error": "^3.0.0", - "@semantic-release/github": "^8.0.0", - "@semantic-release/npm": "^9.0.0", - "@semantic-release/release-notes-generator": "^10.0.0", - "aggregate-error": "^3.0.0", - "cosmiconfig": "^7.0.0", - "debug": "^4.0.0", - "env-ci": "^5.0.0", - "execa": "^5.0.0", - "figures": "^3.0.0", - "find-versions": "^4.0.0", - "get-stream": "^6.0.0", - "git-log-parser": "^1.2.0", - "hook-std": "^2.0.0", - "hosted-git-info": "^4.0.0", - "lodash": "^4.17.21", - "marked": "^4.0.10", - "marked-terminal": "^5.0.0", - "micromatch": "^4.0.2", - "p-each-series": "^2.1.0", - "p-reduce": "^2.0.0", - "read-pkg-up": "^7.0.0", - "resolve-from": "^5.0.0", - "semver": "^7.3.2", - "semver-diff": "^3.1.1", - "signale": "^1.2.1", - "yargs": "^16.2.0" - }, - "dependencies": { - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - } - } - }, - "semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "semver-regex": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", - "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", - "dev": true - }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "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 - } - } - }, - "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "signale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz", - "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==", - "dev": true, - "requires": { - "chalk": "^2.3.2", - "figures": "^2.0.0", - "pkg-conf": "^2.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "requires": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "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 - }, - "source-map-support": { - "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" - } - }, - "spawn-error-forwarder": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", - "integrity": "sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==", - "dev": true - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true - }, - "spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2" - } - }, - "split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "requires": { - "readable-stream": "^3.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", - "dev": true, - "requires": { - "escape-string-regexp": "^2.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } - } - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - }, - "stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", - "dev": true, - "requires": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } - }, - "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, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "requires": { - "min-indent": "^1.0.0" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dev": true, - "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "dev": true - }, - "tempy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", - "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", - "dev": true, - "requires": { - "del": "^6.0.0", - "is-stream": "^2.0.0", - "temp-dir": "^2.0.0", - "type-fest": "^0.16.0", - "unique-string": "^2.0.0" - }, - "dependencies": { - "type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", - "dev": true - } - } - }, - "terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - } - }, - "terser": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.1.tgz", - "integrity": "sha512-hVl35zClmpisy6oaoKALOpS0rDYLxRFLHhRuDlEGTKey9qHjS1w9GMORjuwIMt70Wan4lwsLYyWDVnWgF+KUEw==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - } - }, - "terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "throat": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", - "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "requires": { - "readable-stream": "3" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true - }, - "tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "dependencies": { - "universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true - } - } - }, - "tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha512-kdf4JKs8lbARxWdp7RKdNzoJBhGUcIalSYibuGyHJbmk40pOysQ0+QPvlkCOICOivDWU2IJo2rkrxyTK2AH4fw==", - "dev": true - }, - "trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true - }, - "ts-jest": { - "version": "27.1.4", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.4.tgz", - "integrity": "sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ==", - "dev": true, - "requires": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^27.0.0", - "json5": "2.x", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "20.x" - } - }, - "ts-loader": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.3.1.tgz", - "integrity": "sha512-OkyShkcZTsTwyS3Kt7a4rsT/t2qvEVQuKCTg4LJmpj9fhFR7ukGdZwV6Qq3tRUkqcXtfGpPR7+hFKHCG/0d3Lw==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" - } - }, - "ts-node": { - "version": "10.8.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.0.tgz", - "integrity": "sha512-/fNd5Qh+zTt8Vt1KbYZjRHCE9sI5i7nqfD/dzBBRDeVXZXS6kToW6R7tTU6Nd4XavFs0mAVCg29Q//ML7WsZYA==", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "dependencies": { - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - } - } - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "typescript": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", - "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", - "dev": true - }, - "uglify-js": { - "version": "3.16.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.16.2.tgz", - "integrity": "sha512-AaQNokTNgExWrkEYA24BTNMSjyqEXPSfhqoS0AxmHkCJ4U+Dyy5AvbGV/sqxuxficEfGGoX3zWw9R7QpLFfEsg==", - "dev": true, - "optional": true - }, - "union": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", - "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", - "dev": true, - "requires": { - "qs": "^6.4.0" - } - }, - "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "requires": { - "crypto-random-string": "^2.0.0" - } - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", - "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "dev": true - }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true - } - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true - }, - "w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "requires": { - "browser-process-hrtime": "^1.0.0" - } - }, - "w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "requires": { - "xml-name-validator": "^3.0.0" - } - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "requires": { - "makeerror": "1.0.12" - } - }, - "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true - }, - "webpack": { - "version": "5.80.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.80.0.tgz", - "integrity": "sha512-OIMiq37XK1rWO8mH9ssfFKZsXg4n6klTEDL7S8/HqbAOBBaiy8ABvXvz0dDCXeEF9gqwxSvVk611zFPjS8hJxA==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.13.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.2", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "webpack-cli": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", - "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.2.0", - "@webpack-cli/info": "^1.5.0", - "@webpack-cli/serve": "^1.7.0", - "colorette": "^2.0.14", - "commander": "^7.0.0", - "cross-spawn": "^7.0.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "webpack-merge": "^5.7.3" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - } - } - }, - "webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", - "dev": true, - "requires": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - } - }, - "webpack-dev-server": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz", - "integrity": "sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw==", - "dev": true, - "requires": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.1", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.0.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.4.2" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "ws": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", - "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", - "dev": true, - "requires": {} - } - } - }, - "webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true - }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true - }, - "whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "requires": { - "iconv-lite": "0.4.24" - } - }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, - "requires": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "dev": true, - "requires": {} - }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - }, - "yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "dependencies": { - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", - "dev": true - } - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } } } diff --git a/package.json b/package.json index 38c2c04..9e2f4ed 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "description": "Graph visualization library", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "repository": { "type": "git", @@ -28,12 +28,12 @@ "build:release": "tsc && webpack", "webpack": "webpack", "webpack:watch": "webpack --watch", - "serve": "http-server ./dist/browser/", + "serve": "http-server ./dist/browser/ -o -c-1 -p 8082", "test": "jest --runInBand --detectOpenHandles --forceExit --verbose --useStderr", "coverage": "npm test -- --coverage --collectCoverageFrom='./src/**'", "lint": "eslint .", "lint:fix": "eslint --fix .", - "release": "semantic-release --branches main", + "release": "semantic-release", "prepare": "husky install" }, "dependencies": { @@ -64,7 +64,7 @@ "@types/d3-selection": "3.0.1", "@types/d3-transition": "3.0.1", "@types/d3-zoom": "3.0.1", - "@types/jest": "27.4.1", + "@types/jest": "29.5.12", "@types/leaflet": "1.7.9", "@types/resize-observer-browser": "^0.1.7", "@typescript-eslint/eslint-plugin": "5.24.0", @@ -78,10 +78,10 @@ "eslint-plugin-prettier": "4.0.0", "http-server": "^14.1.1", "husky": "^8.0.1", - "jest": "27.5.1", + "jest": "29.7.0", "prettier": "^2.7.1", "semantic-release": "19.0.3", - "ts-jest": "27.1.4", + "ts-jest": "29.1.2", "ts-loader": "^9.3.1", "ts-node": "10.8.0", "typescript": "4.6.3", @@ -103,5 +103,10 @@ "coverageDirectory": "coverage", "testEnvironment": "node", "testTimeout": 5000 + }, + "release": { + "branches": [ + "main" + ] } -} +} \ No newline at end of file diff --git a/src/events.ts b/src/events.ts index 03e790d..22e5924 100644 --- a/src/events.ts +++ b/src/events.ts @@ -33,36 +33,36 @@ export enum OrbEventType { MOUSE_DOUBLE_CLICK = 'mouse-double-click', } -interface IOrbEventDuration { +export interface IOrbEventDuration { durationMs: number; } -interface IOrbEventProgress { +export interface IOrbEventProgress { progress: number; } -interface IOrbEventMousePosition { +export interface IOrbEventMousePosition { localPoint: IPosition; globalPoint: IPosition; } -interface IOrbEventMouseClickEvent extends IOrbEventMousePosition { +export interface IOrbEventMouseClickEvent extends IOrbEventMousePosition { event: PointerEvent; } -interface IOrbEventMouseMoveEvent extends IOrbEventMousePosition { +export interface IOrbEventMouseMoveEvent extends IOrbEventMousePosition { event: MouseEvent; } -interface IOrbEventMouseEvent extends IOrbEventMousePosition { +export interface IOrbEventMouseEvent extends IOrbEventMousePosition { subject?: INode | IEdge; } -interface IOrbEventMouseNodeEvent { +export interface IOrbEventMouseNodeEvent { node: INode; } -interface IOrbEventMouseEdgeEvent { +export interface IOrbEventMouseEdgeEvent { edge: IEdge; } diff --git a/src/models/edge.ts b/src/models/edge.ts index cb818b6..4b36145 100644 --- a/src/models/edge.ts +++ b/src/models/edge.ts @@ -1,7 +1,9 @@ import { INodeBase, INode } from './node'; -import { GraphObjectState } from './state'; +import { GraphObjectState, IGraphObjectStateOptions, IGraphObjectStateParameters } from './state'; import { Color, IPosition, ICircle, getDistanceToLine } from '../common'; -import { isArrayOfNumbers } from '../utils/type.utils'; +import { isArrayOfNumbers, isFunction, isNumber, isPlainObject } from '../utils/type.utils'; +import { IObserver, ISubject, Subject } from '../utils/observer.utils'; +import { patchProperties } from '../utils/object.utils'; const CURVED_CONTROL_POINT_OFFSET_MIN_SIZE = 4; const CURVED_CONTROL_POINT_OFFSET_MULTIPLIER = 4; @@ -81,11 +83,7 @@ export enum EdgeType { CURVED = 'curved', } -export interface IEdge { - data: E; - position: IEdgePosition; - style: IEdgeStyle; - state: number; +export interface IEdge extends ISubject { readonly id: any; readonly offset: number; readonly start: any; @@ -93,6 +91,12 @@ export interface IEdge { readonly end: any; readonly endNode: INode; readonly type: EdgeType; + getId(): any; + getData(): E; + getPosition(): IEdgePosition; + getStyle(): IEdgeStyle; + getState(): number; + getListeners(): IObserver[]; hasStyle(): boolean; isSelected(): boolean; isHovered(): boolean; @@ -107,20 +111,39 @@ export interface IEdge { getWidth(): number; getColor(): Color | string | undefined; getLineDashPattern(): number[] | null; + setData(data: E): void; + setData(callback: (edge: IEdge) => E): void; + patchData(data: Partial): void; + patchData(callback: (edge: IEdge) => Partial): void; + setStyle(style: IEdgeStyle): void; + setStyle(callback: (edge: IEdge) => IEdgeStyle): void; + patchStyle(style: IEdgeStyle): void; + patchStyle(callback: (edge: IEdge) => IEdgeStyle): void; + setState(state: number): void; + setState(state: IGraphObjectStateParameters): void; + setState(callback: (edge: IEdge) => number): void; + setState(callback: (edge: IEdge) => IGraphObjectStateParameters): void; +} + +export interface IEdgeSettings { + listeners: IObserver[]; } export class EdgeFactory { - static create(data: IEdgeData): IEdge { + static create( + data: IEdgeData, + settings?: IEdgeSettings, + ): IEdge { const type = getEdgeType(data); switch (type) { case EdgeType.STRAIGHT: - return new EdgeStraight(data); + return new EdgeStraight(data, settings); case EdgeType.LOOPBACK: - return new EdgeLoopback(data); + return new EdgeLoopback(data, settings); case EdgeType.CURVED: - return new EdgeCurved(data); + return new EdgeCurved(data, settings); default: - return new EdgeStraight(data); + return new EdgeStraight(data, settings); } } @@ -129,13 +152,18 @@ export class EdgeFactory { data?: Omit, 'data' | 'startNode' | 'endNode'>, ): IEdge { const newEdge = EdgeFactory.create({ - data: edge.data, + data: edge.getData(), offset: data?.offset !== undefined ? data.offset : edge.offset, startNode: edge.startNode, endNode: edge.endNode, }); - newEdge.state = edge.state; - newEdge.style = edge.style; + newEdge.setState(edge.getState()); + newEdge.setStyle(edge.getStyle()); + const listeners = edge.getListeners(); + + for (let i = 0; i < listeners.length; i++) { + newEdge.addListener(listeners[i]); + } return newEdge; } @@ -145,31 +173,56 @@ export const isEdge = (obj: any): obj return obj instanceof EdgeStraight || obj instanceof EdgeCurved || obj instanceof EdgeLoopback; }; -abstract class Edge implements IEdge { - public data: E; +abstract class Edge extends Subject implements IEdge { + protected _data: E; public readonly id: number; public readonly offset: number; public readonly startNode: INode; public readonly endNode: INode; - public style: IEdgeStyle = {}; - public state = GraphObjectState.NONE; - public position: IEdgePosition; + protected _style: IEdgeStyle = {}; + protected _state = GraphObjectState.NONE; + protected _position: IEdgePosition; private _type: EdgeType = EdgeType.STRAIGHT; - constructor(data: IEdgeData) { + constructor(data: IEdgeData, settings?: IEdgeSettings) { + super(); this.id = data.data.id; - this.data = data.data; + this._data = data.data; this.offset = data.offset ?? 0; this.startNode = data.startNode; this.endNode = data.endNode; this._type = getEdgeType(data); - this.position = { id: this.id, source: this.startNode.id, target: this.endNode.id }; + this._position = { id: this.id, source: this.startNode.getId(), target: this.endNode.getId() }; this.startNode.addEdge(this); this.endNode.addEdge(this); + + if (settings && settings.listeners) { + this.listeners = settings.listeners; + } + } + + getId(): number { + return this.id; + } + + getData(): E { + return structuredClone(this._data); + } + + getPosition(): IEdgePosition { + return structuredClone(this._position); + } + + getStyle(): IEdgeStyle { + return structuredClone(this._style); + } + + getState(): number { + return this._state; } get type(): EdgeType { @@ -177,27 +230,27 @@ abstract class Edge implements IEdge 0; + return this._style && Object.keys(this._style).length > 0; } isSelected(): boolean { - return this.state === GraphObjectState.SELECTED; + return this._state === GraphObjectState.SELECTED; } isHovered(): boolean { - return this.state === GraphObjectState.HOVERED; + return this._state === GraphObjectState.HOVERED; } clearState(): void { - this.state = GraphObjectState.NONE; + this._state = GraphObjectState.NONE; } isLoopback(): boolean { @@ -236,25 +289,25 @@ abstract class Edge implements IEdge 0 || (this.style.shadowOffsetX ?? 0) > 0 || (this.style.shadowOffsetY ?? 0) > 0 + (this._style.shadowSize ?? 0) > 0 || (this._style.shadowOffsetX ?? 0) > 0 || (this._style.shadowOffsetY ?? 0) > 0 ); } getWidth(): number { let width = 0; - if (this.style.width !== undefined) { - width = this.style.width; + if (this._style.width !== undefined) { + width = this._style.width; } - if (this.isHovered() && this.style.widthHover !== undefined) { - width = this.style.widthHover; + if (this.isHovered() && this._style.widthHover !== undefined) { + width = this._style.widthHover; } - if (this.isSelected() && this.style.widthSelected !== undefined) { - width = this.style.widthSelected; + if (this.isSelected() && this._style.widthSelected !== undefined) { + width = this._style.widthSelected; } return width; } @@ -262,21 +315,21 @@ abstract class Edge implements IEdge implements IEdge) => E): void; + setData(arg: E | ((edge: IEdge) => E)) { + if (isFunction(arg)) { + this._data = (arg as (edge: IEdge) => E)(this); + } else { + this._data = arg as E; + } + this.notifyListeners(); + } + + patchData(data: Partial): void; + patchData(callback: (edge: IEdge) => Partial): void; + patchData(arg: Partial | ((edge: IEdge) => Partial)) { + let data: Partial; + + if (isFunction(arg)) { + data = (arg as (edge: IEdge) => Partial)(this); + } else { + data = arg as Partial; + } + + patchProperties(this._data, data); + + this.notifyListeners(); + } + + setStyle(style: IEdgeStyle): void; + setStyle(callback: (edge: IEdge) => IEdgeStyle): void; + setStyle(arg: IEdgeStyle | ((edge: IEdge) => IEdgeStyle)): void { + if (isFunction(arg)) { + this._style = (arg as (edge: IEdge) => IEdgeStyle)(this); + } else { + this._style = arg as IEdgeStyle; + } + this.notifyListeners(); + } + + patchStyle(style: IEdgeStyle): void; + patchStyle(callback: (edge: IEdge) => IEdgeStyle): void; + patchStyle(arg: IEdgeStyle | ((edge: IEdge) => IEdgeStyle)) { + let style: IEdgeStyle; + + if (isFunction(arg)) { + style = (arg as (edge: IEdge) => IEdgeStyle)(this); + } else { + style = arg as IEdgeStyle; + } + + patchProperties(this._style, style); + + this.notifyListeners(); + } + + setState(state: number): void; + setState(state: IGraphObjectStateParameters): void; + setState(callback: (edge: IEdge) => number): void; + setState(callback: (edge: IEdge) => IGraphObjectStateParameters): void; + setState( + arg: + | number + | IGraphObjectStateParameters + | ((edge: IEdge) => number) + | ((edge: IEdge) => IGraphObjectStateParameters), + ): void { + let result: number | IGraphObjectStateParameters; + + if (isFunction(arg)) { + result = (arg as (edge: IEdge) => number | IGraphObjectStateParameters)(this); + } else { + result = arg; + } + + if (isNumber(result)) { + this._state = result; + } else if (isPlainObject(result)) { + const options = result.options; + + this._state = this._handleState(result.state, options); + + if (options) { + this.notifyListeners({ + id: this.id, + type: 'edge', + options: options, + }); + + return; + } + } + + this.notifyListeners(); + } + + private _handleState(state: number, options?: Partial): number { + if (options?.isToggle && this._state === state) { + return GraphObjectState.NONE; + } else { + return state; + } + } } const getEdgeType = (data: IEdgeData): EdgeType => { - if (data.startNode.id === data.endNode.id) { + if (data.startNode.getId() === data.endNode.getId()) { return EdgeType.LOOPBACK; } return (data.offset ?? 0) === 0 ? EdgeType.STRAIGHT : EdgeType.CURVED; diff --git a/src/models/graph.ts b/src/models/graph.ts index b80a5b7..071612f 100644 --- a/src/models/graph.ts +++ b/src/models/graph.ts @@ -5,66 +5,93 @@ import { IGraphStyle } from './style'; import { ImageHandler } from '../services/images'; import { getEdgeOffsets } from './topology'; import { IEntityState, EntityState } from '../utils/entity.utils'; +import { IObserver, IObserverDataPayload, ISubject, Subject } from '../utils/observer.utils'; +import { patchProperties } from '../utils/object.utils'; +import { dedupArrays } from '../utils/array.utils'; export interface IGraphData { nodes: N[]; edges: E[]; } +export interface IGraphObjectsIds { + nodeIds: any[]; + edgeIds: any[]; +} + export type IEdgeFilter = (edge: IEdge) => boolean; export type INodeFilter = (node: INode) => boolean; -export interface IGraph { +export interface IGraph extends ISubject { getNodes(filterBy?: INodeFilter): INode[]; getEdges(filterBy?: IEdgeFilter): IEdge[]; getNodeCount(): number; getEdgeCount(): number; getNodeById(id: any): INode | undefined; getEdgeById(id: any): IEdge | undefined; + getNodePositions(filterBy?: INodeFilter): INodePosition[]; getSelectedNodes(): INode[]; getSelectedEdges(): IEdge[]; getHoveredNodes(): INode[]; getHoveredEdges(): IEdge[]; - getNodePositions(): INodePosition[]; setNodePositions(positions: INodePosition[]): void; - getEdgePositions(): IEdgePosition[]; + getEdgePositions(filterBy?: IEdgeFilter): IEdgePosition[]; setDefaultStyle(style: Partial>): void; setup(data: Partial>): void; clearPositions(): void; merge(data: Partial>): void; - remove(data: Partial<{ nodeIds: number[]; edgeIds: number[] }>): void; + remove(data: Partial): void; + removeAll(): void; + removeAllNodes(): void; + removeAllEdges(): void; isEqual(graph: Graph): boolean; getBoundingBox(): IRectangle; getNearestNode(point: IPosition): INode | undefined; getNearestEdge(point: IPosition, minDistance?: number): IEdge | undefined; + setSettings(settings: Partial>): void; } -// TODO: Move this to node events when image listening will be on node level -// TODO: Add global events user can listen for: images-load-start, images-load-end -export interface IGraphSettings { - onLoadedImages: () => void; +export interface IGraphSettings { + // TODO(tlastre): Move this to node events when image listening will be on node level + // TODO(tlastre): Add global events user can listen for: images-load-start, images-load-end + onLoadedImages?: () => void; + onSetupData?: (data: Partial>) => void; + onMergeData?: (data: Partial>) => void; + onRemoveData?: (data: Partial) => void; + listeners?: IObserver[]; } -export class Graph implements IGraph { +export class Graph extends Subject implements IGraph { private _nodes: IEntityState> = new EntityState>({ - getId: (node) => node.id, - sortBy: (node1, node2) => (node1.style.zIndex ?? 0) - (node2.style.zIndex ?? 0), + getId: (node) => node.getId(), + sortBy: (node1, node2) => (node1.getStyle().zIndex ?? 0) - (node2.getStyle().zIndex ?? 0), }); private _edges: IEntityState> = new EntityState>({ - getId: (edge) => edge.id, - sortBy: (edge1, edge2) => (edge1.style.zIndex ?? 0) - (edge2.style.zIndex ?? 0), + getId: (edge) => edge.getId(), + sortBy: (edge1, edge2) => (edge1.getStyle().zIndex ?? 0) - (edge2.getStyle().zIndex ?? 0), }); private _defaultStyle?: Partial>; - private _onLoadedImages?: () => void; + private _settings: IGraphSettings; - constructor(data?: Partial>, settings?: Partial) { - this._onLoadedImages = settings?.onLoadedImages; + constructor(data?: Partial>, settings?: Partial>) { + // TODO(dlozic): How to use object assign here? If I add add and export a default const here, it needs N, E. + super(); + this._settings = settings || {}; const nodes = data?.nodes ?? []; const edges = data?.edges ?? []; + if (settings && settings.listeners) { + this.listeners = settings.listeners; + } + this.notifyListeners = this.notifyListeners.bind(this); this.setup({ nodes, edges }); } + setSettings(settings: Partial>) { + patchProperties(this._settings, settings); + this.notifyListeners(); + } + /** * Returns a list of nodes. * @@ -162,13 +189,14 @@ export class Graph implements IGraph): INodePosition[] { + const nodes = this.getNodes(filterBy); const positions: INodePosition[] = new Array(nodes.length); for (let i = 0; i < nodes.length; i++) { - positions[i] = nodes[i].position; + positions[i] = nodes[i].getPosition(); } return positions; } @@ -182,7 +210,7 @@ export class Graph implements IGraph implements IGraph): IEdgePosition[] { + const edges = this.getEdges(filterBy); const positions: IEdgePosition[] = new Array(edges.length); for (let i = 0; i < edges.length; i++) { - positions[i] = edges[i].position; + positions[i] = edges[i].getPosition(); } return positions; } @@ -225,6 +254,8 @@ export class Graph implements IGraph implements IGraph) { + remove(data: Partial) { const nodeIds = data.nodeIds ?? []; const edgeIds = data.edgeIds ?? []; - this._removeNodes(nodeIds); - this._removeEdges(edgeIds); + const removedNodesData = this._removeNodes(nodeIds); + const removedEdgesData = this._removeEdges(edgeIds); this._applyEdgeOffsets(); this._applyStyle(); + + if (this._settings && this._settings.onRemoveData) { + const removedData: IGraphObjectsIds = { + nodeIds: dedupArrays(removedNodesData.nodeIds, removedEdgesData.nodeIds), + edgeIds: dedupArrays(removedNodesData.edgeIds, removedEdgesData.edgeIds), + }; + + this._settings.onRemoveData(removedData); + } + } + + removeAll() { + const nodeIds = this._nodes.getAll().map((node) => node.id); + const edgeIds = this._edges.getAll().map((edge) => edge.id); + + this.remove({ nodeIds, edgeIds }); + } + + removeAllEdges() { + const edgeIds = this._edges.getAll().map((edge) => edge.id); + + this.remove({ edgeIds }); + } + + removeAllNodes() { + this.removeAll(); } isEqual(graph: Graph): boolean { @@ -267,14 +326,14 @@ export class Graph implements IGraph implements IGraph { + if (data && 'type' in data && 'options' in data && 'isSingle' in data.options) { + if (data.type === 'node' && data.options.isSingle) { + const nodes = this._nodes.getAll(); + + for (let i = 0; i < nodes.length; i++) { + if (nodes[i].id !== data.id) { + nodes[i].clearState(); + } + } + } + + if (data.type === 'edge' && data.options.isSingle) { + const edges = this._edges.getAll(); + + for (let i = 0; i < edges.length; i++) { + if (edges[i].id !== data.id) { + edges[i].clearState(); + } + } + } + } + + this.notifyListeners(data); + }; + private _insertNodes(nodes: N[]) { const newNodes: INode[] = new Array>(nodes.length); for (let i = 0; i < nodes.length; i++) { - newNodes[i] = NodeFactory.create({ data: nodes[i] }, { onLoadedImage: () => this._onLoadedImages?.() }); + newNodes[i] = NodeFactory.create( + { data: nodes[i] }, + { onLoadedImage: () => this._settings?.onLoadedImages?.(), listeners: [this._update] }, + ); } this._nodes.setMany(newNodes); } @@ -367,11 +457,16 @@ export class Graph implements IGraph({ - data: edges[i], - startNode, - endNode, - }), + EdgeFactory.create( + { + data: edges[i], + startNode, + endNode, + }, + { + listeners: [this._update], + }, + ), ); } } @@ -383,11 +478,17 @@ export class Graph implements IGraph({ data: nodes[i] }, { onLoadedImage: () => this._onLoadedImages?.() })); + newNodes.push( + NodeFactory.create( + { data: nodes[i] }, + { onLoadedImage: () => this._settings?.onLoadedImages?.(), listeners: [this._update] }, + ), + ); } this._nodes.setMany(newNodes); } @@ -406,11 +507,16 @@ export class Graph implements IGraph({ - data: newEdgeData, - startNode, - endNode, - }); + const edge = EdgeFactory.create( + { + data: newEdgeData, + startNode, + endNode, + }, + { + listeners: [this._update], + }, + ); newEdges.push(edge); } continue; @@ -418,7 +524,7 @@ export class Graph implements IGraph implements IGraph({ - data: newEdgeData, - offset: existingEdge.offset, - startNode, - endNode, - }); - edge.state = existingEdge.state; - edge.style = existingEdge.style; + const edge = EdgeFactory.create( + { + data: newEdgeData, + offset: existingEdge.offset, + startNode, + endNode, + }, + { + listeners: [this._update], + }, + ); + edge.setState(existingEdge.getState()); + edge.setStyle(existingEdge.getStyle()); newEdges.push(edge); } @@ -448,7 +559,7 @@ export class Graph implements IGraph implements IGraph implements IGraph implements IGraph implements IGraph { - this._onLoadedImages?.(); + this._settings?.onLoadedImages?.(); }); } diff --git a/src/models/node.ts b/src/models/node.ts index 320ddb6..78afeaa 100644 --- a/src/models/node.ts +++ b/src/models/node.ts @@ -1,7 +1,10 @@ import { IEdge, IEdgeBase } from './edge'; import { Color, IPosition, IRectangle, isPointInRectangle } from '../common'; import { ImageHandler } from '../services/images'; -import { GraphObjectState } from './state'; +import { GraphObjectState, IGraphObjectStateOptions, IGraphObjectStateParameters } from './state'; +import { IObserver, ISubject, Subject } from '../utils/observer.utils'; +import { patchProperties } from '../utils/object.utils'; +import { isFunction, isNumber, isPlainObject } from '../utils/type.utils'; /** * Node baseline object with required fields @@ -21,6 +24,15 @@ export interface INodePosition { y?: number; } +export interface INodeCoordinates { + x: number; + y: number; +} + +export interface INodeSetPositionOptions { + isNotifySkipped: boolean; +} + export enum NodeShapeType { CIRCLE = 'circle', DOT = 'dot', @@ -65,12 +77,13 @@ export interface INodeData { data: N; } -export interface INode { - data: N; - position: INodePosition; - style: INodeStyle; - state: number; - readonly id: any; +export interface INode extends ISubject { + id: number; + getId(): number; + getData(): N; + getPosition(): INodePosition; + getStyle(): INodeStyle; + getState(): number; clearPosition(): void; getCenter(): IPosition; getRadius(): number; @@ -95,12 +108,30 @@ export interface INode { getBorderWidth(): number; getBorderColor(): Color | string | undefined; getBackgroundImage(): HTMLImageElement | undefined; + setData(data: N): void; + setData(callback: (node: INode) => N): void; + patchData(data: Partial): void; + patchData(callback: (node: INode) => Partial): void; + setPosition(position: INodeCoordinates | INodePosition, options?: INodeSetPositionOptions): void; + setPosition( + callback: (node: INode) => INodeCoordinates | INodePosition, + options?: INodeSetPositionOptions, + ): void; + setStyle(style: INodeStyle): void; + setStyle(callback: (node: INode) => INodeStyle): void; + patchStyle(style: INodeStyle): void; + patchStyle(callback: (node: INode) => INodeStyle): void; + setState(state: number): void; + setState(state: IGraphObjectStateParameters): void; + setState(callback: (node: INode) => number): void; + setState(callback: (node: INode) => IGraphObjectStateParameters): void; } // TODO: Dirty solution: Find another way to listen for global images, maybe through // events that user can listen for: images-load-start, images-load-end export interface INodeSettings { onLoadedImage: () => void; + listeners: IObserver[]; } export class NodeFactory { @@ -116,40 +147,66 @@ export const isNode = (obj: any): obj return obj instanceof Node; }; -export class Node implements INode { +export class Node extends Subject implements INode { public readonly id: number; - public data: N; - public position: INodePosition; - public style: INodeStyle = {}; - public state = GraphObjectState.NONE; + protected _data: N; + protected _position: INodePosition; + protected _style: INodeStyle = {}; + protected _state = GraphObjectState.NONE; private readonly _inEdgesById: { [id: number]: IEdge } = {}; private readonly _outEdgesById: { [id: number]: IEdge } = {}; private readonly _onLoadedImage?: () => void; constructor(data: INodeData, settings?: Partial) { + super(); this.id = data.data.id; - this.data = data.data; - this.position = { id: this.id }; + this._data = data.data; + this._position = { id: this.id }; this._onLoadedImage = settings?.onLoadedImage; + if (settings && settings.listeners) { + this.listeners = settings.listeners; + } + } + + getId(): number { + return this.id; + } + + getData(): N { + return structuredClone(this._data); + } + + getPosition(): INodePosition { + return structuredClone(this._position); + } + + getStyle(): INodeStyle { + return structuredClone(this._style); + } + + getState(): number { + return this._state; } clearPosition() { - this.position.x = undefined; - this.position.y = undefined; + this._position.x = undefined; + this._position.y = undefined; + + this.notifyListeners(); } getCenter(): IPosition { // This should not be called in the render because nodes without position will be // filtered out - if (this.position.x === undefined || this.position.y === undefined) { + if (this._position.x === undefined || this._position.y === undefined) { return { x: 0, y: 0 }; } - return { x: this.position.x, y: this.position.y }; + return { x: this._position.x, y: this._position.y }; } getRadius(): number { - return this.style.size ?? 0; + return this._style.size ?? 0; } getBorderedRadius(): number { @@ -181,13 +238,13 @@ export class Node implements INode implements INode implements INode implements INode 0; + return this._style && Object.keys(this._style).length > 0; } addEdge(edge: IEdge) { if (edge.start === this.id) { - this._outEdgesById[edge.id] = edge; + this._outEdgesById[edge.getId()] = edge; } if (edge.end === this.id) { - this._inEdgesById[edge.id] = edge; + this._inEdgesById[edge.getId()] = edge; } } removeEdge(edge: IEdge) { - delete this._outEdgesById[edge.id]; - delete this._inEdgesById[edge.id]; + delete this._outEdgesById[edge.getId()]; + delete this._inEdgesById[edge.getId()]; } isSelected(): boolean { - return this.state === GraphObjectState.SELECTED; + return this._state === GraphObjectState.SELECTED; } isHovered(): boolean { - return this.state === GraphObjectState.HOVERED; + return this._state === GraphObjectState.HOVERED; } clearState(): void { - this.state = GraphObjectState.NONE; + this.setState(GraphObjectState.NONE); + + this.notifyListeners(); } getDistanceToBorder(): number { @@ -257,7 +316,7 @@ export class Node implements INode implements INode 0 || (this.style.shadowOffsetX ?? 0) > 0 || (this.style.shadowOffsetY ?? 0) > 0 + (this._style.shadowSize ?? 0) > 0 || (this._style.shadowOffsetX ?? 0) > 0 || (this._style.shadowOffsetY ?? 0) > 0 ); } hasBorder(): boolean { - const hasBorderWidth = (this.style.borderWidth ?? 0) > 0; - const hasBorderWidthSelected = (this.style.borderWidthSelected ?? 0) > 0; + const hasBorderWidth = (this._style.borderWidth ?? 0) > 0; + const hasBorderWidthSelected = (this._style.borderWidthSelected ?? 0) > 0; return hasBorderWidth || (this.isSelected() && hasBorderWidthSelected); } getLabel(): string | undefined { - return this.style.label; + return this._style.label; } getColor(): Color | string | undefined { let color: Color | string | undefined = undefined; - if (this.style.color) { - color = this.style.color; + if (this._style.color) { + color = this._style.color; } - if (this.isHovered() && this.style.colorHover) { - color = this.style.colorHover; + if (this.isHovered() && this._style.colorHover) { + color = this._style.colorHover; } - if (this.isSelected() && this.style.colorSelected) { - color = this.style.colorSelected; + if (this.isSelected() && this._style.colorSelected) { + color = this._style.colorSelected; } return color; @@ -304,11 +363,11 @@ export class Node implements INode 0) { - borderWidth = this.style.borderWidth; + if (this._style.borderWidth && this._style.borderWidth > 0) { + borderWidth = this._style.borderWidth; } - if (this.isSelected() && this.style.borderWidthSelected && this.style.borderWidthSelected > 0) { - borderWidth = this.style.borderWidthSelected; + if (this.isSelected() && this._style.borderWidthSelected && this._style.borderWidthSelected > 0) { + borderWidth = this._style.borderWidthSelected; } return borderWidth; } @@ -320,31 +379,31 @@ export class Node implements INode implements INode) => N): void; + setData(arg: N | ((node: INode) => N)) { + if (isFunction(arg)) { + this._data = (arg as (node: INode) => N)(this); + } else { + this._data = arg as N; + } + this.notifyListeners(); + } + + patchData(data: Partial): void; + patchData(callback: (node: INode) => Partial): void; + patchData(arg: Partial | ((node: INode) => Partial)) { + let data: Partial; + + if (isFunction(arg)) { + data = (arg as (node: INode) => Partial)(this); + } else { + data = arg as Partial; + } + + patchProperties(this._data, data); + + this.notifyListeners(); + } + + setPosition(position: INodeCoordinates | INodePosition, options?: INodeSetPositionOptions): void; + setPosition( + callback: (node: INode) => INodeCoordinates | INodePosition, + options?: INodeSetPositionOptions, + ): void; + setPosition( + arg: INodeCoordinates | INodePosition | ((node: INode) => INodeCoordinates | INodePosition), + options?: INodeSetPositionOptions, + ) { + let position: INodeCoordinates | INodePosition; + if (isFunction(arg)) { + position = (arg as (node: INode) => INodeCoordinates)(this); + } else { + position = arg; + } + + if ('x' in position && 'y' in position) { + this._position.x = position.x; + this._position.y = position.y; + if ('id' in position) { + this._position.id = position.id; + } + } + + if (!options?.isNotifySkipped) { + this.notifyListeners({ id: this.id, ...position }); + } + } + + setStyle(style: INodeStyle): void; + setStyle(callback: (node: INode) => INodeStyle): void; + setStyle(arg: INodeStyle | ((node: INode) => INodeStyle)): void { + if (isFunction(arg)) { + this._style = (arg as (node: INode) => INodeStyle)(this); + } else { + this._style = arg as INodeStyle; + } + this.notifyListeners(); + } + + patchStyle(style: INodeStyle): void; + patchStyle(callback: (node: INode) => INodeStyle): void; + patchStyle(arg: INodeStyle | ((node: INode) => INodeStyle)) { + let style: INodeStyle; + + if (isFunction(arg)) { + style = (arg as (node: INode) => INodeStyle)(this); + } else { + style = arg as INodeStyle; + } + + patchProperties(this._style, style); + + this.notifyListeners(); + } + + setState(state: number): void; + setState(state: IGraphObjectStateParameters): void; + setState(callback: (node: INode) => number): void; + setState(callback: (node: INode) => IGraphObjectStateParameters): void; + setState( + arg: + | number + | IGraphObjectStateParameters + | ((node: INode) => number) + | ((node: INode) => IGraphObjectStateParameters), + ): void { + let result: number | IGraphObjectStateParameters; + + if (isFunction(arg)) { + result = (arg as (node: INode) => number | IGraphObjectStateParameters)(this); + } else { + result = arg; + } + + if (isNumber(result)) { + this._state = result; + } else if (isPlainObject(result)) { + const options = result.options; + + this._state = this._handleState(result.state, options); + + if (options) { + this.notifyListeners({ + id: this.id, + type: 'node', + options: options, + }); + + return; + } + } + + this.notifyListeners(); + } + protected _isPointInBoundingBox(point: IPosition): boolean { return isPointInRectangle(this.getBoundingBox(), point); } + + private _handleState(state: number, options?: Partial): number { + if (options?.isToggle && this._state === state) { + return GraphObjectState.NONE; + } else { + return state; + } + } } diff --git a/src/models/state.ts b/src/models/state.ts index a2f6a38..6a06839 100644 --- a/src/models/state.ts +++ b/src/models/state.ts @@ -1,6 +1,24 @@ +import { GraphObject } from '../utils/observer.utils'; + // Enum is dismissed so user can define custom additional events (numbers) export const GraphObjectState = { NONE: 0, SELECTED: 1, HOVERED: 2, }; + +export interface IGraphObjectStateOptions { + isToggle: boolean; + isSingle: boolean; +} + +export interface IGraphObjectStateParameters { + state: number; + options?: Partial; +} + +export interface ISetStateDataPayload { + id: any; + type: GraphObject; + options: Partial; +} diff --git a/src/models/strategy.ts b/src/models/strategy.ts index ed8fb08..d1fe4a6 100644 --- a/src/models/strategy.ts +++ b/src/models/strategy.ts @@ -229,24 +229,24 @@ const setNodeState = ( options?: ISetShapeStateOptions, ): void => { if (isStateChangeable(node, options)) { - node.state = state; + node.setState(state); } node.getInEdges().forEach((edge) => { if (edge && isStateChangeable(edge, options)) { - edge.state = state; + edge.setState(state); } if (edge.startNode && isStateChangeable(edge.startNode, options)) { - edge.startNode.state = state; + edge.startNode.setState(state); } }); node.getOutEdges().forEach((edge) => { if (edge && isStateChangeable(edge, options)) { - edge.state = state; + edge.setState(state); } if (edge.endNode && isStateChangeable(edge.endNode, options)) { - edge.endNode.state = state; + edge.endNode.setState(state); } }); }; @@ -257,15 +257,15 @@ const setEdgeState = ( options?: ISetShapeStateOptions, ): void => { if (isStateChangeable(edge, options)) { - edge.state = state; + edge.setState(state); } if (edge.startNode && isStateChangeable(edge.startNode, options)) { - edge.startNode.state = state; + edge.startNode.setState(state); } if (edge.endNode && isStateChangeable(edge.endNode, options)) { - edge.endNode.state = state; + edge.endNode.setState(state); } }; @@ -274,5 +274,5 @@ const isStateChangeable = ( options?: ISetShapeStateOptions, ): boolean => { const isOverride = options?.isStateOverride; - return isOverride || (!isOverride && !graphObject.state); + return isOverride || (!isOverride && !graphObject.getState()); }; diff --git a/src/models/style.ts b/src/models/style.ts index 358d2d5..e5bf506 100644 --- a/src/models/style.ts +++ b/src/models/style.ts @@ -33,8 +33,9 @@ export const getDefaultGraphStyle = () const getPredefinedLabel = ( obj: INode | IEdge, ): string | undefined => { + const objData = obj.getData(); for (let i = 0; i < LABEL_PROPERTY_NAMES.length; i++) { - const value = (obj.data as any)[LABEL_PROPERTY_NAMES[i]]; + const value = (objData as any)[LABEL_PROPERTY_NAMES[i]]; if (value !== undefined && value !== null) { return `${value}`; } diff --git a/src/renderer/canvas/canvas-renderer.ts b/src/renderer/canvas/canvas-renderer.ts index 9265d93..3e1eed8 100644 --- a/src/renderer/canvas/canvas-renderer.ts +++ b/src/renderer/canvas/canvas-renderer.ts @@ -150,10 +150,6 @@ export class CanvasRenderer extends Em } private _render(graph: IGraph) { - if (!graph.getNodeCount()) { - return; - } - this.emit(RenderEventType.RENDER_START, undefined); const renderStartedAt = Date.now(); diff --git a/src/renderer/canvas/edge/base.ts b/src/renderer/canvas/edge/base.ts index f6fd2f5..fc338b7 100644 --- a/src/renderer/canvas/edge/base.ts +++ b/src/renderer/canvas/edge/base.ts @@ -52,14 +52,16 @@ const drawEdgeLabel = ( return; } + const edgeStyle = edge.getStyle(); + const label = new Label(edgeLabel, { position: edge.getCenter(), textBaseline: LabelTextBaseline.MIDDLE, properties: { - fontBackgroundColor: edge.style.fontBackgroundColor, - fontColor: edge.style.fontColor, - fontFamily: edge.style.fontFamily, - fontSize: edge.style.fontSize, + fontBackgroundColor: edgeStyle.fontBackgroundColor, + fontColor: edgeStyle.fontColor, + fontFamily: edgeStyle.fontFamily, + fontSize: edgeStyle.fontSize, }, }); drawLabel(context, label); @@ -80,7 +82,7 @@ const drawLine = (context: CanvasRende }; const drawArrow = (context: CanvasRenderingContext2D, edge: IEdge) => { - if (edge.style.arrowSize === 0) { + if (edge.getStyle().arrowSize === 0) { return; } @@ -145,17 +147,19 @@ const setupShadow = ( context: CanvasRenderingContext2D, edge: IEdge, ) => { - if (edge.style.shadowColor) { - context.shadowColor = edge.style.shadowColor.toString(); + const edgeStyle = edge.getStyle(); + + if (edgeStyle.shadowColor) { + context.shadowColor = edgeStyle.shadowColor.toString(); } - if (edge.style.shadowSize) { - context.shadowBlur = edge.style.shadowSize; + if (edgeStyle.shadowSize) { + context.shadowBlur = edgeStyle.shadowSize; } - if (edge.style.shadowOffsetX) { - context.shadowOffsetX = edge.style.shadowOffsetX; + if (edgeStyle.shadowOffsetX) { + context.shadowOffsetX = edgeStyle.shadowOffsetX; } - if (edge.style.shadowOffsetY) { - context.shadowOffsetY = edge.style.shadowOffsetY; + if (edgeStyle.shadowOffsetY) { + context.shadowOffsetY = edgeStyle.shadowOffsetY; } }; @@ -163,16 +167,18 @@ const clearShadow = ( context: CanvasRenderingContext2D, edge: IEdge, ) => { - if (edge.style.shadowColor) { + const edgeStyle = edge.getStyle(); + + if (edgeStyle.shadowColor) { context.shadowColor = 'rgba(0,0,0,0)'; } - if (edge.style.shadowSize) { + if (edgeStyle.shadowSize) { context.shadowBlur = 0; } - if (edge.style.shadowOffsetX) { + if (edgeStyle.shadowOffsetX) { context.shadowOffsetX = 0; } - if (edge.style.shadowOffsetY) { + if (edgeStyle.shadowOffsetY) { context.shadowOffsetY = 0; } }; diff --git a/src/renderer/canvas/edge/types/edge-curved.ts b/src/renderer/canvas/edge/types/edge-curved.ts index 5da1859..0feaabc 100644 --- a/src/renderer/canvas/edge/types/edge-curved.ts +++ b/src/renderer/canvas/edge/types/edge-curved.ts @@ -32,7 +32,7 @@ export const drawCurvedLine = ( * @return {IEdgeArrow} Arrow shape */ export const getCurvedArrowShape = (edge: EdgeCurved): IEdgeArrow => { - const scaleFactor = edge.style.arrowSize ?? 1; + const scaleFactor = edge.getStyle().arrowSize ?? 1; const lineWidth = edge.getWidth() ?? 1; const guideOffset = -0.1; // const source = this.data.source; @@ -104,7 +104,7 @@ const findBorderPoint = ( const viaNode = edge.getCurvedControlPoint(); let node = edge.endNode; let from = false; - if (nearNode.id === edge.startNode.id) { + if (nearNode.getId() === edge.startNode.getId()) { node = edge.startNode; from = true; } diff --git a/src/renderer/canvas/edge/types/edge-loopback.ts b/src/renderer/canvas/edge/types/edge-loopback.ts index 6aaaaaa..7c84808 100644 --- a/src/renderer/canvas/edge/types/edge-loopback.ts +++ b/src/renderer/canvas/edge/types/edge-loopback.ts @@ -29,7 +29,7 @@ export const drawLoopbackLine = ( export const getLoopbackArrowShape = ( edge: EdgeLoopback, ): IEdgeArrow => { - const scaleFactor = edge.style.arrowSize ?? 1; + const scaleFactor = edge.getStyle().arrowSize ?? 1; const lineWidth = edge.getWidth() ?? 1; const source = edge.startNode; // const target = this.data.target; diff --git a/src/renderer/canvas/edge/types/edge-straight.ts b/src/renderer/canvas/edge/types/edge-straight.ts index 67cafdc..c011410 100644 --- a/src/renderer/canvas/edge/types/edge-straight.ts +++ b/src/renderer/canvas/edge/types/edge-straight.ts @@ -33,7 +33,7 @@ export const drawStraightLine = ( export const getStraightArrowShape = ( edge: EdgeStraight, ): IEdgeArrow => { - const scaleFactor = edge.style.arrowSize ?? 1; + const scaleFactor = edge.getStyle().arrowSize ?? 1; const lineWidth = edge.getWidth() ?? 1; const sourcePoint = edge.startNode.getCenter(); const targetPoint = edge.endNode.getCenter(); @@ -63,7 +63,7 @@ const findBorderPoint = ( ): IBorderPosition => { let endNode = edge.endNode; let startNode = edge.startNode; - if (nearNode.id === edge.startNode.id) { + if (nearNode.getId() === edge.startNode.getId()) { endNode = edge.startNode; startNode = edge.endNode; } diff --git a/src/renderer/canvas/node.ts b/src/renderer/canvas/node.ts index 814d7a6..ee4c202 100644 --- a/src/renderer/canvas/node.ts +++ b/src/renderer/canvas/node.ts @@ -2,6 +2,7 @@ import { INodeBase, INode, NodeShapeType } from '../../models/node'; import { IEdgeBase } from '../../models/edge'; import { drawDiamond, drawHexagon, drawSquare, drawStar, drawTriangleDown, drawTriangleUp, drawCircle } from './shapes'; import { drawLabel, Label, LabelTextBaseline } from './label'; +import { Color } from '../../common'; // The label will be `X` of the size below the Node const DEFAULT_LABEL_DISTANCE_SIZE_FROM_NODE = 0.2; @@ -53,7 +54,7 @@ const drawShape = (context: CanvasRend const center = node.getCenter(); const radius = node.getRadius(); - switch (node.style.shape) { + switch (node.getStyle().shape) { case NodeShapeType.SQUARE: { drawSquare(context, center.x, center.y, radius); break; @@ -96,15 +97,16 @@ const drawNodeLabel = ( const center = node.getCenter(); const distance = node.getBorderedRadius() * (1 + DEFAULT_LABEL_DISTANCE_SIZE_FROM_NODE); + const nodeStyle = node.getStyle(); const label = new Label(nodeLabel, { position: { x: center.x, y: center.y + distance }, textBaseline: LabelTextBaseline.TOP, properties: { - fontBackgroundColor: node.style.fontBackgroundColor, - fontColor: node.style.fontColor, - fontFamily: node.style.fontFamily, - fontSize: node.style.fontSize, + fontBackgroundColor: nodeStyle.fontBackgroundColor, + fontColor: nodeStyle.fontColor, + fontFamily: nodeStyle.fontFamily, + fontSize: nodeStyle.fontSize, }, }); drawLabel(context, label); @@ -156,17 +158,19 @@ const setupShadow = ( context: CanvasRenderingContext2D, node: INode, ) => { - if (node.style.shadowColor) { - context.shadowColor = node.style.shadowColor.toString(); + const nodeStyle = node.getStyle(); + + if (nodeStyle.shadowColor) { + context.shadowColor = (nodeStyle.shadowColor as string | Color).toString(); } - if (node.style.shadowSize) { - context.shadowBlur = node.style.shadowSize; + if (nodeStyle.shadowSize) { + context.shadowBlur = nodeStyle.shadowSize as number; } - if (node.style.shadowOffsetX) { - context.shadowOffsetX = node.style.shadowOffsetX; + if (nodeStyle.shadowOffsetX) { + context.shadowOffsetX = nodeStyle.shadowOffsetX as number; } - if (node.style.shadowOffsetY) { - context.shadowOffsetY = node.style.shadowOffsetY; + if (nodeStyle.shadowOffsetY) { + context.shadowOffsetY = nodeStyle.shadowOffsetY as number; } }; @@ -174,16 +178,18 @@ const clearShadow = ( context: CanvasRenderingContext2D, node: INode, ) => { - if (node.style.shadowColor) { + const nodeStyle = node.getStyle(); + + if (nodeStyle.shadowColor) { context.shadowColor = 'rgba(0,0,0,0)'; } - if (node.style.shadowSize) { + if (nodeStyle.shadowSize) { context.shadowBlur = 0; } - if (node.style.shadowOffsetX) { + if (nodeStyle.shadowOffsetX) { context.shadowOffsetX = 0; } - if (node.style.shadowOffsetY) { + if (nodeStyle.shadowOffsetY) { context.shadowOffsetY = 0; } }; diff --git a/src/simulator/engine/d3-simulator-engine.ts b/src/simulator/engine/d3-simulator-engine.ts index 1eb27d5..225fd67 100644 --- a/src/simulator/engine/d3-simulator-engine.ts +++ b/src/simulator/engine/d3-simulator-engine.ts @@ -11,21 +11,22 @@ import { SimulationLinkDatum, } from 'd3-force'; import { IPosition } from '../../common'; -import { ISimulationNode, ISimulationEdge } from '../shared'; +import { ISimulationNode, ISimulationEdge, ISimulationGraph } from '../shared'; import { Emitter } from '../../utils/emitter.utils'; import { isObjectEqual, copyObject } from '../../utils/object.utils'; const MANY_BODY_MAX_DISTANCE_TO_LINK_DISTANCE_RATIO = 100; -const DEFAULT_LINK_DISTANCE = 30; +const DEFAULT_LINK_DISTANCE = 50; export enum D3SimulatorEngineEventType { - TICK = 'tick', - END = 'end', SIMULATION_START = 'simulation-start', SIMULATION_PROGRESS = 'simulation-progress', SIMULATION_END = 'simulation-end', + SIMULATION_TICK = 'simulation-tick', + SIMULATION_RESET = 'simulation-reset', NODE_DRAG = 'node-drag', SETTINGS_UPDATE = 'settings-update', + DATA_CLEARED = 'data-cleared', } export interface ID3SimulatorEngineSettingsAlpha { @@ -72,6 +73,9 @@ export interface ID3SimulatorEngineSettingsPositioning { } export interface ID3SimulatorEngineSettings { + isSimulatingOnDataUpdate: boolean; + isSimulatingOnSettingsUpdate: boolean; + isSimulatingOnUnstick: boolean; isPhysicsEnabled: boolean; alpha: ID3SimulatorEngineSettingsAlpha; centering: ID3SimulatorEngineSettingsCentering | null; @@ -89,12 +93,15 @@ export const getManyBodyMaxDistance = (linkDistance: number) => { }; export const DEFAULT_SETTINGS: ID3SimulatorEngineSettings = { + isSimulatingOnDataUpdate: true, + isSimulatingOnSettingsUpdate: true, + isSimulatingOnUnstick: true, isPhysicsEnabled: false, alpha: { alpha: 1, alphaMin: 0.001, alphaDecay: 0.0228, - alphaTarget: 0.1, + alphaTarget: 0, }, centering: { x: 0, @@ -108,7 +115,7 @@ export const DEFAULT_SETTINGS: ID3SimulatorEngineSettings = { }, links: { distance: DEFAULT_LINK_DISTANCE, - strength: undefined, + strength: 1, iterations: 1, }, manyBody: { @@ -133,11 +140,6 @@ export interface ID3SimulatorProgress { progress: number; } -export interface ID3SimulatorGraph { - nodes: ISimulationNode[]; - edges: ISimulationEdge[]; -} - export interface ID3SimulatorNodeId { id: number; } @@ -151,19 +153,20 @@ interface IRunSimulationOptions { } export type D3SimulatorEvents = { - [D3SimulatorEngineEventType.TICK]: ID3SimulatorGraph; - [D3SimulatorEngineEventType.END]: ID3SimulatorGraph; [D3SimulatorEngineEventType.SIMULATION_START]: undefined; - [D3SimulatorEngineEventType.SIMULATION_PROGRESS]: ID3SimulatorGraph & ID3SimulatorProgress; - [D3SimulatorEngineEventType.SIMULATION_END]: ID3SimulatorGraph; - [D3SimulatorEngineEventType.NODE_DRAG]: ID3SimulatorGraph; + [D3SimulatorEngineEventType.SIMULATION_PROGRESS]: ISimulationGraph & ID3SimulatorProgress; + [D3SimulatorEngineEventType.SIMULATION_END]: ISimulationGraph; + [D3SimulatorEngineEventType.SIMULATION_TICK]: ISimulationGraph; + [D3SimulatorEngineEventType.SIMULATION_RESET]: ISimulationGraph; + [D3SimulatorEngineEventType.NODE_DRAG]: ISimulationGraph; [D3SimulatorEngineEventType.SETTINGS_UPDATE]: ID3SimulatorSettings; + [D3SimulatorEngineEventType.DATA_CLEARED]: ISimulationGraph; }; export class D3SimulatorEngine extends Emitter { - protected readonly linkForce: ForceLink>; - protected readonly simulation: Simulation; - protected readonly settings: ID3SimulatorEngineSettings; + protected _linkForce!: ForceLink>; + protected _simulation!: Simulation; + protected _settings: ID3SimulatorEngineSettings; protected _edges: ISimulationEdge[] = []; protected _nodes: ISimulationNode[] = []; @@ -172,53 +175,69 @@ export class D3SimulatorEngine extends Emitter { protected _isDragging = false; protected _isStabilizing = false; + // These are settings provided during construction if they are specified, + // or during the first call of setSettings if unspecified during construction. + protected _initialSettings: ID3SimulatorEngineSettings | undefined; + constructor(settings?: ID3SimulatorEngineSettings) { super(); - this.linkForce = forceLink>(this._edges).id( - (node) => node.id, - ); - this.simulation = forceSimulation(this._nodes).force('link', this.linkForce).stop(); - - this.settings = Object.assign(copyObject(DEFAULT_SETTINGS), settings); - this.initSimulation(this.settings); - - this.simulation.on('tick', () => { - this.emit(D3SimulatorEngineEventType.TICK, { nodes: this._nodes, edges: this._edges }); - }); + if (settings !== undefined) { + this._initialSettings = Object.assign(copyObject(DEFAULT_SETTINGS), settings); + } - this.simulation.on('end', () => { - this._isDragging = false; - this._isStabilizing = false; - this.emit(D3SimulatorEngineEventType.END, { nodes: this._nodes, edges: this._edges }); - }); + this._settings = this.resetSettings(); + this.clearData(); } getSettings(): ID3SimulatorEngineSettings { - return copyObject(this.settings); + return copyObject(this._settings); } + /** + * Applies the specified settings to the D3 simulator engine. + * + * @param {ID3SimulatorEngineSettingsUpdate} settings Partial D3 simulator engine settings (any property of settings) + */ setSettings(settings: ID3SimulatorEngineSettingsUpdate) { + if (!this._initialSettings) { + this._initialSettings = Object.assign(copyObject(DEFAULT_SETTINGS), settings); + } + const previousSettings = this.getSettings(); - Object.keys(settings).forEach((key) => { - // @ts-ignore - this.settings[key] = settings[key]; - }); + Object.assign(this._settings, settings); - if (isObjectEqual(this.settings, previousSettings)) { + if (isObjectEqual(this._settings, previousSettings)) { return; } - this.initSimulation(settings); - this.emit(D3SimulatorEngineEventType.SETTINGS_UPDATE, { settings: this.settings }); + this._applySettingsToSimulation(settings); + this.emit(D3SimulatorEngineEventType.SETTINGS_UPDATE, { settings: this._settings }); + + const hasPhysicsBeenDisabled = previousSettings.isPhysicsEnabled && !settings.isPhysicsEnabled; + + if (hasPhysicsBeenDisabled) { + this._simulation.stop(); + } else if (this._settings.isSimulatingOnSettingsUpdate) { + // this.runSimulation({ isUpdatingSettings: true }); + this.activateSimulation(); + } + } - this.runSimulation({ isUpdatingSettings: true }); + /** + * Restores simulator engine settings to the initial settings provided during construction. + * + * @return {ID3SimulatorEngineSettings} The default settings patched with the specified parameters in the + * initial settings provided in the constructor or during the first settings update. + */ + resetSettings(): ID3SimulatorEngineSettings { + return Object.assign(copyObject(DEFAULT_SETTINGS), this._initialSettings); } startDragNode() { this._isDragging = true; - if (!this._isStabilizing && this.settings.isPhysicsEnabled) { + if (!this._isStabilizing && this._settings.isPhysicsEnabled) { this.activateSimulation(); } } @@ -236,183 +255,377 @@ export class D3SimulatorEngine extends Emitter { node.fx = data.x; node.fy = data.y; - if (!this.settings.isPhysicsEnabled) { + if (!this._settings.isPhysicsEnabled) { node.x = data.x; node.y = data.y; - - // Notify the client that the node position changed. - // This is otherwise handled by the simulation tick if physics is enabled. - this.emit(D3SimulatorEngineEventType.NODE_DRAG, { nodes: this._nodes, edges: this._edges }); } + + // Notify the client that the node position changed. + this.emit(D3SimulatorEngineEventType.NODE_DRAG, { nodes: this._nodes, edges: this._edges }); } endDragNode(data: ID3SimulatorNodeId) { this._isDragging = false; - this.simulation.alphaTarget(0); + if (this._settings.isPhysicsEnabled) { + this._simulation.alphaTarget(0); + } const node = this._nodes[this._nodeIndexByNodeId[data.id]]; - if (node && this.settings.isPhysicsEnabled) { - releaseNode(node); + // TODO(dlozic): Add special behavior for sticky nodes that have been dragged + if (node && this._settings.isPhysicsEnabled) { + this.unfixNode(node); } } - // Re-heat simulation. - // This does not count as "stabilization" and won't emit any progress. + /** + * Activates the simulation and "re-heats" the nodes so that they converge to a new layout. + * This does not count as "stabilization" and won't emit any progress. + */ activateSimulation() { - if (this.settings.isPhysicsEnabled) { - this.simulation.alphaTarget(this.settings.alpha.alphaTarget).restart(); - this.releaseNodes(); + this.unfixNodes(); // If physics is disabled, the nodes get fixed in the callback from the initial setup (`simulation.on('end', () => {})`). + this._simulation.alpha(this._settings.alpha.alpha).alphaTarget(this._settings.alpha.alphaTarget).restart(); + } + + setupData(data: ISimulationGraph) { + this.clearData(); + + this._initializeNewData(data); + + if (this._settings.isSimulatingOnDataUpdate) { + this._updateSimulationData(); + this._runSimulation(); } } - private fixDefinedNodes(data: ID3SimulatorGraph) { - // Treat nodes that have existing coordinates as "fixed". - for (let i = 0; i < data.nodes.length; i++) { - if (data.nodes[i].x !== null && data.nodes[i].x !== undefined) { - data.nodes[i].fx = data.nodes[i].x; + mergeData(data: Partial) { + this._initializeNewData(data); + + if (this._settings.isSimulatingOnDataUpdate) { + this._updateSimulationData(); + this.activateSimulation(); + } + } + + patchData(data: Partial) { + if (data.nodes) { + data.nodes = this._fixAndStickDefinedNodes(data.nodes); + const nodeIds: { [id: number]: number } = {}; + + for (let i = 0; i < this._nodes.length; i++) { + nodeIds[this._nodes[i].id] = i; } - if (data.nodes[i].y !== null && data.nodes[i].y !== undefined) { - data.nodes[i].fy = data.nodes[i].y; + + for (let i = 0; i < data.nodes.length; i += 1) { + const nodeId: any = data.nodes[i].id; + + if (nodeId in nodeIds) { + const index = nodeIds[nodeId]; + this._nodeIndexByNodeId[nodeId] = index; + this._nodes[index] = data.nodes[i]; + } else { + this._nodes.push(data.nodes[i]); + } } } - return data; - } - addData(data: ID3SimulatorGraph) { - data = this.fixDefinedNodes(data); - this._nodes.concat(data.nodes); - this._edges.concat(data.edges); - this.setNodeIndexByNodeId(); + if (data.edges) { + this._edges = this._edges.concat(data.edges); + } } - clearData() { - this._nodes = []; - this._edges = []; - this.setNodeIndexByNodeId(); + private _initializeNewData(data: Partial) { + if (data.nodes) { + data.nodes = this._fixAndStickDefinedNodes(data.nodes); + for (let i = 0; i < data.nodes.length; i += 1) { + const nodeId = data.nodes[i].id; + + if (this._nodeIndexByNodeId[nodeId]) { + this._nodeIndexByNodeId[nodeId] = i; + } else { + this._nodes.push(data.nodes[i]); + } + } + } else { + this._nodes = []; + } + if (data.edges) { + this._edges = this._edges.concat(data.edges); + } else { + this._edges = []; + } + this._setNodeIndexByNodeId(); } - setData(data: ID3SimulatorGraph) { - data = this.fixDefinedNodes(data); - this.clearData(); - this.addData(data); - } + updateData(data: ISimulationGraph) { + data.nodes = this._fixAndStickDefinedNodes(data.nodes); - updateData(data: ID3SimulatorGraph) { - data = this.fixDefinedNodes(data); // Keep existing nodes along with their (x, y, fx, fy) coordinates to avoid // rearranging the graph layout. // These nodes should not be reloaded into the array because the D3 simulation // will assign to them completely new coordinates, effectively restarting the animation. const newNodeIds = new Set(data.nodes.map((node) => node.id)); - // Remove old nodes that aren't present in the new data. + // Keep old nodes that are present in the new data instead of reassigning them. const oldNodes = this._nodes.filter((node) => newNodeIds.has(node.id)); const newNodes = data.nodes.filter((node) => this._nodeIndexByNodeId[node.id] === undefined); this._nodes = [...oldNodes, ...newNodes]; - this.setNodeIndexByNodeId(); + this._setNodeIndexByNodeId(); // Only keep new links and discard all old links. // Old links won't work as some discrepancies arise between the D3 index property // and Memgraph's `id` property which affects the source->target mapping. this._edges = data.edges; - // Update simulation with new data. - this.simulation.nodes(this._nodes); - this.linkForce.links(this._edges); + if (this._settings.isSimulatingOnSettingsUpdate) { + this._updateSimulationData(); + this.activateSimulation(); + } + } + + /** + * Removes specified data from the simulation. + * + * @param {ISimulationGraph} data Nodes and edges that will be deleted + */ + deleteData(data: Partial<{ nodeIds: number[] | undefined; edgeIds: number[] | undefined }>) { + const nodeIds = new Set(data.nodeIds); + this._nodes = this._nodes.filter((node) => !nodeIds.has(node.id)); + const edgeIds = new Set(data.edgeIds); + this._edges = this._edges.filter((edge) => !edgeIds.has(edge.id)); + this._setNodeIndexByNodeId(); + this._updateSimulationData(); } - simulate() { + /** + * Removes all internal and D3 simulation node and relationship data. + */ + clearData() { + const nodes = this._nodes; + const edges = this._edges; + this._nodes = []; + this._edges = []; + this._setNodeIndexByNodeId(); + this.resetSimulation(); + this.emit(D3SimulatorEngineEventType.DATA_CLEARED, { nodes: nodes, edges: edges }); + } + + /** + * Updates the internal D3 simulation data with the current data. + */ + private _updateSimulationData() { // Update simulation with new data. - this.simulation.nodes(this._nodes); - this.linkForce.links(this._edges); + this._simulation.nodes(this._nodes); + this._linkForce.links(this._edges); + } - // Run simulation "physics". - this.runSimulation(); + /** + * Resets the simulator engine by discarding all existing simulator data (nodes and edges), + * and keeping the current simulator engine settings. + */ + // TODO(Alex): Listeners memory leak (D3 force research) + resetSimulation() { + this._linkForce = forceLink>(this._edges).id( + (node) => node.id, + ); + this._simulation = forceSimulation(this._nodes).force('link', this._linkForce).stop(); - if (!this.settings.isPhysicsEnabled) { - this.fixNodes(); - } + this._applySettingsToSimulation(this._settings); + + this._simulation.on('tick', () => { + this.emit(D3SimulatorEngineEventType.SIMULATION_TICK, { nodes: this._nodes, edges: this._edges }); + }); + + this._simulation.on('end', () => { + this._isDragging = false; + this._isStabilizing = false; + this.emit(D3SimulatorEngineEventType.SIMULATION_END, { nodes: this._nodes, edges: this._edges }); + + if (!this._settings.isPhysicsEnabled) { + this.fixNodes(); + } + }); + + this.emit(D3SimulatorEngineEventType.SIMULATION_RESET, { nodes: this._nodes, edges: this._edges }); } - startSimulation(data: ID3SimulatorGraph) { - this.setData(data); + /** + * Fixes all nodes by setting their `fx` and `fy` properties to `x` and `y`. + * If no nodes are provided, this function fixes all nodes. + * + * @param {ISimulationNode[]} nodes Nodes that are going to be fixed. If undefined, all nodes get fixed. + */ + fixNodes(nodes?: ISimulationNode[]) { + if (!nodes) { + nodes = this._nodes; + } - // Update simulation with new data. - this.simulation.nodes(this._nodes); - this.linkForce.links(this._edges); + for (let i = 0; i < nodes.length; i++) { + this.fixNode(this._nodes[i]); + } + } + + /** + * Releases specified nodes. + * If no nodes are provided, this function releases all nodes. + * + * @param {ISimulationNode[]} nodes Nodes that are going to be released. If undefined, all nodes get released. + */ + unfixNodes(nodes?: ISimulationNode[]) { + if (!nodes) { + nodes = this._nodes; + } - // Run simulation "physics". - this.runSimulation(); + for (let i = 0; i < nodes.length; i++) { + this.unfixNode(this._nodes[i]); + } } - updateSimulation(data: ID3SimulatorGraph) { - // To avoid rearranging the graph layout during node expand/collapse/hide, - // it is necessary to keep existing nodes along with their (x, y) coordinates. - // These nodes should not be reloaded into the array because the D3 simulation - // will assign to them completely new coordinates, effectively restarting the animation. - const newNodeIds = new Set(data.nodes.map((node) => node.id)); + /** + * Fixes a node by setting its `fx` and `fy` properties to `x` and `y`. + * This function is called when disabling physics. + * + * @param {ISimulationNode} node Simulation node that is going to be fixed + */ + fixNode(node: ISimulationNode) { + if (node.sx === null || node.sx === undefined) { + node.fx = node.x; + } + if (node.sy === null || node.sy === undefined) { + node.fy = node.y; + } + } - // const newNodes = data.nodes.filter((node) => !this.nodeIdentities.has(node.id)); - const newNodes = data.nodes.filter((node) => this._nodeIndexByNodeId[node.id] === undefined); - const oldNodes = this._nodes.filter((node) => newNodeIds.has(node.id)); + /** + * Releases a node if it's not sticky by setting its `fx` and `fy` properties to `null`. + * This function is called when enabling physics but the sticky property overpowers physics. + * + * @param {ISimulationNode} node Simulation node that is going to be released + */ + unfixNode(node: ISimulationNode) { + if (node.sx === null || node.sx === undefined) { + node.fx = null; + } + if (node.sy === null || node.sy === undefined) { + node.fy = null; + } + } - if (!this.settings.isPhysicsEnabled) { - oldNodes.forEach((node) => fixNode(node)); + /** + * Sticks the specified nodes into place. + * This overpowers any physics state and also sticks the node to their current positions. + * If no nodes are provided, this function sticks all nodes. + * + * @param {ISimulationNode[]} nodes Nodes that are going to become sticky. If undefined, all nodes get sticked. + */ + stickNodes(nodes?: ISimulationNode[]) { + if (!nodes) { + nodes = this._nodes; } - // Remove old nodes that aren't present in the new data. - this._nodes = [...oldNodes, ...newNodes]; - this.setNodeIndexByNodeId(); + for (let i = 0; i < nodes.length; i++) { + this.stickNode(this._nodes[i]); + } + } - // Only keep new links and discard all old links. - // Old links won't work as some discrepancies arise between the D3 index property - // and Memgraph's `id` property which affects the source->target mapping. - this._edges = data.edges; + /** + * Removes the sticky properties from all specified nodes. + * If physics is enabled, the nodes get unfixed as well. + * If no nodes are provided, this function unsticks all nodes. + * + * @param {ISimulationNode[]} nodes Nodes that are going to be unsticked. If undefined, all nodes get unsticked. + */ + unstickNodes(nodes?: ISimulationNode[]) { + if (!nodes) { + nodes = this._nodes; + } - // Update simulation with new data. - this.simulation.nodes(this._nodes); - this.linkForce.links(this._edges); + for (let i = 0; i < nodes.length; i++) { + this.unstickNode(this._nodes[i]); + } - // If there are no new nodes, there is no need for the simulation - if (!this.settings.isPhysicsEnabled && !newNodes.length) { - this.emit(D3SimulatorEngineEventType.SIMULATION_END, { nodes: this._nodes, edges: this._edges }); - return; + if (this._settings.isSimulatingOnUnstick) { + this.activateSimulation(); } + } - // Run simulation "physics". - this.runSimulation({ isUpdatingSettings: true }); + /** + * Sticks a node into place. + * This function overpowers any physics state and also sticks the node to its current coordinates. + * + * @param {ISimulationNode} node Simulation node that is going to become sticky + */ + stickNode(node: ISimulationNode) { + node.sx = node.x; + node.fx = node.x; + node.sy = node.y; + node.fy = node.y; } - stopSimulation() { - this.simulation.stop(); - this._nodes = []; - this._edges = []; - this.setNodeIndexByNodeId(); - this.simulation.nodes(); - this.linkForce.links(); + /** + * Removes the sticky properties from the node. + * If physics is enabled, the node gets released as well. + * + * @param {ISimulationNode} node Simulation node that gets unstuck + */ + unstickNode(node: ISimulationNode) { + node.sx = null; + node.sy = null; + + if (this._settings.isPhysicsEnabled) { + node.fx = null; + node.fy = null; + } } - protected initSimulation(settings: ID3SimulatorEngineSettingsUpdate) { + /** + * Sticks all nodes thath have a defined position (x and y coordinates). + * This function should be called when the user initially sets up or merges some data. + * If the user provided nodes already have defined `x` **or** `y` properties, they are treated as _"sticky"_. + * Only the specified axis gets immobilized. + * + * @param {ISimulationNode[]} nodes Graph nodes. + * @return {ISimulationNodes[]} Graph nodes with attached `{fx, sx}`, and/or `{fy, sy}` coordinates. + */ + private _fixAndStickDefinedNodes(nodes: ISimulationNode[]): ISimulationNode[] { + for (let i = 0; i < nodes.length; i++) { + if (nodes[i].x !== null && nodes[i].x !== undefined) { + nodes[i].fx = nodes[i].x; + nodes[i].sx = nodes[i].x; + } + if (nodes[i].y !== null && nodes[i].y !== undefined) { + nodes[i].fy = nodes[i].y; + nodes[i].sy = nodes[i].y; + } + } + return nodes; + } + + /** + * Applies the provided settings to the D3 simulation. + * + * @param {ID3SimulatorEngineSettingsUpdate} settings Simulator engine settings + */ + private _applySettingsToSimulation(settings: ID3SimulatorEngineSettingsUpdate) { if (settings.alpha) { - this.simulation + this._simulation .alpha(settings.alpha.alpha) .alphaMin(settings.alpha.alphaMin) .alphaDecay(settings.alpha.alphaDecay) .alphaTarget(settings.alpha.alphaTarget); } if (settings.links) { - this.linkForce.distance(settings.links.distance).iterations(settings.links.iterations); + this._linkForce.distance(settings.links.distance).iterations(settings.links.iterations); } if (settings.collision) { const collision = forceCollide() .radius(settings.collision.radius) .strength(settings.collision.strength) .iterations(settings.collision.iterations); - this.simulation.force('collide', collision); + this._simulation.force('collide', collision); } if (settings.collision === null) { - this.simulation.force('collide', null); + this._simulation.force('collide', null); } if (settings.manyBody) { const manyBody = forceManyBody() @@ -420,51 +633,51 @@ export class D3SimulatorEngine extends Emitter { .theta(settings.manyBody.theta) .distanceMin(settings.manyBody.distanceMin) .distanceMax(settings.manyBody.distanceMax); - this.simulation.force('charge', manyBody); + this._simulation.force('charge', manyBody); } if (settings.manyBody === null) { - this.simulation.force('charge', null); + this._simulation.force('charge', null); } if (settings.positioning?.forceY) { const positioningForceX = forceX(settings.positioning.forceX.x).strength(settings.positioning.forceX.strength); - this.simulation.force('x', positioningForceX); + this._simulation.force('x', positioningForceX); } if (settings.positioning?.forceX === null) { - this.simulation.force('x', null); + this._simulation.force('x', null); } if (settings.positioning?.forceY) { const positioningForceY = forceY(settings.positioning.forceY.y).strength(settings.positioning.forceY.strength); - this.simulation.force('y', positioningForceY); + this._simulation.force('y', positioningForceY); } if (settings.positioning?.forceY === null) { - this.simulation.force('y', null); + this._simulation.force('y', null); } if (settings.centering) { const centering = forceCenter(settings.centering.x, settings.centering.y).strength(settings.centering.strength); - this.simulation.force('center', centering); + this._simulation.force('center', centering); } if (settings.centering === null) { - this.simulation.force('center', null); + this._simulation.force('center', null); } } // This is a blocking action - the user will not be able to interact with the graph // during the simulation process. - protected runSimulation(options?: IRunSimulationOptions) { + private _runSimulation(options?: IRunSimulationOptions) { if (this._isStabilizing) { return; } - if (this.settings.isPhysicsEnabled || options?.isUpdatingSettings) { - this.releaseNodes(); + if (this._settings.isPhysicsEnabled || options?.isUpdatingSettings) { + this.unfixNodes(); } this.emit(D3SimulatorEngineEventType.SIMULATION_START, undefined); this._isStabilizing = true; - this.simulation.alpha(this.settings.alpha.alpha).alphaTarget(this.settings.alpha.alphaTarget).stop(); + this._simulation.alpha(this._settings.alpha.alpha).alphaTarget(this._settings.alpha.alphaTarget).stop(); const totalSimulationSteps = Math.ceil( - Math.log(this.settings.alpha.alphaMin) / Math.log(1 - this.settings.alpha.alphaDecay), + Math.log(this._settings.alpha.alphaMin) / Math.log(1 - this._settings.alpha.alphaDecay), ); let lastProgress = -1; @@ -479,10 +692,10 @@ export class D3SimulatorEngine extends Emitter { progress: currentProgress / 100, }); } - this.simulation.tick(); + this._simulation.tick(); } - if (!this.settings.isPhysicsEnabled) { + if (!this._settings.isPhysicsEnabled) { this.fixNodes(); } @@ -490,41 +703,10 @@ export class D3SimulatorEngine extends Emitter { this.emit(D3SimulatorEngineEventType.SIMULATION_END, { nodes: this._nodes, edges: this._edges }); } - protected setNodeIndexByNodeId() { + private _setNodeIndexByNodeId() { this._nodeIndexByNodeId = {}; for (let i = 0; i < this._nodes.length; i++) { this._nodeIndexByNodeId[this._nodes[i].id] = i; } } - - fixNodes(nodes?: ISimulationNode[]) { - if (!nodes) { - nodes = this._nodes; - } - - for (let i = 0; i < nodes.length; i++) { - fixNode(this._nodes[i]); - } - } - - releaseNodes(nodes?: ISimulationNode[]) { - if (!nodes) { - nodes = this._nodes; - } - - for (let i = 0; i < nodes.length; i++) { - releaseNode(this._nodes[i]); - } - } } - -const fixNode = (node: ISimulationNode) => { - // fx and fy fix the node position in the D3 simulation. - node.fx = node.x; - node.fy = node.y; -}; - -const releaseNode = (node: ISimulationNode) => { - node.fx = null; - node.fy = null; -}; diff --git a/src/simulator/factory.ts b/src/simulator/factory.ts index 8ef2466..e902e6f 100644 --- a/src/simulator/factory.ts +++ b/src/simulator/factory.ts @@ -1,7 +1,8 @@ import { ISimulator } from './shared'; import { MainThreadSimulator } from './types/main-thread-simulator'; -import { WebWorkerSimulator } from './types/web-worker-simulator/simulator'; +import { WebWorkerSimulator } from './types/web-worker-simulator/web-worker-simulator'; +// TODO(dlozic & Alex): CORS handling export class SimulatorFactory { static getSimulator(): ISimulator { try { diff --git a/src/simulator/layout/layout.ts b/src/simulator/layout/layout.ts new file mode 100644 index 0000000..defe2bc --- /dev/null +++ b/src/simulator/layout/layout.ts @@ -0,0 +1,29 @@ +import { IEdgeBase } from '../../models/edge'; +import { INode, INodeBase, INodePosition } from '../../models/node'; +import { CircleLayout } from './layouts/circle'; + +export enum layouts { + DEFAULT = 'default', + CIRCLE = 'circle', +} + +export interface ILayout { + getPositions(nodes: INode[], width: number, height: number): INodePosition[]; +} + +export class Layout implements ILayout { + private readonly _layout: ILayout | null; + + private layoutByLayoutName: Record | null> = { + [layouts.DEFAULT]: null, + [layouts.CIRCLE]: new CircleLayout(), + }; + + constructor(layoutName: string) { + this._layout = this.layoutByLayoutName[layoutName]; + } + + getPositions(nodes: INode[], width: number, height: number): INodePosition[] { + return this._layout === null ? [] : this._layout.getPositions(nodes, width, height); + } +} diff --git a/src/simulator/layout/layouts/circle.ts b/src/simulator/layout/layouts/circle.ts new file mode 100644 index 0000000..b601d78 --- /dev/null +++ b/src/simulator/layout/layouts/circle.ts @@ -0,0 +1,11 @@ +import { IEdgeBase } from '../../../models/edge'; +import { INode, INodeBase, INodePosition } from '../../../models/node'; +import { ILayout } from '../layout'; + +export class CircleLayout implements ILayout { + getPositions(nodes: INode[], width: number, height: number): INodePosition[] { + return nodes.map((node, index) => { + return { id: node.id, x: width / 2, y: height - index * 10 }; + }); + } +} diff --git a/src/simulator/shared.ts b/src/simulator/shared.ts index f3d9d11..7501367 100644 --- a/src/simulator/shared.ts +++ b/src/simulator/shared.ts @@ -3,11 +3,39 @@ import { SimulationLinkDatum, SimulationNodeDatum } from 'd3-force'; import { ID3SimulatorEngineSettings, ID3SimulatorEngineSettingsUpdate } from './engine/d3-simulator-engine'; import { IEmitter } from '../utils/emitter.utils'; -export type ISimulationNode = SimulationNodeDatum & { id: number; mass?: number }; +/** + * Node with sticky coordinates. + * A sticky node is immovable and represents a positioned node with user defined coordinates. + * This node isn't affected by physics. + * This enables a combination of sticky and free nodes where the free nodes are positioned + * by the simulator engine to adjust to the immobilized sticky nodes. + * Not to be confused with fixed coordinates `{ fx, fy }` which are used for physics. + */ +export interface IStickyNode { + sx?: number | null; + sy?: number | null; +} + +export type ISimulationNode = SimulationNodeDatum & + IStickyNode & { + id: number; + mass?: number; + }; export type ISimulationEdge = SimulationLinkDatum & { id: number }; +export interface ISimulationGraph { + nodes: ISimulationNode[]; + edges: ISimulationEdge[]; +} + +export interface ISimulationIds { + nodeIds: number[]; + edgeIds: number[]; +} + export enum SimulatorEventType { SIMULATION_START = 'simulation-start', + SIMULATION_STEP = 'simulation-step', SIMULATION_PROGRESS = 'simulation-progress', SIMULATION_END = 'simulation-end', NODE_DRAG = 'node-drag', @@ -17,6 +45,7 @@ export enum SimulatorEventType { export type SimulatorEvents = { [SimulatorEventType.SIMULATION_START]: undefined; + [SimulatorEventType.SIMULATION_STEP]: ISimulatorEventGraph; [SimulatorEventType.SIMULATION_PROGRESS]: ISimulatorEventGraph & ISimulatorEventProgress; [SimulatorEventType.SIMULATION_END]: ISimulatorEventGraph; [SimulatorEventType.NODE_DRAG]: ISimulatorEventGraph; @@ -25,18 +54,16 @@ export type SimulatorEvents = { }; export interface ISimulator extends IEmitter { - // Sets nodes and edges without running simulation - setData(nodes: ISimulationNode[], edges: ISimulationEdge[]): void; - addData(nodes: ISimulationNode[], edges: ISimulationEdge[]): void; - updateData(nodes: ISimulationNode[], edges: ISimulationEdge[]): void; + setupData(data: ISimulationGraph): void; + mergeData(data: ISimulationGraph): void; + updateData(data: ISimulationGraph): void; + deleteData(data: Partial): void; + patchData(data: Partial): void; clearData(): void; // Simulation handlers simulate(): void; activateSimulation(): void; - startSimulation(nodes: ISimulationNode[], edges: ISimulationEdge[]): void; - updateSimulation(nodes: ISimulationNode[], edges: ISimulationEdge[]): void; - stopSimulation(): void; // Node handlers startDragNode(): void; @@ -68,6 +95,7 @@ export interface ISimulatorEvents { onNodeDrag: (data: ISimulatorEventGraph) => void; onNodeDragEnd: (data: ISimulatorEventGraph) => void; onSimulationStart: () => void; + onSimulationStep: (data: ISimulatorEventGraph) => void; onSimulationProgress: (data: ISimulatorEventGraph & ISimulatorEventProgress) => void; onSimulationEnd: (data: ISimulatorEventGraph) => void; onSettingsUpdate: (data: ISimulatorEventSettings) => void; diff --git a/src/simulator/types/main-thread-simulator.ts b/src/simulator/types/main-thread-simulator.ts index de62998..1bbc36c 100644 --- a/src/simulator/types/main-thread-simulator.ts +++ b/src/simulator/types/main-thread-simulator.ts @@ -1,4 +1,11 @@ -import { ISimulationEdge, ISimulationNode, ISimulator, SimulatorEvents, SimulatorEventType } from '../shared'; +import { + ISimulationNode, + ISimulator, + SimulatorEvents, + SimulatorEventType, + ISimulationGraph, + ISimulationIds, +} from '../shared'; import { IPosition } from '../../common'; import { Emitter } from '../../utils/emitter.utils'; import { @@ -8,97 +15,90 @@ import { } from '../engine/d3-simulator-engine'; export class MainThreadSimulator extends Emitter implements ISimulator { - protected readonly simulator: D3SimulatorEngine; + protected readonly _simulator: D3SimulatorEngine; constructor() { super(); - this.simulator = new D3SimulatorEngine(); - this.simulator.on(D3SimulatorEngineEventType.SIMULATION_START, () => { + this._simulator = new D3SimulatorEngine(); + this._simulator.on(D3SimulatorEngineEventType.SIMULATION_START, () => { this.emit(SimulatorEventType.SIMULATION_START, undefined); }); - this.simulator.on(D3SimulatorEngineEventType.SIMULATION_PROGRESS, (data) => { + this._simulator.on(D3SimulatorEngineEventType.SIMULATION_PROGRESS, (data) => { this.emit(SimulatorEventType.SIMULATION_PROGRESS, data); }); - this.simulator.on(D3SimulatorEngineEventType.SIMULATION_END, (data) => { + this._simulator.on(D3SimulatorEngineEventType.SIMULATION_END, (data) => { this.emit(SimulatorEventType.SIMULATION_END, data); }); - this.simulator.on(D3SimulatorEngineEventType.NODE_DRAG, (data) => { - this.emit(SimulatorEventType.NODE_DRAG_END, data); - }); - this.simulator.on(D3SimulatorEngineEventType.TICK, (data) => { + this._simulator.on(D3SimulatorEngineEventType.NODE_DRAG, (data) => { this.emit(SimulatorEventType.NODE_DRAG, data); }); - this.simulator.on(D3SimulatorEngineEventType.END, (data) => { - this.emit(SimulatorEventType.NODE_DRAG_END, data); + this._simulator.on(D3SimulatorEngineEventType.SIMULATION_TICK, (data) => { + this.emit(SimulatorEventType.SIMULATION_STEP, data); }); - this.simulator.on(D3SimulatorEngineEventType.SETTINGS_UPDATE, (data) => { + this._simulator.on(D3SimulatorEngineEventType.SETTINGS_UPDATE, (data) => { this.emit(SimulatorEventType.SETTINGS_UPDATE, data); }); } - setData(nodes: ISimulationNode[], edges: ISimulationEdge[]) { - this.simulator.setData({ nodes, edges }); + setupData(data: ISimulationGraph) { + this._simulator.setupData(data); } - addData(nodes: ISimulationNode[], edges: ISimulationEdge[]) { - this.simulator.addData({ nodes, edges }); + mergeData(data: ISimulationGraph) { + this._simulator.mergeData(data); } - updateData(nodes: ISimulationNode[], edges: ISimulationEdge[]) { - this.simulator.updateData({ nodes, edges }); - } - - clearData() { - this.simulator.clearData(); + updateData(data: ISimulationGraph) { + this._simulator.updateData(data); } - simulate() { - this.simulator.simulate(); + deleteData(data: ISimulationIds) { + this._simulator.deleteData(data); } - activateSimulation() { - this.simulator.activateSimulation(); + patchData(data: Partial): void { + this._simulator.patchData(data); } - startSimulation(nodes: ISimulationNode[], edges: ISimulationEdge[]) { - this.simulator.startSimulation({ nodes, edges }); + clearData() { + this._simulator.clearData(); } - updateSimulation(nodes: ISimulationNode[], edges: ISimulationEdge[]) { - this.simulator.updateSimulation({ nodes, edges }); + simulate() { + console.log('not implemented'); + // this.simulator.runSimulation(); } - stopSimulation() { - this.simulator.stopSimulation(); + activateSimulation() { + this._simulator.activateSimulation(); } startDragNode() { - this.simulator.startDragNode(); + this._simulator.startDragNode(); } dragNode(nodeId: number, position: IPosition) { - this.simulator.dragNode({ id: nodeId, ...position }); + this._simulator.dragNode({ id: nodeId, ...position }); } endDragNode(nodeId: number) { - this.simulator.endDragNode({ id: nodeId }); + this._simulator.endDragNode({ id: nodeId }); } fixNodes(nodes: ISimulationNode[]) { - this.simulator.fixNodes(nodes); + this._simulator.stickNodes(nodes); } releaseNodes(nodes?: ISimulationNode[] | undefined): void { - this.simulator.releaseNodes(nodes); + this._simulator.unstickNodes(nodes); } setSettings(settings: ID3SimulatorEngineSettingsUpdate) { - this.simulator.setSettings(settings); + this._simulator.setSettings(settings); } terminate() { - this.simulator.removeAllListeners(); + this._simulator.removeAllListeners(); this.removeAllListeners(); - // Do nothing } } diff --git a/src/simulator/types/web-worker-simulator/index.ts b/src/simulator/types/web-worker-simulator/index.ts index 97f396e..92dfcad 100644 --- a/src/simulator/types/web-worker-simulator/index.ts +++ b/src/simulator/types/web-worker-simulator/index.ts @@ -1 +1 @@ -export { WebWorkerSimulator } from './simulator'; +export { WebWorkerSimulator } from './web-worker-simulator'; diff --git a/src/simulator/types/web-worker-simulator/message/worker-input.ts b/src/simulator/types/web-worker-simulator/message/worker-input.ts index a57b8ed..5d28a74 100644 --- a/src/simulator/types/web-worker-simulator/message/worker-input.ts +++ b/src/simulator/types/web-worker-simulator/message/worker-input.ts @@ -8,18 +8,17 @@ import { IWorkerPayload } from './worker-payload'; // (not quite as there is no immediate response to a request) export enum WorkerInputType { - // Set node and edge data without simulating - SetData = 'Set Data', - AddData = 'Add Data', + SetupData = 'Set Data', + MergeData = 'Add Data', UpdateData = 'Update Data', + DeleteData = 'Delete Data', + PatchData = 'Patch Data', ClearData = 'Clear Data', // Simulation message types Simulate = 'Simulate', ActivateSimulation = 'Activate Simulation', - StartSimulation = 'Start Simulation', UpdateSimulation = 'Update Simulation', - StopSimulation = 'Stop Simulation', // Node dragging message types StartDragNode = 'Start Drag Node', @@ -32,16 +31,16 @@ export enum WorkerInputType { SetSettings = 'Set Settings', } -type IWorkerInputSetDataPayload = IWorkerPayload< - WorkerInputType.SetData, +type IWorkerInputSetupDataPayload = IWorkerPayload< + WorkerInputType.SetupData, { nodes: ISimulationNode[]; edges: ISimulationEdge[]; } >; -type IWorkerInputAddDataPayload = IWorkerPayload< - WorkerInputType.AddData, +type IWorkerInputMergeDataPayload = IWorkerPayload< + WorkerInputType.MergeData, { nodes: ISimulationNode[]; edges: ISimulationEdge[]; @@ -56,20 +55,28 @@ type IWorkerInputUpdateDataPayload = IWorkerPayload< } >; +type IWorkerInputDeleteDataPayload = IWorkerPayload< + WorkerInputType.DeleteData, + { + nodeIds: number[] | undefined; + edgeIds: number[] | undefined; + } +>; + +type IWorkerInputPatchDataPayload = IWorkerPayload< + WorkerInputType.PatchData, + { + nodes?: ISimulationNode[]; + edges?: ISimulationEdge[]; + } +>; + type IWorkerInputClearDataPayload = IWorkerPayload; type IWorkerInputSimulatePayload = IWorkerPayload; type IWorkerInputActivateSimulationPayload = IWorkerPayload; -type IWorkerInputStartSimulationPayload = IWorkerPayload< - WorkerInputType.StartSimulation, - { - nodes: ISimulationNode[]; - edges: ISimulationEdge[]; - } ->; - type IWorkerInputUpdateSimulationPayload = IWorkerPayload< WorkerInputType.UpdateSimulation, { @@ -78,8 +85,6 @@ type IWorkerInputUpdateSimulationPayload = IWorkerPayload< } >; -type IWorkerInputStopSimulationPayload = IWorkerPayload; - type IWorkerInputStartDragNodePayload = IWorkerPayload; type IWorkerInputDragNodePayload = IWorkerPayload; @@ -108,15 +113,15 @@ type IWorkerInputReleaseNodesPayload = IWorkerPayload< type IWorkerInputSetSettingsPayload = IWorkerPayload; export type IWorkerInputPayload = - | IWorkerInputSetDataPayload - | IWorkerInputAddDataPayload + | IWorkerInputSetupDataPayload + | IWorkerInputMergeDataPayload | IWorkerInputUpdateDataPayload + | IWorkerInputDeleteDataPayload + | IWorkerInputPatchDataPayload | IWorkerInputClearDataPayload | IWorkerInputSimulatePayload | IWorkerInputActivateSimulationPayload - | IWorkerInputStartSimulationPayload | IWorkerInputUpdateSimulationPayload - | IWorkerInputStopSimulationPayload | IWorkerInputStartDragNodePayload | IWorkerInputDragNodePayload | IWorkerInputFixNodesPayload diff --git a/src/simulator/types/web-worker-simulator/message/worker-output.ts b/src/simulator/types/web-worker-simulator/message/worker-output.ts index a8fdf95..d271bcf 100644 --- a/src/simulator/types/web-worker-simulator/message/worker-output.ts +++ b/src/simulator/types/web-worker-simulator/message/worker-output.ts @@ -4,8 +4,10 @@ import { ID3SimulatorEngineSettings } from '../../../engine/d3-simulator-engine' export enum WorkerOutputType { SIMULATION_START = 'simulation-start', + SIMULATION_STEP = 'simulation-step', SIMULATION_PROGRESS = 'simulation-progress', SIMULATION_END = 'simulation-end', + SIMULATION_TICK = 'simulation-tick', NODE_DRAG = 'node-drag', NODE_DRAG_END = 'node-drag-end', SETTINGS_UPDATE = 'settings-update', @@ -13,6 +15,14 @@ export enum WorkerOutputType { type IWorkerOutputSimulationStartPayload = IWorkerPayload; +type IWorkerOutputSimulationStepPayload = IWorkerPayload< + WorkerOutputType.SIMULATION_STEP, + { + nodes: ISimulationNode[]; + edges: ISimulationEdge[]; + } +>; + type IWorkerOutputSimulationProgressPayload = IWorkerPayload< WorkerOutputType.SIMULATION_PROGRESS, { @@ -55,6 +65,7 @@ type IWorkerOutputSettingsUpdatePayload = IWorkerPayload< export type IWorkerOutputPayload = | IWorkerOutputSimulationStartPayload + | IWorkerOutputSimulationStepPayload | IWorkerOutputSimulationProgressPayload | IWorkerOutputSimulationEndPayload | IWorkerOutputNodeDragPayload diff --git a/src/simulator/types/web-worker-simulator/process.worker.ts b/src/simulator/types/web-worker-simulator/simulator.worker.ts similarity index 68% rename from src/simulator/types/web-worker-simulator/process.worker.ts rename to src/simulator/types/web-worker-simulator/simulator.worker.ts index 6e93b4d..d0d76a2 100644 --- a/src/simulator/types/web-worker-simulator/process.worker.ts +++ b/src/simulator/types/web-worker-simulator/simulator.worker.ts @@ -10,14 +10,6 @@ const emitToMain = (message: IWorkerOutputPayload) => { postMessage(message); }; -simulator.on(D3SimulatorEngineEventType.TICK, (data) => { - emitToMain({ type: WorkerOutputType.NODE_DRAG, data }); -}); - -simulator.on(D3SimulatorEngineEventType.END, (data) => { - emitToMain({ type: WorkerOutputType.NODE_DRAG_END, data }); -}); - simulator.on(D3SimulatorEngineEventType.SIMULATION_START, () => { emitToMain({ type: WorkerOutputType.SIMULATION_START }); }); @@ -31,11 +23,13 @@ simulator.on(D3SimulatorEngineEventType.SIMULATION_END, (data) => { }); simulator.on(D3SimulatorEngineEventType.NODE_DRAG, (data) => { - // Notify the client that the node position changed. - // This is otherwise handled by the simulation tick if physics is enabled. emitToMain({ type: WorkerOutputType.NODE_DRAG, data }); }); +simulator.on(D3SimulatorEngineEventType.SIMULATION_TICK, (data) => { + emitToMain({ type: WorkerOutputType.SIMULATION_STEP, data }); +}); + simulator.on(D3SimulatorEngineEventType.SETTINGS_UPDATE, (data) => { emitToMain({ type: WorkerOutputType.SETTINGS_UPDATE, data }); }); @@ -47,13 +41,13 @@ addEventListener('message', ({ data }: MessageEvent) => { break; } - case WorkerInputType.SetData: { - simulator.setData(data.data); + case WorkerInputType.SetupData: { + simulator.setupData(data.data); break; } - case WorkerInputType.AddData: { - simulator.addData(data.data); + case WorkerInputType.MergeData: { + simulator.mergeData(data.data); break; } @@ -62,28 +56,18 @@ addEventListener('message', ({ data }: MessageEvent) => { break; } - case WorkerInputType.ClearData: { - simulator.clearData(); + case WorkerInputType.DeleteData: { + simulator.deleteData(data.data); break; } - case WorkerInputType.Simulate: { - simulator.simulate(); + case WorkerInputType.PatchData: { + simulator.patchData(data.data); break; } - case WorkerInputType.StartSimulation: { - simulator.startSimulation(data.data); - break; - } - - case WorkerInputType.UpdateSimulation: { - simulator.updateSimulation(data.data); - break; - } - - case WorkerInputType.StopSimulation: { - simulator.stopSimulation(); + case WorkerInputType.ClearData: { + simulator.clearData(); break; } @@ -98,12 +82,12 @@ addEventListener('message', ({ data }: MessageEvent) => { } case WorkerInputType.FixNodes: { - simulator.fixNodes(data.data.nodes); + simulator.stickNodes(data.data.nodes); break; } case WorkerInputType.ReleaseNodes: { - simulator.releaseNodes(data.data.nodes); + simulator.unstickNodes(data.data.nodes); break; } diff --git a/src/simulator/types/web-worker-simulator/simulator.ts b/src/simulator/types/web-worker-simulator/web-worker-simulator.ts similarity index 63% rename from src/simulator/types/web-worker-simulator/simulator.ts rename to src/simulator/types/web-worker-simulator/web-worker-simulator.ts index 01acb46..02f35ea 100644 --- a/src/simulator/types/web-worker-simulator/simulator.ts +++ b/src/simulator/types/web-worker-simulator/web-worker-simulator.ts @@ -1,25 +1,33 @@ import { IPosition } from '../../../common'; -import { ISimulator, ISimulationNode, ISimulationEdge, SimulatorEventType, SimulatorEvents } from '../../shared'; +import { + ISimulator, + ISimulationNode, + ISimulationEdge, + SimulatorEventType, + SimulatorEvents, + ISimulationGraph, + ISimulationIds, +} from '../../shared'; import { ID3SimulatorEngineSettingsUpdate } from '../../engine/d3-simulator-engine'; import { IWorkerInputPayload, WorkerInputType } from './message/worker-input'; import { IWorkerOutputPayload, WorkerOutputType } from './message/worker-output'; import { Emitter } from '../../../utils/emitter.utils'; export class WebWorkerSimulator extends Emitter implements ISimulator { - protected readonly worker: Worker; + protected readonly _worker: Worker; constructor() { super(); - this.worker = new Worker( + this._worker = new Worker( new URL( - /* webpackChunkName: 'process.worker' */ - './process.worker', + /* webpackChunkName: 'simulator.worker' */ + './simulator.worker', import.meta.url, ), { type: 'module' }, ); - this.worker.onmessage = ({ data }: MessageEvent) => { + this._worker.onmessage = ({ data }: MessageEvent) => { switch (data.type) { case WorkerOutputType.SIMULATION_START: { this.emit(SimulatorEventType.SIMULATION_START, undefined); @@ -33,6 +41,10 @@ export class WebWorkerSimulator extends Emitter implements ISim this.emit(SimulatorEventType.SIMULATION_END, data.data); break; } + case WorkerOutputType.SIMULATION_STEP: { + this.emit(SimulatorEventType.SIMULATION_STEP, data.data); + break; + } case WorkerOutputType.NODE_DRAG: { this.emit(SimulatorEventType.NODE_DRAG, data.data); break; @@ -49,16 +61,35 @@ export class WebWorkerSimulator extends Emitter implements ISim }; } - setData(nodes: ISimulationNode[], edges: ISimulationEdge[]) { - this.emitToWorker({ type: WorkerInputType.SetData, data: { nodes, edges } }); + /** + * Creates a new graph with the specified data. Any existing data gets discarded. + * This action creates a new simulation object but keeps the existing simulation settings. + * + * @param {ISimulationGraph} data New graph (nodes and edges). + */ + setupData(data: ISimulationGraph) { + this.emitToWorker({ type: WorkerInputType.SetupData, data }); + } + + /** + * Inserts or updates data to an existing graph. (Also known as upsert) + * + * @param {ISimulationGraph} data Added graph data (nodes and edges). + */ + mergeData(data: ISimulationGraph) { + this.emitToWorker({ type: WorkerInputType.MergeData, data }); + } + + updateData(data: ISimulationGraph) { + this.emitToWorker({ type: WorkerInputType.UpdateData, data }); } - addData(nodes: ISimulationNode[], edges: ISimulationEdge[]) { - this.emitToWorker({ type: WorkerInputType.AddData, data: { nodes, edges } }); + deleteData(data: ISimulationIds) { + this.emitToWorker({ type: WorkerInputType.DeleteData, data }); } - updateData(nodes: ISimulationNode[], edges: ISimulationEdge[]) { - this.emitToWorker({ type: WorkerInputType.UpdateData, data: { nodes, edges } }); + patchData(data: Partial): void { + this.emitToWorker({ type: WorkerInputType.PatchData, data }); } clearData() { @@ -73,18 +104,10 @@ export class WebWorkerSimulator extends Emitter implements ISim this.emitToWorker({ type: WorkerInputType.ActivateSimulation }); } - startSimulation(nodes: ISimulationNode[], edges: ISimulationEdge[]) { - this.emitToWorker({ type: WorkerInputType.StartSimulation, data: { nodes, edges } }); - } - updateSimulation(nodes: ISimulationNode[], edges: ISimulationEdge[]) { this.emitToWorker({ type: WorkerInputType.UpdateSimulation, data: { nodes, edges } }); } - stopSimulation() { - this.emitToWorker({ type: WorkerInputType.StopSimulation }); - } - startDragNode() { this.emitToWorker({ type: WorkerInputType.StartDragNode }); } @@ -110,11 +133,11 @@ export class WebWorkerSimulator extends Emitter implements ISim } terminate() { - this.worker.terminate(); + this._worker.terminate(); this.removeAllListeners(); } protected emitToWorker(message: IWorkerInputPayload) { - this.worker.postMessage(message); + this._worker.postMessage(message); } } diff --git a/src/utils/array.utils.ts b/src/utils/array.utils.ts index 376012a..a9db93b 100644 --- a/src/utils/array.utils.ts +++ b/src/utils/array.utils.ts @@ -15,3 +15,8 @@ export const copyArray = (array: Array): Array => { } return newArray; }; + +export const dedupArrays = (...arrays: T[][]): T[] => { + const combinedArray = arrays.reduce((acc, curr) => acc.concat(curr), []); + return Array.from(new Set(combinedArray)); +}; diff --git a/src/utils/object.utils.ts b/src/utils/object.utils.ts index 08a6426..d6dfcf9 100644 --- a/src/utils/object.utils.ts +++ b/src/utils/object.utils.ts @@ -120,3 +120,11 @@ const copyPlainObject = (obj: Record): Record => { }); return newObject; }; + +export const patchProperties = (target: T, source: T): void => { + const keys = Object.keys(source as Object) as (keyof T)[]; + + for (let i = 0; i < keys.length; i++) { + target[keys[i]] = source[keys[i]]; + } +}; diff --git a/src/utils/observer.utils.ts b/src/utils/observer.utils.ts new file mode 100644 index 0000000..4b9ce60 --- /dev/null +++ b/src/utils/observer.utils.ts @@ -0,0 +1,50 @@ +import { INodeCoordinates, INodePosition } from '../models/node'; +import { ISetStateDataPayload } from '../models/state'; + +export type GraphObject = 'node' | 'edge'; + +export type IObserverDataPayload = INodePosition | INodeCoordinates | ISetStateDataPayload; + +// Using callbacks here to ensure that the Observer update is abstracted from the user +export type IObserver = (data?: IObserverDataPayload) => void; + +export interface ISubject { + listeners: IObserver[]; + + addListener(observer: IObserver): void; + + getListeners(): IObserver[]; + + removeListener(observer: IObserver): void; + + notifyListeners(data?: IObserverDataPayload): void; +} + +export class Subject implements ISubject { + listeners: IObserver[]; + + constructor() { + this.listeners = []; + } + + addListener(observer: IObserver): void { + this.listeners.push(observer); + } + + getListeners(): IObserver[] { + return [...this.listeners]; + } + + removeListener(observer: IObserver): void { + const index = this.listeners.indexOf(observer); + if (index !== -1) { + this.listeners.splice(index, 1); + } + } + + notifyListeners(data?: IObserverDataPayload): void { + for (let i = 0; i < this.listeners.length; i++) { + this.listeners[i](data); + } + } +} diff --git a/src/views/orb-map-view.ts b/src/views/orb-map-view.ts index 01211ab..fc5f811 100644 --- a/src/views/orb-map-view.ts +++ b/src/views/orb-map-view.ts @@ -11,6 +11,7 @@ import { IRenderer, RendererType, RenderEventType, IRendererSettingsInit, IRende import { RendererFactory } from '../renderer/factory'; import { getDefaultGraphStyle } from '../models/style'; import { isBoolean } from '../utils/type.utils'; +import { IObserver } from '../utils/observer.utils'; export interface ILeafletMapTile { instance: L.TileLayer; @@ -85,6 +86,7 @@ export class OrbMapView implements IOr this.render(); } }, + listeners: [this._update], }); this._graph.setDefaultStyle(getDefaultGraphStyle()); this._events = new OrbEmitter(); @@ -201,6 +203,11 @@ export class OrbMapView implements IOr onRendered?.(); } + zoomIn(onRendered?: () => void) { + this._leaflet.zoomIn(); + onRendered?.(); + } + recenter(onRendered?: () => void) { const view = this._graph.getBoundingBox(); const topRightCoordinate = this._leaflet.layerPointToLatLng([view.x, view.y]); @@ -209,6 +216,11 @@ export class OrbMapView implements IOr onRendered?.(); } + zoomOut(onRendered?: () => void) { + this._leaflet.zoomOut(); + onRendered?.(); + } + destroy() { this._renderer.destroy(); this._leaflet.off(); @@ -216,6 +228,10 @@ export class OrbMapView implements IOr this._leaflet.getContainer().outerHTML = ''; } + private _update: IObserver = (): void => { + this.render(); + }; + private _initMap() { const map = document.createElement('div'); map.style.position = 'absolute'; @@ -231,6 +247,7 @@ export class OrbMapView implements IOr private _initLeaflet() { const leaflet = L.map(this._map, { doubleClickZoom: false, + zoomControl: false, }).setView([0, 0], this._settings.map.zoomLevel); leaflet.on('zoomstart', () => { @@ -426,8 +443,7 @@ export class OrbMapView implements IOr } const layerPoint = this._leaflet.latLngToLayerPoint([coordinates.lat, coordinates.lng]); - nodes[i].position.x = layerPoint.x; - nodes[i].position.y = layerPoint.y; + nodes[i].setPosition(layerPoint, { isNotifySkipped: true }); } } diff --git a/src/views/orb-view.ts b/src/views/orb-view.ts index d4832b6..427cc29 100644 --- a/src/views/orb-view.ts +++ b/src/views/orb-view.ts @@ -8,9 +8,9 @@ import { D3ZoomEvent, zoom, ZoomBehavior } from 'd3-zoom'; import { select } from 'd3-selection'; import { IPosition, isEqualPosition } from '../common'; import { ISimulator, SimulatorFactory } from '../simulator'; -import { Graph, IGraph } from '../models/graph'; +import { Graph, IGraph, INodeFilter, IEdgeFilter } from '../models/graph'; import { INode, INodeBase, isNode } from '../models/node'; -import { IEdgeBase, isEdge } from '../models/edge'; +import { IEdge, IEdgeBase, isEdge } from '../models/edge'; import { IOrbView } from './shared'; import { DefaultEventStrategy, IEventStrategy, IEventStrategySettings } from '../models/strategy'; import { ID3SimulatorEngineSettings } from '../simulator/engine/d3-simulator-engine'; @@ -21,6 +21,7 @@ import { RendererFactory } from '../renderer/factory'; import { SimulatorEventType } from '../simulator/shared'; import { getDefaultGraphStyle } from '../models/style'; import { isBoolean } from '../utils/type.utils'; +import { IObserver, IObserverDataPayload } from '../utils/observer.utils'; export interface IGraphInteractionSettings { isDragEnabled: boolean; @@ -36,7 +37,6 @@ export interface IOrbViewSettings { zoomFitTransitionMs: number; isOutOfBoundsDragEnabled: boolean; areCoordinatesRounded: boolean; - isSimulationAnimated: boolean; } export type IOrbViewSettingsInit = Omit< @@ -54,7 +54,7 @@ export class OrbView implements IOrbVi private readonly _renderer: IRenderer; private readonly _simulator: ISimulator; - private _isSimulating = false; + // private _isSimulating = false; private _onSimulationEnd: (() => void) | undefined; private _simulationStartedAt = Date.now(); private _d3Zoom: ZoomBehavior; @@ -62,23 +62,11 @@ export class OrbView implements IOrbVi constructor(container: HTMLElement, settings?: Partial>) { this._container = container; - this._graph = new Graph(undefined, { - onLoadedImages: () => { - // Not to call render() before user's .render() - if (this._renderer.isInitiallyRendered) { - this.render(); - } - }, - }); - this._graph.setDefaultStyle(getDefaultGraphStyle()); - this._events = new OrbEmitter(); - this._settings = { getPosition: settings?.getPosition, zoomFitTransitionMs: 200, isOutOfBoundsDragEnabled: false, areCoordinatesRounded: true, - isSimulationAnimated: true, ...settings, simulation: { isPhysicsEnabled: false, @@ -99,6 +87,18 @@ export class OrbView implements IOrbVi }, }; + this._graph = new Graph(undefined, { + onLoadedImages: () => { + // Not to call render() before user's .render() + if (this._renderer.isInitiallyRendered) { + this.render(); + } + }, + listeners: [this._update], + }); + this._graph.setDefaultStyle(getDefaultGraphStyle()); + this._events = new OrbEmitter(); + this._strategy = new DefaultEventStrategy({ isDefaultSelectEnabled: this._settings.strategy.isDefaultSelectEnabled ?? false, isDefaultHoverEnabled: this._settings.strategy.isDefaultHoverEnabled ?? false, @@ -150,34 +150,68 @@ export class OrbView implements IOrbVi this._simulator = SimulatorFactory.getSimulator(); this._simulator.on(SimulatorEventType.SIMULATION_START, () => { - this._isSimulating = true; + // this._isSimulating = true; this._simulationStartedAt = Date.now(); this._events.emit(OrbEventType.SIMULATION_START, undefined); }); this._simulator.on(SimulatorEventType.SIMULATION_PROGRESS, (data) => { this._graph.setNodePositions(data.nodes); this._events.emit(OrbEventType.SIMULATION_STEP, { progress: data.progress }); - if (this._settings.isSimulationAnimated) { - this._renderer.render(this._graph); - } + this.render(); }); this._simulator.on(SimulatorEventType.SIMULATION_END, (data) => { this._graph.setNodePositions(data.nodes); - this._renderer.render(this._graph); - this._isSimulating = false; + this.render(); + // this._isSimulating = false; this._onSimulationEnd?.(); this._onSimulationEnd = undefined; this._events.emit(OrbEventType.SIMULATION_END, { durationMs: Date.now() - this._simulationStartedAt }); }); + this._simulator.on(SimulatorEventType.SIMULATION_STEP, (data) => { + this._graph.setNodePositions(data.nodes); + this.render(); + }); this._simulator.on(SimulatorEventType.NODE_DRAG, (data) => { this._graph.setNodePositions(data.nodes); - this._renderer.render(this._graph); + this.render(); }); this._simulator.on(SimulatorEventType.SETTINGS_UPDATE, (data) => { this._settings.simulation = data.settings; }); this._simulator.setSettings(this._settings.simulation); + + // TODO(dlozic): Optimize crud operations here. + this._graph.setSettings({ + onSetupData: () => { + // if (this._isSimulating) { + // console.warn('Already running a simulation. Discarding the setup data call.'); + // return; + // } + // this._isSimulating = true; + this._assignPositions(this._graph.getNodes()); + const nodePositions = this._graph.getNodePositions(); + const edgePositions = this._graph.getEdgePositions(); + // this._onSimulationEnd = onRendered; + this._simulator.setupData({ nodes: nodePositions, edges: edgePositions }); + }, + onMergeData: (data) => { + const nodeIds = new Set(data.nodes?.map((node) => node.id)); + const nodeFilter: INodeFilter = (node: INode) => nodeIds.has(node.getId()); + const edgeIds = new Set(data.edges?.map((edge) => edge.id)); + const edgeFilter: IEdgeFilter = (edge: IEdge) => edgeIds.has(edge.getId()); + + this._assignPositions(this._graph.getNodes(nodeFilter)); + + const nodePositions = this._graph.getNodePositions(nodeFilter); + const edgePositions = this._graph.getEdgePositions(edgeFilter); + + this._simulator.mergeData({ nodes: nodePositions, edges: edgePositions }); + }, + onRemoveData: (data) => { + this._simulator.deleteData(data); + }, + }); } get data(): IGraph { @@ -238,26 +272,20 @@ export class OrbView implements IOrbVi } } - render(onRendered?: () => void) { - if (this._isSimulating) { - this._renderer.render(this._graph); - onRendered?.(); - return; - } - + private _assignPositions = (nodes: INode[]) => { if (this._settings.getPosition) { - const nodes = this._graph.getNodes(); for (let i = 0; i < nodes.length; i++) { const position = this._settings.getPosition(nodes[i]); if (position) { - nodes[i].position = { id: nodes[i].id, ...position }; + nodes[i].setPosition({ id: nodes[i].getId(), ...position }, { isNotifySkipped: true }); } } } + }; - this._isSimulating = true; - this._onSimulationEnd = onRendered; - this._startSimulation(); + render(onRendered?: () => void) { + this._renderer.render(this._graph); + onRendered?.(); } recenter(onRendered?: () => void) { @@ -269,8 +297,7 @@ export class OrbView implements IOrbVi .ease(easeLinear) .call(this._d3Zoom.transform, fitZoomTransform) .call(() => { - this._renderer.render(this._graph); - onRendered?.(); + this.render(onRendered); }); } @@ -319,7 +346,7 @@ export class OrbView implements IOrbVi this._dragStartPosition = undefined; } - this._simulator.dragNode(event.subject.id, simulationPoint); + this._simulator.dragNode(event.subject.getId(), simulationPoint); this._events.emit(OrbEventType.NODE_DRAG, { node: event.subject, event: event.sourceEvent, @@ -338,7 +365,7 @@ export class OrbView implements IOrbVi const simulationPoint = this._renderer.getSimulationPosition(mousePoint); if (!isEqualPosition(this._dragStartPosition, mousePoint)) { - this._simulator.endDragNode(event.subject.id); + this._simulator.endDragNode(event.subject.getId()); } this._events.emit(OrbEventType.NODE_DRAG_END, { @@ -356,7 +383,7 @@ export class OrbView implements IOrbVi } this._renderer.transform = event.transform; setTimeout(() => { - this._renderer.render(this._graph); + this.render(); this._events.emit(OrbEventType.TRANSFORM, { transform: event.transform }); }, 1); }; @@ -419,7 +446,7 @@ export class OrbView implements IOrbVi }); if (response.isStateChanged) { - this._renderer.render(this._graph); + this.render(); } }; @@ -457,7 +484,7 @@ export class OrbView implements IOrbVi }); if (response.isStateChanged || response.changedSubject) { - this._renderer.render(this._graph); + this.render(); } }; @@ -495,7 +522,7 @@ export class OrbView implements IOrbVi }); if (response.isStateChanged || response.changedSubject) { - this._renderer.render(this._graph); + this.render(); } }; @@ -533,17 +560,29 @@ export class OrbView implements IOrbVi }); if (response.isStateChanged || response.changedSubject) { - this._renderer.render(this._graph); + this.render(); } }; - private _startSimulation() { - const nodePositions = this._graph.getNodePositions(); - const edgePositions = this._graph.getEdgePositions(); - - this._simulator.updateData(nodePositions, edgePositions); - this._simulator.simulate(); - } + private _update: IObserver = (data?: IObserverDataPayload): void => { + if (data && 'x' in data && 'y' in data && 'id' in data) { + this._simulator.patchData({ + nodes: [ + { + x: data.x, + y: data.y, + sx: data.x, + sy: data.y, + fx: data.x, + fy: data.y, + id: data.id, + }, + ], + edges: [], + }); + } + this.render(); + }; // TODO: Do we keep these fixNodes() { diff --git a/test/models/graph.spec.ts b/test/models/graph.spec.ts index a8f9698..da440f5 100644 --- a/test/models/graph.spec.ts +++ b/test/models/graph.spec.ts @@ -46,9 +46,9 @@ const expectEqualNode = ( } const actualNode: IExpectedNode = { - id: node.id, - data: node.data, - style: node.style, + id: node.getId(), + data: node.getData(), + style: node.getStyle(), inEdges: node .getInEdges() .map((edge) => edge.id) @@ -57,8 +57,8 @@ const expectEqualNode = ( .getOutEdges() .map((edge) => edge.id) .sort(), - state: node.state, - position: node.position, + state: node.getState(), + position: node.getPosition(), }; expect(actualNode).toEqual(expectedNode); }; @@ -77,13 +77,13 @@ const expectEqualEdge = ( id: edge.id, start: edge.start, end: edge.end, - startNodeId: edge.startNode?.id, - endNodeId: edge.endNode?.id, - data: edge.data, - style: edge.style, + startNodeId: edge.startNode?.getId(), + endNodeId: edge.endNode?.getId(), + data: edge.getData(), + style: edge.getStyle(), type: edge.type, offset: edge.offset, - state: edge.state, + state: edge.getState(), }; expect(actualEdge).toEqual(expectedEdge); }; @@ -271,6 +271,113 @@ describe('Graph', () => { }, ]; + const updatedNodes: ITestNode[] = [ + { id: 0, name: 'Mia' }, + { id: 1, name: 'Lana' }, + { id: 2, name: 'Charlie' }, + ]; + + const updatedEdges: ITestEdge[] = [ + { id: 0, start: 1, end: 2, count: 1 }, + { id: 1, start: 2, end: 0, count: 0 }, + { id: 2, start: 0, end: 1, count: 7 }, + { id: 3, start: 1, end: 0, count: 7 }, + { id: 4, start: 2, end: 2, count: 5 }, + ]; + + const updatedExpectedNodes: IExpectedNode[] = [ + { + id: 0, + data: updatedNodes[0], + style: {}, + inEdges: [1, 3], + outEdges: [2], + state: GraphObjectState.NONE, + position: { id: 0 }, + }, + { + id: 1, + data: updatedNodes[1], + style: {}, + inEdges: [2], + outEdges: [0, 3], + state: GraphObjectState.NONE, + position: { id: 1 }, + }, + { + id: 2, + data: updatedNodes[2], + style: {}, + inEdges: [0, 4], + outEdges: [1, 4], + state: GraphObjectState.NONE, + position: { id: 2 }, + }, + ]; + + const updatedExpectedEdges: IExpectedEdge[] = [ + { + id: 0, + start: 1, + end: 2, + startNodeId: 1, + endNodeId: 2, + data: updatedEdges[0], + type: EdgeType.STRAIGHT, + offset: 0, + style: {}, + state: GraphObjectState.NONE, + }, + { + id: 1, + start: 2, + end: 0, + startNodeId: 2, + endNodeId: 0, + data: updatedEdges[1], + type: EdgeType.STRAIGHT, + offset: 0, + style: {}, + state: GraphObjectState.NONE, + }, + { + id: 2, + start: 0, + end: 1, + startNodeId: 0, + endNodeId: 1, + data: updatedEdges[2], + type: EdgeType.CURVED, + offset: 1, + style: {}, + state: GraphObjectState.NONE, + }, + { + id: 3, + start: 1, + end: 0, + startNodeId: 1, + endNodeId: 0, + data: updatedEdges[3], + type: EdgeType.CURVED, + offset: 1, + style: {}, + state: GraphObjectState.NONE, + }, + { + id: 4, + start: 2, + end: 2, + startNodeId: 2, + endNodeId: 2, + data: updatedEdges[4], + type: EdgeType.LOOPBACK, + offset: 1, + style: {}, + state: GraphObjectState.NONE, + }, + ]; + test('should merge new nodes', () => { const graph = new Graph({ nodes, edges }); graph.merge({ nodes: newNodes }); @@ -348,8 +455,26 @@ describe('Graph', () => { }); }); - // TODO @toni: Add tests for updating `data` with the same id, and edge `start` and `end` change - // test('should update existing nodes and edges', () => {}); + test('should update existing nodes and edges', () => { + const graph = new Graph({ nodes, edges }); + graph.merge({ nodes: updatedNodes, edges: updatedEdges }); + + const currentNodes: ITestNode[] = [...updatedNodes]; + const currentExpectedNodes: IExpectedNode[] = [...updatedExpectedNodes]; + + const currentEdges: ITestEdge[] = [...updatedEdges]; + const currentExpectedEdges: IExpectedEdge[] = [...updatedExpectedEdges]; + + expect(graph.getNodeCount()).toEqual(currentNodes.length); + expect(graph.getEdgeCount()).toEqual(currentEdges.length); + + currentNodes.forEach((node, i) => { + expectEqualNode(graph, node, currentExpectedNodes[i]); + }); + currentEdges.forEach((edge, i) => { + expectEqualEdge(graph, edge, currentExpectedEdges[i]); + }); + }); }); describe('remove', () => { @@ -443,7 +568,7 @@ describe('Graph', () => { const style: IGraphStyle = { getNodeStyle(node: INode): INodeStyle | undefined { // Simulate a special case (will be DEFAULT) - if (node.id === 0) { + if (node.getId() === 0) { return undefined; } return nodeStyle; @@ -457,6 +582,19 @@ describe('Graph', () => { }, }; + const styleByInOutEdges: IGraphStyle = { + getNodeStyle(node: INode): INodeStyle | undefined { + // Simulate a special case (will be DEFAULT) + if (node.getInEdges().length > 0 || node.getOutEdges().length > 0) { + return undefined; + } + return nodeStyle; + }, + getEdgeStyle(): IEdgeStyle | undefined { + return edgeStyle; + }, + }; + const newNodes: ITestNode[] = [ { id: 3, name: 'Mia' }, { id: 4, name: 'Lana' }, @@ -471,14 +609,14 @@ describe('Graph', () => { const graph = new Graph({ nodes, edges }); graph.setDefaultStyle(style); - expect(graph.getNodeById(0)?.style).toEqual({}); - expect(graph.getEdgeById(0)?.style).toEqual({}); + expect(graph.getNodeById(0)?.getStyle()).toEqual({}); + expect(graph.getEdgeById(0)?.getStyle()).toEqual({}); nodes.slice(1).forEach((node) => { - expect(graph.getNodeById(node.id)?.style).toEqual(nodeStyle); + expect(graph.getNodeById(node.id)?.getStyle()).toEqual(nodeStyle); }); edges.slice(1).forEach((edge) => { - expect(graph.getEdgeById(edge.id)?.style).toEqual(edgeStyle); + expect(graph.getEdgeById(edge.id)?.getStyle()).toEqual(edgeStyle); }); }); @@ -487,14 +625,14 @@ describe('Graph', () => { graph.setDefaultStyle(style); graph.setup({ nodes, edges }); - expect(graph.getNodeById(0)?.style).toEqual({}); - expect(graph.getEdgeById(0)?.style).toEqual({}); + expect(graph.getNodeById(0)?.getStyle()).toEqual({}); + expect(graph.getEdgeById(0)?.getStyle()).toEqual({}); nodes.slice(1).forEach((node) => { - expect(graph.getNodeById(node.id)?.style).toEqual(nodeStyle); + expect(graph.getNodeById(node.id)?.getStyle()).toEqual(nodeStyle); }); edges.slice(1).forEach((edge) => { - expect(graph.getEdgeById(edge.id)?.style).toEqual(edgeStyle); + expect(graph.getEdgeById(edge.id)?.getStyle()).toEqual(edgeStyle); }); }); @@ -506,14 +644,14 @@ describe('Graph', () => { const currentNodes: ITestNode[] = [...nodes, ...newNodes]; const currentEdges: ITestEdge[] = [...edges, ...newEdges]; - expect(graph.getNodeById(0)?.style).toEqual({}); - expect(graph.getEdgeById(0)?.style).toEqual({}); + expect(graph.getNodeById(0)?.getStyle()).toEqual({}); + expect(graph.getEdgeById(0)?.getStyle()).toEqual({}); currentNodes.slice(1).forEach((node) => { - expect(graph.getNodeById(node.id)?.style).toEqual(nodeStyle); + expect(graph.getNodeById(node.id)?.getStyle()).toEqual(nodeStyle); }); currentEdges.slice(1).forEach((edge) => { - expect(graph.getEdgeById(edge.id)?.style).toEqual(edgeStyle); + expect(graph.getEdgeById(edge.id)?.getStyle()).toEqual(edgeStyle); }); }); @@ -525,14 +663,14 @@ describe('Graph', () => { const currentNodes: ITestNode[] = [...nodes, ...newNodes]; const currentEdges: ITestEdge[] = [...edges, ...newEdges]; - expect(graph.getNodeById(0)?.style).toEqual({}); - expect(graph.getEdgeById(0)?.style).toEqual({}); + expect(graph.getNodeById(0)?.getStyle()).toEqual({}); + expect(graph.getEdgeById(0)?.getStyle()).toEqual({}); currentNodes.slice(1).forEach((node) => { - expect(graph.getNodeById(node.id)?.style).toEqual(nodeStyle); + expect(graph.getNodeById(node.id)?.getStyle()).toEqual(nodeStyle); }); currentEdges.slice(1).forEach((edge) => { - expect(graph.getEdgeById(edge.id)?.style).toEqual(edgeStyle); + expect(graph.getEdgeById(edge.id)?.getStyle()).toEqual(edgeStyle); }); }); @@ -546,14 +684,14 @@ describe('Graph', () => { const currentNodes: ITestNode[] = [...nodes, ...newNodes]; const currentEdges: ITestEdge[] = [...edges, ...newEdges]; - expect(graph.getNodeById(0)?.style).toEqual({ ...DEFAULT_NODE_STYLE, label: nodes[0].name }); - expect(graph.getEdgeById(0)?.style).toEqual(DEFAULT_EDGE_STYLE); + expect(graph.getNodeById(0)?.getStyle()).toEqual({ ...DEFAULT_NODE_STYLE, label: nodes[0].name }); + expect(graph.getEdgeById(0)?.getStyle()).toEqual(DEFAULT_EDGE_STYLE); currentNodes.slice(1).forEach((node) => { - expect(graph.getNodeById(node.id)?.style).toEqual(nodeStyle); + expect(graph.getNodeById(node.id)?.getStyle()).toEqual(nodeStyle); }); currentEdges.slice(1).forEach((edge) => { - expect(graph.getEdgeById(edge.id)?.style).toEqual(edgeStyle); + expect(graph.getEdgeById(edge.id)?.getStyle()).toEqual(edgeStyle); }); }); @@ -564,24 +702,42 @@ describe('Graph', () => { graph.setDefaultStyle(getDefaultGraphStyle()); graph.merge({ nodes: newNodes, edges: newEdges }); - expect(graph.getNodeById(0)?.style).toEqual({ ...DEFAULT_NODE_STYLE, label: nodes[0].name }); - expect(graph.getEdgeById(0)?.style).toEqual(DEFAULT_EDGE_STYLE); + expect(graph.getNodeById(0)?.getStyle()).toEqual({ ...DEFAULT_NODE_STYLE, label: nodes[0].name }); + expect(graph.getEdgeById(0)?.getStyle()).toEqual(DEFAULT_EDGE_STYLE); nodes.slice(1).forEach((node) => { - expect(graph.getNodeById(node.id)?.style).toEqual(nodeStyle); + expect(graph.getNodeById(node.id)?.getStyle()).toEqual(nodeStyle); }); newNodes.forEach((node) => { - expect(graph.getNodeById(node.id)?.style).toEqual({ ...DEFAULT_NODE_STYLE, label: node.name }); + expect(graph.getNodeById(node.id)?.getStyle()).toEqual({ ...DEFAULT_NODE_STYLE, label: node.name }); }); edges.slice(1).forEach((edge) => { - expect(graph.getEdgeById(edge.id)?.style).toEqual(edgeStyle); + expect(graph.getEdgeById(edge.id)?.getStyle()).toEqual(edgeStyle); }); newEdges.forEach((edge) => { - expect(graph.getEdgeById(edge.id)?.style).toEqual(DEFAULT_EDGE_STYLE); + expect(graph.getEdgeById(edge.id)?.getStyle()).toEqual(DEFAULT_EDGE_STYLE); }); }); - // TODO @toni: Add tests where style depends on in/outEdges and then hide an edge -> style should be updated + test('should apply style on edges removed', () => { + const graph = new Graph(); + graph.setDefaultStyle(styleByInOutEdges); + graph.setup({ nodes, edges }); + + graph.getNodes().forEach((node) => { + expect(node.getStyle()).toEqual({}); + }); + + graph.getEdges().forEach((edge) => { + expect(edge.getStyle()).toEqual(edgeStyle); + }); + + graph.remove({ edgeIds: graph.getEdges().map((edge) => edge.id) }); + + graph.getNodes().forEach((node) => { + expect(node.getStyle()).toEqual(nodeStyle); + }); + }); }); }); diff --git a/webpack.config.js b/webpack.config.js index 456fd06..c09811a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -18,7 +18,7 @@ const commonConfiguration = { }, output: { chunkFilename(pathData) { - return pathData.chunk.name === 'process.worker' ? `${name}.worker.js` : `${name}.worker.vendor.js`; + return pathData.chunk.name === 'simulator.worker' ? `${name}.worker.js` : `${name}.worker.vendor.js`; }, filename: `${name}.js`, path: path.resolve(__dirname, 'dist/browser'), @@ -62,7 +62,7 @@ const productionConfiguration = { output: { ...commonConfiguration.output, chunkFilename(pathData) { - return pathData.chunk.name === 'process.worker' ? `${name}.worker.min.js` : `${name}.worker.vendor.min.js`; + return pathData.chunk.name === 'simulator.worker' ? `${name}.worker.min.js` : `${name}.worker.vendor.min.js`; }, filename: `${name}.min.js`, }, From 7cd077ba0cc6d145d0708d3b3a542deb0034c472 Mon Sep 17 00:00:00 2001 From: Oleksandr Ichenskyi <55350107+AlexIchenskiy@users.noreply.github.com> Date: Thu, 28 Mar 2024 07:15:35 +0100 Subject: [PATCH 13/30] New: Add zoom in and out functions (#100) --- src/views/orb-view.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/views/orb-view.ts b/src/views/orb-view.ts index 427cc29..3b5711a 100644 --- a/src/views/orb-view.ts +++ b/src/views/orb-view.ts @@ -564,6 +564,26 @@ export class OrbView implements IOrbVi } }; + zoomIn = (onRendered?: () => void) => { + select(this._renderer.canvas) + .transition() + .duration(this._settings.zoomFitTransitionMs) + .ease(easeLinear) + .call(this._d3Zoom.scaleBy, 1.2) + .call(() => { + this.render(onRendered); + }); + }; + + zoomOut = (onRendered?: () => void) => { + select(this._renderer.canvas) + .transition() + .duration(this._settings.zoomFitTransitionMs) + .ease(easeLinear) + .call(this._d3Zoom.scaleBy, 0.8) + .call(() => this.render(onRendered)); + }; + private _update: IObserver = (data?: IObserverDataPayload): void => { if (data && 'x' in data && 'y' in data && 'id' in data) { this._simulator.patchData({ From 88c300662879f0a4c60455afbf7b3a25fb2c6c6f Mon Sep 17 00:00:00 2001 From: AlexIchenskiy Date: Wed, 15 May 2024 14:48:39 +0200 Subject: [PATCH 14/30] Fix: Skip unnecessary listener notify on set style --- src/models/edge.ts | 32 ++++++++++++++++++++------------ src/models/graph.ts | 6 +++--- src/models/node.ts | 32 ++++++++++++++++++++------------ 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/models/edge.ts b/src/models/edge.ts index 4b36145..26eb5a5 100644 --- a/src/models/edge.ts +++ b/src/models/edge.ts @@ -30,6 +30,10 @@ export interface IEdgePosition { target: any; } +export interface IEdgeSetStyleOptions { + isNotifySkipped: boolean; +} + export enum EdgeLineStyleType { SOLID = 'solid', DASHED = 'dashed', @@ -115,10 +119,10 @@ export interface IEdge extends ISubjec setData(callback: (edge: IEdge) => E): void; patchData(data: Partial): void; patchData(callback: (edge: IEdge) => Partial): void; - setStyle(style: IEdgeStyle): void; - setStyle(callback: (edge: IEdge) => IEdgeStyle): void; - patchStyle(style: IEdgeStyle): void; - patchStyle(callback: (edge: IEdge) => IEdgeStyle): void; + setStyle(style: IEdgeStyle, options?: IEdgeSetStyleOptions): void; + setStyle(callback: (edge: IEdge) => IEdgeStyle, options?: IEdgeSetStyleOptions): void; + patchStyle(style: IEdgeStyle, options?: IEdgeSetStyleOptions): void; + patchStyle(callback: (edge: IEdge) => IEdgeStyle, options?: IEdgeSetStyleOptions): void; setState(state: number): void; setState(state: IGraphObjectStateParameters): void; setState(callback: (edge: IEdge) => number): void; @@ -374,20 +378,22 @@ abstract class Edge extends Subject im this.notifyListeners(); } - setStyle(style: IEdgeStyle): void; - setStyle(callback: (edge: IEdge) => IEdgeStyle): void; - setStyle(arg: IEdgeStyle | ((edge: IEdge) => IEdgeStyle)): void { + setStyle(style: IEdgeStyle, options?: IEdgeSetStyleOptions): void; + setStyle(callback: (edge: IEdge) => IEdgeStyle, options?: IEdgeSetStyleOptions): void; + setStyle(arg: IEdgeStyle | ((edge: IEdge) => IEdgeStyle), options?: IEdgeSetStyleOptions): void { if (isFunction(arg)) { this._style = (arg as (edge: IEdge) => IEdgeStyle)(this); } else { this._style = arg as IEdgeStyle; } - this.notifyListeners(); + if (!options?.isNotifySkipped) { + this.notifyListeners(); + } } - patchStyle(style: IEdgeStyle): void; - patchStyle(callback: (edge: IEdge) => IEdgeStyle): void; - patchStyle(arg: IEdgeStyle | ((edge: IEdge) => IEdgeStyle)) { + patchStyle(style: IEdgeStyle, options?: IEdgeSetStyleOptions): void; + patchStyle(callback: (edge: IEdge) => IEdgeStyle, options?: IEdgeSetStyleOptions): void; + patchStyle(arg: IEdgeStyle | ((edge: IEdge) => IEdgeStyle), options?: IEdgeSetStyleOptions) { let style: IEdgeStyle; if (isFunction(arg)) { @@ -398,7 +404,9 @@ abstract class Edge extends Subject im patchProperties(this._style, style); - this.notifyListeners(); + if (!options?.isNotifySkipped) { + this.notifyListeners(); + } } setState(state: number): void; diff --git a/src/models/graph.ts b/src/models/graph.ts index 071612f..f90555b 100644 --- a/src/models/graph.ts +++ b/src/models/graph.ts @@ -551,7 +551,7 @@ export class Graph extends Subject imp }, ); edge.setState(existingEdge.getState()); - edge.setStyle(existingEdge.getStyle()); + edge.setStyle(existingEdge.getStyle(), { isNotifySkipped: true }); newEdges.push(edge); } @@ -628,7 +628,7 @@ export class Graph extends Subject imp const style = this._defaultStyle.getNodeStyle(newNodes[i]); if (style) { - newNodes[i].setStyle(style); + newNodes[i].setStyle(style, { isNotifySkipped: true }); // TODO Add these checks to node property setup if (style.imageUrl) { styleImageUrls.add(style.imageUrl); @@ -649,7 +649,7 @@ export class Graph extends Subject imp const style = this._defaultStyle.getEdgeStyle(newEdges[i]); if (style) { - newEdges[i].setStyle(style); + newEdges[i].setStyle(style, { isNotifySkipped: true }); } } } diff --git a/src/models/node.ts b/src/models/node.ts index 78afeaa..ae31177 100644 --- a/src/models/node.ts +++ b/src/models/node.ts @@ -33,6 +33,10 @@ export interface INodeSetPositionOptions { isNotifySkipped: boolean; } +export interface INodeSetStyleOptions { + isNotifySkipped: boolean; +} + export enum NodeShapeType { CIRCLE = 'circle', DOT = 'dot', @@ -117,10 +121,10 @@ export interface INode extends ISubjec callback: (node: INode) => INodeCoordinates | INodePosition, options?: INodeSetPositionOptions, ): void; - setStyle(style: INodeStyle): void; - setStyle(callback: (node: INode) => INodeStyle): void; - patchStyle(style: INodeStyle): void; - patchStyle(callback: (node: INode) => INodeStyle): void; + setStyle(style: INodeStyle, options?: INodeSetPositionOptions): void; + setStyle(callback: (node: INode) => INodeStyle, options?: INodeSetPositionOptions): void; + patchStyle(style: INodeStyle, options?: INodeSetPositionOptions): void; + patchStyle(callback: (node: INode) => INodeStyle, options?: INodeSetPositionOptions): void; setState(state: number): void; setState(state: IGraphObjectStateParameters): void; setState(callback: (node: INode) => number): void; @@ -478,20 +482,22 @@ export class Node extends Subject impl } } - setStyle(style: INodeStyle): void; - setStyle(callback: (node: INode) => INodeStyle): void; - setStyle(arg: INodeStyle | ((node: INode) => INodeStyle)): void { + setStyle(style: INodeStyle, options?: INodeSetPositionOptions): void; + setStyle(callback: (node: INode) => INodeStyle, options?: INodeSetPositionOptions): void; + setStyle(arg: INodeStyle | ((node: INode) => INodeStyle), options?: INodeSetPositionOptions): void { if (isFunction(arg)) { this._style = (arg as (node: INode) => INodeStyle)(this); } else { this._style = arg as INodeStyle; } - this.notifyListeners(); + if (!options?.isNotifySkipped) { + this.notifyListeners(); + } } - patchStyle(style: INodeStyle): void; - patchStyle(callback: (node: INode) => INodeStyle): void; - patchStyle(arg: INodeStyle | ((node: INode) => INodeStyle)) { + patchStyle(style: INodeStyle, options?: INodeSetPositionOptions): void; + patchStyle(callback: (node: INode) => INodeStyle, options?: INodeSetPositionOptions): void; + patchStyle(arg: INodeStyle | ((node: INode) => INodeStyle), options?: INodeSetPositionOptions) { let style: INodeStyle; if (isFunction(arg)) { @@ -502,7 +508,9 @@ export class Node extends Subject impl patchProperties(this._style, style); - this.notifyListeners(); + if (!options?.isNotifySkipped) { + this.notifyListeners(); + } } setState(state: number): void; From f273ad8ee0681dd9d048c5c7c3c36f7b92225784 Mon Sep 17 00:00:00 2001 From: AlexIchenskiy Date: Wed, 3 Jul 2024 12:01:16 +0200 Subject: [PATCH 15/30] Fix: remove unnecessary rerender on state change --- src/models/edge.ts | 25 ++++++++++++++++--------- src/models/graph.ts | 2 +- src/models/node.ts | 29 +++++++++++++++++------------ src/models/strategy.ts | 16 ++++++++-------- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/src/models/edge.ts b/src/models/edge.ts index 26eb5a5..d36c8af 100644 --- a/src/models/edge.ts +++ b/src/models/edge.ts @@ -34,6 +34,10 @@ export interface IEdgeSetStyleOptions { isNotifySkipped: boolean; } +export interface IEdgeSetStateOptions { + isNotifySkipped: boolean; +} + export enum EdgeLineStyleType { SOLID = 'solid', DASHED = 'dashed', @@ -123,10 +127,10 @@ export interface IEdge extends ISubjec setStyle(callback: (edge: IEdge) => IEdgeStyle, options?: IEdgeSetStyleOptions): void; patchStyle(style: IEdgeStyle, options?: IEdgeSetStyleOptions): void; patchStyle(callback: (edge: IEdge) => IEdgeStyle, options?: IEdgeSetStyleOptions): void; - setState(state: number): void; - setState(state: IGraphObjectStateParameters): void; - setState(callback: (edge: IEdge) => number): void; - setState(callback: (edge: IEdge) => IGraphObjectStateParameters): void; + setState(state: number, options?: IEdgeSetStateOptions): void; + setState(state: IGraphObjectStateParameters, options?: IEdgeSetStateOptions): void; + setState(callback: (edge: IEdge) => number, options?: IEdgeSetStateOptions): void; + setState(callback: (edge: IEdge) => IGraphObjectStateParameters, options?: IEdgeSetStateOptions): void; } export interface IEdgeSettings { @@ -409,16 +413,17 @@ abstract class Edge extends Subject im } } - setState(state: number): void; - setState(state: IGraphObjectStateParameters): void; - setState(callback: (edge: IEdge) => number): void; - setState(callback: (edge: IEdge) => IGraphObjectStateParameters): void; + setState(state: number, options?: IEdgeSetStateOptions): void; + setState(state: IGraphObjectStateParameters, options?: IEdgeSetStateOptions): void; + setState(callback: (edge: IEdge) => number, options?: IEdgeSetStateOptions): void; + setState(callback: (edge: IEdge) => IGraphObjectStateParameters, options?: IEdgeSetStateOptions): void; setState( arg: | number | IGraphObjectStateParameters | ((edge: IEdge) => number) | ((edge: IEdge) => IGraphObjectStateParameters), + options?: IEdgeSetStateOptions, ): void { let result: number | IGraphObjectStateParameters; @@ -446,7 +451,9 @@ abstract class Edge extends Subject im } } - this.notifyListeners(); + if (!options?.isNotifySkipped) { + this.notifyListeners(); + } } private _handleState(state: number, options?: Partial): number { diff --git a/src/models/graph.ts b/src/models/graph.ts index f90555b..8b7801e 100644 --- a/src/models/graph.ts +++ b/src/models/graph.ts @@ -550,7 +550,7 @@ export class Graph extends Subject imp listeners: [this._update], }, ); - edge.setState(existingEdge.getState()); + edge.setState(existingEdge.getState(), { isNotifySkipped: true }); edge.setStyle(existingEdge.getStyle(), { isNotifySkipped: true }); newEdges.push(edge); } diff --git a/src/models/node.ts b/src/models/node.ts index ae31177..af6b1f4 100644 --- a/src/models/node.ts +++ b/src/models/node.ts @@ -37,6 +37,10 @@ export interface INodeSetStyleOptions { isNotifySkipped: boolean; } +export interface INodeSetStateOptions { + isNotifySkipped: boolean; +} + export enum NodeShapeType { CIRCLE = 'circle', DOT = 'dot', @@ -125,10 +129,10 @@ export interface INode extends ISubjec setStyle(callback: (node: INode) => INodeStyle, options?: INodeSetPositionOptions): void; patchStyle(style: INodeStyle, options?: INodeSetPositionOptions): void; patchStyle(callback: (node: INode) => INodeStyle, options?: INodeSetPositionOptions): void; - setState(state: number): void; - setState(state: IGraphObjectStateParameters): void; - setState(callback: (node: INode) => number): void; - setState(callback: (node: INode) => IGraphObjectStateParameters): void; + setState(state: number, options?: INodeSetStateOptions): void; + setState(state: IGraphObjectStateParameters, options?: INodeSetStateOptions): void; + setState(callback: (node: INode) => number, options?: INodeSetStateOptions): void; + setState(callback: (node: INode) => IGraphObjectStateParameters, options?: INodeSetStateOptions): void; } // TODO: Dirty solution: Find another way to listen for global images, maybe through @@ -303,9 +307,7 @@ export class Node extends Subject impl } clearState(): void { - this.setState(GraphObjectState.NONE); - - this.notifyListeners(); + this.setState(GraphObjectState.NONE, { isNotifySkipped: true }); } getDistanceToBorder(): number { @@ -513,16 +515,17 @@ export class Node extends Subject impl } } - setState(state: number): void; - setState(state: IGraphObjectStateParameters): void; - setState(callback: (node: INode) => number): void; - setState(callback: (node: INode) => IGraphObjectStateParameters): void; + setState(state: number, options?: INodeSetStateOptions): void; + setState(state: IGraphObjectStateParameters, options?: INodeSetStateOptions): void; + setState(callback: (node: INode) => number, options?: INodeSetStateOptions): void; + setState(callback: (node: INode) => IGraphObjectStateParameters, options?: INodeSetStateOptions): void; setState( arg: | number | IGraphObjectStateParameters | ((node: INode) => number) | ((node: INode) => IGraphObjectStateParameters), + options?: INodeSetStateOptions, ): void { let result: number | IGraphObjectStateParameters; @@ -550,7 +553,9 @@ export class Node extends Subject impl } } - this.notifyListeners(); + if (!options?.isNotifySkipped) { + this.notifyListeners(); + } } protected _isPointInBoundingBox(point: IPosition): boolean { diff --git a/src/models/strategy.ts b/src/models/strategy.ts index d1fe4a6..9604963 100644 --- a/src/models/strategy.ts +++ b/src/models/strategy.ts @@ -229,24 +229,24 @@ const setNodeState = ( options?: ISetShapeStateOptions, ): void => { if (isStateChangeable(node, options)) { - node.setState(state); + node.setState(state, { isNotifySkipped: true }); } node.getInEdges().forEach((edge) => { if (edge && isStateChangeable(edge, options)) { - edge.setState(state); + edge.setState(state, { isNotifySkipped: true }); } if (edge.startNode && isStateChangeable(edge.startNode, options)) { - edge.startNode.setState(state); + edge.startNode.setState(state, { isNotifySkipped: true }); } }); node.getOutEdges().forEach((edge) => { if (edge && isStateChangeable(edge, options)) { - edge.setState(state); + edge.setState(state, { isNotifySkipped: true }); } if (edge.endNode && isStateChangeable(edge.endNode, options)) { - edge.endNode.setState(state); + edge.endNode.setState(state, { isNotifySkipped: true }); } }); }; @@ -257,15 +257,15 @@ const setEdgeState = ( options?: ISetShapeStateOptions, ): void => { if (isStateChangeable(edge, options)) { - edge.setState(state); + edge.setState(state, { isNotifySkipped: true }); } if (edge.startNode && isStateChangeable(edge.startNode, options)) { - edge.startNode.setState(state); + edge.startNode.setState(state, { isNotifySkipped: true }); } if (edge.endNode && isStateChangeable(edge.endNode, options)) { - edge.endNode.setState(state); + edge.endNode.setState(state, { isNotifySkipped: true }); } }; From e9133e5ad7651dbb81df699c8207462637bfe015 Mon Sep 17 00:00:00 2001 From: AlexIchenskiy Date: Fri, 12 Jul 2024 12:50:36 +0200 Subject: [PATCH 16/30] Chore: Update documentation --- docs/data.md | 195 ++++++++++++++++++++++++++++--------------- docs/styles.md | 187 +++++++++++++++++++++-------------------- docs/view-default.md | 6 +- docs/view-map.md | 34 +++++--- 4 files changed, 243 insertions(+), 179 deletions(-) diff --git a/docs/data.md b/docs/data.md index f694692..f07f26d 100644 --- a/docs/data.md +++ b/docs/data.md @@ -1,5 +1,4 @@ -Handling graph data in Orb -=== +# Handling graph data in Orb Graph data structure (nodes and edges) is the main part of Orb. Without the graph data structure, there wouldn't be anything to render. Read the following guide to get to know @@ -11,6 +10,31 @@ how to handle graph data in Orb. ## Setup nodes and edges +To set up `nodes` and `edges`, there are a few requirements that Orb expects: + +- Node data object should be a JSON plain object with a defined unique `id`. The value of `id` can + be `any`. All other properties are up to you (e.g. `text` and `myField` in the above example). +- Edge data object should be a JSON plain object with defined unique `id`, `start` (id of + the source node), `end` (id of the target node). The value of `id` can be `any`. All other + properties are up to you. (e.g. `connects` in the above example). + +You can have your own `node` and `edge` types that satisfy those requirements: + +```typescript +export interface MyNode { + id: number; + text: string; + myField: number; +} + +export interface MyEdge { + id: number; + start: number; + end: number; + connects: string; +} +``` + To initialize graph data structure use `orb.data.setup` function that receives `nodes` and `edges`. Here is a simple example of it: @@ -25,44 +49,58 @@ const nodes: MyNode[] = [ ]; const edges: MyEdge[] = [ - { id: 0, start: 0, end: 1, connects: 'A -> B' }, - { id: 1, start: 0, end: 0, connects: 'A -> A' }, + { id: 0, start: 0, end: 1, connects: "A -> B" }, + { id: 1, start: 0, end: 0, connects: "A -> A" }, ]; orb.data.setup({ nodes, edges }); ``` -To set up `nodes` and `edges`, there are a few requirements that Orb expects: - -* Node data object should be a JSON plain object with a defined unique `id`. The value of `id` can - be `any`. All other properties are up to you (e.g. `text` and `myField` in the above example). -* Edge data object should be a JSON plain object with defined unique `id`, `start` (id of - the source node), `end` (id of the target node). The value of `id` can be `any`. All other - properties are up to you. (e.g. `connects` in the above example). - Whenever `orb.data.setup` is called, any previous graph structure will be removed. ### Node Node object (interface `INode`) is created on top of the node data that is provided via -`orb.data.setup` or `orb.data.merge` functions. The Node object contains the information: +`orb.data.setup` or `orb.data.merge` functions. -* `id` - Readonly unique `id` provided on init (same as `.data.id`) -* `data` - User provided information on `orb.data.setup` or `orb.data.merge` -* `style` - Style properties like color, border, size (check more on [Styling guide](./styles.md)). -* `position` - Node `x` and `y` coordinate generated before first render -* `state` - Node state which can be selected (`GraphObjectState.SELECTED`), hovered +#### Node information + +- `id` - Readonly unique `id` provided on init (same as `.getData().id`) +- `data` - User provided information on `orb.data.setup` or `orb.data.merge` +- `style` - Style properties like color, border, size (check more on [Styling guide](./styles.md)). +- `position` - Node `x` and `y` coordinate generated before first render +- `state` - Node state which can be selected (`GraphObjectState.SELECTED`), hovered (`GraphObjectState.HOVERED`), or none (`GraphObjectState.NONE` - default) -There are some useful node functions that you can use such as: +#### Node getters functions + +- `getId()` - Alias for `.id` +- `getData()` - Returns the node data +- `getPosition()` - Returns the node position +- `getStyle()` - Returns the node style +- `getState()` - Returns the node state +- `getCenter()` - Alias for `.position` +- `getRadius()` - Alias for `.getStyle().size` +- `getBorderedRadius()` - Alias for `.getStyle().size + .getStyle().borderWidth` +- `getInEdges()` - Returns a list of inbound edges connected to the node +- `getOutEdges()` - Returns a list of outbound edges connected to the node +- `getEdges()` - Returns a list of all edges connected to the node, inbound and outbound +- `getAdjacentNodes()` - Returns a list of adjacent nodes +- `getLabel()` - Returns the node label +- `getColor()` - Returns the node color + +#### Node setter/patch functions -* `getCenter()` - Alias for `.position` -* `getRadius()` - Alias for `.style.size` -* `getBorderedRadius()` - Alias for `.style.size + .style.borderWidth` -* `getInEdges()` - Returns a list of inbound edges connected to the node -* `getOutEdges()` - Returns a list of outbound edges connected to the node -* `getEdges()` - Returns a list of all edges connected to the node, inbound and outbound -* `getAdjacentNodes()` - Returns a list of adjacent nodes +All of the setter/patch functions for nodes are able to accept the raw data of the corresponding type or the callback that returns this data. + +- `setData()` - Replaces the node data with the provided data +- `patchData()` - Replaces the node data entries with the provided ones +- `setPosition()` - Sets the node current position +- `setStyle()` - Sets the node current style +- `patchStyle()` - Replaces the node style entries with the provided ones +- `setState()` - Sets the node current state + +`position`, `style` and `state` setters can accept optional `options` argument. It can be used to skip the rerender on data change which can be useful for performance while changing the data of many nodes. Check the example to get to know node handling better: @@ -79,43 +117,62 @@ const nodes: MyNode[] = [ orb.data.setup({ nodes }); const node = orb.data.getNodeById(0); -console.log(node.id); // Output: 0 -console.log(node.data); // Output: { id: 0, text: "Node A", myField: 12 } +console.log(node.getId()); // Output: 0 +console.log(node.getData()); // Output: { id: 0, text: "Node A", myField: 12 } // Set node color to red -node.style.color = '#FF0000'; -console.log(node.style); // Output: { ..., color: '#FF0000' } +node.patchStyle({ color: "#FF0000" }); +console.log(node.getStyle()); // Output: { ..., color: '#FF0000' } ``` ### Edge Edge object (interface `IEdge`) is created on top of the edge data that is provided via -`orb.data.setup` or `orb.data.merge` functions. The Edge object contains the information: - -* `id` - Readonly unique `id` provided on init (same as `.data.id`) -* `data` - User provided information on `orb.data.setup` or `orb.data.merge` -* `start` - Readonly `start` provided on init (same as `.data.start`) -* `end` - Readonly `end` provided on init (same as `.data.end`) -* `startNode` - Reference to the start node (`INode`) that edge connects -* `endNode` - Reference to the end node (`INode`) that edge connects -* `style` - Style properties like color, border, size (check more on [Styling guide](./styles.md)). -* `state` - Edge state which can be selected (`GraphObjectState.SELECTED`), hovered +`orb.data.setup` or `orb.data.merge` functions. + +#### Edge information + +- `id` - Readonly unique `id` provided on init (same as `.getData().id`) +- `data` - User provided information on `orb.data.setup` or `orb.data.merge` +- `start` - Readonly `start` provided on init (same as `.getData().start`) +- `end` - Readonly `end` provided on init (same as `.getData().end`) +- `startNode` - Reference to the start node (`INode`) that edge connects +- `endNode` - Reference to the end node (`INode`) that edge connects +- `style` - Style properties like color, border, size (check more on [Styling guide](./styles.md)). +- `state` - Edge state which can be selected (`GraphObjectState.SELECTED`), hovered (`GraphObjectState.HOVERED`), or none (`GraphObjectState.NONE` - default) -* `type` - Edge line type which can be: - * straight (`EdgeType.STRAIGHT`) - if there are 1x, 3x, 5x, ... edges connecting nodes A and B, +- `type` - Edge line type which can be: + - straight (`EdgeType.STRAIGHT`) - if there are 1x, 3x, 5x, ... edges connecting nodes A and B, one edge will be a straight line edge. If there are multiple edges, other edges will be curved not to overlap with each other - * curved (`EdgeType.CURVED`) - if there is more than one edge connecting nodes A and B, some + - curved (`EdgeType.CURVED`) - if there is more than one edge connecting nodes A and B, some of those edges will be curved, so they do not overlap with each other - * loopback (`EdgeType.LOOPBACK) - connects a node to itself + - loopback (`EdgeType.LOOPBACK) - connects a node to itself + +#### Edge getters function + +- `getId()` - Alias for `.id` +- `getData()` - Getter for edge data +- `getPosition()` - Getter for edge position +- `getStyle()` - Getter for edge style +- `getState()` - Getter for edge state +- `getCenter()` - Gets the center edge position calculated by edge type and connected node positions +- `getWidth()` - Alias for `.style.width` +- `isLoopback()` - Checks if edge is a loopback type: connects a node to itself. +- `isStraight()` - Checks if edge is a straight line edge +- `isCurved()` - Checks if edge is a curved line edge. + +#### Edge setters/patch functions + +All of the setter/patch functions for edges are able to accept the raw data of the corresponding type or the callback that returns this data. -There are some useful node functions that you can use such as: +- `setData()` - Replaces the edge data with the provided data +- `patchData()` - Replaces the edge data entries with the provided ones +- `setStyle()` - Sets the edge current style +- `patchStyle()` - Replaces the edge style entries with the provided ones +- `setState()` - Sets the edge current state -* `getCenter()` - Gets the center edge position calculated by edge type and connected node positions -* `getWidth()` - Alias for `.style.width` -* `isLoopback()` - Checks if edge is a loopback type: connects a node to itself. -* `isStraight()` - Checks if edge is a straight line edge -* `isCurved()` - Checks if edge is a curved line edge. +`style` and `state` setters can accept optional `options` argument. It can be used to skip the rerender on data change which can be useful for performance while changing the data of many edges. Check the example to get to know edge handling better: @@ -130,21 +187,21 @@ const nodes: MyNode[] = [ ]; const edges: MyEdge[] = [ - { id: 0, start: 0, end: 1, connects: 'A -> B' }, - { id: 1, start: 0, end: 0, connects: 'A -> A' }, + { id: 0, start: 0, end: 1, connects: "A -> B" }, + { id: 1, start: 0, end: 0, connects: "A -> A" }, ]; orb.data.setup({ nodes, edges }); const edge = orb.data.geEdgeById(0); -console.log(edge.id); // Output: 0 -console.log(edge.data); // Output: { id: 0, start: 0, end: 1, connects: 'A -> B' } -console.log(edge.startNode.data); // Output: { id: 0, text: "Node A", myField: 12 } -console.log(edge.endNode.data); // Output: { id: 1, text: "Node B", myField: 77 } +console.log(edge.getId()); // Output: 0 +console.log(edge.getData()); // Output: { id: 0, start: 0, end: 1, connects: 'A -> B' } +console.log(edge.startNode.getData()); // Output: { id: 0, text: "Node A", myField: 12 } +console.log(edge.endNode.getData()); // Output: { id: 1, text: "Node B", myField: 77 } // Set edge line color to red -edge.style.color = '#FF0000'; -console.log(edge.style); // Output: { ..., color: '#FF0000' } +edge.patchStyle({ color: "#FF0000" }); +console.log(edge.getStyle()); // Output: { ..., color: '#FF0000' } ``` ## Merge nodes and edges @@ -164,8 +221,8 @@ const nodes: MyNode[] = [ ]; const edges: MyEdge[] = [ - { id: 0, start: 0, end: 1, connects: 'A -> B' }, - { id: 1, start: 0, end: 0, connects: 'A -> A' }, + { id: 0, start: 0, end: 1, connects: "A -> B" }, + { id: 1, start: 0, end: 0, connects: "A -> A" }, ]; orb.data.setup({ nodes, edges }); @@ -181,12 +238,12 @@ orb.data.merge({ ], edges: [ // This will update the edge with id = 1 because it already exists. `edge.data` will be updated, - // but also, edge will disconnect from previous nodes and connect to the new ones (0 -> 2). - { id: 1, start: 0, end: 2, connects: 'A -> C' }, + // but also, edge will disconnect from previous nodes and connect to the new ones (0 -> 2). + { id: 1, start: 0, end: 2, connects: "A -> C" }, // This will be a new edge in the graph because edge with id = 2 doesn't exist - { id: 2, start: 2, end: 1, connects: 'C -> B' }, + { id: 2, start: 2, end: 1, connects: "C -> B" }, // This edge will be dismissed because node with id = 7 doesn't exist - { id: 3, start: 2, end: 8, connects: 'C -> ?' }, + { id: 3, start: 2, end: 8, connects: "C -> ?" }, ], }); console.log(orb.data.getNodeCount()); // Output: 3 @@ -209,8 +266,8 @@ const nodes: MyNode[] = [ ]; const edges: MyEdge[] = [ - { id: 0, start: 0, end: 1, text: 'A -> B' }, - { id: 1, start: 0, end: 0, text: 'A -> A' }, + { id: 0, start: 0, end: 1, text: "A -> B" }, + { id: 1, start: 0, end: 0, text: "A -> A" }, ]; orb.data.setup({ nodes, edges }); @@ -230,13 +287,13 @@ orb.data.remove({ nodeIds: [0] }); orb.data.remove({ nodeIds: [0, 1, 2], edgeIds: [0] }); // Remove just edges -orb.data.remove({ edgeIds: [0, 1, 2 ] }); +orb.data.remove({ edgeIds: [0, 1, 2] }); ``` If you need to remove everything, you can do it with `remove` or even with `setup`: ```typescript -const nodeIds = orb.data.getNodes().map(node => node.id); +const nodeIds = orb.data.getNodes().map((node) => node.getId()); // No need to get edges because if we remove all the nodes, all the edges will be removed too orb.data.remove({ nodeIds: nodeIds }); @@ -258,7 +315,7 @@ const edges = orb.data.getEdges(); const nodeCount = orb.data.getNodeCount(); const edgeCount = orb.data.getEdgeCount(); -// Returns specific node or edge by id. If node or edge doesn't exist, it will return undefined +// Returns specific node or edge by id. If node or edge doesn't exist, it will return undefined const node = orb.data.getNodeById(0); const edge = orb.data.getEdgeById(0); diff --git a/docs/styles.md b/docs/styles.md index b44e4e9..d5ad90f 100644 --- a/docs/styles.md +++ b/docs/styles.md @@ -1,5 +1,4 @@ -Styling nodes and edges in Orb -=== +# Styling nodes and edges in Orb Styling nodes and edges in Orb refers to the configuration of colors, size, width, and other visual properties. In the following section, you can find all the details and available style properties to @@ -14,7 +13,7 @@ through which you can get and set style properties. ```typescript const node = orb.data.getNodeById(0); // Set node size to 10 -node.style.size = 10; +node.patchStyle({ size: 10 }); ``` ## Properties @@ -22,31 +21,31 @@ node.style.size = 10; The interface that defines all the node style properties is `INodeStyle`. It contains the following properties: -| Property name | Type | Description | -| --------------------- | ------------------- | ----------------------------------------------- | -| `borderColor` | Color | string | Node border color. | -| `borderColorHover` | Color | string | Node border color on mouse hover event. If not defined, `borderColor` is used. | -| `borderColorSelected` | Color | string | Node border color on mouse click event. If not defined, `borderColor` is used. | -| `borderWidth` | number | Node border width. | -| `borderWidthSelected` | number | Node border width on mouse click event. If not defined, `borderWidth` is used. | -| `color` | Color | string | Node background color. The default is `#1d87c9`. | -| `colorHover` | Color | string | Node background color on mouse hover event. If not defined `color` is used. | -| `colorSelected` | Color | string | Node background color on mouse click event. If not defined `color` is used. | -| `fontBackgroundColor` | Color | string | Node text (label) background color. | -| `fontColor` | Color | string | Node text (label) font color. The default is `#000000`. | -| `fontFamily` | string | Node text (label) font family. The default is `"Roboto, sans-serif"`. | -| `fontSize` | number | Node text (label) font size. The default is `4`. | -| `imageUrl` | string | Image used for a node background. If image is defined, `color` won't be used. | -| `imageUrlSelected` | string | Image used for a node background on mouse click event. If image is defined, `colorSelected` and `color` won't be used. | -| `label` | string | Node text content. Text content will be shown below the node if `fontSize` is greater than zero. | -| `shadowColor` | Color | string | Node background shadow color. | -| `shadowSize` | number | Node shadow blur size. If set to `0` the shadow will be a solid color defined by `shadowColor`. | -| `shadowOffsetX` | number | Node shadow horizontal offset. A positive value puts the shadow on the right side of the element, a negative value puts the shadow on the left side of the element. | -| `shadowOffsetY` | number | Node shadow vertical offset. A positive value puts the shadow below the element, a negative value puts the shadow above the element. | +| Property name | Type | Description | +| --------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `borderColor` | Color | string | Node border color. | +| `borderColorHover` | Color | string | Node border color on mouse hover event. If not defined, `borderColor` is used. | +| `borderColorSelected` | Color | string | Node border color on mouse click event. If not defined, `borderColor` is used. | +| `borderWidth` | number | Node border width. | +| `borderWidthSelected` | number | Node border width on mouse click event. If not defined, `borderWidth` is used. | +| `color` | Color | string | Node background color. The default is `#1d87c9`. | +| `colorHover` | Color | string | Node background color on mouse hover event. If not defined `color` is used. | +| `colorSelected` | Color | string | Node background color on mouse click event. If not defined `color` is used. | +| `fontBackgroundColor` | Color | string | Node text (label) background color. | +| `fontColor` | Color | string | Node text (label) font color. The default is `#000000`. | +| `fontFamily` | string | Node text (label) font family. The default is `"Roboto, sans-serif"`. | +| `fontSize` | number | Node text (label) font size. The default is `4`. | +| `imageUrl` | string | Image used for a node background. If image is defined, `color` won't be used. | +| `imageUrlSelected` | string | Image used for a node background on mouse click event. If image is defined, `colorSelected` and `color` won't be used. | +| `label` | string | Node text content. Text content will be shown below the node if `fontSize` is greater than zero. | +| `shadowColor` | Color | string | Node background shadow color. | +| `shadowSize` | number | Node shadow blur size. If set to `0` the shadow will be a solid color defined by `shadowColor`. | +| `shadowOffsetX` | number | Node shadow horizontal offset. A positive value puts the shadow on the right side of the element, a negative value puts the shadow on the left side of the element. | +| `shadowOffsetY` | number | Node shadow vertical offset. A positive value puts the shadow below the element, a negative value puts the shadow above the element. | | `shape` | NodeShapeType | Node shape enum. Possible values are: `CIRCLE`, `DOT` (same as circle), `SQUARE`, `DIAMOND`, `TRIANGLE`, `TRIANGLE_DOWN`, `STAR`, `HEXAGON`. Default is `NodeShapeEnum.CIRCLE`. | -| `size` | number | Node size (usually the radius). The default is `5`. | -| `mass` | number | Node mass. _(Currently not used)_ | -| `zIndex` | number | Specifies the stack order of an element during rendering. The default is `0`. | +| `size` | number | Node size (usually the radius). The default is `5`. | +| `mass` | number | Node mass. _(Currently not used)_ | +| `zIndex` | number | Specifies the stack order of an element during rendering. The default is `0`. | ## Shape enumeration @@ -54,14 +53,14 @@ The enum `NodeShapeType` which is used for the node `shape` property is defined ```typescript export enum NodeShapeType { - CIRCLE = 'circle', - DOT = 'dot', - SQUARE = 'square', - DIAMOND = 'diamond', - TRIANGLE = 'triangle', - TRIANGLE_DOWN = 'triangleDown', - STAR = 'star', - HEXAGON = 'hexagon', + CIRCLE = "circle", + DOT = "dot", + SQUARE = "square", + DIAMOND = "diamond", + TRIANGLE = "triangle", + TRIANGLE_DOWN = "triangleDown", + STAR = "star", + HEXAGON = "hexagon", } ``` @@ -72,10 +71,10 @@ Default node style values are defined as follows: ```typescript const DEFAULT_NODE_STYLE: INodeStyle = { size: 5, - color: new Color('#1d87c9'), + color: new Color("#1d87c9"), fontSize: 4, - fontColor: '#000000', - fontFamily: 'Roboto, sans-serif', + fontColor: "#000000", + fontFamily: "Roboto, sans-serif", shape: NodeShapeType.CIRCLE, }; ``` @@ -115,7 +114,7 @@ through which you can get and set style properties. ```typescript const edge = orb.data.getEdgebyId(0); // Set edge width to 1 -edge.style.width = 1; +edge.patchStyle({ width: 1 }); ``` ## Properties @@ -123,26 +122,26 @@ edge.style.width = 1; The interface that defines all the node properties is `IEdgeStyle`. It contains the following style properties: -| Property name | Type | Description | -| --------------------- | ------------------- | --------------------------------------------------- | +| Property name | Type | Description | +| --------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `arrowSize` | number | The scale of the edge arrow compared to the `width` of the edge. If set to `0`, an arrow will be dismissed. The default is `1` (follows the size of the edge `width`). | -| `color` | Color | string | Edge line color. The default is `#ababab`. | -| `colorHover` | Color | string | Edge line color on mouse hover event. If not defined `color` is used. | -| `colorSelected` | Color | string | Edge line color on mouse click event. If not defined `color` is used. | -| `fontBackgroundColor` | Color | string | Edge text (label) background color. -| `fontColor` | Color | string | Edge text (label) font color. The default is `#000000`. | -| `fontFamily` | string | Edge text (label) font family. The default is `"Roboto, sans-serif"`. | -| `fontSize` | number | Edge text (label) font size. The default is `4`. | -| `label` | string | Edge text content. Text content will be shown at the middle of the edge line if `fontSize` is greater than zero. | -| `shadowColor` | Color | string | Edge line background shadow color. | -| `shadowSize` | number | Edge line shadow blur size. If set to `0` the shadow will be a solid color defined by `shadowColor`. | -| `shadowOffsetX` | number | Edge shadow horizontal offset. A positive value puts the shadow on the right side of the line, a negative value puts the shadow on the left side of the line. | -| `shadowOffsetY` | number | Edge shadow vertical offset. A positive value puts the shadow below the line, a negative value puts the shadow above the line. | -| `width` | number | Edge line width. If the width is `0`, the edge won't be drawn. The default is `0.3`. | -| `widthHover` | number | Edge line width on mouse hover event. If not defined `width` is used. | -| `widthSelected` | number | Edge line width on mouse click event. If not defined `width` is used. | -| `zIndex` | number | Specifies the stack order of an element during rendering. The default is `0`. | -| `lineStyle` | object | Allows to customize the style of edges in the graph visualization. The default is `{type: 'solid'}` | +| `color` | Color | string | Edge line color. The default is `#ababab`. | +| `colorHover` | Color | string | Edge line color on mouse hover event. If not defined `color` is used. | +| `colorSelected` | Color | string | Edge line color on mouse click event. If not defined `color` is used. | +| `fontBackgroundColor` | Color | string | Edge text (label) background color. | +| `fontColor` | Color | string | Edge text (label) font color. The default is `#000000`. | +| `fontFamily` | string | Edge text (label) font family. The default is `"Roboto, sans-serif"`. | +| `fontSize` | number | Edge text (label) font size. The default is `4`. | +| `label` | string | Edge text content. Text content will be shown at the middle of the edge line if `fontSize` is greater than zero. | +| `shadowColor` | Color | string | Edge line background shadow color. | +| `shadowSize` | number | Edge line shadow blur size. If set to `0` the shadow will be a solid color defined by `shadowColor`. | +| `shadowOffsetX` | number | Edge shadow horizontal offset. A positive value puts the shadow on the right side of the line, a negative value puts the shadow on the left side of the line. | +| `shadowOffsetY` | number | Edge shadow vertical offset. A positive value puts the shadow below the line, a negative value puts the shadow above the line. | +| `width` | number | Edge line width. If the width is `0`, the edge won't be drawn. The default is `0.3`. | +| `widthHover` | number | Edge line width on mouse hover event. If not defined `width` is used. | +| `widthSelected` | number | Edge line width on mouse click event. If not defined `width` is used. | +| `zIndex` | number | Specifies the stack order of an element during rendering. The default is `0`. | +| `lineStyle` | object | Allows to customize the style of edges in the graph visualization. The default is `{type: 'solid'}` | ## Default style values @@ -150,12 +149,12 @@ Default edge style values are defined as follows: ```typescript const DEFAULT_EDGE_STYLE: IEdgeStyle = { - color: new Color('#ababab'), + color: new Color("#ababab"), width: 0.3, fontSize: 4, arrowSize: 1, - fontColor: '#000000', - fontFamily: 'Roboto, sans-serif', + fontColor: "#000000", + fontFamily: "Roboto, sans-serif", }; ``` @@ -168,17 +167,17 @@ Orb exports a utility class `Color` which you can use to define colors too. It c functions for easier color handling: ```typescript -import { Color } from '@memgraph/orb'; +import { Color } from "@memgraph/orb"; // Constructor always receives a color HEX code -const red = new Color('#FF0000'); +const red = new Color("#FF0000"); // Returns darker or lighter color by input factor (default is 0.3) const darkerRed = red.getDarkerColor(); const lighterRed = red.getLighterColor(); // Mix two colors (RGB values are joined and divided by 2) -const mixedColor = red.getMixedColor(new Color('#ffffff')); +const mixedColor = red.getMixedColor(new Color("#ffffff")); // Get a color object by RGB values, not HEX code const redByRGB = Color.getColorFromRGB({ r: 255, g: 0, b: 0 }); @@ -191,26 +190,27 @@ If you would like to have a lighter/darker tone of a node on node select/hover, that with `getLighterColor` or `getDarkerColor` functions: ```typescript -const nodeBaseColor = new Color('#FF0000'); +const nodeBaseColor = new Color("#FF0000"); -node.style.color = nodeBaseColor; -node.style.colorSelected = nodeBaseColor.getDarkerColor(); -node.style.colorHover = nodeBaseColor.getLighterColor(); +node.patchStyle({ color: nodeBaseColor }); +node.patchStyle({ colorSelected: nodeBaseColor.getDarkerColor() }); +node.patchStyle({ colorHover: nodeBaseColor.getLighterColor() }); ``` # Setting up styles There are two ways to set up a style: -* Setting up default style which is an initial style applied to new nodes and new edges -* Changing the style properties of particular nodes and edges + +- Setting up default style which is an initial style applied to new nodes and new edges +- Changing the style properties of particular nodes and edges ## Setting default style Orb comes with a default style which you can override with the function `orb.data.setDefaultStyle`. The function expects an object where you can define one or both style callback functions: -* `getNodeStyle(node)` - expects an object containing node style properties. -* `getEdgeStyle(edge)` - expects an object containing edge style properties. +- `getNodeStyle(node)` - expects an object containing node style properties. +- `getEdgeStyle(edge)` - expects an object containing edge style properties. The default style is an easy way to set up a style that will be applied to all newly created nodes or edges. With it, you don't need to worry about setting up style properties for each @@ -220,7 +220,7 @@ node or edge. orb.data.setDefaultStyle({ getNodeStyle(node) { return { - color: '#FF0000', + color: "#FF0000", fontSize: 10, size: 10, label: `Node: ${node.data.title}`, @@ -228,7 +228,7 @@ orb.data.setDefaultStyle({ }, getEdgeStyle() { return { - color: '#000000', + color: "#000000", width: 3, }; }, @@ -240,7 +240,6 @@ orb.data.setDefaultStyle({ // For all the `newNodes` and `newEdges` that have a new unique ID, a default // style defined above will be automatically applied orb.data.merge({ nodes: newNodes, edges: newEdges }); - ``` Without a default style, you would need to do the following after each call of `orb.data.setup` @@ -250,22 +249,22 @@ or `orb.data.merge` where new nodes/edges are created: // Without default style, after each call of `orb.data.setup` or `orb.data.merge` // you need to call the following code orb.data.getNodes().forEach((node) => { - node.style = { - color: '#FF0000', + node.setStyle({ + color: "#FF0000", fontSize: 10, size: 10, label: `Node: ${node.data.title}`, - }; + }); }); orb.data.getEdges().forEach((edge) => { - edge.style = { - color: '#000000', + edge.setStyle({ + color: "#000000", width: 3, - }; + }); }); // For all the `newNodes` and `newEdges` that have a new unique ID, Orb's default -// style will be applied, not the style properties above +// style will be applied, not the style properties above orb.data.merge({ nodes: newNodes, edges: newEdges }); ``` @@ -276,28 +275,28 @@ node (`INode`) or edge (`IEdge`) object. Using those objects, you can change the any time: ```typescript -import { OrbView, OrbEventType } from '@memgraph/orb'; +import { OrbView, OrbEventType } from "@memgraph/orb"; const orb = new OrbView(container); orb.data.setup({ nodes, edges }); const node = orb.data.getNodeById(0); // Override existing node style properties with the new ones -node.style = { - color: '#FF0000', +node.setStyle({ + color: "#FF0000", fontSize: 10, size: 10, label: `Node: ${node.data.title}`, -}; +}); // Change the width of all the edges to 1, but keep other style properties orb.data.getEdges().forEach((edge) => { - edge.style.width = 1; + edge.patchStyle({ width: 1 }); }); orb.events.on(OrbEventType.NODE_CLICK, ({ node }) => { // If a node is clicked, set its size to be 10 - node.style.size = 10; + node.patchStyle({ size: 10 }); }); ``` @@ -315,7 +314,7 @@ without setting `(node|edge).style.label = ""` or `(node|edge).style.fontSize = each node/edge, you can use the view settings to enable/disable labels globally: ```typescript -import { OrbView } from '@memgraph/orb'; +import { OrbView } from "@memgraph/orb"; // Change on view init const orb = new OrbView(container, { @@ -345,7 +344,7 @@ for the large number of nodes/edges. To simplify the way to disable/enable shado whole graph you can use the view settings to enable/disable shadows globally: ```typescript -import { OrbView } from '@memgraph/orb'; +import { OrbView } from "@memgraph/orb"; // Change on view init const orb = new OrbView(container, { @@ -372,17 +371,17 @@ properties are `true`. Additional performance affected property is the transparency of nodes/edges that are not selected nor hovered. Default Orb behavior on node/edge select (click) and hover to make all other nodes 30% -transparent, so the selection/hover is easily visible. +transparent, so the selection/hover is easily visible. You can configure the transparency with the following two properties: -* `contextAlphaOnEvent` - Transparency factor between 0 (hidden) and 1 (opaque). The default +- `contextAlphaOnEvent` - Transparency factor between 0 (hidden) and 1 (opaque). The default is `0.3`. -* `contextAlphaOnEventIsEnabled` - Enable or disable transparency regardless of the factor. +- `contextAlphaOnEventIsEnabled` - Enable or disable transparency regardless of the factor. The default is `true`. ```typescript -import { OrbView } from '@memgraph/orb'; +import { OrbView } from "@memgraph/orb"; // Change on view init const orb = new OrbView(container, { diff --git a/docs/view-default.md b/docs/view-default.md index 217e9bc..6d2fb78 100644 --- a/docs/view-default.md +++ b/docs/view-default.md @@ -244,7 +244,7 @@ const edges: MyEdge[] = [ ]; const orb = new OrbView(container, { - getPosition: (node) => ({ x: node.data.posX, y: node.data.posY }), + getPosition: (node) => ({ x: node.getData().posX, y: node.getData().posY }), }); // Initialize nodes and edges @@ -398,7 +398,7 @@ after the initialization with a view function `setSettings`: import { OrbView } from "@memgraph/orb"; const orb = new OrbView(container, { - getPosition: (node) => ({ x: node.data.posY, y: node.data.posX }), + getPosition: (node) => ({ x: node.getData().posY, y: node.getData().posX }), zoomFitTransformMs: 1000, render: { shadowIsEnabled: false, @@ -413,7 +413,7 @@ const settings = orb.getSettings(); // Change the x and y axis orb.setSettings({ - getPosition: (node) => ({ x: node.data.posY, y: node.data.posX }), + getPosition: (node) => ({ x: node.getData().posY, y: node.getData().posX }), }); // Change the zoom fit and transform time while recentering and disable shadows diff --git a/docs/view-map.md b/docs/view-map.md index 26c1cb8..4daa32b 100644 --- a/docs/view-map.md +++ b/docs/view-map.md @@ -32,7 +32,10 @@ const edges: MyEdge[] = [ ]; const orb = new OrbMapView(container, { - getGeoPosition: (node) => ({ lat: node.data.lat, lng: node.data.lng }), + getGeoPosition: (node) => ({ + lat: node.getData().lat, + lng: node.getData().lng, + }), }); // Assign a default style @@ -43,7 +46,7 @@ orb.data.setDefaultStyle({ borderWidth: 1, color: "#DD2222", fontSize: 10, - label: node.data.label, + label: node.getData().label, size: 10, }; }, @@ -81,14 +84,14 @@ const mapAttribution = const orb = new OrbMapView(container, { getGeoPosition: (node) => ({ - lat: node.data.latitude, - lng: node.data.longitude, + lat: node.getData().latitude, + lng: node.getData().longitude, }), map: { zoomLevel: 5, tile: { instance: new L.TileLayer( - "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" + "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" ), attribution: mapAttribution, }, @@ -217,14 +220,14 @@ Disabled by default (`false`). The optional property `strategy` has two properties that you can enable/disable: -* `isDefaultSelectEnabled` - when `true`, the default selection strategy is used on mouse click: - * If there is a node at the mouse click point, the node, its edges, and adjacent nodes will change +- `isDefaultSelectEnabled` - when `true`, the default selection strategy is used on mouse click: + - If there is a node at the mouse click point, the node, its edges, and adjacent nodes will change its state to `GraphObjectState.SELECTED`. Style properties that end with `...Selected` will be applied to all the selected objects (e.g. `borderColorSelected`). - * If there is an edge at the mouse click point, the edge and its starting and ending nodes will change + - If there is an edge at the mouse click point, the edge and its starting and ending nodes will change its state to `GraphObjectState.SELECTED`. -* `isDefaultHoverEnabled` - when `true`, the default hover strategy is used on mouse move: - * If there is a node at the mouse pointer, the node, its edges, and adjacent nodes will change its state to +- `isDefaultHoverEnabled` - when `true`, the default hover strategy is used on mouse move: + - If there is a node at the mouse pointer, the node, its edges, and adjacent nodes will change its state to `GraphObjectState.HOVERED`. Style properties that end with `...Hovered` will be applied to all the hovered objects (e.g. `borderColorHovered`). @@ -232,7 +235,7 @@ With property `strategy` you can disable the above behavior and implement your s top of events `OrbEventType.MOUSE_CLICK` and `OrbEventType.MOUSE_MOVE`, e.g: ```typescript -import { isNode, OrbEventType, GraphObjectState } from '@memgraph/orb'; +import { isNode, OrbEventType, GraphObjectState } from "@memgraph/orb"; // Disable default select and hover strategy orb.setSettings({ @@ -257,7 +260,9 @@ orb.events.on(OrbEventType.MOUSE_CLICK, (event) => { // Clicked on unselected node if (event.subject && isNode(event.subject) && !event.subject.isSelected()) { // Deselect the previously selected nodes - orb.data.getNodes((node) => node.isSelected()).forEach((node) => node.clearState()); + orb.data + .getNodes((node) => node.isSelected()) + .forEach((node) => node.clearState()); // Select the new node event.subject.state = GraphObjectState.SELECTED; orb.render(); @@ -276,7 +281,10 @@ const settings = orb.getSettings(); // Change the way how geo coordinates are defined on nodes orb.setSettings({ - getGeoPosition: (node) => ({ lat: node.data.lat, lng: node.data.lng }), + getGeoPosition: (node) => ({ + lat: node.getData().lat, + lng: node.getData().lng, + }), }); // Change the zoom level and disable shadows From aad6a2ef2077860cc69c7a2ee7c690befc40219e Mon Sep 17 00:00:00 2001 From: AlexIchenskiy Date: Fri, 12 Jul 2024 13:44:27 +0200 Subject: [PATCH 17/30] Fix: Node/edge getter performance issue --- src/models/edge.ts | 9 ++++++--- src/models/node.ts | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/models/edge.ts b/src/models/edge.ts index d36c8af..0a3374b 100644 --- a/src/models/edge.ts +++ b/src/models/edge.ts @@ -218,15 +218,18 @@ abstract class Edge extends Subject im } getData(): E { - return structuredClone(this._data); + // no shallow/deep copy here due to the performance issues + return this._data; } getPosition(): IEdgePosition { - return structuredClone(this._position); + // no shallow/deep copy here due to the performance issues + return this._position; } getStyle(): IEdgeStyle { - return structuredClone(this._style); + // no shallow/deep copy here due to the performance issues + return this._style; } getState(): number { diff --git a/src/models/node.ts b/src/models/node.ts index af6b1f4..262c4a9 100644 --- a/src/models/node.ts +++ b/src/models/node.ts @@ -182,15 +182,18 @@ export class Node extends Subject impl } getData(): N { - return structuredClone(this._data); + // no shallow/deep copy here due to the performance issues + return this._data; } getPosition(): INodePosition { - return structuredClone(this._position); + // no shallow/deep copy here due to the performance issues + return this._position; } getStyle(): INodeStyle { - return structuredClone(this._style); + // no shallow/deep copy here due to the performance issues + return this._style; } getState(): number { From 2570888801a0d38525c5f9b3980dbd88b0ec9ab5 Mon Sep 17 00:00:00 2001 From: AlexIchenskiy Date: Mon, 15 Jul 2024 08:08:59 +0200 Subject: [PATCH 18/30] Chore: Add data change docs example --- examples/example-dynamic-change.html | 110 +++++++++++++++++++++++++++ examples/index.html | 9 +++ 2 files changed, 119 insertions(+) create mode 100644 examples/example-dynamic-change.html diff --git a/examples/example-dynamic-change.html b/examples/example-dynamic-change.html new file mode 100644 index 0000000..bedbe39 --- /dev/null +++ b/examples/example-dynamic-change.html @@ -0,0 +1,110 @@ + + + + + + Orb | Data dynamics: Update nodes and edges data + + + + +
+

Example 7 - Data dynamics

+

+ Renders a simple graph to show graph data dynamics: updating nodes and edges data. + In intervals of 3 seconds, 1 node gets new size and 1 node gets new color + (green or red) and a new border color (white or black). Node will change its + unselected color to blue on node click event. +

+ + +
+
+ + + diff --git a/examples/index.html b/examples/index.html index 78b0c65..98f29f1 100644 --- a/examples/index.html +++ b/examples/index.html @@ -62,5 +62,14 @@

Orb Examples

longitude values.

+
+

  • Example 7 - Data dynamics
  • +

    + Renders a simple graph to show graph data dynamics: updating nodes and edges data. + In intervals of 3 seconds, 1 node gets new size and 1 node gets new color + (green or red) and a new border color (white or black). Node will change its + unselected color to blue on node click event. +

    +
    From 0825293f4f73d30a8d6f7cacb89cc34f50c6e891 Mon Sep 17 00:00:00 2001 From: AlexIchenskiy Date: Mon, 15 Jul 2024 08:14:35 +0200 Subject: [PATCH 19/30] Fix: Docs typos --- docs/styles.md | 10 +++++----- docs/view-default.md | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/styles.md b/docs/styles.md index 7553997..8a3ef9c 100644 --- a/docs/styles.md +++ b/docs/styles.md @@ -96,8 +96,8 @@ const orb = new OrbView(container); orb.data.setDefaultStyle({ getNodeStyle: (node) => { return { - ...node.style, - label: node.data.name, + ...node.getStyle(), + label: node.getData().name, }; }, }); @@ -223,7 +223,7 @@ orb.data.setDefaultStyle({ color: "#FF0000", fontSize: 10, size: 10, - label: `Node: ${node.data.title}`, + label: `Node: ${node.getData().title}`, }; }, getEdgeStyle() { @@ -253,7 +253,7 @@ orb.data.getNodes().forEach((node) => { color: "#FF0000", fontSize: 10, size: 10, - label: `Node: ${node.data.title}`, + label: `Node: ${node.getData().title}`, }); }); orb.data.getEdges().forEach((edge) => { @@ -286,7 +286,7 @@ node.setStyle({ color: "#FF0000", fontSize: 10, size: 10, - label: `Node: ${node.data.title}`, + label: `Node: ${node.getData().title}`, }); // Change the width of all the edges to 1, but keep other style properties diff --git a/docs/view-default.md b/docs/view-default.md index 6d2fb78..849796a 100644 --- a/docs/view-default.md +++ b/docs/view-default.md @@ -263,8 +263,8 @@ access your original properties through `.data` property. There you can find all your nodes that you assigned in the `orb.data.setup()` function. Here you can use your original properties to indicate which ones represent your node coordinates -(`node.data.posX`, `node.data.posY`). All you have to do is return a `IPosition` that requires -2 basic properties: `x` and `y` (`{ x: node.data.posX, y: node.data.posY }`). +(`node.getData().posX`, `node.getData().posY`). All you have to do is return a `IPosition` that requires +2 basic properties: `x` and `y` (`{ x: node.getData().posX, y: node.getData().posY }`). ### Property `render` From 5771996197dec521ed44ec1290a6430bfd013962 Mon Sep 17 00:00:00 2001 From: Oleksandr Ichenskyi <55350107+AlexIchenskiy@users.noreply.github.com> Date: Mon, 15 Jul 2024 09:39:14 +0200 Subject: [PATCH 20/30] Fix: Disable source map generation (#105) --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index bb28c93..828dd58 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ "module": "esnext", "lib": ["DOM", "ES6"], "declaration": true, - "sourceMap": true, + "sourceMap": false, "outDir": "./dist", "moduleResolution": "node", "esModuleInterop": true, From f538efe0ae86d4c78e4e82596c77ed87ff02098e Mon Sep 17 00:00:00 2001 From: Oleksandr Ichenskyi <55350107+AlexIchenskiy@users.noreply.github.com> Date: Tue, 3 Jun 2025 17:09:32 +0200 Subject: [PATCH 21/30] New: Add tree layout (#107) * New: Add new layouts * New: Add layout options * Chore: Make layout dynamically changeable * Chore: Update docs * Fix: Naming typo * Chore: Refactor layouts * New: Enable layout node add/remove * Chore: Improve behavior for recurrent nodes * Chore: Move some simulator settings to layout * Chore: Refactor code quality and performance * Fix: Layout behavior on change * Chore: Add recenter on layout change * Fix: Layout change behavior * Fix: Simulation behavior on data deletion * Chore: Add recenter on layout change --- docs/view-default.md | 38 ++++ examples/example-hierarchical-layout.html | 94 ++++++++++ examples/index.html | 6 + src/models/graph.ts | 21 +++ src/simulator/engine/d3-simulator-engine.ts | 20 +- src/simulator/layout/layout.ts | 52 ++++-- src/simulator/layout/layouts/circle.ts | 11 -- src/simulator/layout/layouts/circular.ts | 37 ++++ src/simulator/layout/layouts/force.ts | 11 ++ src/simulator/layout/layouts/grid.ts | 38 ++++ src/simulator/layout/layouts/hierarchical.ts | 163 ++++++++++++++++ src/simulator/shared.ts | 1 + src/simulator/types/main-thread-simulator.ts | 4 + .../message/worker-input.ts | 4 + .../web-worker-simulator/simulator.worker.ts | 5 + .../web-worker-simulator.ts | 4 + src/views/orb-view.ts | 176 ++++++++++++++---- 17 files changed, 620 insertions(+), 65 deletions(-) create mode 100644 examples/example-hierarchical-layout.html delete mode 100644 src/simulator/layout/layouts/circle.ts create mode 100644 src/simulator/layout/layouts/circular.ts create mode 100644 src/simulator/layout/layouts/force.ts create mode 100644 src/simulator/layout/layouts/grid.ts create mode 100644 src/simulator/layout/layouts/hierarchical.ts diff --git a/docs/view-default.md b/docs/view-default.md index 849796a..56e14d1 100644 --- a/docs/view-default.md +++ b/docs/view-default.md @@ -61,6 +61,16 @@ interface IOrbViewSettings { }; }; }; + // For graph layouting (if present, physics is disabled) + layout: { + type: 'hierarchical' | 'grid' | 'circular'; + options: null | { + orientation: 'vertical' | 'horizontal'; + reversed: boolean; + } | { + radius: number; + } + }; // For canvas rendering and events render: { devicePixelRatio: number | null; @@ -266,6 +276,34 @@ Here you can use your original properties to indicate which ones represent your (`node.getData().posX`, `node.getData().posY`). All you have to do is return a `IPosition` that requires 2 basic properties: `x` and `y` (`{ x: node.getData().posX, y: node.getData().posY }`). +### Property `layout` + +If you want to use one of the predefined layouts (hierarchical (tree), grid, circular...) you can specify +the optional property `layout`. Simulation physics are ignored when a layout is applied. There is no layout +applied by default. + +#### Property `type` + +You can specify the desired layout using the `type` property that can have one of the following values: + +- `hierarchical` - a tree-like layout style that tries to portrait graph nodes in a hierarchy + +- `circular` - arranges the nodes of the graph in a circle + +- `grid` - a layout where nodes are aligned in rows and columns + +#### Property `options` + +Each layout type has its own option list you can tweak in order to change the layout behaviour. + +- `hierarchical` + - `orientation` - The tree orientation that could be whether `vertical` (by default) or `horizontal` + - `reversed` - Whether the orientation is reversed. Default orientation is top-bottom for vertical and + left-right for horizontal which is reversed when this property is set to `true`. Disabled by default `false` + +- `circular` + - `radius` - Radius of the circle in relativa units. + ### Property `render` Optional property `render` has several rendering options that you can tweak. Read more about them diff --git a/examples/example-hierarchical-layout.html b/examples/example-hierarchical-layout.html new file mode 100644 index 0000000..0a03d09 --- /dev/null +++ b/examples/example-hierarchical-layout.html @@ -0,0 +1,94 @@ + + + + + + Orb | Simple hierarchical graph + + + + +
    +

    Example 8 - Hierarchical layout

    +

    Renders a simple graph with hierarchical layout.

    + + +
    +
    + + + diff --git a/examples/index.html b/examples/index.html index 98f29f1..73edf37 100644 --- a/examples/index.html +++ b/examples/index.html @@ -71,5 +71,11 @@

    Orb Examples

    unselected color to blue on node click event.

    +
    +

  • Example 8 - Hierarchical layout
  • +

    + Renders a simple graph with hierarchical layout (tree-like). +

    +
    diff --git a/src/models/graph.ts b/src/models/graph.ts index 8b7801e..7bcf0e0 100644 --- a/src/models/graph.ts +++ b/src/models/graph.ts @@ -8,6 +8,7 @@ import { IEntityState, EntityState } from '../utils/entity.utils'; import { IObserver, IObserverDataPayload, ISubject, Subject } from '../utils/observer.utils'; import { patchProperties } from '../utils/object.utils'; import { dedupArrays } from '../utils/array.utils'; +import { ILayout } from '../simulator/layout/layout'; export interface IGraphData { nodes: N[]; @@ -50,6 +51,7 @@ export interface IGraph extends ISubje getNearestNode(point: IPosition): INode | undefined; getNearestEdge(point: IPosition, minDistance?: number): IEdge | undefined; setSettings(settings: Partial>): void; + setLayout(layout: ILayout | undefined): void; } export interface IGraphSettings { @@ -73,6 +75,7 @@ export class Graph extends Subject imp }); private _defaultStyle?: Partial>; private _settings: IGraphSettings; + private _layout: ILayout | undefined; constructor(data?: Partial>, settings?: Partial>) { // TODO(dlozic): How to use object assign here? If I add add and export a default const here, it needs N, E. @@ -92,6 +95,11 @@ export class Graph extends Subject imp this.notifyListeners(); } + setLayout(layout: ILayout | undefined): void { + this._layout = layout; + this._resetLayout(); + } + /** * Returns a list of nodes. * @@ -274,6 +282,7 @@ export class Graph extends Subject imp this._applyEdgeOffsets(); this._applyStyle(); + this._resetLayout(); this._settings?.onMergeData?.(data); } @@ -287,6 +296,7 @@ export class Graph extends Subject imp this._applyEdgeOffsets(); this._applyStyle(); + this._resetLayout(); if (this._settings && this._settings.onRemoveData) { const removedData: IGraphObjectsIds = { @@ -603,6 +613,17 @@ export class Graph extends Subject imp return { nodeIds: [], edgeIds: removedEdgeIds }; } + private _resetLayout(): void { + if (!this._layout) { + this.clearPositions(); + return; + } + + const positions = this._layout.getPositions(this.getNodes()); + this.setNodePositions(positions); + this.notifyListeners(); + } + private _applyEdgeOffsets() { const graphEdges = this.getEdges(); const edgeOffsets = getEdgeOffsets(graphEdges); diff --git a/src/simulator/engine/d3-simulator-engine.ts b/src/simulator/engine/d3-simulator-engine.ts index 225fd67..f20346f 100644 --- a/src/simulator/engine/d3-simulator-engine.ts +++ b/src/simulator/engine/d3-simulator-engine.ts @@ -20,6 +20,7 @@ const DEFAULT_LINK_DISTANCE = 50; export enum D3SimulatorEngineEventType { SIMULATION_START = 'simulation-start', + SIMULATION_STOP = 'simulation-stop', SIMULATION_PROGRESS = 'simulation-progress', SIMULATION_END = 'simulation-end', SIMULATION_TICK = 'simulation-tick', @@ -282,10 +283,18 @@ export class D3SimulatorEngine extends Emitter { * This does not count as "stabilization" and won't emit any progress. */ activateSimulation() { - this.unfixNodes(); // If physics is disabled, the nodes get fixed in the callback from the initial setup (`simulation.on('end', () => {})`). + if (this._settings.isPhysicsEnabled) { + this.unfixNodes(); // If physics is disabled, the nodes get fixed in the callback from the initial setup (`simulation.on('end', () => {})`). + } else { + this.fixNodes(); + } this._simulation.alpha(this._settings.alpha.alpha).alphaTarget(this._settings.alpha.alphaTarget).restart(); } + stopSimulation() { + this._simulation.stop(); + } + setupData(data: ISimulationGraph) { this.clearData(); @@ -300,6 +309,10 @@ export class D3SimulatorEngine extends Emitter { mergeData(data: Partial) { this._initializeNewData(data); + if (!this._settings.isPhysicsEnabled) { + this.fixNodes(); + } + if (this._settings.isSimulatingOnDataUpdate) { this._updateSimulationData(); this.activateSimulation(); @@ -394,7 +407,10 @@ export class D3SimulatorEngine extends Emitter { const edgeIds = new Set(data.edgeIds); this._edges = this._edges.filter((edge) => !edgeIds.has(edge.id)); this._setNodeIndexByNodeId(); - this._updateSimulationData(); + if (this._settings.isSimulatingOnDataUpdate) { + this._updateSimulationData(); + this.activateSimulation(); + } } /** diff --git a/src/simulator/layout/layout.ts b/src/simulator/layout/layout.ts index defe2bc..e666e4f 100644 --- a/src/simulator/layout/layout.ts +++ b/src/simulator/layout/layout.ts @@ -1,29 +1,43 @@ import { IEdgeBase } from '../../models/edge'; import { INode, INodeBase, INodePosition } from '../../models/node'; -import { CircleLayout } from './layouts/circle'; +import { CircularLayout, ICircularLayoutOptions } from './layouts/circular'; +import { IForceLayoutOptions } from './layouts/force'; +import { GridLayout, IGridLayoutOptions } from './layouts/grid'; +import { HierarchicalLayout, IHierarchicalLayoutOptions } from './layouts/hierarchical'; -export enum layouts { - DEFAULT = 'default', - CIRCLE = 'circle', +export type LayoutType = 'circular' | 'force' | 'grid' | 'hierarchical'; + +export type LayoutSettingsMap = { + circular: ICircularLayoutOptions; + force: IForceLayoutOptions; + grid: IGridLayoutOptions; + hierarchical: IHierarchicalLayoutOptions; +}; + +export interface ILayoutSettings { + type: LayoutType; + options?: LayoutSettingsMap[LayoutType]; } export interface ILayout { - getPositions(nodes: INode[], width: number, height: number): INodePosition[]; + getPositions(nodes: INode[]): INodePosition[]; } -export class Layout implements ILayout { - private readonly _layout: ILayout | null; - - private layoutByLayoutName: Record | null> = { - [layouts.DEFAULT]: null, - [layouts.CIRCLE]: new CircleLayout(), - }; - - constructor(layoutName: string) { - this._layout = this.layoutByLayoutName[layoutName]; - } - - getPositions(nodes: INode[], width: number, height: number): INodePosition[] { - return this._layout === null ? [] : this._layout.getPositions(nodes, width, height); +export class LayoutFactory { + static create( + settings?: Partial, + ): ILayout | undefined { + switch (settings?.type) { + case 'circular': + return new CircularLayout(settings.options as ICircularLayoutOptions); + case 'force': + return undefined; + case 'grid': + return new GridLayout(settings.options as IGridLayoutOptions); + case 'hierarchical': + return new HierarchicalLayout(settings.options as IHierarchicalLayoutOptions); + default: + throw new Error('Incorrect layout type.'); + } } } diff --git a/src/simulator/layout/layouts/circle.ts b/src/simulator/layout/layouts/circle.ts deleted file mode 100644 index b601d78..0000000 --- a/src/simulator/layout/layouts/circle.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { IEdgeBase } from '../../../models/edge'; -import { INode, INodeBase, INodePosition } from '../../../models/node'; -import { ILayout } from '../layout'; - -export class CircleLayout implements ILayout { - getPositions(nodes: INode[], width: number, height: number): INodePosition[] { - return nodes.map((node, index) => { - return { id: node.id, x: width / 2, y: height - index * 10 }; - }); - } -} diff --git a/src/simulator/layout/layouts/circular.ts b/src/simulator/layout/layouts/circular.ts new file mode 100644 index 0000000..693d9a0 --- /dev/null +++ b/src/simulator/layout/layouts/circular.ts @@ -0,0 +1,37 @@ +import { IEdgeBase } from '../../../models/edge'; +import { INode, INodeBase, INodePosition } from '../../../models/node'; +import { ILayout } from '../layout'; + +export interface ICircularLayoutOptions { + radius?: number; + centerX?: number; + centerY?: number; +} + +export const DEFAULT_CIRCULAR_LAYOUT_OPTIONS: Required = { + radius: 100, + centerX: 0, + centerY: 0, +}; + +export class CircularLayout implements ILayout { + private _config: Required; + + constructor(options?: ICircularLayoutOptions) { + this._config = { ...DEFAULT_CIRCULAR_LAYOUT_OPTIONS, ...options }; + } + + getPositions(nodes: INode[]): INodePosition[] { + const angleStep = (2 * Math.PI) / nodes.length; + + const positions = nodes.map((node, index) => { + return { + id: node.id, + x: this._config.centerX + this._config.radius * Math.cos(angleStep * index), + y: this._config.centerY + this._config.radius * Math.sin(angleStep * index), + }; + }); + + return positions; + } +} diff --git a/src/simulator/layout/layouts/force.ts b/src/simulator/layout/layouts/force.ts new file mode 100644 index 0000000..29edc22 --- /dev/null +++ b/src/simulator/layout/layouts/force.ts @@ -0,0 +1,11 @@ +export interface IForceLayoutOptions { + centerX?: number; + centerY?: number; + nodeDistance?: number; +} + +export const DEFAULT_FORCE_LAYOUT_OPTIONS: Required = { + centerX: 0, + centerY: 0, + nodeDistance: 50, +}; diff --git a/src/simulator/layout/layouts/grid.ts b/src/simulator/layout/layouts/grid.ts new file mode 100644 index 0000000..e48470b --- /dev/null +++ b/src/simulator/layout/layouts/grid.ts @@ -0,0 +1,38 @@ +import { IEdgeBase } from '../../../models/edge'; +import { INode, INodeBase, INodePosition } from '../../../models/node'; +import { ILayout } from '../layout'; + +export interface IGridLayoutOptions { + rowGap?: number; + colGap?: number; +} + +export const DEFAULT_GRID_LAYOUT_OPTIONS: Required = { + rowGap: 50, + colGap: 50, +}; + +export class GridLayout implements ILayout { + private _config: Required; + + constructor(options?: IGridLayoutOptions) { + this._config = { ...DEFAULT_GRID_LAYOUT_OPTIONS, ...options }; + } + + getPositions(nodes: INode[]): INodePosition[] { + const rows = Math.ceil(Math.sqrt(nodes.length)); + const cols = Math.ceil(nodes.length / rows); + + const positions: INodePosition[] = []; + + for (let i = 0; i < nodes.length; i++) { + const row = Math.floor(i / cols); + const col = i % cols; + const x = col * this._config.colGap; + const y = row * this._config.rowGap; + positions.push({ id: nodes[i].getId(), x, y }); + } + + return positions; + } +} diff --git a/src/simulator/layout/layouts/hierarchical.ts b/src/simulator/layout/layouts/hierarchical.ts new file mode 100644 index 0000000..777c1f1 --- /dev/null +++ b/src/simulator/layout/layouts/hierarchical.ts @@ -0,0 +1,163 @@ +import { IEdge, IEdgeBase } from '../../../models/edge'; +import { INode, INodeBase, INodePosition } from '../../../models/node'; +import { ILayout } from '../layout'; + +export type HierarchicalLayoutOrientation = 'horizontal' | 'vertical'; + +export interface IHierarchicalLayoutOptions { + nodeGap?: number; + levelGap?: number; + treeGap?: number; + orientation?: HierarchicalLayoutOrientation; + reversed?: boolean; +} + +export const DEFAULT_HIERARCHICAL_LAYOUT_OPTIONS: Required = { + nodeGap: 50, + levelGap: 50, + treeGap: 100, + orientation: 'vertical', + reversed: false, +}; + +export class HierarchicalLayout implements ILayout { + private _config: Required; + + constructor(options?: IHierarchicalLayoutOptions) { + this._config = { ...DEFAULT_HIERARCHICAL_LAYOUT_OPTIONS, ...options }; + } + + getPositions(nodes: INode[]): INodePosition[] { + const components = this.getConnectedComponents(nodes); + const positions: INodePosition[] = new Array(nodes.length); + let maxX = 0; + let maxHeight = 0; + let counter = 0; + + for (let i = 0; i < components.length; i++) { + const levels: Map[]> = this.assignLevels(components[i]); + const maxLevelSize = Math.max(...Array.from(levels.values()).map((levelNodes) => levelNodes.length)); + + if (levels.size * this._config.levelGap > maxHeight) { + maxHeight = levels.size * this._config.levelGap; + } + + let offsetX = i === 0 ? 0 : this._config.treeGap + maxX; + + if (i > 0) { + offsetX += ((maxLevelSize - 1) * this._config.nodeGap) / 2; + } + + for (let j = 0; j < levels.size; j++) { + const y = j * this._config.levelGap; + const level = levels.get(j); + if (!level) { + continue; + } + + const width = level.length * this._config.nodeGap; + + for (let k = 0; k < level.length; k++) { + const node = level[k]; + const x = width / 2 - k * this._config.nodeGap + offsetX; + if (x > maxX) { + maxX = x; + } + + positions[counter++] = { + id: node.getId(), + x: this._config.orientation === 'horizontal' ? y : x, + y: this._config.orientation === 'horizontal' ? x : y, + }; + } + } + } + + if (this._config.reversed === true) { + positions.forEach((position) => { + if (this._config.orientation === 'horizontal' && position.x !== undefined) { + position.x = maxX - position.x; + } + if (this._config.orientation === 'vertical' && position.y !== undefined) { + position.y = maxHeight - position.y; + } + }); + } + + return positions; + } + + getConnectedComponents = (nodes: INode[]): INode[][] => { + const visited = new Set>(); + const components: INode[][] = []; + + for (let i = 0; i < nodes.length; i++) { + if (visited.has(nodes[i])) { + continue; + } + + const component: INode[] = []; + const queue: INode[] = [nodes[i]]; + visited.add(nodes[i]); + + while (queue.length > 0) { + const current = queue.pop(); + + if (current) { + component.push(current); + const neighbors = current.getAdjacentNodes(); + for (let j = 0; j < neighbors.length; j++) { + if (visited.has(neighbors[j])) { + continue; + } + + visited.add(neighbors[j]); + queue.push(neighbors[j]); + } + } + } + + components.push(component); + } + + return components; + }; + + assignLevels = (nodes: INode[]): Map[]> => { + const levels = new Map[]>(); + const visited = new Set>(); + + let root = nodes.filter((node) => this.getExternalInEdges(node).length === 0)[0]; + + if (!root) { + root = nodes.sort((a, b) => this.getExternalInEdges(a).length - this.getExternalInEdges(b).length)[0]; + } + + const queue: [INode, number][] = [[root, 0]]; + + for (const [node, level] of queue) { + if (visited.has(node)) { + continue; + } + + visited.add(node); + if (levels.has(level)) { + levels.get(level)?.push(node); + } else { + levels.set(level, [node]); + } + + const neighbors = node.getAdjacentNodes(); + + for (let i = 0; i < neighbors.length; i++) { + queue.push([neighbors[i], level + 1]); + } + } + + return levels; + }; + + getExternalInEdges = (node: INode): IEdge[] => { + return node.getInEdges().filter((edge) => edge.startNode.id !== edge.endNode.id); + }; +} diff --git a/src/simulator/shared.ts b/src/simulator/shared.ts index 7501367..b1190de 100644 --- a/src/simulator/shared.ts +++ b/src/simulator/shared.ts @@ -64,6 +64,7 @@ export interface ISimulator extends IEmitter { // Simulation handlers simulate(): void; activateSimulation(): void; + stopSimulation(): void; // Node handlers startDragNode(): void; diff --git a/src/simulator/types/main-thread-simulator.ts b/src/simulator/types/main-thread-simulator.ts index 1bbc36c..b560b33 100644 --- a/src/simulator/types/main-thread-simulator.ts +++ b/src/simulator/types/main-thread-simulator.ts @@ -73,6 +73,10 @@ export class MainThreadSimulator extends Emitter implements ISi this._simulator.activateSimulation(); } + stopSimulation() { + this._simulator.stopSimulation(); + } + startDragNode() { this._simulator.startDragNode(); } diff --git a/src/simulator/types/web-worker-simulator/message/worker-input.ts b/src/simulator/types/web-worker-simulator/message/worker-input.ts index 5d28a74..c252d4a 100644 --- a/src/simulator/types/web-worker-simulator/message/worker-input.ts +++ b/src/simulator/types/web-worker-simulator/message/worker-input.ts @@ -19,6 +19,7 @@ export enum WorkerInputType { Simulate = 'Simulate', ActivateSimulation = 'Activate Simulation', UpdateSimulation = 'Update Simulation', + StopSimulation = 'Stop Simulation', // Node dragging message types StartDragNode = 'Start Drag Node', @@ -77,6 +78,8 @@ type IWorkerInputSimulatePayload = IWorkerPayload; type IWorkerInputActivateSimulationPayload = IWorkerPayload; +type IWorkerInputStopSimulationPayload = IWorkerPayload; + type IWorkerInputUpdateSimulationPayload = IWorkerPayload< WorkerInputType.UpdateSimulation, { @@ -121,6 +124,7 @@ export type IWorkerInputPayload = | IWorkerInputClearDataPayload | IWorkerInputSimulatePayload | IWorkerInputActivateSimulationPayload + | IWorkerInputStopSimulationPayload | IWorkerInputUpdateSimulationPayload | IWorkerInputStartDragNodePayload | IWorkerInputDragNodePayload diff --git a/src/simulator/types/web-worker-simulator/simulator.worker.ts b/src/simulator/types/web-worker-simulator/simulator.worker.ts index d0d76a2..f07da1d 100644 --- a/src/simulator/types/web-worker-simulator/simulator.worker.ts +++ b/src/simulator/types/web-worker-simulator/simulator.worker.ts @@ -41,6 +41,11 @@ addEventListener('message', ({ data }: MessageEvent) => { break; } + case WorkerInputType.StopSimulation: { + simulator.stopSimulation(); + break; + } + case WorkerInputType.SetupData: { simulator.setupData(data.data); break; diff --git a/src/simulator/types/web-worker-simulator/web-worker-simulator.ts b/src/simulator/types/web-worker-simulator/web-worker-simulator.ts index 02f35ea..005d043 100644 --- a/src/simulator/types/web-worker-simulator/web-worker-simulator.ts +++ b/src/simulator/types/web-worker-simulator/web-worker-simulator.ts @@ -104,6 +104,10 @@ export class WebWorkerSimulator extends Emitter implements ISim this.emitToWorker({ type: WorkerInputType.ActivateSimulation }); } + stopSimulation() { + this.emitToWorker({ type: WorkerInputType.StopSimulation }); + } + updateSimulation(nodes: ISimulationNode[], edges: ISimulationEdge[]) { this.emitToWorker({ type: WorkerInputType.UpdateSimulation, data: { nodes, edges } }); } diff --git a/src/views/orb-view.ts b/src/views/orb-view.ts index 3b5711a..16ea79d 100644 --- a/src/views/orb-view.ts +++ b/src/views/orb-view.ts @@ -13,7 +13,12 @@ import { INode, INodeBase, isNode } from '../models/node'; import { IEdge, IEdgeBase, isEdge } from '../models/edge'; import { IOrbView } from './shared'; import { DefaultEventStrategy, IEventStrategy, IEventStrategySettings } from '../models/strategy'; -import { ID3SimulatorEngineSettings } from '../simulator/engine/d3-simulator-engine'; +import { + DEFAULT_SETTINGS, + ID3SimulatorEngineSettings, + ID3SimulatorEngineSettingsCentering, + ID3SimulatorEngineSettingsLinks, +} from '../simulator/engine/d3-simulator-engine'; import { copyObject } from '../utils/object.utils'; import { OrbEmitter, OrbEventType } from '../events'; import { IRenderer, RenderEventType, IRendererSettingsInit, IRendererSettings } from '../renderer/shared'; @@ -22,6 +27,8 @@ import { SimulatorEventType } from '../simulator/shared'; import { getDefaultGraphStyle } from '../models/style'; import { isBoolean } from '../utils/type.utils'; import { IObserver, IObserverDataPayload } from '../utils/observer.utils'; +import { ILayoutSettings, LayoutFactory } from '../simulator/layout/layout'; +import { DEFAULT_FORCE_LAYOUT_OPTIONS } from '../simulator/layout/layouts/force'; export interface IGraphInteractionSettings { isDragEnabled: boolean; @@ -34,6 +41,7 @@ export interface IOrbViewSettings { render: Partial; strategy: Partial; interaction: Partial; + layout: Partial; zoomFitTransitionMs: number; isOutOfBoundsDragEnabled: boolean; areCoordinatesRounded: boolean; @@ -72,6 +80,10 @@ export class OrbView implements IOrbVi isPhysicsEnabled: false, ...settings?.simulation, }, + layout: { + type: 'force', + ...settings?.layout, + }, render: { ...settings?.render, }, @@ -149,36 +161,30 @@ export class OrbView implements IOrbVi .on('dblclick.zoom', this.mouseDoubleClicked); this._simulator = SimulatorFactory.getSimulator(); - this._simulator.on(SimulatorEventType.SIMULATION_START, () => { - // this._isSimulating = true; - this._simulationStartedAt = Date.now(); - this._events.emit(OrbEventType.SIMULATION_START, undefined); - }); - this._simulator.on(SimulatorEventType.SIMULATION_PROGRESS, (data) => { - this._graph.setNodePositions(data.nodes); - this._events.emit(OrbEventType.SIMULATION_STEP, { progress: data.progress }); - this.render(); - }); - this._simulator.on(SimulatorEventType.SIMULATION_END, (data) => { - this._graph.setNodePositions(data.nodes); - this.render(); - // this._isSimulating = false; - this._onSimulationEnd?.(); - this._onSimulationEnd = undefined; - this._events.emit(OrbEventType.SIMULATION_END, { durationMs: Date.now() - this._simulationStartedAt }); - }); - this._simulator.on(SimulatorEventType.SIMULATION_STEP, (data) => { - this._graph.setNodePositions(data.nodes); - this.render(); - }); - this._simulator.on(SimulatorEventType.NODE_DRAG, (data) => { - this._graph.setNodePositions(data.nodes); - this.render(); - }); - this._simulator.on(SimulatorEventType.SETTINGS_UPDATE, (data) => { - this._settings.simulation = data.settings; - }); + if (this._settings.layout.type === 'force') { + this._enableSimulation(); + } + + if (this._settings.layout.options) { + const _options = { + ...DEFAULT_FORCE_LAYOUT_OPTIONS, + ...this._settings.layout.options, + }; + + this._settings.simulation.centering = { + ...(DEFAULT_SETTINGS.centering as Required), + ...this._settings.simulation.centering, + x: _options.centerX, + y: _options.centerY, + }; + + this._settings.simulation.links = { + ...(DEFAULT_SETTINGS.links as Required), + ...this._settings.simulation.links, + distance: _options.nodeDistance, + }; + } this._simulator.setSettings(this._settings.simulation); // TODO(dlozic): Optimize crud operations here. @@ -193,6 +199,9 @@ export class OrbView implements IOrbVi const nodePositions = this._graph.getNodePositions(); const edgePositions = this._graph.getEdgePositions(); // this._onSimulationEnd = onRendered; + if (this._settings.layout) { + this._graph.setLayout(LayoutFactory.create(this._settings.layout)); + } this._simulator.setupData({ nodes: nodePositions, edges: edgePositions }); }, onMergeData: (data) => { @@ -203,10 +212,12 @@ export class OrbView implements IOrbVi this._assignPositions(this._graph.getNodes(nodeFilter)); - const nodePositions = this._graph.getNodePositions(nodeFilter); - const edgePositions = this._graph.getEdgePositions(edgeFilter); + if (this._settings.layout.type === 'force') { + const nodePositions = this._graph.getNodePositions(nodeFilter); + const edgePositions = this._graph.getEdgePositions(edgeFilter); - this._simulator.mergeData({ nodes: nodePositions, edges: edgePositions }); + this._simulator.mergeData({ nodes: nodePositions, edges: edgePositions }); + } }, onRemoveData: (data) => { this._simulator.deleteData(data); @@ -244,6 +255,37 @@ export class OrbView implements IOrbVi this._settings.render = this._renderer.getSettings(); } + if (settings.layout) { + const shouldRecenter = this._settings.layout.type !== settings.layout.type; + this._settings.layout = { + ...this._settings.layout, + ...settings.layout, + }; + + this._graph.setLayout(LayoutFactory.create(this._settings.layout)); + + const nodePositions = this._graph.getNodePositions(); + const edgePositions = this._graph.getEdgePositions(); + + this._simulator.setupData({ nodes: nodePositions, edges: edgePositions }); + + if (this._settings.layout.type === 'force') { + this._enableSimulation(); + this._simulator.releaseNodes(); + } else { + this._disableSimulation(); + this._simulator.clearData(); + } + + if (shouldRecenter) { + this._simulator.once(SimulatorEventType.SIMULATION_END, () => { + this.recenter(); + }); + } + + this.render(); + } + if (settings.strategy) { if (isBoolean(settings.strategy.isDefaultHoverEnabled)) { this._settings.strategy.isDefaultHoverEnabled = settings.strategy.isDefaultHoverEnabled; @@ -604,6 +646,74 @@ export class OrbView implements IOrbVi this.render(); }; + private _enableSimulation = () => { + this._simulator.on(SimulatorEventType.SIMULATION_START, () => { + // this._isSimulating = true; + this._simulationStartedAt = Date.now(); + this._events.emit(OrbEventType.SIMULATION_START, undefined); + }); + this._simulator.on(SimulatorEventType.SIMULATION_PROGRESS, (data) => { + this._graph.setNodePositions(data.nodes); + this._events.emit(OrbEventType.SIMULATION_STEP, { progress: data.progress }); + this.render(); + }); + this._simulator.on(SimulatorEventType.SIMULATION_END, (data) => { + this._graph.setNodePositions(data.nodes); + this.render(); + // this._isSimulating = false; + this._onSimulationEnd?.(); + this._onSimulationEnd = undefined; + this._events.emit(OrbEventType.SIMULATION_END, { durationMs: Date.now() - this._simulationStartedAt }); + }); + this._simulator.on(SimulatorEventType.SIMULATION_STEP, (data) => { + this._graph.setNodePositions(data.nodes); + this.render(); + }); + this._simulator.on(SimulatorEventType.NODE_DRAG, (data) => { + this._graph.setNodePositions(data.nodes); + this.render(); + }); + this._simulator.on(SimulatorEventType.SETTINGS_UPDATE, (data) => { + this._settings.simulation = data.settings; + }); + + this._simulator.activateSimulation(); + }; + + private _disableSimulation = () => { + this._simulator.off(SimulatorEventType.SIMULATION_START, () => { + // this._isSimulating = true; + this._simulationStartedAt = Date.now(); + this._events.emit(OrbEventType.SIMULATION_START, undefined); + }); + this._simulator.off(SimulatorEventType.SIMULATION_PROGRESS, (data) => { + this._graph.setNodePositions(data.nodes); + this._events.emit(OrbEventType.SIMULATION_STEP, { progress: data.progress }); + this.render(); + }); + this._simulator.off(SimulatorEventType.SIMULATION_END, (data) => { + this._graph.setNodePositions(data.nodes); + this.render(); + // this._isSimulating = false; + this._onSimulationEnd?.(); + this._onSimulationEnd = undefined; + this._events.emit(OrbEventType.SIMULATION_END, { durationMs: Date.now() - this._simulationStartedAt }); + }); + this._simulator.off(SimulatorEventType.SIMULATION_STEP, (data) => { + this._graph.setNodePositions(data.nodes); + this.render(); + }); + this._simulator.off(SimulatorEventType.NODE_DRAG, (data) => { + this._graph.setNodePositions(data.nodes); + this.render(); + }); + this._simulator.off(SimulatorEventType.SETTINGS_UPDATE, (data) => { + this._settings.simulation = data.settings; + }); + + this._simulator.stopSimulation(); + }; + // TODO: Do we keep these fixNodes() { this._simulator.fixNodes(); From 572be3fdcc5ede50d37f5f540ff0d6f2fef42a75 Mon Sep 17 00:00:00 2001 From: Oleksandr Ichenskyi <55350107+AlexIchenskiy@users.noreply.github.com> Date: Thu, 5 Mar 2026 10:47:35 +0100 Subject: [PATCH 22/30] Fix: Change layout engine logic (#108) * Fix: Change layout engine logic * New: Add simulation cancellation logic * Chore: Remove leftover code * Fix: Hierarchical layout recenter logic * Chore: Refactor package versions and code logic * Fix: Refactor function types --- .eslintrc | 4 +- docs/view-default.md | 145 +- package-lock.json | 3906 +++++++++++------ package.json | 18 +- src/models/graph.ts | 21 - src/models/interaction.ts | 67 + src/models/strategy.ts | 122 +- src/renderer/canvas/canvas-renderer.ts | 18 +- src/renderer/shared.ts | 7 +- src/simulator/engine/d3-simulator-engine.ts | 728 --- .../engine/engines/base-layout-engine.ts | 61 + .../engines/dynamic/force-layout-engine.ts | 506 +++ .../engines/static/circular-layout-engine.ts | 49 + .../engines/static/grid-layout-engine.ts | 53 + .../static/hierarchical-layout-engine.ts | 220 + .../engines/static/static-layout-engine.ts | 233 + src/simulator/engine/factory.ts | 29 + src/simulator/engine/shared.ts | 203 + src/simulator/factory.ts | 9 +- src/simulator/index.ts | 2 + src/simulator/layout/layout.ts | 43 - src/simulator/layout/layouts/circular.ts | 37 - src/simulator/layout/layouts/force.ts | 11 - src/simulator/layout/layouts/grid.ts | 38 - src/simulator/layout/layouts/hierarchical.ts | 163 - src/simulator/shared.ts | 9 +- src/simulator/types/main-thread-simulator.ts | 107 +- .../message/worker-input.ts | 9 +- .../message/worker-output.ts | 4 +- .../web-worker-simulator/simulator.worker.ts | 150 +- .../web-worker-simulator.ts | 25 +- src/utils/function.utils.ts | 32 +- src/utils/graph.utils.ts | 145 + src/utils/object.utils.ts | 2 +- src/views/orb-map-view.ts | 12 +- src/views/orb-view.ts | 190 +- src/views/shared.ts | 2 + 37 files changed, 4404 insertions(+), 2976 deletions(-) create mode 100644 src/models/interaction.ts delete mode 100644 src/simulator/engine/d3-simulator-engine.ts create mode 100644 src/simulator/engine/engines/base-layout-engine.ts create mode 100644 src/simulator/engine/engines/dynamic/force-layout-engine.ts create mode 100644 src/simulator/engine/engines/static/circular-layout-engine.ts create mode 100644 src/simulator/engine/engines/static/grid-layout-engine.ts create mode 100644 src/simulator/engine/engines/static/hierarchical-layout-engine.ts create mode 100644 src/simulator/engine/engines/static/static-layout-engine.ts create mode 100644 src/simulator/engine/factory.ts create mode 100644 src/simulator/engine/shared.ts delete mode 100644 src/simulator/layout/layout.ts delete mode 100644 src/simulator/layout/layouts/circular.ts delete mode 100644 src/simulator/layout/layouts/force.ts delete mode 100644 src/simulator/layout/layouts/grid.ts delete mode 100644 src/simulator/layout/layouts/hierarchical.ts create mode 100644 src/utils/graph.utils.ts diff --git a/.eslintrc b/.eslintrc index a2f3666..0f31eb6 100644 --- a/.eslintrc +++ b/.eslintrc @@ -33,7 +33,8 @@ { "singleQuote": true, "trailingComma": "all", - "printWidth": 120 + "printWidth": 120, + "endOfLine": "auto" } ], "brace-style": ["error", "1tbs"], @@ -52,6 +53,7 @@ ], "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/no-unsafe-function-type": "off", "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/ban-types": "off", "jest/no-standalone-expect": "off", diff --git a/docs/view-default.md b/docs/view-default.md index 56e14d1..34b7659 100644 --- a/docs/view-default.md +++ b/docs/view-default.md @@ -109,42 +109,49 @@ The default settings that `OrbView` uses is: ```typescript const defaultSettings = { - simulation: { - isPhysicsEnabled: false; - alpha: { - alpha: 1, - alphaMin: 0.001, - alphaDecay: 0.0228, - alphaTarget: 0.1, - }, - centering: { - x: 0, - y: 0, - strength: 1, - }, - collision: { - radius: 15, - strength: 1, - iterations: 1, - }, - links: { - distance: 30, - iterations: 1, - }, - manyBody: { - strength: -100, - theta: 0.9, - distanceMin: 0, - distanceMax: 3000, - }, - positioning: { - forceX: { - x: 0, - strength: 0.1, + layout: { + type: 'force', + options: { + isPhysicsEnabled: false, + isSimulatingOnDataUpdate: true, + isSimulatingOnSettingsUpdate: true, + isSimulatingOnUnstick: true, + alpha: { + alpha: 1, + alphaMin: 0.001, + alphaDecay: 0.0228, + alphaTarget: 0, }, - forceY: { + centering: { + x: 0, y: 0, - strength: 0.1, + strength: 1, + }, + collision: { + radius: 15, + strength: 1, + iterations: 1, + }, + links: { + distance: DEFAULT_LINK_DISTANCE, + strength: 1, + iterations: 1, + }, + manyBody: { + strength: -100, + theta: 0.9, + distanceMin: 0, + distanceMax: getManyBodyMaxDistance(DEFAULT_LINK_DISTANCE), + }, + positioning: { + forceX: { + x: 0, + strength: 0.1, + }, + forceY: { + y: 0, + strength: 0.1, + }, }, }, }, @@ -168,13 +175,13 @@ const defaultSettings = { isDefaultHoverEnabled: true, }, interaction: { - isDragEnabled: true; - isZoomEnabled: true; + isDragEnabled: true, + isZoomEnabled: true, }, zoomFitTransitionMs: 200, isOutOfBoundsDragEnabled: false, areCoordinatesRounded: true, - areCollapsedContainerDimensionsAllowed: false; + areCollapsedContainerDimensionsAllowed: false, } ``` @@ -189,13 +196,6 @@ There are two basic ways to use the `OrbView` API based on the node positions: - **Fixed coordinates** - You provide node coordinates through the `getPosition()` callback function. -#### Simulated node positions - -In this mode, the `OrbView` arranges node positions by internally calculating their -coordinates using the [D3.js](https://d3js.org/) library, or more specifically, -[`d3-force`](https://github.com/d3/d3-force). This method is applied by default - you don't -need to initialize Orb with any additional configuration. - ![](./assets/view-default-simulated.png) ```typescript @@ -278,14 +278,20 @@ Here you can use your original properties to indicate which ones represent your ### Property `layout` -If you want to use one of the predefined layouts (hierarchical (tree), grid, circular...) you can specify -the optional property `layout`. Simulation physics are ignored when a layout is applied. There is no layout -applied by default. +The optional property `layout` controls how graph nodes are positioned. You can choose between +a physics-based force layout or one of the predefined static layouts (hierarchical (tree), grid, +circular). The default layout is `force`. #### Property `type` You can specify the desired layout using the `type` property that can have one of the following values: +- `force` - fine-grained [D3.js](https://d3js.org/) simulation engine settings. They include `isPhysicsEnabled`, `alpha`, +`centering`, `collision`, `links`, `manyBody`, and `positioning`. You can use `isPhysicsEnabled` +to enable or disable physics. You can read more about the other settings on the official +[`d3-force docs`](https://github.com/d3/d3-force). This may be condensed into fewer, more abstract +settings in the future + - `hierarchical` - a tree-like layout style that tries to portrait graph nodes in a hierarchy - `circular` - arranges the nodes of the graph in a circle @@ -304,6 +310,43 @@ Each layout type has its own option list you can tweak in order to change the la - `circular` - `radius` - Radius of the circle in relativa units. +- `grid` + - `rowGap` - The gap between rows of nodes. Default `50`. + - `colGap` - The gap between columns of nodes. Default `50`. + +- `force` + - `isPhysicsEnabled` - Enables or disables continuous physics simulation. Disabled by default (`false`). + - `isSimulatingOnDataUpdate` - Whether to run simulation when graph data is updated. Enabled by default (`true`). + - `isSimulatingOnSettingsUpdate` - Whether to re-run simulation when settings are updated. Enabled by default (`true`). + - `isSimulatingOnUnstick` - Whether to re-run simulation when a node is unstuck. Enabled by default (`true`). + - `alpha` - Fine-grained control over the simulation's annealing process. + - `alpha` - Current alpha value. Default `1`. + - `alphaMin` - Minimum alpha threshold below which simulation stops. Default `0.001`. + - `alphaDecay` - Rate at which alpha decreases over time. Default `0.0228`. + - `alphaTarget` - Target alpha the simulation converges toward. Default `0`. + - `centering` - Centers the graph around a point. + - `x` - X coordinate of the center. Default `0`. + - `y` - Y coordinate of the center. Default `0`. + - `strength` - Strength of the centering force. Default `1`. + - `collision` - Prevents nodes from overlapping. + - `radius` - Collision radius per node. Default `15`. + - `strength` - Strength of the collision force. Default `1`. + - `iterations` - Number of iterations per tick. Default `1`. + - `links` - Controls the length and rigidity of edges. + - `distance` - Desired distance between linked nodes. + - `strength` - Strength of the link force. Default `1`. + - `iterations` - Number of iterations per tick. Default `1`. + - `manyBody` - Simulates attraction or repulsion between all nodes. + - `strength` - Negative values repel, positive attract. Default `-100`. + - `theta` - Barnes-Hut approximation parameter. Default `0.9`. + - `distanceMin` - Minimum distance between nodes. Default `0`. + - `distanceMax` - Maximum distance over which force applies. + - `positioning` - Applies independent forces along each axis. + - `forceX.x` - Target X position. Default `0`. + - `forceX.strength` - Strength of the X positioning force. Default `0.1`. + - `forceY.y` - Target Y position. Default `0`. + - `forceY.strength` - Strength of the Y positioning force. Default `0.1`. + ### Property `render` Optional property `render` has several rendering options that you can tweak. Read more about them @@ -398,14 +441,6 @@ These properties provide a straightforward way to enable or disable dragging and orb.setSettings({ interaction: { isDragEnabled: false, isZoomEnabled: true } }); ``` -### Property `simulation` - -Fine-grained D3 simulation engine settings. They include `isPhysicsEnabled`, `alpha`, -`centering`, `collision`, `links`, `manyBody`, and `positioning`. You can use `isPhysicsEnabled` -to enable or disable physics. You can read more about the other settings on the official -[`d3-force docs`](https://github.com/d3/d3-force). This may be condensed into fewer, more abstract -settings in the future. - ### Property `zoomFitTransitionMs` Use this property to adjust the transition time when re-centering the graph. Defaults to `200ms`. diff --git a/package-lock.json b/package-lock.json index aacbcc3..ac11942 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,27 +31,27 @@ "@types/jest": "29.5.12", "@types/leaflet": "1.7.9", "@types/resize-observer-browser": "^0.1.7", - "@typescript-eslint/eslint-plugin": "5.24.0", - "@typescript-eslint/parser": "5.24.0", + "@typescript-eslint/eslint-plugin": "8.56.1", + "@typescript-eslint/parser": "8.56.1", "conventional-changelog-eslint": "3.0.9", "copy-webpack-plugin": "^11.0.0", - "eslint": "8.15.0", + "eslint": "8.57.0", "eslint-config-google": "0.14.0", "eslint-config-prettier": "8.5.0", - "eslint-plugin-jest": "26.2.2", - "eslint-plugin-prettier": "4.0.0", + "eslint-plugin-jest": "29.15.0", + "eslint-plugin-prettier": "5.5.5", "http-server": "^14.1.1", "husky": "^8.0.1", "jest": "29.7.0", - "prettier": "^2.7.1", + "prettier": "3.8.1", "semantic-release": "19.0.3", "ts-jest": "29.1.2", "ts-loader": "^9.3.1", - "ts-node": "10.8.0", - "typescript": "4.6.3", + "ts-node": "10.9.2", + "typescript": "5.9.3", "webpack": "^5.73.0", "webpack-cli": "^4.10.0", - "webpack-dev-server": "^4.9.3" + "webpack-dev-server": "5.2.0" }, "engines": { "node": ">=18.0.0" @@ -71,89 +71,20 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", @@ -356,19 +287,21 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -383,109 +316,28 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "@babel/types": "^7.29.0" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -671,14 +523,15 @@ } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "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==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -715,14 +568,14 @@ } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -880,15 +733,6 @@ "node": ">=v14" } }, - "node_modules/@commitlint/load/node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/@commitlint/load/node_modules/cosmiconfig": { "version": "8.1.3", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", @@ -907,62 +751,6 @@ "url": "https://github.com/sponsors/d-fischer" } }, - "node_modules/@commitlint/load/node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/@commitlint/load/node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, "node_modules/@commitlint/message": { "version": "17.0.0", "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.0.0.tgz", @@ -1098,16 +886,46 @@ "node": ">=10.0.0" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", + "espree": "^9.6.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -1116,13 +934,17 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/eslintrc/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", @@ -1138,36 +960,65 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" @@ -1199,10 +1050,11 @@ } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -1553,17 +1405,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz", - "integrity": "sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, "node_modules/@jridgewell/resolve-uri": { @@ -1575,46 +1424,471 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { + "node_modules/@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, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsonjoy.com/base64": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=6.0.0" + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", - "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", + "node_modules/@jsonjoy.com/buffers": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.67.0.tgz", + "integrity": "sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/codegen": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-1.0.0.tgz", + "integrity": "sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==", "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-core": { + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.56.11.tgz", + "integrity": "sha512-wThHjzUp01ImIjfCwhs+UnFkeGPFAymwLEkOtenHewaKe2pTP12p6r1UuwikA9NEvNf9Vlck92r8fb8n/MWM5w==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jsonjoy.com/fs-node-builtins": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.56.11", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "node_modules/@jsonjoy.com/fs-fsa": { + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.56.11.tgz", + "integrity": "sha512-ZYlF3XbMayyp97xEN8ZvYutU99PCHjM64mMZvnCseXkCJXJDVLAwlF8Q/7q/xiWQRsv3pQBj1WXHd9eEyYcaCQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.56.11", + "@jsonjoy.com/fs-node-builtins": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.56.11", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "node_modules/@jsonjoy.com/fs-node": { + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.56.11.tgz", + "integrity": "sha512-D65YrnP6wRuZyEWoSFnBJSr5zARVpVBGctnhie4rCsMuGXNzX7IHKaOt85/Aj7SSoG1N2+/xlNjWmkLvZ2H3Tg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.56.11", + "@jsonjoy.com/fs-node-builtins": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.56.11", + "@jsonjoy.com/fs-print": "4.56.11", + "@jsonjoy.com/fs-snapshot": "4.56.11", + "glob-to-regex.js": "^1.0.0", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-builtins": { + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.56.11.tgz", + "integrity": "sha512-CNmt3a0zMCIhniFLXtzPWuUxXFU+U+2VyQiIrgt/rRVeEJNrMQUABaRbVxR0Ouw1LyR9RjaEkPM6nYpED+y43A==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-to-fsa": { + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.56.11.tgz", + "integrity": "sha512-5OzGdvJDgZVo+xXWEYo72u81zpOWlxlbG4d4nL+hSiW+LKlua/dldNgPrpWxtvhgyntmdFQad2UTxFyGjJAGhA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jsonjoy.com/fs-fsa": "4.56.11", + "@jsonjoy.com/fs-node-builtins": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.56.11" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-utils": { + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.56.11.tgz", + "integrity": "sha512-JADOZFDA3wRfsuxkT0+MYc4F9hJO2PYDaY66kRTG6NqGX3+bqmKu66YFYAbII/tEmQWPZeHoClUB23rtQM9UPg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.56.11" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-print": { + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.56.11.tgz", + "integrity": "sha512-rnaKRgCRIn8JGTjxhS0JPE38YM3Pj/H7SW4/tglhIPbfKEkky7dpPayNKV2qy25SZSL15oFVgH/62dMZ/z7cyA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-utils": "4.56.11", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot": { + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.56.11.tgz", + "integrity": "sha512-IIldPX+cIRQuUol9fQzSS3hqyECxVpYMJQMqdU3dCKZFRzEl1rkIkw4P6y7Oh493sI7YdxZlKr/yWdzEWZ1wGQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^17.65.0", + "@jsonjoy.com/fs-node-utils": "4.56.11", + "@jsonjoy.com/json-pack": "^17.65.0", + "@jsonjoy.com/util": "^17.65.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/base64": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.67.0.tgz", + "integrity": "sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/codegen": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.67.0.tgz", + "integrity": "sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pack": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.67.0.tgz", + "integrity": "sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "17.67.0", + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0", + "@jsonjoy.com/json-pointer": "17.67.0", + "@jsonjoy.com/util": "17.67.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pointer": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.67.0.tgz", + "integrity": "sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/util": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/util": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.67.0.tgz", + "integrity": "sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.21.0.tgz", + "integrity": "sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "^1.1.2", + "@jsonjoy.com/buffers": "^1.2.0", + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/json-pointer": "^1.0.2", + "@jsonjoy.com/util": "^1.9.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pointer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-1.0.2.tgz", + "integrity": "sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/util": "^1.9.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.9.0.tgz", + "integrity": "sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^1.0.0", + "@jsonjoy.com/codegen": "^1.0.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true, + "license": "MIT" }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -1652,28 +1926,27 @@ } }, "node_modules/@octokit/auth-token": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.0.tgz", - "integrity": "sha512-MDNFUBcJIptB9At7HiV7VCvU3NcL4GnfCQaP8C5lrxWrRPMJBnemYtehaKSOlaM7AYxeRyj9etenu8LVpSpVaQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz", + "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==", "dev": true, - "dependencies": { - "@octokit/types": "^6.0.3" - }, + "license": "MIT", "engines": { "node": ">= 14" } }, "node_modules/@octokit/core": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.0.4.tgz", - "integrity": "sha512-sUpR/hc4Gc7K34o60bWC7WUH6Q7T6ftZ2dUmepSyJr9PRF76/qqkWjE2SOEzCqLA5W83SaISymwKtxks+96hPQ==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz", + "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", "@octokit/request": "^6.0.0", "@octokit/request-error": "^3.0.0", - "@octokit/types": "^6.0.3", + "@octokit/types": "^9.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" }, @@ -1682,12 +1955,13 @@ } }, "node_modules/@octokit/endpoint": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.0.tgz", - "integrity": "sha512-Kz/mIkOTjs9rV50hf/JK9pIDl4aGwAtT8pry6Rpy+hVXkAPhXanNQRxMoq6AeRgDCZR6t/A1zKniY2V1YhrzlQ==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz", + "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", "dev": true, + "license": "MIT", "dependencies": { - "@octokit/types": "^6.0.3", + "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" }, @@ -1696,13 +1970,14 @@ } }, "node_modules/@octokit/graphql": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.0.tgz", - "integrity": "sha512-1ZZ8tX4lUEcLPvHagfIVu5S2xpHYXAmgN0+95eAOPoaVPzCfUXJtA5vASafcpWcO86ze0Pzn30TAx72aB2aguQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", + "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/request": "^6.0.0", - "@octokit/types": "^6.0.3", + "@octokit/types": "^9.0.0", "universal-user-agent": "^6.0.0" }, "engines": { @@ -1710,18 +1985,21 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "12.10.1", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.10.1.tgz", - "integrity": "sha512-P+SukKanjFY0ZhsK6wSVnQmxTP2eVPPE8OPSNuxaMYtgVzwJZgfGdwlYjf4RlRU4vLEw4ts2fsE2icG4nZ5ddQ==", - "dev": true + "version": "18.1.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.1.1.tgz", + "integrity": "sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==", + "dev": true, + "license": "MIT" }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-3.0.0.tgz", - "integrity": "sha512-fvw0Q5IXnn60D32sKeLIxgXCEZ7BTSAjJd8cFAE6QU5qUp0xo7LjFUjjX1J5D7HgN355CN4EXE4+Q1/96JaNUA==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", + "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", "dev": true, + "license": "MIT", "dependencies": { - "@octokit/types": "^6.39.0" + "@octokit/tsconfig": "^1.0.2", + "@octokit/types": "^9.2.3" }, "engines": { "node": ">= 14" @@ -1730,40 +2008,50 @@ "@octokit/core": ">=4" } }, - "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "node_modules/@octokit/plugin-retry": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-4.1.6.tgz", + "integrity": "sha512-obkYzIgEC75r8+9Pnfiiqy3y/x1bc3QLE5B7qvv9wi9Kj0R5tGQFC6QMBg1154WQ9lAVypuQDGyp3hNpp15gQQ==", "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^9.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 14" + }, "peerDependencies": { "@octokit/core": ">=3" } }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.1.2.tgz", - "integrity": "sha512-sAfSKtLHNq0UQ2iFuI41I6m5SK6bnKFRJ5kUjDRVbmQXiRVi4aQiIcgG4cM7bt+bhSiWL4HwnTxDkWFlKeKClA==", + "node_modules/@octokit/plugin-throttling": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-5.2.3.tgz", + "integrity": "sha512-C9CFg9mrf6cugneKiaI841iG8DOv6P5XXkjmiNNut+swePxQ7RWEdAZRp5rJoE1hjsIqiYcKa/ZkOQ+ujPI39Q==", "dev": true, + "license": "MIT", "dependencies": { - "@octokit/types": "^6.40.0", - "deprecation": "^2.3.1" + "@octokit/types": "^9.0.0", + "bottleneck": "^2.15.3" }, "engines": { "node": ">= 14" }, "peerDependencies": { - "@octokit/core": ">=3" + "@octokit/core": "^4.0.0" } }, "node_modules/@octokit/request": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.0.tgz", - "integrity": "sha512-7IAmHnaezZrgUqtRShMlByJK33MT9ZDnMRgZjnRrRV9a/jzzFwKGz0vxhFU6i7VMLraYcQ1qmcAOin37Kryq+Q==", + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz", + "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", - "@octokit/types": "^6.16.1", + "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", "node-fetch": "^2.6.7", "universal-user-agent": "^6.0.0" @@ -1773,12 +2061,13 @@ } }, "node_modules/@octokit/request-error": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.0.tgz", - "integrity": "sha512-WBtpzm9lR8z4IHIMtOqr6XwfkGvMOOILNLxsWvDwtzm/n7f5AWuqJTXQXdDtOvPfTDrH4TPhEvW2qMlR4JFA2w==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", + "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", "dev": true, + "license": "MIT", "dependencies": { - "@octokit/types": "^6.0.3", + "@octokit/types": "^9.0.0", "deprecation": "^2.0.0", "once": "^1.4.0" }, @@ -1786,28 +2075,34 @@ "node": ">= 14" } }, - "node_modules/@octokit/rest": { - "version": "19.0.3", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.3.tgz", - "integrity": "sha512-5arkTsnnRT7/sbI4fqgSJ35KiFaN7zQm0uQiQtivNQLI8RQx8EHwJCajcTUwmaCMNDg7tdCvqAnc7uvHHPxrtQ==", + "node_modules/@octokit/tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", + "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", "dev": true, - "dependencies": { - "@octokit/core": "^4.0.0", - "@octokit/plugin-paginate-rest": "^3.0.0", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } + "license": "MIT" }, "node_modules/@octokit/types": { - "version": "6.40.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.40.0.tgz", - "integrity": "sha512-MFZOU5r8SwgJWDMhrLUSvyJPtVsqA6VnbVI3TNbsmw+Jnvrktzvq2fYES/6RiJA/5Ykdwq4mJmtlYUfW7CGjmw==", + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", + "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", "dev": true, + "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^12.10.0" + "@octokit/openapi-types": "^18.0.0" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" } }, "node_modules/@pnpm/config.env-replace": { @@ -1931,62 +2226,50 @@ } }, "node_modules/@semantic-release/github": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-8.0.5.tgz", - "integrity": "sha512-9pGxRM3gv1hgoZ/muyd4pWnykdIUVfCiev6MXE9lOyGQof4FQy95GFE26nDcifs9ZG7bBzV8ue87bo/y1zVf0g==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-8.1.0.tgz", + "integrity": "sha512-erR9E5rpdsz0dW1I7785JtndQuMWN/iDcemcptf67tBNOmBUN0b2YNOgcjYUnBpgRpZ5ozfBHrK7Bz+2ets/Dg==", "dev": true, + "license": "MIT", "dependencies": { - "@octokit/rest": "^19.0.0", - "@semantic-release/error": "^2.2.0", + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^6.1.2", + "@octokit/plugin-retry": "^4.1.3", + "@octokit/plugin-throttling": "^5.2.3", + "@semantic-release/error": "^3.0.0", "aggregate-error": "^3.0.0", - "bottleneck": "^2.18.1", "debug": "^4.0.0", "dir-glob": "^3.0.0", - "fs-extra": "^10.0.0", + "fs-extra": "^11.0.0", "globby": "^11.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", "issue-parser": "^6.0.0", "lodash": "^4.17.4", "mime": "^3.0.0", "p-filter": "^2.0.0", - "p-retry": "^4.0.0", "url-join": "^4.0.0" }, "engines": { - "node": ">=14.17" - }, - "peerDependencies": { - "semantic-release": ">=18.0.0-beta.1" - } - }, - "node_modules/@semantic-release/github/node_modules/@semantic-release/error": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-2.2.0.tgz", - "integrity": "sha512-9Tj/qn+y2j+sjCI3Jd+qseGtHjOAeg7dU2/lVcqIQ9TV3QDaDXDYXcoOHU+7o2Hwh8L8ymL4gfuO7KxDs3q2zg==", - "dev": true - }, - "node_modules/@semantic-release/github/node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0-beta.1" } }, - "node_modules/@semantic-release/github/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "node_modules/@semantic-release/github/node_modules/fs-extra": { + "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, + "license": "MIT", "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">= 6" + "node": ">=14.14" } }, "node_modules/@semantic-release/github/node_modules/mime": { @@ -2166,10 +2449,11 @@ } }, "node_modules/@types/bonjour": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", - "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -2184,10 +2468,11 @@ } }, "node_modules/@types/connect-history-api-fallback": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", - "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", "dev": true, + "license": "MIT", "dependencies": { "@types/express-serve-static-core": "*", "@types/node": "*" @@ -2255,52 +2540,58 @@ } }, "node_modules/@types/eslint": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.5.tgz", - "integrity": "sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==", + "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.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "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.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", - "dev": true + "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/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", "dev": true, + "license": "MIT", "dependencies": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", + "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", - "@types/serve-static": "*" + "@types/serve-static": "^1" } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.29", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.29.tgz", - "integrity": "sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q==", + "version": "4.19.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "@types/qs": "*", - "@types/range-parser": "*" + "@types/range-parser": "*", + "@types/send": "*" } }, "node_modules/@types/geojson": { @@ -2318,6 +2609,13 @@ "@types/node": "*" } }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/http-proxy": { "version": "1.17.9", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", @@ -2362,10 +2660,11 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true + "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/leaflet": { "version": "1.7.9", @@ -2377,10 +2676,11 @@ } }, "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" }, "node_modules/@types/minimist": { "version": "1.2.2", @@ -2394,6 +2694,16 @@ "integrity": "sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==", "dev": true }, + "node_modules/@types/node-forge": { + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", + "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", @@ -2425,35 +2735,61 @@ "dev": true }, "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "dev": true + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", "dev": true, + "license": "MIT", "dependencies": { "@types/express": "*" } }, "node_modules/@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", "dev": true, + "license": "MIT", "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "node_modules/@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -2465,10 +2801,11 @@ "dev": true }, "node_modules/@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "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": "*" } @@ -2489,115 +2826,159 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.24.0.tgz", - "integrity": "sha512-6bqFGk6wa9+6RrU++eLknKyDqXU1Oc8nyoLu5a1fU17PNRJd9UBr56rMF7c4DRaRtnarlkQ4jwxUbvBo8cNlpw==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.1.tgz", + "integrity": "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "5.24.0", - "@typescript-eslint/type-utils": "5.24.0", - "@typescript-eslint/utils": "5.24.0", - "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/type-utils": "8.56.1", + "@typescript-eslint/utils": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.4.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@typescript-eslint/parser": "^8.56.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.24.0.tgz", - "integrity": "sha512-4q29C6xFYZ5B2CXqSBBdcS0lPyfM9M09DoQLtHS5kf+WbpV8pBBhHDLNhXfgyVwFnhrhYzOu7xmg02DzxeF2Uw==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz", + "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "5.24.0", - "@typescript-eslint/types": "5.24.0", - "@typescript-eslint/typescript-estree": "5.24.0", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "debug": "^4.4.3" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", + "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.56.1", + "@typescript-eslint/types": "^8.56.1", + "debug": "^4.4.3" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.24.0.tgz", - "integrity": "sha512-WpMWipcDzGmMzdT7NtTjRXFabx10WleLUGrJpuJLGaxSqpcyq5ACpKSD5VE40h2nz3melQ91aP4Du7lh9FliCA==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz", + "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.24.0", - "@typescript-eslint/visitor-keys": "5.24.0" + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", + "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.24.0.tgz", - "integrity": "sha512-uGi+sQiM6E5CeCZYBXiaIvIChBXru4LZ1tMoeKbh1Lze+8BO9syUG07594C4lvN2YPT4KVeIupOJkVI+9/DAmQ==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz", + "integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "5.24.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1", + "@typescript-eslint/utils": "8.56.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.24.0.tgz", - "integrity": "sha512-Tpg1c3shTDgTmZd3qdUyd+16r/pGmVaVEbLs+ufuWP0EruVbUiEOmpBBQxBb9a8iPRxi8Rb2oiwOxuZJzSq11A==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz", + "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==", "dev": true, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2605,216 +2986,305 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.24.0.tgz", - "integrity": "sha512-zcor6vQkQmZAQfebSPVwUk/FD+CvnsnlfKXYeQDsWXRF+t7SBPmIfNia/wQxCSeu1h1JIjwV2i9f5/DdSp/uDw==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", + "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.24.0", - "@typescript-eslint/visitor-keys": "5.24.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@typescript-eslint/project-service": "8.56.1", + "@typescript-eslint/tsconfig-utils": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/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, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/@typescript-eslint/utils": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.24.0.tgz", - "integrity": "sha512-K05sbWoeCBJH8KXu6hetBJ+ukG0k2u2KlgD3bN+v+oBKm8adJqVHpSSLHNzqyuv0Lh4GVSAUgZ5lB4icmPmWLw==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz", + "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==", "dev": true, + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.24.0", - "@typescript-eslint/types": "5.24.0", - "@typescript-eslint/typescript-estree": "5.24.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.24.0.tgz", - "integrity": "sha512-qzGwSXMyMnogcAo+/2fU+jhlPPVMXlIH2PeAonIKjJSoDKl1+lJVvG5Z5Oud36yU0TWK2cs1p/FaSN5J2OUFYA==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz", + "integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.24.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "8.56.1", + "eslint-visitor-keys": "^5.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.5.tgz", - "integrity": "sha512-LHY/GSAZZRpsNQH+/oHqhRQ5FT7eoULcBqgfyTB5nQHogFnK3/7QoN7dLnwSE/JkUAF0SrRuclT7ODqMFtWxxQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.5.tgz", - "integrity": "sha512-1j1zTIC5EZOtCplMBG/IEwLtUojtwFVwdyVMbL/hwWqbzlQoJsWCOavrdnLkemwNoC/EOwtUFch3fuo+cbcXYQ==", - "dev": true + "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, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.5.tgz", - "integrity": "sha512-L65bDPmfpY0+yFrsgz8b6LhXmbbs38OnwDCf6NpnMUYqa+ENfE5Dq9E42ny0qz/PdR0LJyq/T5YijPnU8AXEpA==", - "dev": true + "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, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.5.tgz", - "integrity": "sha512-fDKo1gstwFFSfacIeH5KfwzjykIE6ldh1iH9Y/8YkAZrhmu4TctqYjSh7t0K2VyDSXOZJ1MLhht/k9IvYGcIxg==", - "dev": true + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.5.tgz", - "integrity": "sha512-DhykHXM0ZABqfIGYNv93A5KKDw/+ywBFnuWybZZWcuzWHfbp21wUfRkbtz7dMGwGgT4iXjWuhRMA2Mzod6W4WA==", + "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, + "license": "MIT", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.5", - "@webassemblyjs/helper-api-error": "1.11.5", + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.5.tgz", - "integrity": "sha512-oC4Qa0bNcqnjAowFn7MPCETQgDYytpsfvz4ujZz63Zu/a/v71HeCAAmZsgZ3YVKec3zSPYytG3/PrRCqbtcAvA==", - "dev": true + "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, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.5.tgz", - "integrity": "sha512-uEoThA1LN2NA+K3B9wDo3yKlBfVtC6rh0i4/6hvbz071E8gTNZD/pT0MsBf7MeD6KbApMSkaAK0XeKyOZC7CIA==", + "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, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.5.tgz", - "integrity": "sha512-37aGq6qVL8A8oPbPrSGMBcp38YZFXcHfiROflJn9jxSdSMMM5dS5P/9e2/TpaJuhE+wFrbukN2WI6Hw9MH5acg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, + "license": "MIT", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.5.tgz", - "integrity": "sha512-ajqrRSXaTJoPW+xmkfYN6l8VIeNnR4vBOTQO9HzR7IygoCcKWkICbKFbVTNMjMgMREqXEr0+2M6zukzM47ZUfQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.5.tgz", - "integrity": "sha512-WiOhulHKTZU5UPlRl53gHR8OxdGsSOxqfpqWeA2FmcwBMaoEdz6b2x2si3IwC9/fSPLfe8pBMRTHVMk5nlwnFQ==", - "dev": true + "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, + "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.5.tgz", - "integrity": "sha512-C0p9D2fAu3Twwqvygvf42iGCQ4av8MFBLiTb+08SZ4cEdwzWx9QeAHDo1E2k+9s/0w1DM40oflJOpkZ8jW4HCQ==", + "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, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/helper-wasm-section": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5", - "@webassemblyjs/wasm-opt": "1.11.5", - "@webassemblyjs/wasm-parser": "1.11.5", - "@webassemblyjs/wast-printer": "1.11.5" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.5.tgz", - "integrity": "sha512-14vteRlRjxLK9eSyYFvw1K8Vv+iPdZU0Aebk3j6oB8TQiQYuO6hj9s4d7qf6f2HJr2khzvNldAFG13CgdkAIfA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/ieee754": "1.11.5", - "@webassemblyjs/leb128": "1.11.5", - "@webassemblyjs/utf8": "1.11.5" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.5.tgz", - "integrity": "sha512-tcKwlIXstBQgbKy1MlbDMlXaxpucn42eb17H29rawYLxm5+MsEmgPzeCP8B1Cl69hCice8LeKgZpRUAPtqYPgw==", + "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, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5", - "@webassemblyjs/wasm-parser": "1.11.5" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.5.tgz", - "integrity": "sha512-SVXUIwsLQlc8srSD7jejsfTU83g7pIGr2YYNb9oHdtldSxaOhvA5xwvIiWIfcX8PlSakgqMXsLpLfbbJ4cBYew==", + "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, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-api-error": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/ieee754": "1.11.5", - "@webassemblyjs/leb128": "1.11.5", - "@webassemblyjs/utf8": "1.11.5" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.5.tgz", - "integrity": "sha512-f7Pq3wvg3GSPUPzR0F6bmI89Hdb+u9WXrSKc4v+N0aV0q6r42WoF92Jp2jEorBEBRoRNXgjp53nBniDXcqZYPA==", + "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, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.5", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, @@ -2858,13 +3328,15 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "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 + "dev": true, + "license": "Apache-2.0" }, "node_modules/accepts": { "version": "1.3.8", @@ -2880,10 +3352,11 @@ } }, "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "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": { "acorn": "bin/acorn" }, @@ -2891,13 +3364,17 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "node_modules/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, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, "peerDependencies": { - "acorn": "^8" + "acorn": "^8.14.0" } }, "node_modules/acorn-jsx": { @@ -2905,20 +3382,19 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, - "dependencies": { - "debug": "4" - }, + "license": "MIT", "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/aggregate-error": { @@ -2935,15 +3411,16 @@ } }, "node_modules/ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "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.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", @@ -3079,12 +3556,6 @@ "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", "dev": true }, - "node_modules/array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", @@ -3243,12 +3714,25 @@ "@babel/core": "^7.0.0" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -3268,58 +3752,56 @@ "dev": true }, "node_modules/before-after-hook": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", - "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==", - "dev": true + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "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.11.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", "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/body-parser/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -3328,16 +3810,16 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/bonjour-service": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.13.tgz", - "integrity": "sha512-LWKRU/7EqDUC9CTAQtuZl5HzBALoCYwtLhffW3et7vZMwv3bWLpJf8bRYlMD5OCcDpTfnPgNCV4yo9ZIaJGMiA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", + "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", "dev": true, + "license": "MIT", "dependencies": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" } @@ -3346,34 +3828,37 @@ "version": "2.19.5", "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -3389,11 +3874,13 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -3429,23 +3916,58 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/call-bind": { + "node_modules/call-bind-apply-helpers": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3487,9 +4009,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001591", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz", - "integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==", + "version": "1.0.30001776", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001776.tgz", + "integrity": "sha512-sg01JDPzZ9jGshqKSckOQthXnYwOEP50jeVFhaSFbZcOy05TiuuaffDOfcwtCisJ9kNQuLBFibYywv2Bgm9osw==", "dev": true, "funding": [ { @@ -3504,7 +4026,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/cardinal": { "version": "2.1.1", @@ -3545,16 +4068,11 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -3567,6 +4085,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -3576,6 +4097,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -3718,7 +4240,8 @@ "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 + "dev": true, + "license": "MIT" }, "node_modules/compare-func": { "version": "2.0.0", @@ -3743,17 +4266,18 @@ } }, "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "dev": true, + "license": "MIT", "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", + "bytes": "3.1.2", + "compressible": "~2.0.18", "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", "vary": "~1.1.2" }, "engines": { @@ -3775,6 +4299,37 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3837,6 +4392,7 @@ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -3952,10 +4508,11 @@ "dev": true }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -4096,10 +4653,11 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -4254,12 +4812,13 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "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.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -4328,7 +4887,8 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/deepmerge": { "version": "4.3.1", @@ -4339,25 +4899,47 @@ "node": ">=0.10.0" } }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", "dev": true, + "license": "MIT", "dependencies": { - "execa": "^5.0.0" + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" }, "engines": { - "node": ">= 10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/del": { @@ -4402,6 +4984,7 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -4410,13 +4993,15 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -4438,10 +5023,11 @@ "dev": true }, "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" } @@ -4467,17 +5053,12 @@ "node": ">=8" } }, - "node_modules/dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", - "dev": true - }, "node_modules/dns-packet": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.4.0.tgz", - "integrity": "sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", "dev": true, + "license": "MIT", "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" }, @@ -4509,6 +5090,21 @@ "node": ">=8" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -4522,13 +5118,15 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.4.685", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.685.tgz", - "integrity": "sha512-yDYeobbTEe4TNooEzOQO6xFqg9XnAkVy2Lod1C1B2it8u47JNLYvl9nLDWBamqUakWB8Jc1hhS1uHUNYTNQdfw==", - "dev": true + "version": "1.5.307", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", + "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", + "dev": true, + "license": "ISC" }, "node_modules/emittery": { "version": "0.13.1", @@ -4549,22 +5147,24 @@ "dev": true }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/enhanced-resolve": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.13.0.tgz", - "integrity": "sha512-eyV8f0y1+bzyfh8xAwW/WTSZpLbjhqc4ne9eGSH4Zo2ejdyiNG9pU6mf9DG8a7+Auk6MFTlNOT4Y2y/9k8GKVg==", + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", + "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.0" }, "engines": { "node": ">=10.13.0" @@ -4605,17 +5205,52 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", - "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==", - "dev": true + "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": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "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" } @@ -4639,46 +5274,51 @@ } }, "node_modules/eslint": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz", - "integrity": "sha512-GG5USZ1jhCu8HJkzGgeK8/+RGnHaNYZGrGDzUtigK3BsGESW/rs2az23XqE0WVwDxy1VRvvjSSGu5nB0Bu+6SA==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "license": "MIT", "dependencies": { - "@eslint/eslintrc": "^1.2.3", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" @@ -4715,19 +5355,22 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "26.2.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.2.2.tgz", - "integrity": "sha512-etSFZ8VIFX470aA6kTqDPhIq7YWe0tjBcboFNV3WeiC18PJ/AVonGhuTwlmuz2fBkH8FJHA7JQ4k7GsQIj1Gew==", + "version": "29.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.15.0.tgz", + "integrity": "sha512-ZCGr7vTH2WSo2hrK5oM2RULFmMruQ7W3cX7YfwoTiPfzTGTFBMmrVIz45jZHd++cGKj/kWf02li/RhTGcANJSA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^5.10.0" + "@typescript-eslint/utils": "^8.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.12.0 || ^22.0.0 || >=24.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/eslint-plugin": "^8.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "jest": "*", + "typescript": ">=4.8.4 <6.0.0" }, "peerDependenciesMeta": { "@typescript-eslint/eslint-plugin": { @@ -4735,84 +5378,75 @@ }, "jest": { "optional": true + }, + "typescript": { + "optional": true } } }, "node_modules/eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz", + "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==", "dev": true, + "license": "MIT", "dependencies": { - "prettier-linter-helpers": "^1.0.0" + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.12" }, "engines": { - "node": ">=6.0.0" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" }, "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" }, "peerDependenciesMeta": { - "eslint-config-prettier": { + "@types/eslint": { "optional": true - } - } - }, - "node_modules/eslint-scope": { - "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" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" + }, + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "node_modules/eslint-scope": { + "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" + }, "engines": { - "node": ">=10" + "node": ">=8.0.0" } }, "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/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", @@ -4825,16 +5459,20 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/estraverse": { @@ -4842,6 +5480,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -4853,17 +5492,21 @@ "dev": true }, "node_modules/espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.7.1", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { @@ -4880,10 +5523,11 @@ } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -4896,6 +5540,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -4944,6 +5589,7 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -5012,45 +5658,50 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "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.2", - "content-disposition": "0.5.4", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "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.7", + "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "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" }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/array-flatten": { @@ -5101,10 +5752,11 @@ "dev": true }, "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/fast-glob": { "version": "3.2.11", @@ -5144,7 +5796,25 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" + }, + "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" + } + ], + "license": "BSD-3-Clause" }, "node_modules/fastest-levenshtein": { "version": "1.0.14", @@ -5222,10 +5892,11 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -5234,17 +5905,18 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", "dev": true, + "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "statuses": "2.0.1", + "statuses": "~2.0.2", "unpipe": "~1.0.0" }, "engines": { @@ -5256,6 +5928,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -5264,7 +5937,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/find-up": { "version": "5.0.0", @@ -5350,6 +6024,7 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -5398,12 +6073,6 @@ "node": ">=12" } }, - "node_modules/fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", - "dev": true - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -5425,16 +6094,14 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/gensync": { "version": "1.0.0-beta.2", @@ -5455,14 +6122,25 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", - "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5477,6 +6155,20 @@ "node": ">=8.0.0" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -5573,11 +6265,29 @@ "node": ">=10.13.0" } }, + "node_modules/glob-to-regex.js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", + "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/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 + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/global-dirs": { "version": "0.1.1", @@ -5592,10 +6302,11 @@ } }, "node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -5626,12 +6337,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -5690,10 +6421,11 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -5701,6 +6433,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -5743,12 +6488,6 @@ "wbuf": "^1.1.0" } }, - "node_modules/html-entities": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", - "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==", - "dev": true - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -5762,19 +6501,24 @@ "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, + "license": "MIT", "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-parser-js": { @@ -5797,11 +6541,26 @@ "node": ">=8.0.0" } }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", "dev": true, + "license": "MIT", "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", @@ -5897,16 +6656,17 @@ } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, + "license": "MIT", "dependencies": { - "agent-base": "6", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/human-signals": { @@ -5933,11 +6693,22 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.18" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "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" }, @@ -6125,10 +6896,11 @@ } }, "node_modules/ipaddr.js": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", - "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.3.0.tgz", + "integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10" } @@ -6144,6 +6916,7 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -6164,15 +6937,16 @@ } }, "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, + "license": "MIT", "bin": { "is-docker": "cli.js" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6217,11 +6991,44 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-network-error": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.1.tgz", + "integrity": "sha512-6QCxa49rQbmUWLfk0nuGqzql9U8uaV2H6279bRErPBHe/109hCzsLUBUHfbEtvLIHBd6hyXbgedBSHevm43Edw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -6267,6 +7074,7 @@ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6296,15 +7104,19 @@ } }, "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", "dev": true, + "license": "MIT", "dependencies": { - "is-docker": "^2.0.0" + "is-inside-container": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/isarray": { @@ -7094,6 +7906,7 @@ "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": "*", "merge-stream": "^2.0.0", @@ -7108,6 +7921,7 @@ "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" }, @@ -7122,13 +7936,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "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" }, @@ -7245,6 +8061,17 @@ "node": ">=6" } }, + "node_modules/launch-editor": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.13.1.tgz", + "integrity": "sha512-lPSddlAAluRKJ7/cjRFoXUFzaX7q/YKI7yPHuEvSJVqoXvFnJov1/Ud87Aa4zULIbA9Nja4mSPK8l0z/7eV2wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.1.1", + "shell-quote": "^1.8.3" + } + }, "node_modules/leaflet": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.8.0.tgz", @@ -7264,6 +8091,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -7325,12 +8153,17 @@ } }, "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/locate-path": { @@ -7349,10 +8182,11 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "dev": true, + "license": "MIT" }, "node_modules/lodash.capitalize": { "version": "4.2.1", @@ -7554,25 +8388,54 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/memfs": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz", - "integrity": "sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw==", + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.56.11.tgz", + "integrity": "sha512-/GodtwVeKVIHZKLUSr2ZdOxKBC5hHki4JNCU22DoCGPEHr5o2PD5U721zvESKyWwCfTfavFl9WZYgA13OAYK0g==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "fs-monkey": "^1.0.3" + "@jsonjoy.com/fs-core": "4.56.11", + "@jsonjoy.com/fs-fsa": "4.56.11", + "@jsonjoy.com/fs-node": "4.56.11", + "@jsonjoy.com/fs-node-builtins": "4.56.11", + "@jsonjoy.com/fs-node-to-fsa": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.56.11", + "@jsonjoy.com/fs-print": "4.56.11", + "@jsonjoy.com/fs-snapshot": "4.56.11", + "@jsonjoy.com/json-pack": "^1.11.0", + "@jsonjoy.com/util": "^1.9.0", + "glob-to-regex.js": "^1.0.1", + "thingies": "^2.5.0", + "tree-dump": "^1.0.3", + "tslib": "^2.0.0" }, - "engines": { - "node": ">= 4.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, "node_modules/meow": { @@ -7612,12 +8475,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -7643,12 +8510,13 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -7713,10 +8581,11 @@ "dev": true }, "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" }, @@ -7766,16 +8635,18 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "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/multicast-dns": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", "dev": true, + "license": "MIT", "dependencies": { "dns-packet": "^5.2.2", "thunky": "^1.0.2" @@ -7821,10 +8692,11 @@ } }, "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, + "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -7840,33 +8712,12 @@ } } }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "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.3.3", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz", + "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==", "dev": true, + "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" } @@ -7878,10 +8729,11 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" }, "node_modules/normalize-package-data": { "version": "3.0.3", @@ -10498,10 +11350,14 @@ "license": "ISC" }, "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -10517,6 +11373,7 @@ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -10525,10 +11382,11 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -10558,17 +11416,19 @@ } }, "node_modules/open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", "dev": true, + "license": "MIT", "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -10584,17 +11444,18 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -10697,16 +11558,21 @@ } }, "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", "dev": true, + "license": "MIT", "dependencies": { - "@types/retry": "0.12.0", + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", "retry": "^0.13.1" }, "engines": { - "node": ">=8" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-try": { @@ -10791,10 +11657,11 @@ "dev": true }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true + "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" }, "node_modules/path-type": { "version": "4.0.0", @@ -10806,10 +11673,11 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", @@ -10940,30 +11808,33 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, + "license": "MIT", "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", "dev": true, + "license": "MIT", "dependencies": { "fast-diff": "^1.1.2" }, @@ -11080,12 +11951,13 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "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.4" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -11142,29 +12014,21 @@ } }, "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/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -11329,6 +12193,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -11370,18 +12235,6 @@ "esprima": "~4.0.0" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/registry-auth-token": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", @@ -11482,6 +12335,7 @@ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -11511,6 +12365,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -11547,18 +12414,19 @@ "dev": true }, "node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "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", - "ajv": "^8.8.0", + "ajv": "^8.9.0", "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" + "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 10.13.0" }, "funding": { "type": "opencollective", @@ -11578,11 +12446,13 @@ "dev": true }, "node_modules/selfsigned": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.1.tgz", - "integrity": "sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, + "license": "MIT", "dependencies": { + "@types/node-forge": "^1.3.0", "node-forge": "^1" }, "engines": { @@ -11707,24 +12577,25 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", "dev": true, + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "range-parser": "~1.2.1", - "statuses": "2.0.1" + "statuses": "~2.0.2" }, "engines": { "node": ">= 0.8.0" @@ -11735,6 +12606,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -11743,19 +12615,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/send/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 + "dev": true, + "license": "MIT" }, "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "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" } @@ -11839,15 +12707,16 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", "dev": true, + "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "~0.19.1" }, "engines": { "node": ">= 0.8.0" @@ -11857,7 +12726,8 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/shallow-clone": { "version": "3.0.1", @@ -11892,15 +12762,90 @@ "node": ">=8" } }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12049,6 +12994,7 @@ "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", "source-map": "^0.6.0" @@ -12199,10 +13145,11 @@ } }, "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, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -12344,13 +13291,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/synckit": { + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/temp-dir": { @@ -12394,13 +13362,14 @@ } }, "node_modules/terser": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.1.tgz", - "integrity": "sha512-hVl35zClmpisy6oaoKALOpS0rDYLxRFLHhRuDlEGTKey9qHjS1w9GMORjuwIMt70Wan4lwsLYyWDVnWgF+KUEw==", + "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.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -12411,80 +13380,17 @@ "node": ">=10" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "node_modules/terser-webpack-plugin": { + "version": "5.3.17", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.17.tgz", + "integrity": "sha512-YR7PtUp6GMU91BgSJmlaX/rS2lGDbAF7D+Wtq7hRO+MiljNmodYvqslzCFiYVAgW+Qoaaia/QUIP4lGXufjdZw==", "dev": true, + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" }, "engines": { "node": ">= 10.13.0" @@ -12492,6 +13398,20 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } } }, "node_modules/test-exclude": { @@ -12523,6 +13443,23 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thingies": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz", + "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "^2" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -12556,7 +13493,56 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } }, "node_modules/tmpl": { "version": "1.0.5", @@ -12564,20 +13550,12 @@ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -12590,16 +13568,41 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.6" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, "node_modules/traverse": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", "integrity": "sha512-kdf4JKs8lbARxWdp7RKdNzoJBhGUcIalSYibuGyHJbmk40pOysQ0+QPvlkCOICOivDWU2IJo2rkrxyTK2AH4fw==", "dev": true }, + "node_modules/tree-dump": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", + "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", @@ -12609,6 +13612,19 @@ "node": ">=8" } }, + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, "node_modules/ts-jest": { "version": "29.1.2", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", @@ -12696,10 +13712,11 @@ } }, "node_modules/ts-node": { - "version": "10.8.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.0.tgz", - "integrity": "sha512-/fNd5Qh+zTt8Vt1KbYZjRHCE9sI5i7nqfD/dzBBRDeVXZXS6kToW6R7tTU6Nd4XavFs0mAVCg29Q//ML7WsZYA==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -12747,32 +13764,19 @@ "node": ">=0.4.0" } }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -12794,6 +13798,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -12806,6 +13811,7 @@ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -12815,16 +13821,17 @@ } }, "node_modules/typescript": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", - "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/uglify-js": { @@ -12865,10 +13872,11 @@ } }, "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "dev": true, + "license": "ISC" }, "node_modules/universalify": { "version": "2.0.0", @@ -12884,14 +13892,15 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "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": [ { @@ -12907,9 +13916,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -12957,12 +13967,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -13012,10 +14016,11 @@ } }, "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "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": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -13033,36 +14038,45 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, "node_modules/webpack": { - "version": "5.80.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.80.0.tgz", - "integrity": "sha512-OIMiq37XK1rWO8mH9ssfFKZsXg4n6klTEDL7S8/HqbAOBBaiy8ABvXvz0dDCXeEF9gqwxSvVk611zFPjS8hJxA==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", + "version": "5.105.4", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.4.tgz", + "integrity": "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==", + "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.16.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.13.0", - "es-module-lexer": "^1.2.1", + "enhanced-resolve": "^5.20.0", + "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", + "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.2", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.17", + "watchpack": "^2.5.1", + "webpack-sources": "^3.3.4" }, "bin": { "webpack": "bin/webpack.js" @@ -13137,100 +14151,115 @@ } }, "node_modules/webpack-dev-middleware": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", - "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.5.tgz", + "integrity": "sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==", "dev": true, + "license": "MIT", "dependencies": { "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", + "memfs": "^4.43.1", + "mime-types": "^3.0.1", + "on-finished": "^2.4.1", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware/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/webpack-dev-middleware/node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/webpack-dev-server": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz", - "integrity": "sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw==", - "dev": true, - "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.1", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.0.tgz", + "integrity": "sha512-90SqqYXA2SK36KcT6o1bvwvZfJFcmoamqeJY7+boioffX9g9C0wjjJRGUrQIuh43pb0ttX7+ssavmj/WN2RHtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", "colorette": "^2.0.10", "compression": "^1.7.4", "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", + "express": "^4.21.2", "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.0.1", + "http-proxy-middleware": "^2.0.7", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.4.2" + "webpack-dev-middleware": "^7.4.2", + "ws": "^8.18.0" }, "bin": { "webpack-dev-server": "bin/webpack-dev-server.js" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", - "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "webpack": "^5.0.0" }, "peerDependenciesMeta": { - "bufferutil": { + "webpack": { "optional": true }, - "utf-8-validate": { + "webpack-cli": { "optional": true } } @@ -13249,62 +14278,21 @@ } }, "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.4.tgz", + "integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "node_modules/webpack/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, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } + "license": "ISC" }, "node_modules/websocket-driver": { "version": "0.7.4", @@ -13329,6 +14317,17 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -13355,6 +14354,7 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -13401,6 +14401,44 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "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/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 9e2f4ed..bfb4610 100644 --- a/package.json +++ b/package.json @@ -67,27 +67,27 @@ "@types/jest": "29.5.12", "@types/leaflet": "1.7.9", "@types/resize-observer-browser": "^0.1.7", - "@typescript-eslint/eslint-plugin": "5.24.0", - "@typescript-eslint/parser": "5.24.0", + "@typescript-eslint/eslint-plugin": "8.56.1", + "@typescript-eslint/parser": "8.56.1", "conventional-changelog-eslint": "3.0.9", "copy-webpack-plugin": "^11.0.0", - "eslint": "8.15.0", + "eslint": "8.57.0", "eslint-config-google": "0.14.0", "eslint-config-prettier": "8.5.0", - "eslint-plugin-jest": "26.2.2", - "eslint-plugin-prettier": "4.0.0", + "eslint-plugin-jest": "29.15.0", + "eslint-plugin-prettier": "5.5.5", "http-server": "^14.1.1", "husky": "^8.0.1", "jest": "29.7.0", - "prettier": "^2.7.1", + "prettier": "3.8.1", "semantic-release": "19.0.3", "ts-jest": "29.1.2", "ts-loader": "^9.3.1", - "ts-node": "10.8.0", - "typescript": "4.6.3", + "ts-node": "10.9.2", + "typescript": "5.9.3", "webpack": "^5.73.0", "webpack-cli": "^4.10.0", - "webpack-dev-server": "^4.9.3" + "webpack-dev-server": "5.2.0" }, "jest": { "moduleFileExtensions": [ diff --git a/src/models/graph.ts b/src/models/graph.ts index 7bcf0e0..8b7801e 100644 --- a/src/models/graph.ts +++ b/src/models/graph.ts @@ -8,7 +8,6 @@ import { IEntityState, EntityState } from '../utils/entity.utils'; import { IObserver, IObserverDataPayload, ISubject, Subject } from '../utils/observer.utils'; import { patchProperties } from '../utils/object.utils'; import { dedupArrays } from '../utils/array.utils'; -import { ILayout } from '../simulator/layout/layout'; export interface IGraphData { nodes: N[]; @@ -51,7 +50,6 @@ export interface IGraph extends ISubje getNearestNode(point: IPosition): INode | undefined; getNearestEdge(point: IPosition, minDistance?: number): IEdge | undefined; setSettings(settings: Partial>): void; - setLayout(layout: ILayout | undefined): void; } export interface IGraphSettings { @@ -75,7 +73,6 @@ export class Graph extends Subject imp }); private _defaultStyle?: Partial>; private _settings: IGraphSettings; - private _layout: ILayout | undefined; constructor(data?: Partial>, settings?: Partial>) { // TODO(dlozic): How to use object assign here? If I add add and export a default const here, it needs N, E. @@ -95,11 +92,6 @@ export class Graph extends Subject imp this.notifyListeners(); } - setLayout(layout: ILayout | undefined): void { - this._layout = layout; - this._resetLayout(); - } - /** * Returns a list of nodes. * @@ -282,7 +274,6 @@ export class Graph extends Subject imp this._applyEdgeOffsets(); this._applyStyle(); - this._resetLayout(); this._settings?.onMergeData?.(data); } @@ -296,7 +287,6 @@ export class Graph extends Subject imp this._applyEdgeOffsets(); this._applyStyle(); - this._resetLayout(); if (this._settings && this._settings.onRemoveData) { const removedData: IGraphObjectsIds = { @@ -613,17 +603,6 @@ export class Graph extends Subject imp return { nodeIds: [], edgeIds: removedEdgeIds }; } - private _resetLayout(): void { - if (!this._layout) { - this.clearPositions(); - return; - } - - const positions = this._layout.getPositions(this.getNodes()); - this.setNodePositions(positions); - this.notifyListeners(); - } - private _applyEdgeOffsets() { const graphEdges = this.getEdges(); const edgeOffsets = getEdgeOffsets(graphEdges); diff --git a/src/models/interaction.ts b/src/models/interaction.ts new file mode 100644 index 0000000..5e6c6c5 --- /dev/null +++ b/src/models/interaction.ts @@ -0,0 +1,67 @@ +import { hoverEdge, hoverNode, selectEdge, selectNode, unhoverAll, unselectAll } from '../utils/graph.utils'; +import { IEdgeBase } from './edge'; +import { IGraph } from './graph'; +import { INodeBase } from './node'; + +export interface IGraphInteraction { + selectNodeById(id: any): boolean; + selectEdgeById(id: any): boolean; + unselectAll(): number; + hoverNodeById(id: any): boolean; + hoverEdgeById(id: any): boolean; + unhoverAll(): number; +} + +export class GraphInteraction implements IGraphInteraction { + private _graph: IGraph; + + constructor(graph: IGraph) { + this._graph = graph; + } + + selectNodeById(id: any): boolean { + const node = this._graph.getNodeById(id); + if (!node) { + return false; + } + selectNode(node); + return true; + } + + selectEdgeById(id: any): boolean { + const edge = this._graph.getEdgeById(id); + if (!edge) { + return false; + } + selectEdge(edge); + return true; + } + + unselectAll(): number { + const { changedCount } = unselectAll(this._graph); + return changedCount; + } + + hoverNodeById(id: any): boolean { + const node = this._graph.getNodeById(id); + if (!node) { + return false; + } + hoverNode(node); + return true; + } + + hoverEdgeById(id: any): boolean { + const edge = this._graph.getEdgeById(id); + if (!edge) { + return false; + } + hoverEdge(edge); + return true; + } + + unhoverAll(): number { + const { changedCount } = unhoverAll(this._graph); + return changedCount; + } +} diff --git a/src/models/strategy.ts b/src/models/strategy.ts index 9604963..a3580b6 100644 --- a/src/models/strategy.ts +++ b/src/models/strategy.ts @@ -2,7 +2,7 @@ import { INode, INodeBase } from './node'; import { IEdge, IEdgeBase } from './edge'; import { IGraph } from './graph'; import { IPosition } from '../common'; -import { GraphObjectState } from './state'; +import { hoverOnlyNode, selectOnlyEdge, selectOnlyNode, unhoverAll, unselectAll } from '../utils/graph.utils'; export interface IEventStrategySettings { isDefaultSelectEnabled: boolean; @@ -37,7 +37,7 @@ export class DefaultEventStrategy impl const node = graph.getNearestNode(point); if (node) { if (this.isSelectEnabled) { - selectNode(graph, node); + selectOnlyNode(graph, node); } return { @@ -49,7 +49,7 @@ export class DefaultEventStrategy impl const edge = graph.getNearestEdge(point); if (edge) { if (this.isSelectEnabled) { - selectEdge(graph, edge); + selectOnlyEdge(graph, edge); } return { @@ -79,7 +79,7 @@ export class DefaultEventStrategy impl } if (this.isHoverEnabled) { - hoverNode(graph, node); + hoverOnlyNode(graph, node); } this._lastHoveredNode = node; @@ -104,7 +104,7 @@ export class DefaultEventStrategy impl const node = graph.getNearestNode(point); if (node) { if (this.isSelectEnabled) { - selectNode(graph, node); + selectOnlyNode(graph, node); } return { @@ -116,7 +116,7 @@ export class DefaultEventStrategy impl const edge = graph.getNearestEdge(point); if (edge) { if (this.isSelectEnabled) { - selectEdge(graph, edge); + selectOnlyEdge(graph, edge); } return { @@ -139,7 +139,7 @@ export class DefaultEventStrategy impl const node = graph.getNearestNode(point); if (node) { if (this.isSelectEnabled) { - selectNode(graph, node); + selectOnlyNode(graph, node); } return { @@ -151,7 +151,7 @@ export class DefaultEventStrategy impl const edge = graph.getNearestEdge(point); if (edge) { if (this.isSelectEnabled) { - selectEdge(graph, edge); + selectOnlyEdge(graph, edge); } return { @@ -170,109 +170,3 @@ export class DefaultEventStrategy impl }; } } - -const selectNode = (graph: IGraph, node: INode) => { - unselectAll(graph); - setNodeState(node, GraphObjectState.SELECTED, { isStateOverride: true }); -}; - -const selectEdge = (graph: IGraph, edge: IEdge) => { - unselectAll(graph); - setEdgeState(edge, GraphObjectState.SELECTED, { isStateOverride: true }); -}; - -const unselectAll = (graph: IGraph): { changedCount: number } => { - const selectedNodes = graph.getNodes((node) => node.isSelected()); - for (let i = 0; i < selectedNodes.length; i++) { - selectedNodes[i].clearState(); - } - - const selectedEdges = graph.getEdges((edge) => edge.isSelected()); - for (let i = 0; i < selectedEdges.length; i++) { - selectedEdges[i].clearState(); - } - - return { changedCount: selectedNodes.length + selectedEdges.length }; -}; - -const hoverNode = (graph: IGraph, node: INode) => { - unhoverAll(graph); - setNodeState(node, GraphObjectState.HOVERED); -}; - -// const hoverEdge = (graph: Graph, edge: Edge) => { -// unhoverAll(graph); -// setEdgeState(edge, GraphObjectState.HOVERED); -// }; - -const unhoverAll = (graph: IGraph): { changedCount: number } => { - const hoveredNodes = graph.getNodes((node) => node.isHovered()); - for (let i = 0; i < hoveredNodes.length; i++) { - hoveredNodes[i].clearState(); - } - - const hoveredEdges = graph.getEdges((edge) => edge.isHovered()); - for (let i = 0; i < hoveredEdges.length; i++) { - hoveredEdges[i].clearState(); - } - - return { changedCount: hoveredNodes.length + hoveredEdges.length }; -}; - -interface ISetShapeStateOptions { - isStateOverride: boolean; -} - -const setNodeState = ( - node: INode, - state: number, - options?: ISetShapeStateOptions, -): void => { - if (isStateChangeable(node, options)) { - node.setState(state, { isNotifySkipped: true }); - } - - node.getInEdges().forEach((edge) => { - if (edge && isStateChangeable(edge, options)) { - edge.setState(state, { isNotifySkipped: true }); - } - if (edge.startNode && isStateChangeable(edge.startNode, options)) { - edge.startNode.setState(state, { isNotifySkipped: true }); - } - }); - - node.getOutEdges().forEach((edge) => { - if (edge && isStateChangeable(edge, options)) { - edge.setState(state, { isNotifySkipped: true }); - } - if (edge.endNode && isStateChangeable(edge.endNode, options)) { - edge.endNode.setState(state, { isNotifySkipped: true }); - } - }); -}; - -const setEdgeState = ( - edge: IEdge, - state: number, - options?: ISetShapeStateOptions, -): void => { - if (isStateChangeable(edge, options)) { - edge.setState(state, { isNotifySkipped: true }); - } - - if (edge.startNode && isStateChangeable(edge.startNode, options)) { - edge.startNode.setState(state, { isNotifySkipped: true }); - } - - if (edge.endNode && isStateChangeable(edge.endNode, options)) { - edge.endNode.setState(state, { isNotifySkipped: true }); - } -}; - -const isStateChangeable = ( - graphObject: INode | IEdge, - options?: ISetShapeStateOptions, -): boolean => { - const isOverride = options?.isStateOverride; - return isOverride || (!isOverride && !graphObject.getState()); -}; diff --git a/src/renderer/canvas/canvas-renderer.ts b/src/renderer/canvas/canvas-renderer.ts index 3e1eed8..7b99861 100644 --- a/src/renderer/canvas/canvas-renderer.ts +++ b/src/renderer/canvas/canvas-renderer.ts @@ -10,6 +10,7 @@ import { DEFAULT_RENDERER_HEIGHT, DEFAULT_RENDERER_SETTINGS, DEFAULT_RENDERER_WIDTH, + IFitZoomTransformOptions, IRenderer, IRendererSettings, RendererEvents as RE, @@ -285,12 +286,23 @@ export class CanvasRenderer extends Em this._context.save(); } - getFitZoomTransform(graph: IGraph): ZoomTransform { + getFitZoomTransform(graph: IGraph, options?: IFitZoomTransformOptions): ZoomTransform { // Graph view is a bounding box of the graph nodes that takes into // account node positions (x, y) and node sizes (style: size + border width) const graphView = graph.getBoundingBox(); - const graphMiddleX = graphView.x + graphView.width / 2; - const graphMiddleY = graphView.y + graphView.height / 2; + const graphMiddleX = + options?.anchorX === 'center' + ? graphView.x + graphView.width / 2 + : options?.anchorX === 'end' + ? graphView.x + graphView.width + : 0; + + const graphMiddleY = + options?.anchorY === 'center' + ? graphView.y + graphView.height / 2 + : options?.anchorY === 'end' + ? graphView.y + graphView.height + : 0; // Simulation view is actually a renderer view (canvas) but in the coordinate system of // the simulator: node position (x, y). We want to fit a graph view into a simulation view. diff --git a/src/renderer/shared.ts b/src/renderer/shared.ts index a5719bc..7ad965e 100644 --- a/src/renderer/shared.ts +++ b/src/renderer/shared.ts @@ -36,6 +36,11 @@ export interface IRendererSettingsInit extends IRendererSettings { type: RendererType; } +export interface IFitZoomTransformOptions { + anchorX?: 'start' | 'center' | 'end'; + anchorY?: 'start' | 'center' | 'end'; +} + export type RendererEvents = { [RenderEventType.RESIZE]: undefined; [RenderEventType.RENDER_START]: undefined; @@ -60,7 +65,7 @@ export interface IRenderer extends IEm render(graph: IGraph): void; reset(): void; - getFitZoomTransform(graph: IGraph): ZoomTransform; + getFitZoomTransform(graph: IGraph, options?: IFitZoomTransformOptions): ZoomTransform; getSimulationPosition(canvasPoint: IPosition): IPosition; /** diff --git a/src/simulator/engine/d3-simulator-engine.ts b/src/simulator/engine/d3-simulator-engine.ts deleted file mode 100644 index f20346f..0000000 --- a/src/simulator/engine/d3-simulator-engine.ts +++ /dev/null @@ -1,728 +0,0 @@ -import { - forceCenter, - forceCollide, - forceLink, - ForceLink, - forceManyBody, - forceSimulation, - forceX, - forceY, - Simulation, - SimulationLinkDatum, -} from 'd3-force'; -import { IPosition } from '../../common'; -import { ISimulationNode, ISimulationEdge, ISimulationGraph } from '../shared'; -import { Emitter } from '../../utils/emitter.utils'; -import { isObjectEqual, copyObject } from '../../utils/object.utils'; - -const MANY_BODY_MAX_DISTANCE_TO_LINK_DISTANCE_RATIO = 100; -const DEFAULT_LINK_DISTANCE = 50; - -export enum D3SimulatorEngineEventType { - SIMULATION_START = 'simulation-start', - SIMULATION_STOP = 'simulation-stop', - SIMULATION_PROGRESS = 'simulation-progress', - SIMULATION_END = 'simulation-end', - SIMULATION_TICK = 'simulation-tick', - SIMULATION_RESET = 'simulation-reset', - NODE_DRAG = 'node-drag', - SETTINGS_UPDATE = 'settings-update', - DATA_CLEARED = 'data-cleared', -} - -export interface ID3SimulatorEngineSettingsAlpha { - alpha: number; - alphaMin: number; - alphaDecay: number; - alphaTarget: number; -} - -export interface ID3SimulatorEngineSettingsCentering { - x: number; - y: number; - strength: number; -} - -export interface ID3SimulatorEngineSettingsCollision { - radius: number; - strength: number; - iterations: number; -} - -export interface ID3SimulatorEngineSettingsLinks { - distance: number; - strength?: number; - iterations: number; -} - -export interface ID3SimulatorEngineSettingsManyBody { - strength: number; - theta: number; - distanceMin: number; - distanceMax: number; -} - -export interface ID3SimulatorEngineSettingsPositioning { - forceX: { - x: number; - strength: number; - }; - forceY: { - y: number; - strength: number; - }; -} - -export interface ID3SimulatorEngineSettings { - isSimulatingOnDataUpdate: boolean; - isSimulatingOnSettingsUpdate: boolean; - isSimulatingOnUnstick: boolean; - isPhysicsEnabled: boolean; - alpha: ID3SimulatorEngineSettingsAlpha; - centering: ID3SimulatorEngineSettingsCentering | null; - collision: ID3SimulatorEngineSettingsCollision | null; - links: ID3SimulatorEngineSettingsLinks; - manyBody: ID3SimulatorEngineSettingsManyBody | null; - positioning: ID3SimulatorEngineSettingsPositioning | null; -} - -export type ID3SimulatorEngineSettingsUpdate = Partial; - -export const getManyBodyMaxDistance = (linkDistance: number) => { - const distance = linkDistance > 0 ? linkDistance : 1; - return distance * MANY_BODY_MAX_DISTANCE_TO_LINK_DISTANCE_RATIO; -}; - -export const DEFAULT_SETTINGS: ID3SimulatorEngineSettings = { - isSimulatingOnDataUpdate: true, - isSimulatingOnSettingsUpdate: true, - isSimulatingOnUnstick: true, - isPhysicsEnabled: false, - alpha: { - alpha: 1, - alphaMin: 0.001, - alphaDecay: 0.0228, - alphaTarget: 0, - }, - centering: { - x: 0, - y: 0, - strength: 1, - }, - collision: { - radius: 15, - strength: 1, - iterations: 1, - }, - links: { - distance: DEFAULT_LINK_DISTANCE, - strength: 1, - iterations: 1, - }, - manyBody: { - strength: -100, - theta: 0.9, - distanceMin: 0, - distanceMax: getManyBodyMaxDistance(DEFAULT_LINK_DISTANCE), - }, - positioning: { - forceX: { - x: 0, - strength: 0.1, - }, - forceY: { - y: 0, - strength: 0.1, - }, - }, -}; - -export interface ID3SimulatorProgress { - progress: number; -} - -export interface ID3SimulatorNodeId { - id: number; -} - -export interface ID3SimulatorSettings { - settings: ID3SimulatorEngineSettings; -} - -interface IRunSimulationOptions { - isUpdatingSettings: boolean; -} - -export type D3SimulatorEvents = { - [D3SimulatorEngineEventType.SIMULATION_START]: undefined; - [D3SimulatorEngineEventType.SIMULATION_PROGRESS]: ISimulationGraph & ID3SimulatorProgress; - [D3SimulatorEngineEventType.SIMULATION_END]: ISimulationGraph; - [D3SimulatorEngineEventType.SIMULATION_TICK]: ISimulationGraph; - [D3SimulatorEngineEventType.SIMULATION_RESET]: ISimulationGraph; - [D3SimulatorEngineEventType.NODE_DRAG]: ISimulationGraph; - [D3SimulatorEngineEventType.SETTINGS_UPDATE]: ID3SimulatorSettings; - [D3SimulatorEngineEventType.DATA_CLEARED]: ISimulationGraph; -}; - -export class D3SimulatorEngine extends Emitter { - protected _linkForce!: ForceLink>; - protected _simulation!: Simulation; - protected _settings: ID3SimulatorEngineSettings; - - protected _edges: ISimulationEdge[] = []; - protected _nodes: ISimulationNode[] = []; - protected _nodeIndexByNodeId: Record = {}; - - protected _isDragging = false; - protected _isStabilizing = false; - - // These are settings provided during construction if they are specified, - // or during the first call of setSettings if unspecified during construction. - protected _initialSettings: ID3SimulatorEngineSettings | undefined; - - constructor(settings?: ID3SimulatorEngineSettings) { - super(); - - if (settings !== undefined) { - this._initialSettings = Object.assign(copyObject(DEFAULT_SETTINGS), settings); - } - - this._settings = this.resetSettings(); - this.clearData(); - } - - getSettings(): ID3SimulatorEngineSettings { - return copyObject(this._settings); - } - - /** - * Applies the specified settings to the D3 simulator engine. - * - * @param {ID3SimulatorEngineSettingsUpdate} settings Partial D3 simulator engine settings (any property of settings) - */ - setSettings(settings: ID3SimulatorEngineSettingsUpdate) { - if (!this._initialSettings) { - this._initialSettings = Object.assign(copyObject(DEFAULT_SETTINGS), settings); - } - - const previousSettings = this.getSettings(); - Object.assign(this._settings, settings); - - if (isObjectEqual(this._settings, previousSettings)) { - return; - } - - this._applySettingsToSimulation(settings); - this.emit(D3SimulatorEngineEventType.SETTINGS_UPDATE, { settings: this._settings }); - - const hasPhysicsBeenDisabled = previousSettings.isPhysicsEnabled && !settings.isPhysicsEnabled; - - if (hasPhysicsBeenDisabled) { - this._simulation.stop(); - } else if (this._settings.isSimulatingOnSettingsUpdate) { - // this.runSimulation({ isUpdatingSettings: true }); - this.activateSimulation(); - } - } - - /** - * Restores simulator engine settings to the initial settings provided during construction. - * - * @return {ID3SimulatorEngineSettings} The default settings patched with the specified parameters in the - * initial settings provided in the constructor or during the first settings update. - */ - resetSettings(): ID3SimulatorEngineSettings { - return Object.assign(copyObject(DEFAULT_SETTINGS), this._initialSettings); - } - - startDragNode() { - this._isDragging = true; - - if (!this._isStabilizing && this._settings.isPhysicsEnabled) { - this.activateSimulation(); - } - } - - dragNode(data: ID3SimulatorNodeId & IPosition) { - const node = this._nodes[this._nodeIndexByNodeId[data.id]]; - if (!node) { - return; - } - - if (!this._isDragging) { - this.startDragNode(); - } - - node.fx = data.x; - node.fy = data.y; - - if (!this._settings.isPhysicsEnabled) { - node.x = data.x; - node.y = data.y; - } - - // Notify the client that the node position changed. - this.emit(D3SimulatorEngineEventType.NODE_DRAG, { nodes: this._nodes, edges: this._edges }); - } - - endDragNode(data: ID3SimulatorNodeId) { - this._isDragging = false; - - if (this._settings.isPhysicsEnabled) { - this._simulation.alphaTarget(0); - } - const node = this._nodes[this._nodeIndexByNodeId[data.id]]; - // TODO(dlozic): Add special behavior for sticky nodes that have been dragged - if (node && this._settings.isPhysicsEnabled) { - this.unfixNode(node); - } - } - - /** - * Activates the simulation and "re-heats" the nodes so that they converge to a new layout. - * This does not count as "stabilization" and won't emit any progress. - */ - activateSimulation() { - if (this._settings.isPhysicsEnabled) { - this.unfixNodes(); // If physics is disabled, the nodes get fixed in the callback from the initial setup (`simulation.on('end', () => {})`). - } else { - this.fixNodes(); - } - this._simulation.alpha(this._settings.alpha.alpha).alphaTarget(this._settings.alpha.alphaTarget).restart(); - } - - stopSimulation() { - this._simulation.stop(); - } - - setupData(data: ISimulationGraph) { - this.clearData(); - - this._initializeNewData(data); - - if (this._settings.isSimulatingOnDataUpdate) { - this._updateSimulationData(); - this._runSimulation(); - } - } - - mergeData(data: Partial) { - this._initializeNewData(data); - - if (!this._settings.isPhysicsEnabled) { - this.fixNodes(); - } - - if (this._settings.isSimulatingOnDataUpdate) { - this._updateSimulationData(); - this.activateSimulation(); - } - } - - patchData(data: Partial) { - if (data.nodes) { - data.nodes = this._fixAndStickDefinedNodes(data.nodes); - const nodeIds: { [id: number]: number } = {}; - - for (let i = 0; i < this._nodes.length; i++) { - nodeIds[this._nodes[i].id] = i; - } - - for (let i = 0; i < data.nodes.length; i += 1) { - const nodeId: any = data.nodes[i].id; - - if (nodeId in nodeIds) { - const index = nodeIds[nodeId]; - this._nodeIndexByNodeId[nodeId] = index; - this._nodes[index] = data.nodes[i]; - } else { - this._nodes.push(data.nodes[i]); - } - } - } - - if (data.edges) { - this._edges = this._edges.concat(data.edges); - } - } - - private _initializeNewData(data: Partial) { - if (data.nodes) { - data.nodes = this._fixAndStickDefinedNodes(data.nodes); - for (let i = 0; i < data.nodes.length; i += 1) { - const nodeId = data.nodes[i].id; - - if (this._nodeIndexByNodeId[nodeId]) { - this._nodeIndexByNodeId[nodeId] = i; - } else { - this._nodes.push(data.nodes[i]); - } - } - } else { - this._nodes = []; - } - if (data.edges) { - this._edges = this._edges.concat(data.edges); - } else { - this._edges = []; - } - this._setNodeIndexByNodeId(); - } - - updateData(data: ISimulationGraph) { - data.nodes = this._fixAndStickDefinedNodes(data.nodes); - - // Keep existing nodes along with their (x, y, fx, fy) coordinates to avoid - // rearranging the graph layout. - // These nodes should not be reloaded into the array because the D3 simulation - // will assign to them completely new coordinates, effectively restarting the animation. - const newNodeIds = new Set(data.nodes.map((node) => node.id)); - - // Keep old nodes that are present in the new data instead of reassigning them. - const oldNodes = this._nodes.filter((node) => newNodeIds.has(node.id)); - const newNodes = data.nodes.filter((node) => this._nodeIndexByNodeId[node.id] === undefined); - - this._nodes = [...oldNodes, ...newNodes]; - this._setNodeIndexByNodeId(); - - // Only keep new links and discard all old links. - // Old links won't work as some discrepancies arise between the D3 index property - // and Memgraph's `id` property which affects the source->target mapping. - this._edges = data.edges; - - if (this._settings.isSimulatingOnSettingsUpdate) { - this._updateSimulationData(); - this.activateSimulation(); - } - } - - /** - * Removes specified data from the simulation. - * - * @param {ISimulationGraph} data Nodes and edges that will be deleted - */ - deleteData(data: Partial<{ nodeIds: number[] | undefined; edgeIds: number[] | undefined }>) { - const nodeIds = new Set(data.nodeIds); - this._nodes = this._nodes.filter((node) => !nodeIds.has(node.id)); - const edgeIds = new Set(data.edgeIds); - this._edges = this._edges.filter((edge) => !edgeIds.has(edge.id)); - this._setNodeIndexByNodeId(); - if (this._settings.isSimulatingOnDataUpdate) { - this._updateSimulationData(); - this.activateSimulation(); - } - } - - /** - * Removes all internal and D3 simulation node and relationship data. - */ - clearData() { - const nodes = this._nodes; - const edges = this._edges; - this._nodes = []; - this._edges = []; - this._setNodeIndexByNodeId(); - this.resetSimulation(); - this.emit(D3SimulatorEngineEventType.DATA_CLEARED, { nodes: nodes, edges: edges }); - } - - /** - * Updates the internal D3 simulation data with the current data. - */ - private _updateSimulationData() { - // Update simulation with new data. - this._simulation.nodes(this._nodes); - this._linkForce.links(this._edges); - } - - /** - * Resets the simulator engine by discarding all existing simulator data (nodes and edges), - * and keeping the current simulator engine settings. - */ - // TODO(Alex): Listeners memory leak (D3 force research) - resetSimulation() { - this._linkForce = forceLink>(this._edges).id( - (node) => node.id, - ); - this._simulation = forceSimulation(this._nodes).force('link', this._linkForce).stop(); - - this._applySettingsToSimulation(this._settings); - - this._simulation.on('tick', () => { - this.emit(D3SimulatorEngineEventType.SIMULATION_TICK, { nodes: this._nodes, edges: this._edges }); - }); - - this._simulation.on('end', () => { - this._isDragging = false; - this._isStabilizing = false; - this.emit(D3SimulatorEngineEventType.SIMULATION_END, { nodes: this._nodes, edges: this._edges }); - - if (!this._settings.isPhysicsEnabled) { - this.fixNodes(); - } - }); - - this.emit(D3SimulatorEngineEventType.SIMULATION_RESET, { nodes: this._nodes, edges: this._edges }); - } - - /** - * Fixes all nodes by setting their `fx` and `fy` properties to `x` and `y`. - * If no nodes are provided, this function fixes all nodes. - * - * @param {ISimulationNode[]} nodes Nodes that are going to be fixed. If undefined, all nodes get fixed. - */ - fixNodes(nodes?: ISimulationNode[]) { - if (!nodes) { - nodes = this._nodes; - } - - for (let i = 0; i < nodes.length; i++) { - this.fixNode(this._nodes[i]); - } - } - - /** - * Releases specified nodes. - * If no nodes are provided, this function releases all nodes. - * - * @param {ISimulationNode[]} nodes Nodes that are going to be released. If undefined, all nodes get released. - */ - unfixNodes(nodes?: ISimulationNode[]) { - if (!nodes) { - nodes = this._nodes; - } - - for (let i = 0; i < nodes.length; i++) { - this.unfixNode(this._nodes[i]); - } - } - - /** - * Fixes a node by setting its `fx` and `fy` properties to `x` and `y`. - * This function is called when disabling physics. - * - * @param {ISimulationNode} node Simulation node that is going to be fixed - */ - fixNode(node: ISimulationNode) { - if (node.sx === null || node.sx === undefined) { - node.fx = node.x; - } - if (node.sy === null || node.sy === undefined) { - node.fy = node.y; - } - } - - /** - * Releases a node if it's not sticky by setting its `fx` and `fy` properties to `null`. - * This function is called when enabling physics but the sticky property overpowers physics. - * - * @param {ISimulationNode} node Simulation node that is going to be released - */ - unfixNode(node: ISimulationNode) { - if (node.sx === null || node.sx === undefined) { - node.fx = null; - } - if (node.sy === null || node.sy === undefined) { - node.fy = null; - } - } - - /** - * Sticks the specified nodes into place. - * This overpowers any physics state and also sticks the node to their current positions. - * If no nodes are provided, this function sticks all nodes. - * - * @param {ISimulationNode[]} nodes Nodes that are going to become sticky. If undefined, all nodes get sticked. - */ - stickNodes(nodes?: ISimulationNode[]) { - if (!nodes) { - nodes = this._nodes; - } - - for (let i = 0; i < nodes.length; i++) { - this.stickNode(this._nodes[i]); - } - } - - /** - * Removes the sticky properties from all specified nodes. - * If physics is enabled, the nodes get unfixed as well. - * If no nodes are provided, this function unsticks all nodes. - * - * @param {ISimulationNode[]} nodes Nodes that are going to be unsticked. If undefined, all nodes get unsticked. - */ - unstickNodes(nodes?: ISimulationNode[]) { - if (!nodes) { - nodes = this._nodes; - } - - for (let i = 0; i < nodes.length; i++) { - this.unstickNode(this._nodes[i]); - } - - if (this._settings.isSimulatingOnUnstick) { - this.activateSimulation(); - } - } - - /** - * Sticks a node into place. - * This function overpowers any physics state and also sticks the node to its current coordinates. - * - * @param {ISimulationNode} node Simulation node that is going to become sticky - */ - stickNode(node: ISimulationNode) { - node.sx = node.x; - node.fx = node.x; - node.sy = node.y; - node.fy = node.y; - } - - /** - * Removes the sticky properties from the node. - * If physics is enabled, the node gets released as well. - * - * @param {ISimulationNode} node Simulation node that gets unstuck - */ - unstickNode(node: ISimulationNode) { - node.sx = null; - node.sy = null; - - if (this._settings.isPhysicsEnabled) { - node.fx = null; - node.fy = null; - } - } - - /** - * Sticks all nodes thath have a defined position (x and y coordinates). - * This function should be called when the user initially sets up or merges some data. - * If the user provided nodes already have defined `x` **or** `y` properties, they are treated as _"sticky"_. - * Only the specified axis gets immobilized. - * - * @param {ISimulationNode[]} nodes Graph nodes. - * @return {ISimulationNodes[]} Graph nodes with attached `{fx, sx}`, and/or `{fy, sy}` coordinates. - */ - private _fixAndStickDefinedNodes(nodes: ISimulationNode[]): ISimulationNode[] { - for (let i = 0; i < nodes.length; i++) { - if (nodes[i].x !== null && nodes[i].x !== undefined) { - nodes[i].fx = nodes[i].x; - nodes[i].sx = nodes[i].x; - } - if (nodes[i].y !== null && nodes[i].y !== undefined) { - nodes[i].fy = nodes[i].y; - nodes[i].sy = nodes[i].y; - } - } - return nodes; - } - - /** - * Applies the provided settings to the D3 simulation. - * - * @param {ID3SimulatorEngineSettingsUpdate} settings Simulator engine settings - */ - private _applySettingsToSimulation(settings: ID3SimulatorEngineSettingsUpdate) { - if (settings.alpha) { - this._simulation - .alpha(settings.alpha.alpha) - .alphaMin(settings.alpha.alphaMin) - .alphaDecay(settings.alpha.alphaDecay) - .alphaTarget(settings.alpha.alphaTarget); - } - if (settings.links) { - this._linkForce.distance(settings.links.distance).iterations(settings.links.iterations); - } - if (settings.collision) { - const collision = forceCollide() - .radius(settings.collision.radius) - .strength(settings.collision.strength) - .iterations(settings.collision.iterations); - this._simulation.force('collide', collision); - } - if (settings.collision === null) { - this._simulation.force('collide', null); - } - if (settings.manyBody) { - const manyBody = forceManyBody() - .strength(settings.manyBody.strength) - .theta(settings.manyBody.theta) - .distanceMin(settings.manyBody.distanceMin) - .distanceMax(settings.manyBody.distanceMax); - this._simulation.force('charge', manyBody); - } - if (settings.manyBody === null) { - this._simulation.force('charge', null); - } - if (settings.positioning?.forceY) { - const positioningForceX = forceX(settings.positioning.forceX.x).strength(settings.positioning.forceX.strength); - this._simulation.force('x', positioningForceX); - } - if (settings.positioning?.forceX === null) { - this._simulation.force('x', null); - } - if (settings.positioning?.forceY) { - const positioningForceY = forceY(settings.positioning.forceY.y).strength(settings.positioning.forceY.strength); - this._simulation.force('y', positioningForceY); - } - if (settings.positioning?.forceY === null) { - this._simulation.force('y', null); - } - if (settings.centering) { - const centering = forceCenter(settings.centering.x, settings.centering.y).strength(settings.centering.strength); - this._simulation.force('center', centering); - } - if (settings.centering === null) { - this._simulation.force('center', null); - } - } - - // This is a blocking action - the user will not be able to interact with the graph - // during the simulation process. - private _runSimulation(options?: IRunSimulationOptions) { - if (this._isStabilizing) { - return; - } - if (this._settings.isPhysicsEnabled || options?.isUpdatingSettings) { - this.unfixNodes(); - } - - this.emit(D3SimulatorEngineEventType.SIMULATION_START, undefined); - - this._isStabilizing = true; - this._simulation.alpha(this._settings.alpha.alpha).alphaTarget(this._settings.alpha.alphaTarget).stop(); - - const totalSimulationSteps = Math.ceil( - Math.log(this._settings.alpha.alphaMin) / Math.log(1 - this._settings.alpha.alphaDecay), - ); - - let lastProgress = -1; - for (let i = 0; i < totalSimulationSteps; i++) { - const currentProgress = Math.round((i * 100) / totalSimulationSteps); - // Emit progress maximum of 100 times (every percent) - if (currentProgress > lastProgress) { - lastProgress = currentProgress; - this.emit(D3SimulatorEngineEventType.SIMULATION_PROGRESS, { - nodes: this._nodes, - edges: this._edges, - progress: currentProgress / 100, - }); - } - this._simulation.tick(); - } - - if (!this._settings.isPhysicsEnabled) { - this.fixNodes(); - } - - this._isStabilizing = false; - this.emit(D3SimulatorEngineEventType.SIMULATION_END, { nodes: this._nodes, edges: this._edges }); - } - - private _setNodeIndexByNodeId() { - this._nodeIndexByNodeId = {}; - for (let i = 0; i < this._nodes.length; i++) { - this._nodeIndexByNodeId[this._nodes[i].id] = i; - } - } -} diff --git a/src/simulator/engine/engines/base-layout-engine.ts b/src/simulator/engine/engines/base-layout-engine.ts new file mode 100644 index 0000000..1df8506 --- /dev/null +++ b/src/simulator/engine/engines/base-layout-engine.ts @@ -0,0 +1,61 @@ +import { IPosition } from '../../../common'; +import { Emitter } from '../../../utils/emitter.utils'; +import { ISimulationNode, ISimulationEdge, ISimulationGraph, ISimulationIds, SimulatorEvents } from '../../shared'; +import { ILayoutEngine, IEngineSettingsUpdate, LayoutType } from '../shared'; + +export abstract class BaseLayoutEngine extends Emitter implements ILayoutEngine { + protected _nodes: ISimulationNode[] = []; + protected _edges: ISimulationEdge[] = []; + protected _nodeIndexByNodeId: Record = {}; + protected _cancelSimulation = false; + private _schedulerPort: MessagePort | null = null; + + abstract readonly type: LayoutType; + + abstract setupData(data: ISimulationGraph): void; + abstract mergeData(data: ISimulationGraph): void; + abstract updateData(data: ISimulationGraph): void; + abstract deleteData(data: Partial): void; + abstract patchData(data: Partial): void; + abstract clearData(): void; + + abstract activateSimulation(): void; + abstract stopSimulation(): void; + + abstract startDragNode(): void; + abstract dragNode(nodeId: number, position: IPosition): void; + abstract endDragNode(nodeId: number): void; + abstract fixNodes(nodes?: ISimulationNode[]): void; + abstract releaseNodes(nodes?: ISimulationNode[]): void; + + abstract setSettings(settings: IEngineSettingsUpdate): void; + + terminate(): void { + this._cancelSimulation = true; + this._schedulerPort?.close(); + this._schedulerPort = null; + this.removeAllListeners(); + } + + // use MessageChannel for microtask-like scheduling that avoids setTimeout's ~4ms minimum delay + protected _scheduleNext(callback: () => void): void { + if (typeof MessageChannel !== 'undefined') { + const channel = new MessageChannel(); + this._schedulerPort = channel.port2; + channel.port1.onmessage = () => { + this._schedulerPort = null; + callback(); + }; + channel.port2.postMessage(null); + } else { + setTimeout(callback, 0); + } + } + + protected _rebuildNodeIndex(): void { + this._nodeIndexByNodeId = {}; + for (let i = 0; i < this._nodes.length; i++) { + this._nodeIndexByNodeId[this._nodes[i].id] = i; + } + } +} diff --git a/src/simulator/engine/engines/dynamic/force-layout-engine.ts b/src/simulator/engine/engines/dynamic/force-layout-engine.ts new file mode 100644 index 0000000..40dd4f8 --- /dev/null +++ b/src/simulator/engine/engines/dynamic/force-layout-engine.ts @@ -0,0 +1,506 @@ +import { + forceCenter, + forceCollide, + forceLink, + ForceLink, + forceManyBody, + forceSimulation, + forceX, + forceY, + Simulation, + SimulationLinkDatum, +} from 'd3-force'; +import { IPosition } from '../../../../common'; +import { ISimulationNode, ISimulationGraph, ISimulationIds, SimulatorEventType } from '../../../shared'; +import { isObjectEqual, copyObject } from '../../../../utils/object.utils'; +import { IEngineSettingsUpdate, IForceLayoutOptions, DEFAULT_FORCE_LAYOUT_OPTIONS, LayoutType } from '../../shared'; +import { BaseLayoutEngine } from '../base-layout-engine'; + +const MAX_SIMULATION_STEPS = 500; +const CHUNK_SIZE = 100; + +interface IRunSimulationOptions { + isUpdatingSettings: boolean; +} + +export class ForceLayoutEngine extends BaseLayoutEngine { + private _linkForce!: ForceLink>; + private _simulation!: Simulation; + private _settings: IForceLayoutOptions; + + private _isDragging = false; + private _isStabilizing = false; + + private _initialSettings: IForceLayoutOptions | undefined; + + readonly type: LayoutType = 'force'; + + constructor(options?: IForceLayoutOptions) { + super(); + this._settings = { + ...DEFAULT_FORCE_LAYOUT_OPTIONS, + ...options, + }; + this.clearData(); + } + + setSettings(settings: IEngineSettingsUpdate) { + const forceSettings = settings as Partial; + + if (!this._initialSettings) { + this._initialSettings = Object.assign(copyObject(DEFAULT_FORCE_LAYOUT_OPTIONS), forceSettings); + } + + const previousSettings = copyObject(this._settings); + Object.assign(this._settings, forceSettings); + + if (isObjectEqual(this._settings, previousSettings)) { + return; + } + + this._applySettingsToSimulation(forceSettings); + this.emit(SimulatorEventType.SETTINGS_UPDATE, { + settings: { type: 'force', options: this._settings }, + }); + + const hasPhysicsBeenDisabled = previousSettings.isPhysicsEnabled && !forceSettings.isPhysicsEnabled; + + if (hasPhysicsBeenDisabled) { + this._simulation.stop(); + } else if (this._settings.isSimulatingOnSettingsUpdate && this._nodes.length > 0) { + this.activateSimulation(); + } + } + + setupData(data: ISimulationGraph) { + this.clearData(); + this._initializeNewData(data); + + if (this._settings.isSimulatingOnDataUpdate) { + this._updateSimulationData(); + this._runSimulation(); + } + } + + mergeData(data: ISimulationGraph) { + this._initializeNewData(data); + + if (!this._settings.isPhysicsEnabled) { + this._pinNodes(); + } + + if (this._settings.isSimulatingOnDataUpdate) { + this._updateSimulationData(); + this.activateSimulation(); + } + } + + updateData(data: ISimulationGraph) { + const newNodeIds = new Set(data.nodes.map((node) => node.id)); + const oldNodes = this._nodes.filter((node) => newNodeIds.has(node.id)); + const newNodes = data.nodes.filter((node) => this._nodeIndexByNodeId[node.id] === undefined); + + this._nodes = [...oldNodes, ...newNodes]; + this._rebuildNodeIndex(); + this._edges = data.edges; + + if (this._settings.isSimulatingOnSettingsUpdate) { + this._updateSimulationData(); + this.activateSimulation(); + } + } + + deleteData(data: Partial) { + if (data.nodeIds) { + const nodeIds = new Set(data.nodeIds); + this._nodes = this._nodes.filter((node) => !nodeIds.has(node.id)); + } + if (data.edgeIds) { + const edgeIds = new Set(data.edgeIds); + this._edges = this._edges.filter((edge) => !edgeIds.has(edge.id)); + } + this._rebuildNodeIndex(); + + if (this._settings.isSimulatingOnDataUpdate) { + this._updateSimulationData(); + this.activateSimulation(); + } + } + + patchData(data: Partial) { + if (data.nodes) { + const nodeIds: { [id: number]: number } = {}; + + for (let i = 0; i < this._nodes.length; i++) { + nodeIds[this._nodes[i].id] = i; + } + + for (let i = 0; i < data.nodes.length; i += 1) { + const nodeId: number = data.nodes[i].id; + + if (nodeId in nodeIds) { + const index = nodeIds[nodeId]; + this._nodeIndexByNodeId[nodeId] = index; + this._nodes[index] = data.nodes[i]; + } else { + this._nodes.push(data.nodes[i]); + } + } + } + + if (data.edges) { + const edgeIds: { [id: number]: number } = {}; + for (let i = 0; i < this._edges.length; i++) { + edgeIds[this._edges[i].id] = i; + } + for (let i = 0; i < data.edges.length; i++) { + const edgeId = data.edges[i].id; + if (edgeId in edgeIds) { + this._edges[edgeIds[edgeId]] = data.edges[i]; + } else { + this._edges.push(data.edges[i]); + } + } + } + } + + clearData() { + this._nodes = []; + this._edges = []; + this._rebuildNodeIndex(); + this._resetSimulation(); + } + + activateSimulation() { + if (this._settings.isPhysicsEnabled) { + this._unpinNodes(); + } else { + this._pinNodes(); + } + this._simulation.alpha(this._settings.alpha.alpha).alphaTarget(this._settings.alpha.alphaTarget).restart(); + } + + stopSimulation() { + this._simulation.stop(); + } + + startDragNode() { + this._isDragging = true; + + if (!this._isStabilizing && this._settings.isPhysicsEnabled) { + this.activateSimulation(); + } + } + + dragNode(nodeId: number, position: IPosition) { + const node = this._nodes[this._nodeIndexByNodeId[nodeId]]; + if (!node) { + return; + } + + if (!this._isDragging) { + this.startDragNode(); + } + + node.fx = position.x; + node.fy = position.y; + + if (!this._settings.isPhysicsEnabled) { + node.x = position.x; + node.y = position.y; + } + + this.emit(SimulatorEventType.NODE_DRAG, { nodes: this._nodes, edges: this._edges }); + } + + endDragNode(nodeId: number) { + this._isDragging = false; + + if (this._settings.isPhysicsEnabled) { + this._simulation.alphaTarget(0); + } + const node = this._nodes[this._nodeIndexByNodeId[nodeId]]; + if (node && this._settings.isPhysicsEnabled) { + this._unpinNode(node); + } + } + + fixNodes(nodes?: ISimulationNode[]) { + if (!nodes) { + nodes = this._nodes; + } + for (let i = 0; i < nodes.length; i++) { + this._stickNode(nodes[i]); + } + } + + releaseNodes(nodes?: ISimulationNode[]) { + if (!nodes) { + nodes = this._nodes; + } + for (let i = 0; i < nodes.length; i++) { + this._unstickNode(nodes[i]); + } + + if (this._settings.isSimulatingOnUnstick && this._nodes.length > 0) { + this.activateSimulation(); + } + } + + terminate() { + super.terminate(); + this._simulation?.stop(); + } + + // TODO(Alex): Listeners memory leak (D3 force research) + private _resetSimulation() { + if (this._simulation) { + this._simulation.stop(); + this._simulation.on('tick', null).on('end', null); + } + + this._linkForce = forceLink>(this._edges).id( + (node) => node.id, + ); + this._simulation = forceSimulation(this._nodes).force('link', this._linkForce).stop(); + + this._applySettingsToSimulation(this._settings); + + this._simulation.on('tick', () => { + this.emit(SimulatorEventType.SIMULATION_STEP, { nodes: this._nodes, edges: this._edges }); + }); + + this._simulation.on('end', () => { + this._isDragging = false; + this._isStabilizing = false; + this.emit(SimulatorEventType.SIMULATION_END, { nodes: this._nodes, edges: this._edges }); + + if (!this._settings.isPhysicsEnabled) { + this._pinNodes(); + } + }); + } + + private _runSimulation(options?: IRunSimulationOptions) { + if (this._isStabilizing || this._cancelSimulation) { + return; + } + + if (this._settings.isPhysicsEnabled || options?.isUpdatingSettings) { + this._unpinNodes(); + } + + this.emit(SimulatorEventType.SIMULATION_START, undefined); + + this._isStabilizing = true; + this._simulation.alpha(this._settings.alpha.alpha).alphaTarget(this._settings.alpha.alphaTarget).stop(); + + const totalSimulationSteps = Math.min( + MAX_SIMULATION_STEPS, + Math.ceil(Math.log(this._settings.alpha.alphaMin) / Math.log(1 - this._settings.alpha.alphaDecay)), + ); + + let lastProgress = -1; + let step = 0; + + const runChunk = () => { + if (this._cancelSimulation) { + this._isStabilizing = false; + this._cancelSimulation = false; + return; + } + + const end = Math.min(step + CHUNK_SIZE, totalSimulationSteps); + + for (; step < end; step++) { + this._simulation.tick(); + + const currentProgress = Math.round((step * 100) / totalSimulationSteps); + if (currentProgress > lastProgress) { + lastProgress = currentProgress; + this.emit(SimulatorEventType.SIMULATION_PROGRESS, { + nodes: this._nodes, + edges: this._edges, + progress: currentProgress / 100, + }); + } + } + + if (step < totalSimulationSteps && !this._cancelSimulation) { + this._scheduleNext(runChunk); + } else { + if (!this._settings.isPhysicsEnabled) { + this._pinNodes(); + } + + this._isStabilizing = false; + this._cancelSimulation = false; + this.emit(SimulatorEventType.SIMULATION_END, { nodes: this._nodes, edges: this._edges }); + } + }; + + runChunk(); + } + + private _updateSimulationData() { + this._simulation.nodes(this._nodes); + this._linkForce.links(this._edges); + } + + private _initializeNewData(data: Partial) { + if (data.nodes) { + for (let i = 0; i < data.nodes.length; i += 1) { + const nodeId = data.nodes[i].id; + + if (this._nodeIndexByNodeId[nodeId] !== undefined) { + this._nodeIndexByNodeId[nodeId] = i; + } else { + this._nodes.push(data.nodes[i]); + } + } + } else { + this._nodes = []; + } + + if (data.edges) { + const edgeIds: { [id: number]: number } = {}; + for (let i = 0; i < this._edges.length; i++) { + edgeIds[this._edges[i].id] = i; + } + for (let i = 0; i < data.edges.length; i++) { + const edgeId = data.edges[i].id; + if (edgeId in edgeIds) { + this._edges[edgeIds[edgeId]] = data.edges[i]; + } else { + this._edges.push(data.edges[i]); + } + } + } else { + this._edges = []; + } + + this._rebuildNodeIndex(); + } + + private _pinNodes(nodes?: ISimulationNode[]) { + if (!nodes) { + nodes = this._nodes; + } + for (let i = 0; i < nodes.length; i++) { + this._pinNode(this._nodes[i]); + } + } + + private _unpinNodes(nodes?: ISimulationNode[]) { + if (!nodes) { + nodes = this._nodes; + } + + for (let i = 0; i < nodes.length; i++) { + this._unpinNode(this._nodes[i]); + } + } + + private _pinNode(node: ISimulationNode) { + if (node.sx === null || node.sx === undefined) { + node.fx = node.x; + } + + if (node.sy === null || node.sy === undefined) { + node.fy = node.y; + } + } + + private _unpinNode(node: ISimulationNode) { + if (node.sx === null || node.sx === undefined) { + node.fx = null; + } + + if (node.sy === null || node.sy === undefined) { + node.fy = null; + } + } + + private _stickNode(node: ISimulationNode) { + node.sx = node.x; + node.fx = node.x; + node.sy = node.y; + node.fy = node.y; + } + + private _unstickNode(node: ISimulationNode) { + node.sx = null; + node.sy = null; + + if (this._settings.isPhysicsEnabled) { + node.fx = null; + node.fy = null; + } + } + + private _applySettingsToSimulation(settings: Partial) { + if (settings.alpha) { + this._simulation + .alpha(settings.alpha.alpha) + .alphaMin(settings.alpha.alphaMin) + .alphaDecay(settings.alpha.alphaDecay) + .alphaTarget(settings.alpha.alphaTarget); + } + + if (settings.links) { + this._linkForce.distance(settings.links.distance).iterations(settings.links.iterations); + } + + if (settings.collision) { + const collision = forceCollide() + .radius(settings.collision.radius) + .strength(settings.collision.strength) + .iterations(settings.collision.iterations); + this._simulation.force('collide', collision); + } + + if (settings.collision === null) { + this._simulation.force('collide', null); + } + + if (settings.manyBody) { + const manyBody = forceManyBody() + .strength(settings.manyBody.strength) + .theta(settings.manyBody.theta) + .distanceMin(settings.manyBody.distanceMin) + .distanceMax(settings.manyBody.distanceMax); + this._simulation.force('charge', manyBody); + } + + if (settings.manyBody === null) { + this._simulation.force('charge', null); + } + + if (settings.positioning?.forceX) { + const positioningForceX = forceX(settings.positioning.forceX.x).strength(settings.positioning.forceX.strength); + this._simulation.force('x', positioningForceX); + } + + if (settings.positioning?.forceX === null) { + this._simulation.force('x', null); + } + + if (settings.positioning?.forceY) { + const positioningForceY = forceY(settings.positioning.forceY.y).strength(settings.positioning.forceY.strength); + this._simulation.force('y', positioningForceY); + } + + if (settings.positioning?.forceY === null) { + this._simulation.force('y', null); + } + + if (settings.centering) { + const centering = forceCenter(settings.centering.x, settings.centering.y).strength(settings.centering.strength); + this._simulation.force('center', centering); + } + + if (settings.centering === null) { + this._simulation.force('center', null); + } + } +} diff --git a/src/simulator/engine/engines/static/circular-layout-engine.ts b/src/simulator/engine/engines/static/circular-layout-engine.ts new file mode 100644 index 0000000..24b3903 --- /dev/null +++ b/src/simulator/engine/engines/static/circular-layout-engine.ts @@ -0,0 +1,49 @@ +import { ISimulationNode, ISimulationEdge } from '../../../shared'; +import { ICircularLayoutOptions, DEFAULT_CIRCULAR_LAYOUT_OPTIONS, LayoutType } from '../../shared'; +import { CHUNK_SIZE, StaticLayoutEngine } from './static-layout-engine'; + +export class CircularLayoutEngine extends StaticLayoutEngine { + protected _config: ICircularLayoutOptions; + + readonly type: LayoutType = 'circular'; + + constructor(options?: ICircularLayoutOptions) { + super(); + this._config = { ...DEFAULT_CIRCULAR_LAYOUT_OPTIONS, ...options }; + } + + protected calculatePositions( + nodes: ISimulationNode[], + _edges: ISimulationEdge[], + onProgress: (progress: number) => void, + isCancelled: () => boolean, + onComplete: () => void, + ) { + const angleStep = (2 * Math.PI) / nodes.length; + let lastProgress = -1; + let step = 0; + + const runChunk = () => { + if (isCancelled()) { + onComplete(); + return; + } + + const end = Math.min(step + CHUNK_SIZE, nodes.length); + + for (; step < end; step++) { + nodes[step].x = this._config.centerX + this._config.radius * Math.cos(angleStep * step); + nodes[step].y = this._config.centerY + this._config.radius * Math.sin(angleStep * step); + } + + if (step < nodes.length && !this._cancelSimulation) { + lastProgress = this._emitProgress(step + 1, nodes.length, lastProgress, onProgress); + this._scheduleNext(runChunk); + } else { + onComplete(); + } + }; + + runChunk(); + } +} diff --git a/src/simulator/engine/engines/static/grid-layout-engine.ts b/src/simulator/engine/engines/static/grid-layout-engine.ts new file mode 100644 index 0000000..d4b51de --- /dev/null +++ b/src/simulator/engine/engines/static/grid-layout-engine.ts @@ -0,0 +1,53 @@ +import { ISimulationNode, ISimulationEdge } from '../../../shared'; +import { IGridLayoutOptions, DEFAULT_GRID_LAYOUT_OPTIONS, LayoutType } from '../../shared'; +import { CHUNK_SIZE, StaticLayoutEngine } from './static-layout-engine'; + +export class GridLayoutEngine extends StaticLayoutEngine { + protected _config: IGridLayoutOptions; + + readonly type: LayoutType = 'grid'; + + constructor(options?: IGridLayoutOptions) { + super(); + this._config = { ...DEFAULT_GRID_LAYOUT_OPTIONS, ...options }; + } + + protected calculatePositions( + nodes: ISimulationNode[], + _edges: ISimulationEdge[], + onProgress: (progress: number) => void, + isCancelled: () => boolean, + onComplete: () => void, + ) { + const rows = Math.ceil(Math.sqrt(nodes.length)); + const cols = Math.ceil(nodes.length / rows); + let lastProgress = -1; + let step = 0; + + const runChunk = () => { + if (isCancelled()) { + onComplete(); + return; + } + + const end = Math.min(step + CHUNK_SIZE, nodes.length); + + for (; step < end; step++) { + const row = Math.floor(step / cols); + const col = step % cols; + nodes[step].x = col * this._config.colGap; + nodes[step].y = row * this._config.rowGap; + } + + if (step < nodes.length && !this._cancelSimulation) { + console.log(step); + lastProgress = this._emitProgress(step + 1, nodes.length, lastProgress, onProgress); + this._scheduleNext(runChunk); + } else { + onComplete(); + } + }; + + runChunk(); + } +} diff --git a/src/simulator/engine/engines/static/hierarchical-layout-engine.ts b/src/simulator/engine/engines/static/hierarchical-layout-engine.ts new file mode 100644 index 0000000..4c1fdae --- /dev/null +++ b/src/simulator/engine/engines/static/hierarchical-layout-engine.ts @@ -0,0 +1,220 @@ +import { ISimulationNode, ISimulationEdge } from '../../../shared'; +import { IHierarchicalLayoutOptions, DEFAULT_HIERARCHICAL_LAYOUT_OPTIONS, LayoutType } from '../../shared'; +import { StaticLayoutEngine } from './static-layout-engine'; + +export class HierarchicalLayoutEngine extends StaticLayoutEngine { + protected _config: IHierarchicalLayoutOptions; + + readonly type: LayoutType = 'hierarchical'; + + constructor(options?: IHierarchicalLayoutOptions) { + super(); + this._config = { ...DEFAULT_HIERARCHICAL_LAYOUT_OPTIONS, ...options }; + } + + protected calculatePositions( + nodes: ISimulationNode[], + edges: ISimulationEdge[], + onProgress: (progress: number) => void, + isCancelled: () => boolean, + onComplete: () => void, + ) { + const { adjacency, inDegree } = this._buildAdjacency(nodes, edges); + const components = this._getConnectedComponents(nodes, adjacency); + + let maxX = 0; + let maxHeight = 0; + let counter = 0; + let lastProgress = -1; + let componentIndex = 0; + + const processComponent = () => { + if (isCancelled() || componentIndex >= components.length) { + if (!isCancelled() && this._config.reversed) { + this._applyReversal(nodes, maxX, maxHeight); + } + onComplete(); + return; + } + + const levels = this._assignLevels(components[componentIndex], adjacency, inDegree); + const maxLevelSize = Math.max(...Array.from(levels.values()).map((level) => level.length)); + + if (levels.size * this._config.levelGap > maxHeight) { + maxHeight = levels.size * this._config.levelGap; + } + + let offsetX = componentIndex === 0 ? 0 : this._config.treeGap + maxX; + + if (componentIndex > 0) { + offsetX += ((maxLevelSize - 1) * this._config.nodeGap) / 2; + } + + for (let j = 0; j < levels.size; j++) { + const y = j * this._config.levelGap; + const level = levels.get(j); + if (!level) { + continue; + } + + const width = level.length * this._config.nodeGap; + + for (let k = 0; k < level.length; k++) { + const nodeId = level[k]; + const nodeIndex = this._nodeIndexByNodeId[nodeId]; + const x = width / 2 - k * this._config.nodeGap + offsetX; + + if (x > maxX) { + maxX = x; + } + + if (nodeIndex !== undefined) { + nodes[nodeIndex].x = this._config.orientation === 'horizontal' ? y : x; + nodes[nodeIndex].y = this._config.orientation === 'horizontal' ? x : y; + } + + counter++; + } + } + + componentIndex++; + + if (componentIndex < components.length && !this._cancelSimulation) { + lastProgress = this._emitProgress(counter, nodes.length, lastProgress, onProgress); + this._scheduleNext(processComponent); + } else { + if (!isCancelled() && this._config.reversed) { + this._applyReversal(nodes, maxX, maxHeight); + } + onComplete(); + } + }; + + processComponent(); + } + + private _applyReversal(nodes: ISimulationNode[], maxX: number, maxHeight: number) { + for (let i = 0; i < nodes.length; i++) { + if (this._config.orientation === 'horizontal' && nodes[i].x !== undefined) { + nodes[i].x = maxX - (nodes[i].x ?? 0); + } + if (this._config.orientation === 'vertical' && nodes[i].y !== undefined) { + nodes[i].y = maxHeight - (nodes[i].y ?? 0); + } + } + } + + private _buildAdjacency( + _nodes: ISimulationNode[], + edges: ISimulationEdge[], + ): { adjacency: Map; inDegree: Map } { + const adjacency = new Map(); + const inDegree = new Map(); + + for (let i = 0; i < edges.length; i++) { + const sourceId = this._getEdgeEndpointId(edges[i].source); + const targetId = this._getEdgeEndpointId(edges[i].target); + + if (sourceId === targetId) { + continue; + } + + if (!adjacency.has(sourceId)) { + adjacency.set(sourceId, []); + } + if (!adjacency.has(targetId)) { + adjacency.set(targetId, []); + } + + adjacency.get(sourceId)?.push(targetId); + adjacency.get(targetId)?.push(sourceId); + + inDegree.set(targetId, (inDegree.get(targetId) ?? 0) + 1); + } + + return { adjacency, inDegree }; + } + + private _getConnectedComponents(nodes: ISimulationNode[], adjacency: Map): number[][] { + const visited = new Set(); + const components: number[][] = []; + + for (let i = 0; i < nodes.length; i++) { + const nodeId = nodes[i].id; + if (visited.has(nodeId)) { + continue; + } + + const component: number[] = []; + const queue: number[] = [nodeId]; + visited.add(nodeId); + + while (queue.length > 0) { + const current = queue.pop(); + if (current === undefined) { + continue; + } + + component.push(current); + + const neighbors = adjacency.get(current) ?? []; + for (let j = 0; j < neighbors.length; j++) { + if (!visited.has(neighbors[j])) { + visited.add(neighbors[j]); + queue.push(neighbors[j]); + } + } + } + + components.push(component); + } + + return components; + } + + private _assignLevels( + componentNodeIds: number[], + adjacency: Map, + inDegree: Map, + ): Map { + const levels = new Map(); + const visited = new Set(); + + let root = componentNodeIds.find((id) => (inDegree.get(id) ?? 0) === 0); + if (root === undefined) { + root = componentNodeIds.reduce((minId, id) => + (inDegree.get(id) ?? 0) < (inDegree.get(minId) ?? 0) ? id : minId, + ); + } + + const queue: [number, number][] = [[root, 0]]; + + for (const [nodeId, level] of queue) { + if (visited.has(nodeId)) { + continue; + } + + visited.add(nodeId); + + if (levels.has(level)) { + levels.get(level)?.push(nodeId); + } else { + levels.set(level, [nodeId]); + } + + const neighbors = adjacency.get(nodeId) ?? []; + for (let i = 0; i < neighbors.length; i++) { + queue.push([neighbors[i], level + 1]); + } + } + + return levels; + } + + private _getEdgeEndpointId(endpoint: number | string | ISimulationNode): number { + if (typeof endpoint === 'object') { + return endpoint.id; + } + return endpoint as number; + } +} diff --git a/src/simulator/engine/engines/static/static-layout-engine.ts b/src/simulator/engine/engines/static/static-layout-engine.ts new file mode 100644 index 0000000..08f9869 --- /dev/null +++ b/src/simulator/engine/engines/static/static-layout-engine.ts @@ -0,0 +1,233 @@ +import { IPosition } from '../../../../common'; +import { copyObject, isObjectEqual } from '../../../../utils/object.utils'; +import { + ISimulationNode, + ISimulationEdge, + ISimulationGraph, + ISimulationIds, + SimulatorEventType, +} from '../../../shared'; +import { IEngineSettingsUpdate, ILayoutOptionsBase, LayoutType } from '../../shared'; +import { BaseLayoutEngine } from '../base-layout-engine'; + +export const CHUNK_SIZE = 5000; + +export abstract class StaticLayoutEngine extends BaseLayoutEngine { + protected abstract _config: T; + + private _isCalculating = false; + private _pendingRecalculation = false; + + abstract readonly type: LayoutType; + + setupData(data: ISimulationGraph) { + this._nodes = [...data.nodes]; + this._edges = [...data.edges]; + this._rebuildNodeIndex(); + this._calculateAndEmit(); + } + + mergeData(data: ISimulationGraph) { + if (data.nodes) { + for (let i = 0; i < data.nodes.length; i++) { + const existingIndex = this._nodeIndexByNodeId[data.nodes[i].id]; + if (existingIndex !== undefined) { + this._nodes[existingIndex] = data.nodes[i]; + } else { + this._nodes.push(data.nodes[i]); + } + } + } + + if (data.edges) { + const edgeIds: { [id: number]: number } = {}; + for (let i = 0; i < this._edges.length; i++) { + edgeIds[this._edges[i].id] = i; + } + for (let i = 0; i < data.edges.length; i++) { + const edgeId = data.edges[i].id; + if (edgeId in edgeIds) { + this._edges[edgeIds[edgeId]] = data.edges[i]; + } else { + this._edges.push(data.edges[i]); + } + } + } + + this._rebuildNodeIndex(); + this._calculateAndEmit(); + } + + updateData(data: ISimulationGraph) { + const newNodeIds = new Set(data.nodes.map((node) => node.id)); + const oldNodes = this._nodes.filter((node) => newNodeIds.has(node.id)); + const newNodes = data.nodes.filter((node) => this._nodeIndexByNodeId[node.id] === undefined); + + this._nodes = [...oldNodes, ...newNodes]; + this._edges = data.edges; + this._rebuildNodeIndex(); + this._calculateAndEmit(); + } + + deleteData(data: Partial) { + if (data.nodeIds) { + const nodeIds = new Set(data.nodeIds); + this._nodes = this._nodes.filter((node) => !nodeIds.has(node.id)); + } + + if (data.edgeIds) { + const edgeIds = new Set(data.edgeIds); + this._edges = this._edges.filter((edge) => !edgeIds.has(edge.id)); + } + + this._rebuildNodeIndex(); + this._calculateAndEmit(); + } + + patchData(data: Partial) { + if (data.nodes) { + for (let i = 0; i < data.nodes.length; i++) { + const id: number = data.nodes[i].id; + const index = this._nodeIndexByNodeId[id]; + if (index !== undefined) { + this._nodes[index] = data.nodes[i]; + } else { + this._nodes.push(data.nodes[i]); + this._nodeIndexByNodeId[id] = this._nodes.length - 1; + } + } + } + + if (data.edges) { + const edgeIds: { [id: number]: number } = {}; + for (let i = 0; i < this._edges.length; i++) { + edgeIds[this._edges[i].id] = i; + } + for (let i = 0; i < data.edges.length; i++) { + const edgeId = data.edges[i].id; + if (edgeId in edgeIds) { + this._edges[edgeIds[edgeId]] = data.edges[i]; + } else { + this._edges.push(data.edges[i]); + } + } + } + } + + clearData() { + this._nodes = []; + this._edges = []; + this._nodeIndexByNodeId = {}; + } + + activateSimulation() { + // No-op for static layouts + } + + stopSimulation() { + // No-op for static layouts + } + + startDragNode() { + // No-op for static layouts + } + + dragNode(nodeId: number, position: IPosition) { + const index = this._nodeIndexByNodeId[nodeId]; + if (index !== undefined) { + const node = this._nodes[index]; + node.x = position.x; + node.y = position.y; + node.fx = position.x; + node.fy = position.y; + this.emit(SimulatorEventType.NODE_DRAG, { nodes: this._nodes, edges: this._edges }); + } + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + endDragNode(_nodeId: number) { + // No-op for static layouts + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + fixNodes(_nodes?: ISimulationNode[]) { + // No-op for static layouts + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + releaseNodes(_nodes?: ISimulationNode[]) { + // No-op for static layouts + } + + setSettings(settings: IEngineSettingsUpdate) { + const previous = copyObject(this._config); + Object.assign(this._config, settings); + + if (!isObjectEqual(this._config, previous) && this._nodes.length > 0) { + this._calculateAndEmit(); + } + } + + terminate() { + this._pendingRecalculation = false; + super.terminate(); + } + + protected _calculateAndEmit() { + if (this._nodes.length === 0 || this._cancelSimulation) { + return; + } + + if (this._isCalculating) { + this._pendingRecalculation = true; + return; + } + + this._isCalculating = true; + this.emit(SimulatorEventType.SIMULATION_START, undefined); + + this.calculatePositions( + this._nodes, + this._edges, + (progress) => { + this.emit(SimulatorEventType.SIMULATION_PROGRESS, { + nodes: this._nodes, + edges: this._edges, + progress, + }); + }, + () => this._cancelSimulation, + () => { + this._isCalculating = false; + + if (!this._cancelSimulation) { + this.emit(SimulatorEventType.SIMULATION_END, { nodes: this._nodes, edges: this._edges }); + } + + this._cancelSimulation = false; + + if (this._pendingRecalculation) { + this._pendingRecalculation = false; + this._calculateAndEmit(); + } + }, + ); + } + + protected abstract calculatePositions( + nodes: ISimulationNode[], + edges: ISimulationEdge[], + onProgress: (progress: number) => void, + isCancelled: () => boolean, + onComplete: () => void, + ): void; + + protected _emitProgress(index: number, total: number, lastProgress: number, onProgress: (p: number) => void): number { + const currentProgress = Math.round((index * 100) / total); + if (currentProgress > lastProgress) { + onProgress(currentProgress / 100); + return currentProgress; + } + return lastProgress; + } +} diff --git a/src/simulator/engine/factory.ts b/src/simulator/engine/factory.ts new file mode 100644 index 0000000..aa1e058 --- /dev/null +++ b/src/simulator/engine/factory.ts @@ -0,0 +1,29 @@ +import { + ILayoutEngine, + ILayoutSettings, + ICircularLayoutOptions, + IGridLayoutOptions, + IHierarchicalLayoutOptions, + IForceLayoutOptions, +} from './shared'; +import { ForceLayoutEngine } from './engines/dynamic/force-layout-engine'; +import { CircularLayoutEngine } from './engines/static/circular-layout-engine'; +import { GridLayoutEngine } from './engines/static/grid-layout-engine'; +import { HierarchicalLayoutEngine } from './engines/static/hierarchical-layout-engine'; +import { DeepPartial } from '../../utils/type.utils'; + +export class LayoutEngineFactory { + static create(settings?: DeepPartial): ILayoutEngine { + switch (settings?.type) { + case 'circular': + return new CircularLayoutEngine(settings.options as ICircularLayoutOptions); + case 'grid': + return new GridLayoutEngine(settings.options as IGridLayoutOptions); + case 'hierarchical': + return new HierarchicalLayoutEngine(settings.options as IHierarchicalLayoutOptions); + case 'force': + default: + return new ForceLayoutEngine(settings?.options as IForceLayoutOptions); + } + } +} diff --git a/src/simulator/engine/shared.ts b/src/simulator/engine/shared.ts new file mode 100644 index 0000000..4bf5ac1 --- /dev/null +++ b/src/simulator/engine/shared.ts @@ -0,0 +1,203 @@ +import { IPosition } from '../../common'; +import { IEmitter } from '../../utils/emitter.utils'; +import { DeepPartial } from '../../utils/type.utils'; +import { ISimulationNode, ISimulationGraph, ISimulationIds, SimulatorEvents } from '../shared'; + +export type LayoutType = 'circular' | 'force' | 'grid' | 'hierarchical'; + +export interface ILayoutOptionsBase { + anchorX?: 'start' | 'center' | 'end'; + anchorY?: 'start' | 'center' | 'end'; +} + +export interface ICircularLayoutOptions extends ILayoutOptionsBase { + radius: number; + centerX: number; + centerY: number; +} + +export const DEFAULT_CIRCULAR_LAYOUT_OPTIONS: ICircularLayoutOptions = { + radius: 100, + centerX: 0, + centerY: 0, +}; + +export interface IForceLayoutOptions extends ILayoutOptionsBase { + isSimulatingOnDataUpdate: boolean; + isSimulatingOnSettingsUpdate: boolean; + isSimulatingOnUnstick: boolean; + isPhysicsEnabled: boolean; + alpha: IForceLayoutAlpha; + centering: IForceLayoutCentering | null; + collision: IForceLayoutCollision | null; + links: IForceLayoutLinks; + manyBody: IForceLayoutManyBody | null; + positioning: IForceLayoutPositioning | null; +} + +const MANY_BODY_MAX_DISTANCE_TO_LINK_DISTANCE_RATIO = 100; +const DEFAULT_LINK_DISTANCE = 50; + +export const getManyBodyMaxDistance = (linkDistance: number) => { + const distance = linkDistance > 0 ? linkDistance : 1; + return distance * MANY_BODY_MAX_DISTANCE_TO_LINK_DISTANCE_RATIO; +}; + +export const DEFAULT_FORCE_LAYOUT_OPTIONS: IForceLayoutOptions = { + isSimulatingOnDataUpdate: true, + isSimulatingOnSettingsUpdate: true, + isSimulatingOnUnstick: true, + isPhysicsEnabled: false, + alpha: { + alpha: 1, + alphaMin: 0.05, // default alphaMin is 0.001, which results in 285 ticks to converge. Using 0.05 converges to similar stable results in 106 ticks + alphaDecay: 0.028, + alphaTarget: 0, + }, + centering: { + x: 0, + y: 0, + strength: 1, + }, + collision: { + radius: 15, + strength: 1, + iterations: 1, + }, + links: { + distance: DEFAULT_LINK_DISTANCE, + strength: 1, + iterations: 1, + }, + manyBody: { + strength: -100, + theta: 0.9, + distanceMin: 0, + distanceMax: getManyBodyMaxDistance(DEFAULT_LINK_DISTANCE), + }, + positioning: { + forceX: { + x: 0, + strength: 0.1, + }, + forceY: { + y: 0, + strength: 0.1, + }, + }, + anchorX: 'center', + anchorY: 'center', +}; + +export interface IGridLayoutOptions extends ILayoutOptionsBase { + rowGap: number; + colGap: number; +} + +export const DEFAULT_GRID_LAYOUT_OPTIONS: IGridLayoutOptions = { + rowGap: 50, + colGap: 50, +}; + +export type HierarchicalLayoutOrientation = 'horizontal' | 'vertical'; + +export interface IHierarchicalLayoutOptions extends ILayoutOptionsBase { + nodeGap: number; + levelGap: number; + treeGap: number; + orientation: HierarchicalLayoutOrientation; + reversed: boolean; +} + +export const DEFAULT_HIERARCHICAL_LAYOUT_OPTIONS: IHierarchicalLayoutOptions = { + nodeGap: 50, + levelGap: 50, + treeGap: 100, + orientation: 'vertical', + reversed: false, +}; + +export type LayoutSettingsMap = { + circular: ICircularLayoutOptions; + force: IForceLayoutOptions; + grid: IGridLayoutOptions; + hierarchical: IHierarchicalLayoutOptions; +}; + +export interface ILayoutSettings { + type: LayoutType; + options?: DeepPartial; +} + +export interface IForceLayoutAlpha { + alpha: number; + alphaMin: number; + alphaDecay: number; + alphaTarget: number; +} + +export interface IForceLayoutCentering { + x: number; + y: number; + strength: number; +} + +export interface IForceLayoutCollision { + radius: number; + strength: number; + iterations: number; +} + +export interface IForceLayoutLinks { + distance: number; + strength?: number; + iterations: number; +} + +export interface IForceLayoutManyBody { + strength: number; + theta: number; + distanceMin: number; + distanceMax: number; +} + +export interface IForceLayoutPositioning { + forceX: { + x: number; + strength: number; + }; + forceY: { + y: number; + strength: number; + }; +} + +export type IEngineSettingsUpdate = + | Partial + | Partial + | Partial + | Partial; + +export interface ILayoutEngine extends IEmitter { + readonly type: LayoutType; + + setupData(data: ISimulationGraph): void; + mergeData(data: ISimulationGraph): void; + updateData(data: ISimulationGraph): void; + deleteData(data: Partial): void; + patchData(data: Partial): void; + clearData(): void; + + activateSimulation(): void; + stopSimulation(): void; + + startDragNode(): void; + dragNode(nodeId: number, position: IPosition): void; + endDragNode(nodeId: number): void; + fixNodes(nodes?: ISimulationNode[]): void; + releaseNodes(nodes?: ISimulationNode[]): void; + + setSettings(settings: IEngineSettingsUpdate): void; + + terminate(): void; +} diff --git a/src/simulator/factory.ts b/src/simulator/factory.ts index e902e6f..4470442 100644 --- a/src/simulator/factory.ts +++ b/src/simulator/factory.ts @@ -1,13 +1,16 @@ +import { DeepPartial } from '../utils/type.utils'; +import { ILayoutSettings } from './engine/shared'; import { ISimulator } from './shared'; import { MainThreadSimulator } from './types/main-thread-simulator'; import { WebWorkerSimulator } from './types/web-worker-simulator/web-worker-simulator'; // TODO(dlozic & Alex): CORS handling export class SimulatorFactory { - static getSimulator(): ISimulator { + static getSimulator(settings?: DeepPartial): ISimulator { + const layoutSettings: DeepPartial = { type: 'force', ...settings }; try { if (typeof Worker !== 'undefined') { - return new WebWorkerSimulator(); + return new WebWorkerSimulator(layoutSettings); } throw new Error('WebWorkers are unavailable in your environment.'); } catch (err) { @@ -15,7 +18,7 @@ export class SimulatorFactory { 'Could not create simulator in a WebWorker context. All calculations will be done in the main thread.', err, ); - return new MainThreadSimulator(); + return new MainThreadSimulator(layoutSettings); } } } diff --git a/src/simulator/index.ts b/src/simulator/index.ts index 2c02f6d..52154cd 100644 --- a/src/simulator/index.ts +++ b/src/simulator/index.ts @@ -1,2 +1,4 @@ export { SimulatorFactory } from './factory'; export { ISimulator, ISimulationNode, ISimulationEdge } from './shared'; +export { ILayoutEngine, ILayoutSettings, LayoutType, IEngineSettingsUpdate } from './engine/shared'; +export { LayoutEngineFactory } from './engine/factory'; diff --git a/src/simulator/layout/layout.ts b/src/simulator/layout/layout.ts deleted file mode 100644 index e666e4f..0000000 --- a/src/simulator/layout/layout.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { IEdgeBase } from '../../models/edge'; -import { INode, INodeBase, INodePosition } from '../../models/node'; -import { CircularLayout, ICircularLayoutOptions } from './layouts/circular'; -import { IForceLayoutOptions } from './layouts/force'; -import { GridLayout, IGridLayoutOptions } from './layouts/grid'; -import { HierarchicalLayout, IHierarchicalLayoutOptions } from './layouts/hierarchical'; - -export type LayoutType = 'circular' | 'force' | 'grid' | 'hierarchical'; - -export type LayoutSettingsMap = { - circular: ICircularLayoutOptions; - force: IForceLayoutOptions; - grid: IGridLayoutOptions; - hierarchical: IHierarchicalLayoutOptions; -}; - -export interface ILayoutSettings { - type: LayoutType; - options?: LayoutSettingsMap[LayoutType]; -} - -export interface ILayout { - getPositions(nodes: INode[]): INodePosition[]; -} - -export class LayoutFactory { - static create( - settings?: Partial, - ): ILayout | undefined { - switch (settings?.type) { - case 'circular': - return new CircularLayout(settings.options as ICircularLayoutOptions); - case 'force': - return undefined; - case 'grid': - return new GridLayout(settings.options as IGridLayoutOptions); - case 'hierarchical': - return new HierarchicalLayout(settings.options as IHierarchicalLayoutOptions); - default: - throw new Error('Incorrect layout type.'); - } - } -} diff --git a/src/simulator/layout/layouts/circular.ts b/src/simulator/layout/layouts/circular.ts deleted file mode 100644 index 693d9a0..0000000 --- a/src/simulator/layout/layouts/circular.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { IEdgeBase } from '../../../models/edge'; -import { INode, INodeBase, INodePosition } from '../../../models/node'; -import { ILayout } from '../layout'; - -export interface ICircularLayoutOptions { - radius?: number; - centerX?: number; - centerY?: number; -} - -export const DEFAULT_CIRCULAR_LAYOUT_OPTIONS: Required = { - radius: 100, - centerX: 0, - centerY: 0, -}; - -export class CircularLayout implements ILayout { - private _config: Required; - - constructor(options?: ICircularLayoutOptions) { - this._config = { ...DEFAULT_CIRCULAR_LAYOUT_OPTIONS, ...options }; - } - - getPositions(nodes: INode[]): INodePosition[] { - const angleStep = (2 * Math.PI) / nodes.length; - - const positions = nodes.map((node, index) => { - return { - id: node.id, - x: this._config.centerX + this._config.radius * Math.cos(angleStep * index), - y: this._config.centerY + this._config.radius * Math.sin(angleStep * index), - }; - }); - - return positions; - } -} diff --git a/src/simulator/layout/layouts/force.ts b/src/simulator/layout/layouts/force.ts deleted file mode 100644 index 29edc22..0000000 --- a/src/simulator/layout/layouts/force.ts +++ /dev/null @@ -1,11 +0,0 @@ -export interface IForceLayoutOptions { - centerX?: number; - centerY?: number; - nodeDistance?: number; -} - -export const DEFAULT_FORCE_LAYOUT_OPTIONS: Required = { - centerX: 0, - centerY: 0, - nodeDistance: 50, -}; diff --git a/src/simulator/layout/layouts/grid.ts b/src/simulator/layout/layouts/grid.ts deleted file mode 100644 index e48470b..0000000 --- a/src/simulator/layout/layouts/grid.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { IEdgeBase } from '../../../models/edge'; -import { INode, INodeBase, INodePosition } from '../../../models/node'; -import { ILayout } from '../layout'; - -export interface IGridLayoutOptions { - rowGap?: number; - colGap?: number; -} - -export const DEFAULT_GRID_LAYOUT_OPTIONS: Required = { - rowGap: 50, - colGap: 50, -}; - -export class GridLayout implements ILayout { - private _config: Required; - - constructor(options?: IGridLayoutOptions) { - this._config = { ...DEFAULT_GRID_LAYOUT_OPTIONS, ...options }; - } - - getPositions(nodes: INode[]): INodePosition[] { - const rows = Math.ceil(Math.sqrt(nodes.length)); - const cols = Math.ceil(nodes.length / rows); - - const positions: INodePosition[] = []; - - for (let i = 0; i < nodes.length; i++) { - const row = Math.floor(i / cols); - const col = i % cols; - const x = col * this._config.colGap; - const y = row * this._config.rowGap; - positions.push({ id: nodes[i].getId(), x, y }); - } - - return positions; - } -} diff --git a/src/simulator/layout/layouts/hierarchical.ts b/src/simulator/layout/layouts/hierarchical.ts deleted file mode 100644 index 777c1f1..0000000 --- a/src/simulator/layout/layouts/hierarchical.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { IEdge, IEdgeBase } from '../../../models/edge'; -import { INode, INodeBase, INodePosition } from '../../../models/node'; -import { ILayout } from '../layout'; - -export type HierarchicalLayoutOrientation = 'horizontal' | 'vertical'; - -export interface IHierarchicalLayoutOptions { - nodeGap?: number; - levelGap?: number; - treeGap?: number; - orientation?: HierarchicalLayoutOrientation; - reversed?: boolean; -} - -export const DEFAULT_HIERARCHICAL_LAYOUT_OPTIONS: Required = { - nodeGap: 50, - levelGap: 50, - treeGap: 100, - orientation: 'vertical', - reversed: false, -}; - -export class HierarchicalLayout implements ILayout { - private _config: Required; - - constructor(options?: IHierarchicalLayoutOptions) { - this._config = { ...DEFAULT_HIERARCHICAL_LAYOUT_OPTIONS, ...options }; - } - - getPositions(nodes: INode[]): INodePosition[] { - const components = this.getConnectedComponents(nodes); - const positions: INodePosition[] = new Array(nodes.length); - let maxX = 0; - let maxHeight = 0; - let counter = 0; - - for (let i = 0; i < components.length; i++) { - const levels: Map[]> = this.assignLevels(components[i]); - const maxLevelSize = Math.max(...Array.from(levels.values()).map((levelNodes) => levelNodes.length)); - - if (levels.size * this._config.levelGap > maxHeight) { - maxHeight = levels.size * this._config.levelGap; - } - - let offsetX = i === 0 ? 0 : this._config.treeGap + maxX; - - if (i > 0) { - offsetX += ((maxLevelSize - 1) * this._config.nodeGap) / 2; - } - - for (let j = 0; j < levels.size; j++) { - const y = j * this._config.levelGap; - const level = levels.get(j); - if (!level) { - continue; - } - - const width = level.length * this._config.nodeGap; - - for (let k = 0; k < level.length; k++) { - const node = level[k]; - const x = width / 2 - k * this._config.nodeGap + offsetX; - if (x > maxX) { - maxX = x; - } - - positions[counter++] = { - id: node.getId(), - x: this._config.orientation === 'horizontal' ? y : x, - y: this._config.orientation === 'horizontal' ? x : y, - }; - } - } - } - - if (this._config.reversed === true) { - positions.forEach((position) => { - if (this._config.orientation === 'horizontal' && position.x !== undefined) { - position.x = maxX - position.x; - } - if (this._config.orientation === 'vertical' && position.y !== undefined) { - position.y = maxHeight - position.y; - } - }); - } - - return positions; - } - - getConnectedComponents = (nodes: INode[]): INode[][] => { - const visited = new Set>(); - const components: INode[][] = []; - - for (let i = 0; i < nodes.length; i++) { - if (visited.has(nodes[i])) { - continue; - } - - const component: INode[] = []; - const queue: INode[] = [nodes[i]]; - visited.add(nodes[i]); - - while (queue.length > 0) { - const current = queue.pop(); - - if (current) { - component.push(current); - const neighbors = current.getAdjacentNodes(); - for (let j = 0; j < neighbors.length; j++) { - if (visited.has(neighbors[j])) { - continue; - } - - visited.add(neighbors[j]); - queue.push(neighbors[j]); - } - } - } - - components.push(component); - } - - return components; - }; - - assignLevels = (nodes: INode[]): Map[]> => { - const levels = new Map[]>(); - const visited = new Set>(); - - let root = nodes.filter((node) => this.getExternalInEdges(node).length === 0)[0]; - - if (!root) { - root = nodes.sort((a, b) => this.getExternalInEdges(a).length - this.getExternalInEdges(b).length)[0]; - } - - const queue: [INode, number][] = [[root, 0]]; - - for (const [node, level] of queue) { - if (visited.has(node)) { - continue; - } - - visited.add(node); - if (levels.has(level)) { - levels.get(level)?.push(node); - } else { - levels.set(level, [node]); - } - - const neighbors = node.getAdjacentNodes(); - - for (let i = 0; i < neighbors.length; i++) { - queue.push([neighbors[i], level + 1]); - } - } - - return levels; - }; - - getExternalInEdges = (node: INode): IEdge[] => { - return node.getInEdges().filter((edge) => edge.startNode.id !== edge.endNode.id); - }; -} diff --git a/src/simulator/shared.ts b/src/simulator/shared.ts index b1190de..683e444 100644 --- a/src/simulator/shared.ts +++ b/src/simulator/shared.ts @@ -1,7 +1,8 @@ import { IPosition } from '../common'; import { SimulationLinkDatum, SimulationNodeDatum } from 'd3-force'; -import { ID3SimulatorEngineSettings, ID3SimulatorEngineSettingsUpdate } from './engine/d3-simulator-engine'; import { IEmitter } from '../utils/emitter.utils'; +import { ILayoutSettings } from './engine/shared'; +import { DeepPartial } from '../utils/type.utils'; /** * Node with sticky coordinates. @@ -62,7 +63,6 @@ export interface ISimulator extends IEmitter { clearData(): void; // Simulation handlers - simulate(): void; activateSimulation(): void; stopSimulation(): void; @@ -74,8 +74,9 @@ export interface ISimulator extends IEmitter { releaseNodes(nodes?: ISimulationNode[]): void; // Settings handlers - setSettings(settings: ID3SimulatorEngineSettingsUpdate): void; + setSettings(settings: DeepPartial): void; + isSimulationRunning(): boolean; terminate(): void; } @@ -89,7 +90,7 @@ export interface ISimulatorEventProgress { } export interface ISimulatorEventSettings { - settings: ID3SimulatorEngineSettings; + settings: ILayoutSettings; } export interface ISimulatorEvents { diff --git a/src/simulator/types/main-thread-simulator.ts b/src/simulator/types/main-thread-simulator.ts index b560b33..9a930d5 100644 --- a/src/simulator/types/main-thread-simulator.ts +++ b/src/simulator/types/main-thread-simulator.ts @@ -8,101 +8,114 @@ import { } from '../shared'; import { IPosition } from '../../common'; import { Emitter } from '../../utils/emitter.utils'; -import { - D3SimulatorEngine, - D3SimulatorEngineEventType, - ID3SimulatorEngineSettingsUpdate, -} from '../engine/d3-simulator-engine'; +import { ILayoutEngine, ILayoutSettings } from '../engine/shared'; +import { LayoutEngineFactory } from '../engine/factory'; +import { DeepPartial } from '../../utils/type.utils'; export class MainThreadSimulator extends Emitter implements ISimulator { - protected readonly _simulator: D3SimulatorEngine; + private _engine: ILayoutEngine; + private _isSimulationRunning = false; - constructor() { + constructor(settings: DeepPartial) { super(); - this._simulator = new D3SimulatorEngine(); - this._simulator.on(D3SimulatorEngineEventType.SIMULATION_START, () => { - this.emit(SimulatorEventType.SIMULATION_START, undefined); - }); - this._simulator.on(D3SimulatorEngineEventType.SIMULATION_PROGRESS, (data) => { - this.emit(SimulatorEventType.SIMULATION_PROGRESS, data); - }); - this._simulator.on(D3SimulatorEngineEventType.SIMULATION_END, (data) => { - this.emit(SimulatorEventType.SIMULATION_END, data); - }); - this._simulator.on(D3SimulatorEngineEventType.NODE_DRAG, (data) => { - this.emit(SimulatorEventType.NODE_DRAG, data); - }); - this._simulator.on(D3SimulatorEngineEventType.SIMULATION_TICK, (data) => { - this.emit(SimulatorEventType.SIMULATION_STEP, data); - }); - this._simulator.on(D3SimulatorEngineEventType.SETTINGS_UPDATE, (data) => { - this.emit(SimulatorEventType.SETTINGS_UPDATE, data); - }); + this._engine = LayoutEngineFactory.create(settings); + this._wireEngineEvents(); } setupData(data: ISimulationGraph) { - this._simulator.setupData(data); + this._engine.setupData(data); } mergeData(data: ISimulationGraph) { - this._simulator.mergeData(data); + this._engine.mergeData(data); } updateData(data: ISimulationGraph) { - this._simulator.updateData(data); + this._engine.updateData(data); } deleteData(data: ISimulationIds) { - this._simulator.deleteData(data); + this._engine.deleteData(data); } patchData(data: Partial): void { - this._simulator.patchData(data); + this._engine.patchData(data); } clearData() { - this._simulator.clearData(); - } - - simulate() { - console.log('not implemented'); - // this.simulator.runSimulation(); + this._engine.clearData(); } activateSimulation() { - this._simulator.activateSimulation(); + this._engine.activateSimulation(); } stopSimulation() { - this._simulator.stopSimulation(); + this._engine.stopSimulation(); } startDragNode() { - this._simulator.startDragNode(); + this._engine.startDragNode(); } dragNode(nodeId: number, position: IPosition) { - this._simulator.dragNode({ id: nodeId, ...position }); + this._engine.dragNode(nodeId, position); } endDragNode(nodeId: number) { - this._simulator.endDragNode({ id: nodeId }); + this._engine.endDragNode(nodeId); } fixNodes(nodes: ISimulationNode[]) { - this._simulator.stickNodes(nodes); + this._engine.fixNodes(nodes); } releaseNodes(nodes?: ISimulationNode[] | undefined): void { - this._simulator.unstickNodes(nodes); + this._engine.releaseNodes(nodes); + } + + setSettings(settings: ILayoutSettings) { + if (settings.type === this._engine.type && settings.options) { + this._engine.setSettings(settings.options); + return; + } + + this._engine.removeAllListeners(); + this._engine.terminate(); + this._engine = LayoutEngineFactory.create(settings); + this._wireEngineEvents(); } - setSettings(settings: ID3SimulatorEngineSettingsUpdate) { - this._simulator.setSettings(settings); + isSimulationRunning(): boolean { + return this._isSimulationRunning; } terminate() { - this._simulator.removeAllListeners(); + this._engine.removeAllListeners(); + this._engine.terminate(); this.removeAllListeners(); } + + private _wireEngineEvents() { + this._engine.on(SimulatorEventType.SIMULATION_START, () => { + this.emit(SimulatorEventType.SIMULATION_START, undefined); + this._isSimulationRunning = true; + }); + this._engine.on(SimulatorEventType.SIMULATION_PROGRESS, (data) => { + this.emit(SimulatorEventType.SIMULATION_PROGRESS, data); + }); + this._engine.on(SimulatorEventType.SIMULATION_END, (data) => { + this.emit(SimulatorEventType.SIMULATION_END, data); + this._isSimulationRunning = false; + }); + this._engine.on(SimulatorEventType.SIMULATION_STEP, (data) => { + this.emit(SimulatorEventType.SIMULATION_STEP, data); + }); + this._engine.on(SimulatorEventType.NODE_DRAG, (data) => { + this.emit(SimulatorEventType.NODE_DRAG, data); + }); + this._engine.on(SimulatorEventType.SETTINGS_UPDATE, (data) => { + this.emit(SimulatorEventType.SETTINGS_UPDATE, data); + }); + } } diff --git a/src/simulator/types/web-worker-simulator/message/worker-input.ts b/src/simulator/types/web-worker-simulator/message/worker-input.ts index c252d4a..45e830d 100644 --- a/src/simulator/types/web-worker-simulator/message/worker-input.ts +++ b/src/simulator/types/web-worker-simulator/message/worker-input.ts @@ -1,7 +1,8 @@ import { IPosition } from '../../../../common'; import { ISimulationNode, ISimulationEdge } from '../../../shared'; -import { ID3SimulatorEngineSettingsUpdate } from '../../../engine/d3-simulator-engine'; import { IWorkerPayload } from './worker-payload'; +import { ILayoutSettings } from '../../../engine/shared'; +import { DeepPartial } from '../../../../utils/type.utils'; // Messages are objects going into the simulation worker. // They can be thought of similar to requests. @@ -16,7 +17,6 @@ export enum WorkerInputType { ClearData = 'Clear Data', // Simulation message types - Simulate = 'Simulate', ActivateSimulation = 'Activate Simulation', UpdateSimulation = 'Update Simulation', StopSimulation = 'Stop Simulation', @@ -74,8 +74,6 @@ type IWorkerInputPatchDataPayload = IWorkerPayload< type IWorkerInputClearDataPayload = IWorkerPayload; -type IWorkerInputSimulatePayload = IWorkerPayload; - type IWorkerInputActivateSimulationPayload = IWorkerPayload; type IWorkerInputStopSimulationPayload = IWorkerPayload; @@ -113,7 +111,7 @@ type IWorkerInputReleaseNodesPayload = IWorkerPayload< } >; -type IWorkerInputSetSettingsPayload = IWorkerPayload; +type IWorkerInputSetSettingsPayload = IWorkerPayload>; export type IWorkerInputPayload = | IWorkerInputSetupDataPayload @@ -122,7 +120,6 @@ export type IWorkerInputPayload = | IWorkerInputDeleteDataPayload | IWorkerInputPatchDataPayload | IWorkerInputClearDataPayload - | IWorkerInputSimulatePayload | IWorkerInputActivateSimulationPayload | IWorkerInputStopSimulationPayload | IWorkerInputUpdateSimulationPayload diff --git a/src/simulator/types/web-worker-simulator/message/worker-output.ts b/src/simulator/types/web-worker-simulator/message/worker-output.ts index d271bcf..7325e60 100644 --- a/src/simulator/types/web-worker-simulator/message/worker-output.ts +++ b/src/simulator/types/web-worker-simulator/message/worker-output.ts @@ -1,6 +1,6 @@ import { ISimulationNode, ISimulationEdge } from '../../../shared'; import { IWorkerPayload } from './worker-payload'; -import { ID3SimulatorEngineSettings } from '../../../engine/d3-simulator-engine'; +import { ILayoutSettings } from '../../../engine/shared'; export enum WorkerOutputType { SIMULATION_START = 'simulation-start', @@ -59,7 +59,7 @@ type IWorkerOutputNodeDragEndPayload = IWorkerPayload< type IWorkerOutputSettingsUpdatePayload = IWorkerPayload< WorkerOutputType.SETTINGS_UPDATE, { - settings: ID3SimulatorEngineSettings; + settings: ILayoutSettings; } >; diff --git a/src/simulator/types/web-worker-simulator/simulator.worker.ts b/src/simulator/types/web-worker-simulator/simulator.worker.ts index f07da1d..e922c5c 100644 --- a/src/simulator/types/web-worker-simulator/simulator.worker.ts +++ b/src/simulator/types/web-worker-simulator/simulator.worker.ts @@ -1,109 +1,61 @@ // / -import { D3SimulatorEngine, D3SimulatorEngineEventType } from '../../engine/d3-simulator-engine'; +import { LayoutEngineFactory } from '../../engine/factory'; +import { ILayoutEngine, ILayoutSettings } from '../../engine/shared'; +import { SimulatorEventType } from '../../shared'; import { IWorkerInputPayload, WorkerInputType } from './message/worker-input'; import { IWorkerOutputPayload, WorkerOutputType } from './message/worker-output'; -const simulator = new D3SimulatorEngine(); - -const emitToMain = (message: IWorkerOutputPayload) => { - // @ts-ignore Web worker postMessage is a global function - postMessage(message); +let engine: ILayoutEngine | null = null; + +const emitToMain = (message: IWorkerOutputPayload) => postMessage(message); + +function wireEngineEvents(target: ILayoutEngine) { + target.on(SimulatorEventType.SIMULATION_START, () => emitToMain({ type: WorkerOutputType.SIMULATION_START })); + target.on(SimulatorEventType.SIMULATION_PROGRESS, (data) => + emitToMain({ type: WorkerOutputType.SIMULATION_PROGRESS, data }), + ); + target.on(SimulatorEventType.SIMULATION_END, (data) => emitToMain({ type: WorkerOutputType.SIMULATION_END, data })); + target.on(SimulatorEventType.SIMULATION_STEP, (data) => emitToMain({ type: WorkerOutputType.SIMULATION_STEP, data })); + target.on(SimulatorEventType.NODE_DRAG, (data) => emitToMain({ type: WorkerOutputType.NODE_DRAG, data })); + target.on(SimulatorEventType.SETTINGS_UPDATE, (data) => emitToMain({ type: WorkerOutputType.SETTINGS_UPDATE, data })); +} + +type ExtractPayload = Extract; +type EngineHandler = (engine: ILayoutEngine, payload: ExtractPayload) => void; + +const handlers: { [T in WorkerInputType]?: EngineHandler } = { + [WorkerInputType.SetupData]: (e, { data }) => e.setupData(data), + [WorkerInputType.MergeData]: (e, { data }) => e.mergeData(data), + [WorkerInputType.UpdateData]: (e, { data }) => e.updateData(data), + [WorkerInputType.DeleteData]: (e, { data }) => e.deleteData(data), + [WorkerInputType.PatchData]: (e, { data }) => e.patchData(data), + [WorkerInputType.ClearData]: (e) => e.clearData(), + [WorkerInputType.ActivateSimulation]: (e) => e.activateSimulation(), + [WorkerInputType.StopSimulation]: (e) => e.stopSimulation(), + [WorkerInputType.StartDragNode]: (e) => e.startDragNode(), + [WorkerInputType.DragNode]: (e, { data }) => e.dragNode(data.id, { x: data.x, y: data.y }), + [WorkerInputType.EndDragNode]: (e, { data }) => e.endDragNode(data.id), + [WorkerInputType.FixNodes]: (e, { data }) => e.fixNodes(data.nodes), + [WorkerInputType.ReleaseNodes]: (e, { data }) => e.releaseNodes(data.nodes), }; -simulator.on(D3SimulatorEngineEventType.SIMULATION_START, () => { - emitToMain({ type: WorkerOutputType.SIMULATION_START }); -}); - -simulator.on(D3SimulatorEngineEventType.SIMULATION_PROGRESS, (data) => { - emitToMain({ type: WorkerOutputType.SIMULATION_PROGRESS, data }); -}); - -simulator.on(D3SimulatorEngineEventType.SIMULATION_END, (data) => { - emitToMain({ type: WorkerOutputType.SIMULATION_END, data }); -}); - -simulator.on(D3SimulatorEngineEventType.NODE_DRAG, (data) => { - emitToMain({ type: WorkerOutputType.NODE_DRAG, data }); -}); - -simulator.on(D3SimulatorEngineEventType.SIMULATION_TICK, (data) => { - emitToMain({ type: WorkerOutputType.SIMULATION_STEP, data }); -}); - -simulator.on(D3SimulatorEngineEventType.SETTINGS_UPDATE, (data) => { - emitToMain({ type: WorkerOutputType.SETTINGS_UPDATE, data }); -}); - addEventListener('message', ({ data }: MessageEvent) => { - switch (data.type) { - case WorkerInputType.ActivateSimulation: { - simulator.activateSimulation(); - break; - } - - case WorkerInputType.StopSimulation: { - simulator.stopSimulation(); - break; - } - - case WorkerInputType.SetupData: { - simulator.setupData(data.data); - break; - } - - case WorkerInputType.MergeData: { - simulator.mergeData(data.data); - break; - } - - case WorkerInputType.UpdateData: { - simulator.updateData(data.data); - break; - } - - case WorkerInputType.DeleteData: { - simulator.deleteData(data.data); - break; - } - - case WorkerInputType.PatchData: { - simulator.patchData(data.data); - break; - } - - case WorkerInputType.ClearData: { - simulator.clearData(); - break; - } - - case WorkerInputType.StartDragNode: { - simulator.startDragNode(); - break; - } - - case WorkerInputType.DragNode: { - simulator.dragNode(data.data); - break; - } - - case WorkerInputType.FixNodes: { - simulator.stickNodes(data.data.nodes); - break; - } - - case WorkerInputType.ReleaseNodes: { - simulator.unstickNodes(data.data.nodes); - break; - } - - case WorkerInputType.EndDragNode: { - simulator.endDragNode(data.data); - break; - } + if (data.type === WorkerInputType.SetSettings) { + const settings = data.data as ILayoutSettings; + if (settings.type === engine?.type && settings.options) { + engine?.setSettings(settings.options); + return; + } + + engine?.removeAllListeners(); + engine?.terminate(); + engine = LayoutEngineFactory.create(settings); + wireEngineEvents(engine); + return; + } - case WorkerInputType.SetSettings: { - simulator.setSettings(data.data); - break; - } + if (engine) { + const handler = handlers[data.type] as EngineHandler | undefined; + handler?.(engine, data); } }); diff --git a/src/simulator/types/web-worker-simulator/web-worker-simulator.ts b/src/simulator/types/web-worker-simulator/web-worker-simulator.ts index 005d043..ce5cf3e 100644 --- a/src/simulator/types/web-worker-simulator/web-worker-simulator.ts +++ b/src/simulator/types/web-worker-simulator/web-worker-simulator.ts @@ -8,15 +8,17 @@ import { ISimulationGraph, ISimulationIds, } from '../../shared'; -import { ID3SimulatorEngineSettingsUpdate } from '../../engine/d3-simulator-engine'; import { IWorkerInputPayload, WorkerInputType } from './message/worker-input'; import { IWorkerOutputPayload, WorkerOutputType } from './message/worker-output'; import { Emitter } from '../../../utils/emitter.utils'; +import { ILayoutSettings } from '../../engine/shared'; +import { DeepPartial } from '../../../utils/type.utils'; export class WebWorkerSimulator extends Emitter implements ISimulator { protected readonly _worker: Worker; + private _isSimulationRunning = false; - constructor() { + constructor(settings: DeepPartial) { super(); this._worker = new Worker( new URL( @@ -27,10 +29,13 @@ export class WebWorkerSimulator extends Emitter implements ISim { type: 'module' }, ); + this.emitToWorker({ type: WorkerInputType.SetSettings, data: settings }); + this._worker.onmessage = ({ data }: MessageEvent) => { switch (data.type) { case WorkerOutputType.SIMULATION_START: { this.emit(SimulatorEventType.SIMULATION_START, undefined); + this._isSimulationRunning = true; break; } case WorkerOutputType.SIMULATION_PROGRESS: { @@ -39,6 +44,7 @@ export class WebWorkerSimulator extends Emitter implements ISim } case WorkerOutputType.SIMULATION_END: { this.emit(SimulatorEventType.SIMULATION_END, data.data); + this._isSimulationRunning = false; break; } case WorkerOutputType.SIMULATION_STEP: { @@ -96,10 +102,6 @@ export class WebWorkerSimulator extends Emitter implements ISim this.emitToWorker({ type: WorkerInputType.ClearData }); } - simulate() { - this.emitToWorker({ type: WorkerInputType.Simulate }); - } - activateSimulation() { this.emitToWorker({ type: WorkerInputType.ActivateSimulation }); } @@ -132,8 +134,15 @@ export class WebWorkerSimulator extends Emitter implements ISim this.emitToWorker({ type: WorkerInputType.ReleaseNodes, data: { nodes } }); } - setSettings(settings: ID3SimulatorEngineSettingsUpdate) { - this.emitToWorker({ type: WorkerInputType.SetSettings, data: settings }); + setSettings(settings: ILayoutSettings) { + this.emitToWorker({ + type: WorkerInputType.SetSettings, + data: settings, + } satisfies IWorkerInputPayload); + } + + isSimulationRunning(): boolean { + return this._isSimulationRunning; } terminate() { diff --git a/src/utils/function.utils.ts b/src/utils/function.utils.ts index dcfd73e..7c6dc3f 100644 --- a/src/utils/function.utils.ts +++ b/src/utils/function.utils.ts @@ -1,28 +1,26 @@ export const throttle = (fn: Function, waitMs = 300) => { - let isInThrottle = false; - let lastTimer: ReturnType; - let lastTimestamp: number = Date.now(); + let lastTime = 0; + let timer: ReturnType | null = null; return function () { // eslint-disable-next-line prefer-rest-params const args = arguments; const now = Date.now(); + const remaining = waitMs - (now - lastTime); - if (!isInThrottle) { + if (remaining <= 0) { + if (timer) { + clearTimeout(timer); + timer = null; + } + lastTime = now; fn(...args); - lastTimestamp = now; - isInThrottle = true; - return; - } - - clearTimeout(lastTimer); - const timerWaitMs = Math.max(waitMs - (now - lastTimestamp), 0); - - lastTimer = setTimeout(() => { - if (now - lastTimestamp >= waitMs) { + } else if (!timer) { + timer = setTimeout(() => { + lastTime = Date.now(); + timer = null; fn(...args); - lastTimestamp = now; - } - }, timerWaitMs); + }, remaining); + } }; }; diff --git a/src/utils/graph.utils.ts b/src/utils/graph.utils.ts new file mode 100644 index 0000000..b969614 --- /dev/null +++ b/src/utils/graph.utils.ts @@ -0,0 +1,145 @@ +import { IEdge, IEdgeBase } from '../models/edge'; +import { IGraph } from '../models/graph'; +import { INode, INodeBase } from '../models/node'; +import { GraphObjectState } from '../models/state'; +import { IFitZoomTransformOptions } from '../renderer/shared'; +import { ILayoutSettings } from '../simulator'; +import { IHierarchicalLayoutOptions } from '../simulator/engine/shared'; + +export const selectNode = (node: INode) => { + setNodeState(node, GraphObjectState.SELECTED, { isStateOverride: true }); +}; + +export const selectEdge = (edge: IEdge) => { + setEdgeState(edge, GraphObjectState.SELECTED, { isStateOverride: true }); +}; + +export const selectOnlyNode = (graph: IGraph, node: INode) => { + unselectAll(graph); + selectNode(node); +}; + +export const selectOnlyEdge = (graph: IGraph, edge: IEdge) => { + unselectAll(graph); + selectEdge(edge); +}; + +export const unselectAll = ( + graph: IGraph, +): { changedCount: number } => { + const selectedNodes = graph.getNodes((node) => node.isSelected()); + for (let i = 0; i < selectedNodes.length; i++) { + selectedNodes[i].clearState(); + } + + const selectedEdges = graph.getEdges((edge) => edge.isSelected()); + for (let i = 0; i < selectedEdges.length; i++) { + selectedEdges[i].clearState(); + } + + return { changedCount: selectedNodes.length + selectedEdges.length }; +}; + +export const hoverNode = (node: INode) => { + setNodeState(node, GraphObjectState.HOVERED); +}; + +export const hoverOnlyNode = (graph: IGraph, node: INode) => { + unhoverAll(graph); + hoverNode(node); +}; + +export const hoverEdge = (edge: IEdge) => { + setEdgeState(edge, GraphObjectState.HOVERED); +}; + +export const hoverOnlyEdge = (graph: IGraph, edge: IEdge) => { + unhoverAll(graph); + hoverEdge(edge); +}; + +export const unhoverAll = (graph: IGraph): { changedCount: number } => { + const hoveredNodes = graph.getNodes((node) => node.isHovered()); + for (let i = 0; i < hoveredNodes.length; i++) { + hoveredNodes[i].clearState(); + } + + const hoveredEdges = graph.getEdges((edge) => edge.isHovered()); + for (let i = 0; i < hoveredEdges.length; i++) { + hoveredEdges[i].clearState(); + } + + return { changedCount: hoveredNodes.length + hoveredEdges.length }; +}; + +export interface ISetShapeStateOptions { + isStateOverride: boolean; +} + +export const setNodeState = ( + node: INode, + state: number, + options?: ISetShapeStateOptions, +): void => { + if (isStateChangeable(node, options)) { + node.setState(state, { isNotifySkipped: true }); + } + + node.getInEdges().forEach((edge) => { + if (edge && isStateChangeable(edge, options)) { + edge.setState(state, { isNotifySkipped: true }); + } + if (edge.startNode && isStateChangeable(edge.startNode, options)) { + edge.startNode.setState(state, { isNotifySkipped: true }); + } + }); + + node.getOutEdges().forEach((edge) => { + if (edge && isStateChangeable(edge, options)) { + edge.setState(state, { isNotifySkipped: true }); + } + if (edge.endNode && isStateChangeable(edge.endNode, options)) { + edge.endNode.setState(state, { isNotifySkipped: true }); + } + }); +}; + +export const setEdgeState = ( + edge: IEdge, + state: number, + options?: ISetShapeStateOptions, +): void => { + if (isStateChangeable(edge, options)) { + edge.setState(state, { isNotifySkipped: true }); + } + + if (edge.startNode && isStateChangeable(edge.startNode, options)) { + edge.startNode.setState(state, { isNotifySkipped: true }); + } + + if (edge.endNode && isStateChangeable(edge.endNode, options)) { + edge.endNode.setState(state, { isNotifySkipped: true }); + } +}; + +export const isStateChangeable = ( + graphObject: INode | IEdge, + options?: ISetShapeStateOptions, +): boolean => { + const isOverride = options?.isStateOverride; + return isOverride || (!isOverride && !graphObject.getState()); +}; + +export const getLayoutAnchors = (layout: ILayoutSettings): IFitZoomTransformOptions => { + if (layout.type === 'hierarchical') { + const opts = layout.options as IHierarchicalLayoutOptions; + return { + anchorX: opts.anchorX ?? (opts.orientation === 'horizontal' ? (opts.reversed ? 'end' : 'start') : 'center'), + anchorY: opts.anchorY ?? (opts.orientation === 'vertical' ? (opts.reversed ? 'end' : 'start') : 'center'), + }; + } + return { + anchorX: layout.options?.anchorX ?? 'center', + anchorY: layout.options?.anchorY ?? 'center', + }; +}; diff --git a/src/utils/object.utils.ts b/src/utils/object.utils.ts index d6dfcf9..debcc7d 100644 --- a/src/utils/object.utils.ts +++ b/src/utils/object.utils.ts @@ -122,7 +122,7 @@ const copyPlainObject = (obj: Record): Record => { }; export const patchProperties = (target: T, source: T): void => { - const keys = Object.keys(source as Object) as (keyof T)[]; + const keys = Object.keys(source as object) as (keyof T)[]; for (let i = 0; i < keys.length; i++) { target[keys[i]] = source[keys[i]]; diff --git a/src/views/orb-map-view.ts b/src/views/orb-map-view.ts index fc5f811..91b0f4f 100644 --- a/src/views/orb-map-view.ts +++ b/src/views/orb-map-view.ts @@ -12,6 +12,7 @@ import { RendererFactory } from '../renderer/factory'; import { getDefaultGraphStyle } from '../models/style'; import { isBoolean } from '../utils/type.utils'; import { IObserver } from '../utils/observer.utils'; +import { GraphInteraction, IGraphInteraction } from '../models/interaction'; export interface ILeafletMapTile { instance: L.TileLayer; @@ -70,6 +71,7 @@ export class OrbMapView implements IOr private _graph: IGraph; private _events: OrbEmitter; private _strategy: IEventStrategy; + private _interaction: IGraphInteraction; private _settings: IOrbMapViewSettings; private _map: HTMLDivElement; @@ -90,6 +92,7 @@ export class OrbMapView implements IOr }); this._graph.setDefaultStyle(getDefaultGraphStyle()); this._events = new OrbEmitter(); + this._interaction = new GraphInteraction(this._graph); this._settings = { areCollapsedContainerDimensionsAllowed: false, @@ -153,6 +156,10 @@ export class OrbMapView implements IOr return this._events; } + get interaction(): IGraphInteraction { + return this._interaction; + } + get leaflet(): L.Map { return this._leaflet; } @@ -198,9 +205,12 @@ export class OrbMapView implements IOr } render(onRendered?: () => void) { + if (onRendered) { + this._renderer.once(RenderEventType.RENDER_END, () => onRendered()); + } + this._updateGraphPositions(); this._renderer.render(this._graph); - onRendered?.(); } zoomIn(onRendered?: () => void) { diff --git a/src/views/orb-view.ts b/src/views/orb-view.ts index 16ea79d..532d38e 100644 --- a/src/views/orb-view.ts +++ b/src/views/orb-view.ts @@ -13,22 +13,23 @@ import { INode, INodeBase, isNode } from '../models/node'; import { IEdge, IEdgeBase, isEdge } from '../models/edge'; import { IOrbView } from './shared'; import { DefaultEventStrategy, IEventStrategy, IEventStrategySettings } from '../models/strategy'; -import { - DEFAULT_SETTINGS, - ID3SimulatorEngineSettings, - ID3SimulatorEngineSettingsCentering, - ID3SimulatorEngineSettingsLinks, -} from '../simulator/engine/d3-simulator-engine'; +import { DEFAULT_FORCE_LAYOUT_OPTIONS, ILayoutSettings } from '../simulator/engine/shared'; import { copyObject } from '../utils/object.utils'; import { OrbEmitter, OrbEventType } from '../events'; -import { IRenderer, RenderEventType, IRendererSettingsInit, IRendererSettings } from '../renderer/shared'; +import { + IRenderer, + RenderEventType, + IRendererSettingsInit, + IRendererSettings, + IFitZoomTransformOptions, +} from '../renderer/shared'; import { RendererFactory } from '../renderer/factory'; import { SimulatorEventType } from '../simulator/shared'; import { getDefaultGraphStyle } from '../models/style'; import { isBoolean } from '../utils/type.utils'; import { IObserver, IObserverDataPayload } from '../utils/observer.utils'; -import { ILayoutSettings, LayoutFactory } from '../simulator/layout/layout'; -import { DEFAULT_FORCE_LAYOUT_OPTIONS } from '../simulator/layout/layouts/force'; +import { GraphInteraction, IGraphInteraction } from '../models/interaction'; +import { getLayoutAnchors } from '../utils/graph.utils'; export interface IGraphInteractionSettings { isDragEnabled: boolean; @@ -37,7 +38,6 @@ export interface IGraphInteractionSettings { export interface IOrbViewSettings { getPosition?(node: INode): IPosition | undefined; - simulation: Partial; render: Partial; strategy: Partial; interaction: Partial; @@ -58,12 +58,11 @@ export class OrbView implements IOrbVi private _events: OrbEmitter; private _strategy: IEventStrategy; private _settings: IOrbViewSettings; + private _interaction: IGraphInteraction; private readonly _renderer: IRenderer; private readonly _simulator: ISimulator; - // private _isSimulating = false; - private _onSimulationEnd: (() => void) | undefined; private _simulationStartedAt = Date.now(); private _d3Zoom: ZoomBehavior; private _dragStartPosition: IPosition | undefined; @@ -76,13 +75,9 @@ export class OrbView implements IOrbVi isOutOfBoundsDragEnabled: false, areCoordinatesRounded: true, ...settings, - simulation: { - isPhysicsEnabled: false, - ...settings?.simulation, - }, layout: { type: 'force', - ...settings?.layout, + ...(settings?.layout ?? DEFAULT_FORCE_LAYOUT_OPTIONS), }, render: { ...settings?.render, @@ -110,6 +105,7 @@ export class OrbView implements IOrbVi }); this._graph.setDefaultStyle(getDefaultGraphStyle()); this._events = new OrbEmitter(); + this._interaction = new GraphInteraction(this._graph); this._strategy = new DefaultEventStrategy({ isDefaultSelectEnabled: this._settings.strategy.isDefaultSelectEnabled ?? false, @@ -160,48 +156,14 @@ export class OrbView implements IOrbVi .on('contextmenu', this.mouseRightClicked) .on('dblclick.zoom', this.mouseDoubleClicked); - this._simulator = SimulatorFactory.getSimulator(); - - if (this._settings.layout.type === 'force') { - this._enableSimulation(); - } - - if (this._settings.layout.options) { - const _options = { - ...DEFAULT_FORCE_LAYOUT_OPTIONS, - ...this._settings.layout.options, - }; - - this._settings.simulation.centering = { - ...(DEFAULT_SETTINGS.centering as Required), - ...this._settings.simulation.centering, - x: _options.centerX, - y: _options.centerY, - }; - - this._settings.simulation.links = { - ...(DEFAULT_SETTINGS.links as Required), - ...this._settings.simulation.links, - distance: _options.nodeDistance, - }; - } - this._simulator.setSettings(this._settings.simulation); + this._simulator = SimulatorFactory.getSimulator(this._settings.layout); + this._initializeSimulationEvents(); - // TODO(dlozic): Optimize crud operations here. this._graph.setSettings({ onSetupData: () => { - // if (this._isSimulating) { - // console.warn('Already running a simulation. Discarding the setup data call.'); - // return; - // } - // this._isSimulating = true; this._assignPositions(this._graph.getNodes()); const nodePositions = this._graph.getNodePositions(); const edgePositions = this._graph.getEdgePositions(); - // this._onSimulationEnd = onRendered; - if (this._settings.layout) { - this._graph.setLayout(LayoutFactory.create(this._settings.layout)); - } this._simulator.setupData({ nodes: nodePositions, edges: edgePositions }); }, onMergeData: (data) => { @@ -212,12 +174,9 @@ export class OrbView implements IOrbVi this._assignPositions(this._graph.getNodes(nodeFilter)); - if (this._settings.layout.type === 'force') { - const nodePositions = this._graph.getNodePositions(nodeFilter); - const edgePositions = this._graph.getEdgePositions(edgeFilter); - - this._simulator.mergeData({ nodes: nodePositions, edges: edgePositions }); - } + const nodePositions = this._graph.getNodePositions(nodeFilter); + const edgePositions = this._graph.getEdgePositions(edgeFilter); + this._simulator.mergeData({ nodes: nodePositions, edges: edgePositions }); }, onRemoveData: (data) => { this._simulator.deleteData(data); @@ -233,6 +192,10 @@ export class OrbView implements IOrbVi return this._events; } + get interaction(): IGraphInteraction { + return this._interaction; + } + getSettings(): IOrbViewSettings { return copyObject(this._settings); } @@ -242,14 +205,6 @@ export class OrbView implements IOrbVi this._settings.getPosition = settings.getPosition; } - if (settings.simulation) { - this._settings.simulation = { - ...this._settings.simulation, - ...settings.simulation, - }; - this._simulator.setSettings(this._settings.simulation); - } - if (settings.render) { this._renderer.setSettings(settings.render); this._settings.render = this._renderer.getSettings(); @@ -262,28 +217,26 @@ export class OrbView implements IOrbVi ...settings.layout, }; - this._graph.setLayout(LayoutFactory.create(this._settings.layout)); - const nodePositions = this._graph.getNodePositions(); const edgePositions = this._graph.getEdgePositions(); - this._simulator.setupData({ nodes: nodePositions, edges: edgePositions }); - - if (this._settings.layout.type === 'force') { - this._enableSimulation(); - this._simulator.releaseNodes(); - } else { - this._disableSimulation(); - this._simulator.clearData(); + if (shouldRecenter) { + for (let i = 0; i < nodePositions.length; i++) { + delete (nodePositions[i] as any).x; + delete (nodePositions[i] as any).y; + } } + this._simulator.setSettings(this._settings.layout); + this._simulator.releaseNodes(); + if (shouldRecenter) { this._simulator.once(SimulatorEventType.SIMULATION_END, () => { this.recenter(); }); } - this.render(); + this._simulator.setupData({ nodes: nodePositions, edges: edgePositions }); } if (settings.strategy) { @@ -326,21 +279,40 @@ export class OrbView implements IOrbVi }; render(onRendered?: () => void) { + if (onRendered) { + if (this._simulator.isSimulationRunning()) { + this._simulator.once(SimulatorEventType.SIMULATION_END, () => { + this._renderer.once(RenderEventType.RENDER_END, () => onRendered()); + }); + } else { + this._renderer.once(RenderEventType.RENDER_END, () => onRendered()); + } + } + this._renderer.render(this._graph); - onRendered?.(); } - recenter(onRendered?: () => void) { - const fitZoomTransform = this._renderer.getFitZoomTransform(this._graph); + recenter(options?: Partial, onRendered?: () => void): void; + recenter(onRendered?: () => void): void; + recenter(optionsOrCallback?: Partial | (() => void), onRendered?: () => void) { + if (typeof optionsOrCallback === 'function') { + onRendered = optionsOrCallback; + optionsOrCallback = undefined; + } + + const layoutAnchors = getLayoutAnchors(this._settings.layout as ILayoutSettings); + const recenterOptions: IFitZoomTransformOptions = { + ...layoutAnchors, + ...optionsOrCallback, + }; + const fitZoomTransform = this._renderer.getFitZoomTransform(this._graph, recenterOptions); select(this._renderer.canvas) .transition() .duration(this._settings.zoomFitTransitionMs) .ease(easeLinear) .call(this._d3Zoom.transform, fitZoomTransform) - .call(() => { - this.render(onRendered); - }); + .on('end', () => this.render(onRendered)); } destroy() { @@ -612,9 +584,7 @@ export class OrbView implements IOrbVi .duration(this._settings.zoomFitTransitionMs) .ease(easeLinear) .call(this._d3Zoom.scaleBy, 1.2) - .call(() => { - this.render(onRendered); - }); + .on('end', () => this.render(onRendered)); }; zoomOut = (onRendered?: () => void) => { @@ -623,7 +593,7 @@ export class OrbView implements IOrbVi .duration(this._settings.zoomFitTransitionMs) .ease(easeLinear) .call(this._d3Zoom.scaleBy, 0.8) - .call(() => this.render(onRendered)); + .on('end', () => this.render(onRendered)); }; private _update: IObserver = (data?: IObserverDataPayload): void => { @@ -646,9 +616,8 @@ export class OrbView implements IOrbVi this.render(); }; - private _enableSimulation = () => { + private _initializeSimulationEvents = () => { this._simulator.on(SimulatorEventType.SIMULATION_START, () => { - // this._isSimulating = true; this._simulationStartedAt = Date.now(); this._events.emit(OrbEventType.SIMULATION_START, undefined); }); @@ -660,9 +629,6 @@ export class OrbView implements IOrbVi this._simulator.on(SimulatorEventType.SIMULATION_END, (data) => { this._graph.setNodePositions(data.nodes); this.render(); - // this._isSimulating = false; - this._onSimulationEnd?.(); - this._onSimulationEnd = undefined; this._events.emit(OrbEventType.SIMULATION_END, { durationMs: Date.now() - this._simulationStartedAt }); }); this._simulator.on(SimulatorEventType.SIMULATION_STEP, (data) => { @@ -674,44 +640,8 @@ export class OrbView implements IOrbVi this.render(); }); this._simulator.on(SimulatorEventType.SETTINGS_UPDATE, (data) => { - this._settings.simulation = data.settings; - }); - - this._simulator.activateSimulation(); - }; - - private _disableSimulation = () => { - this._simulator.off(SimulatorEventType.SIMULATION_START, () => { - // this._isSimulating = true; - this._simulationStartedAt = Date.now(); - this._events.emit(OrbEventType.SIMULATION_START, undefined); + this._settings.layout.options = data.settings?.options; }); - this._simulator.off(SimulatorEventType.SIMULATION_PROGRESS, (data) => { - this._graph.setNodePositions(data.nodes); - this._events.emit(OrbEventType.SIMULATION_STEP, { progress: data.progress }); - this.render(); - }); - this._simulator.off(SimulatorEventType.SIMULATION_END, (data) => { - this._graph.setNodePositions(data.nodes); - this.render(); - // this._isSimulating = false; - this._onSimulationEnd?.(); - this._onSimulationEnd = undefined; - this._events.emit(OrbEventType.SIMULATION_END, { durationMs: Date.now() - this._simulationStartedAt }); - }); - this._simulator.off(SimulatorEventType.SIMULATION_STEP, (data) => { - this._graph.setNodePositions(data.nodes); - this.render(); - }); - this._simulator.off(SimulatorEventType.NODE_DRAG, (data) => { - this._graph.setNodePositions(data.nodes); - this.render(); - }); - this._simulator.off(SimulatorEventType.SETTINGS_UPDATE, (data) => { - this._settings.simulation = data.settings; - }); - - this._simulator.stopSimulation(); }; // TODO: Do we keep these diff --git a/src/views/shared.ts b/src/views/shared.ts index 98c28aa..4578dde 100644 --- a/src/views/shared.ts +++ b/src/views/shared.ts @@ -2,10 +2,12 @@ import { INodeBase } from '../models/node'; import { IEdgeBase } from '../models/edge'; import { IGraph } from '../models/graph'; import { OrbEmitter } from '../events'; +import { IGraphInteraction } from '../models/interaction'; export interface IOrbView { data: IGraph; events: OrbEmitter; + interaction: IGraphInteraction; getSettings(): S; setSettings(settings: Partial): void; render(onRendered?: () => void): void; From 875ae32f9ec76497727a14bb176df7dda84651ec Mon Sep 17 00:00:00 2001 From: Oleksandr Ichenskyi <55350107+AlexIchenskiy@users.noreply.github.com> Date: Fri, 3 Jul 2026 17:02:16 +0200 Subject: [PATCH 23/30] New: Add multiselect (#110) * New: Add multiselect * Chore: Simplify logic --- src/models/interaction.ts | 44 +++++++++++++++++---- src/models/strategy.ts | 58 +++++++++++++++++++++++----- src/utils/graph.utils.ts | 80 +++++++++++++++++++++++++++++++++++---- src/views/orb-map-view.ts | 18 ++++++++- src/views/orb-view.ts | 18 ++++++++- 5 files changed, 191 insertions(+), 27 deletions(-) diff --git a/src/models/interaction.ts b/src/models/interaction.ts index 5e6c6c5..a8fedd6 100644 --- a/src/models/interaction.ts +++ b/src/models/interaction.ts @@ -1,11 +1,23 @@ -import { hoverEdge, hoverNode, selectEdge, selectNode, unhoverAll, unselectAll } from '../utils/graph.utils'; +import { + hoverEdge, + hoverNode, + ISelectionOptions, + selectEdge, + selectNode, + unhoverAll, + unselectAll, + unselectEdge, + unselectNode, +} from '../utils/graph.utils'; import { IEdgeBase } from './edge'; import { IGraph } from './graph'; import { INodeBase } from './node'; export interface IGraphInteraction { - selectNodeById(id: any): boolean; - selectEdgeById(id: any): boolean; + selectNodeById(id: any, options?: ISelectionOptions): boolean; + selectEdgeById(id: any, options?: ISelectionOptions): boolean; + unselectNodeById(id: any, options?: ISelectionOptions): boolean; + unselectEdgeById(id: any, options?: ISelectionOptions): boolean; unselectAll(): number; hoverNodeById(id: any): boolean; hoverEdgeById(id: any): boolean; @@ -19,21 +31,39 @@ export class GraphInteraction implemen this._graph = graph; } - selectNodeById(id: any): boolean { + selectNodeById(id: any, options?: ISelectionOptions): boolean { const node = this._graph.getNodeById(id); if (!node) { return false; } - selectNode(node); + selectNode(node, options); return true; } - selectEdgeById(id: any): boolean { + selectEdgeById(id: any, options?: ISelectionOptions): boolean { const edge = this._graph.getEdgeById(id); if (!edge) { return false; } - selectEdge(edge); + selectEdge(edge, options); + return true; + } + + unselectNodeById(id: any, options?: ISelectionOptions): boolean { + const node = this._graph.getNodeById(id); + if (!node) { + return false; + } + unselectNode(node, options); + return true; + } + + unselectEdgeById(id: any, options?: ISelectionOptions): boolean { + const edge = this._graph.getEdgeById(id); + if (!edge) { + return false; + } + unselectEdge(edge, options); return true; } diff --git a/src/models/strategy.ts b/src/models/strategy.ts index a3580b6..2eb7c36 100644 --- a/src/models/strategy.ts +++ b/src/models/strategy.ts @@ -2,11 +2,21 @@ import { INode, INodeBase } from './node'; import { IEdge, IEdgeBase } from './edge'; import { IGraph } from './graph'; import { IPosition } from '../common'; -import { hoverOnlyNode, selectOnlyEdge, selectOnlyNode, unhoverAll, unselectAll } from '../utils/graph.utils'; +import { + hoverOnlyNode, + selectOnlyEdge, + selectOnlyNode, + toggleEdgeSelection, + toggleNodeSelection, + unhoverAll, + unselectAll, +} from '../utils/graph.utils'; export interface IEventStrategySettings { isDefaultSelectEnabled: boolean; isDefaultHoverEnabled: boolean; + isDefaultMultiSelectEnabled: boolean; + isDefaultSelectCascadeEnabled: boolean; } export interface IEventStrategyResponse { @@ -14,10 +24,20 @@ export interface IEventStrategyResponse | IEdge; } +export interface IEventStrategyClickOptions { + isAppend?: boolean; +} + export interface IEventStrategy { isSelectEnabled: boolean; isHoverEnabled: boolean; - onMouseClick: (graph: IGraph, point: IPosition) => IEventStrategyResponse; + isMultiSelectEnabled: boolean; + isSelectCascadeEnabled: boolean; + onMouseClick: ( + graph: IGraph, + point: IPosition, + options?: IEventStrategyClickOptions, + ) => IEventStrategyResponse; onMouseMove: (graph: IGraph, point: IPosition) => IEventStrategyResponse; onMouseRightClick: (graph: IGraph, point: IPosition) => IEventStrategyResponse; onMouseDoubleClick: (graph: IGraph, point: IPosition) => IEventStrategyResponse; @@ -27,17 +47,31 @@ export class DefaultEventStrategy impl private _lastHoveredNode?: INode; public isSelectEnabled: boolean; public isHoverEnabled: boolean; + public isMultiSelectEnabled: boolean; + public isSelectCascadeEnabled: boolean; constructor(settings: IEventStrategySettings) { this.isSelectEnabled = settings.isDefaultSelectEnabled; this.isHoverEnabled = settings.isDefaultHoverEnabled; + this.isMultiSelectEnabled = settings.isDefaultMultiSelectEnabled; + this.isSelectCascadeEnabled = settings.isDefaultSelectCascadeEnabled; } - onMouseClick(graph: IGraph, point: IPosition): IEventStrategyResponse { + onMouseClick( + graph: IGraph, + point: IPosition, + options?: IEventStrategyClickOptions, + ): IEventStrategyResponse { + const isAppend = this.isMultiSelectEnabled && (options?.isAppend ?? false); + const node = graph.getNearestNode(point); if (node) { if (this.isSelectEnabled) { - selectOnlyNode(graph, node); + if (isAppend) { + toggleNodeSelection(node); + } else { + selectOnlyNode(graph, node, { cascade: this.isSelectCascadeEnabled }); + } } return { @@ -49,7 +83,11 @@ export class DefaultEventStrategy impl const edge = graph.getNearestEdge(point); if (edge) { if (this.isSelectEnabled) { - selectOnlyEdge(graph, edge); + if (isAppend) { + toggleEdgeSelection(edge); + } else { + selectOnlyEdge(graph, edge, { cascade: this.isSelectCascadeEnabled }); + } } return { @@ -58,7 +96,7 @@ export class DefaultEventStrategy impl }; } - if (!this.isSelectEnabled) { + if (!this.isSelectEnabled || isAppend) { return { isStateChanged: false }; } @@ -104,7 +142,7 @@ export class DefaultEventStrategy impl const node = graph.getNearestNode(point); if (node) { if (this.isSelectEnabled) { - selectOnlyNode(graph, node); + selectOnlyNode(graph, node, { cascade: this.isSelectCascadeEnabled }); } return { @@ -116,7 +154,7 @@ export class DefaultEventStrategy impl const edge = graph.getNearestEdge(point); if (edge) { if (this.isSelectEnabled) { - selectOnlyEdge(graph, edge); + selectOnlyEdge(graph, edge, { cascade: this.isSelectCascadeEnabled }); } return { @@ -139,7 +177,7 @@ export class DefaultEventStrategy impl const node = graph.getNearestNode(point); if (node) { if (this.isSelectEnabled) { - selectOnlyNode(graph, node); + selectOnlyNode(graph, node, { cascade: this.isSelectCascadeEnabled }); } return { @@ -151,7 +189,7 @@ export class DefaultEventStrategy impl const edge = graph.getNearestEdge(point); if (edge) { if (this.isSelectEnabled) { - selectOnlyEdge(graph, edge); + selectOnlyEdge(graph, edge, { cascade: this.isSelectCascadeEnabled }); } return { diff --git a/src/utils/graph.utils.ts b/src/utils/graph.utils.ts index b969614..6d0765f 100644 --- a/src/utils/graph.utils.ts +++ b/src/utils/graph.utils.ts @@ -6,22 +6,86 @@ import { IFitZoomTransformOptions } from '../renderer/shared'; import { ILayoutSettings } from '../simulator'; import { IHierarchicalLayoutOptions } from '../simulator/engine/shared'; -export const selectNode = (node: INode) => { - setNodeState(node, GraphObjectState.SELECTED, { isStateOverride: true }); +export interface ISelectionOptions { + cascade?: boolean; +} + +export const selectNode = ( + node: INode, + options?: ISelectionOptions, +) => { + if (options?.cascade ?? true) { + setNodeState(node, GraphObjectState.SELECTED, { isStateOverride: true }); + } else { + node.setState(GraphObjectState.SELECTED, { isNotifySkipped: true }); + } +}; + +export const selectEdge = ( + edge: IEdge, + options?: ISelectionOptions, +) => { + if (options?.cascade ?? true) { + setEdgeState(edge, GraphObjectState.SELECTED, { isStateOverride: true }); + } else { + edge.setState(GraphObjectState.SELECTED, { isNotifySkipped: true }); + } +}; + +export const unselectNode = ( + node: INode, + options?: ISelectionOptions, +) => { + if (options?.cascade ?? true) { + setNodeState(node, GraphObjectState.NONE, { isStateOverride: true }); + } else { + node.clearState(); + } }; -export const selectEdge = (edge: IEdge) => { - setEdgeState(edge, GraphObjectState.SELECTED, { isStateOverride: true }); +export const unselectEdge = ( + edge: IEdge, + options?: ISelectionOptions, +) => { + if (options?.cascade ?? true) { + setEdgeState(edge, GraphObjectState.NONE, { isStateOverride: true }); + } else { + edge.clearState(); + } }; -export const selectOnlyNode = (graph: IGraph, node: INode) => { +export const selectOnlyNode = ( + graph: IGraph, + node: INode, + options?: ISelectionOptions, +) => { unselectAll(graph); - selectNode(node); + selectNode(node, options); }; -export const selectOnlyEdge = (graph: IGraph, edge: IEdge) => { +export const selectOnlyEdge = ( + graph: IGraph, + edge: IEdge, + options?: ISelectionOptions, +) => { unselectAll(graph); - selectEdge(edge); + selectEdge(edge, options); +}; + +export const toggleNodeSelection = (node: INode) => { + if (node.isSelected()) { + unselectNode(node, { cascade: false }); + } else { + selectNode(node, { cascade: false }); + } +}; + +export const toggleEdgeSelection = (edge: IEdge) => { + if (edge.isSelected()) { + unselectEdge(edge, { cascade: false }); + } else { + selectEdge(edge, { cascade: false }); + } }; export const unselectAll = ( diff --git a/src/views/orb-map-view.ts b/src/views/orb-map-view.ts index 91b0f4f..5d59819 100644 --- a/src/views/orb-map-view.ts +++ b/src/views/orb-map-view.ts @@ -108,6 +108,8 @@ export class OrbMapView implements IOr strategy: { isDefaultHoverEnabled: true, isDefaultSelectEnabled: true, + isDefaultMultiSelectEnabled: false, + isDefaultSelectCascadeEnabled: true, ...settings?.strategy, }, }; @@ -115,6 +117,8 @@ export class OrbMapView implements IOr this._strategy = new DefaultEventStrategy({ isDefaultSelectEnabled: this._settings.strategy.isDefaultSelectEnabled ?? false, isDefaultHoverEnabled: this._settings.strategy.isDefaultHoverEnabled ?? false, + isDefaultMultiSelectEnabled: this._settings.strategy.isDefaultMultiSelectEnabled ?? true, + isDefaultSelectCascadeEnabled: this._settings.strategy.isDefaultSelectCascadeEnabled ?? true, }); try { @@ -201,6 +205,16 @@ export class OrbMapView implements IOr this._settings.strategy.isDefaultSelectEnabled = settings.strategy.isDefaultSelectEnabled; this._strategy.isSelectEnabled = this._settings.strategy.isDefaultSelectEnabled; } + + if (isBoolean(settings.strategy.isDefaultMultiSelectEnabled)) { + this._settings.strategy.isDefaultMultiSelectEnabled = settings.strategy.isDefaultMultiSelectEnabled; + this._strategy.isMultiSelectEnabled = this._settings.strategy.isDefaultMultiSelectEnabled; + } + + if (isBoolean(settings.strategy.isDefaultSelectCascadeEnabled)) { + this._settings.strategy.isDefaultSelectCascadeEnabled = settings.strategy.isDefaultSelectCascadeEnabled; + this._strategy.isSelectCascadeEnabled = this._settings.strategy.isDefaultSelectCascadeEnabled; + } } } @@ -349,7 +363,9 @@ export class OrbMapView implements IOr this._renderer.render(this._graph); } } else if (event.type === 'click') { - const response = this._strategy.onMouseClick(this._graph, point); + const response = this._strategy.onMouseClick(this._graph, point, { + isAppend: event.originalEvent.shiftKey, + }); const subject = response.changedSubject; if (subject) { diff --git a/src/views/orb-view.ts b/src/views/orb-view.ts index 532d38e..61b1efc 100644 --- a/src/views/orb-view.ts +++ b/src/views/orb-view.ts @@ -85,6 +85,8 @@ export class OrbView implements IOrbVi strategy: { isDefaultHoverEnabled: true, isDefaultSelectEnabled: true, + isDefaultMultiSelectEnabled: false, + isDefaultSelectCascadeEnabled: true, ...settings?.strategy, }, interaction: { @@ -110,6 +112,8 @@ export class OrbView implements IOrbVi this._strategy = new DefaultEventStrategy({ isDefaultSelectEnabled: this._settings.strategy.isDefaultSelectEnabled ?? false, isDefaultHoverEnabled: this._settings.strategy.isDefaultHoverEnabled ?? false, + isDefaultMultiSelectEnabled: this._settings.strategy.isDefaultMultiSelectEnabled ?? true, + isDefaultSelectCascadeEnabled: this._settings.strategy.isDefaultSelectCascadeEnabled ?? true, }); try { @@ -249,6 +253,16 @@ export class OrbView implements IOrbVi this._settings.strategy.isDefaultSelectEnabled = settings.strategy.isDefaultSelectEnabled; this._strategy.isSelectEnabled = this._settings.strategy.isDefaultSelectEnabled; } + + if (isBoolean(settings.strategy.isDefaultMultiSelectEnabled)) { + this._settings.strategy.isDefaultMultiSelectEnabled = settings.strategy.isDefaultMultiSelectEnabled; + this._strategy.isMultiSelectEnabled = this._settings.strategy.isDefaultMultiSelectEnabled; + } + + if (isBoolean(settings.strategy.isDefaultSelectCascadeEnabled)) { + this._settings.strategy.isDefaultSelectCascadeEnabled = settings.strategy.isDefaultSelectCascadeEnabled; + this._strategy.isSelectCascadeEnabled = this._settings.strategy.isDefaultSelectCascadeEnabled; + } } // Check if interaction settings are provided @@ -468,7 +482,9 @@ export class OrbView implements IOrbVi const mousePoint = this.getCanvasMousePosition(event); const simulationPoint = this._renderer.getSimulationPosition(mousePoint); - const response = this._strategy.onMouseClick(this._graph, simulationPoint); + const response = this._strategy.onMouseClick(this._graph, simulationPoint, { + isAppend: event.shiftKey, + }); const subject = response.changedSubject; if (subject) { From ee2118370b92d631721fb12e25385113414dad20 Mon Sep 17 00:00:00 2001 From: Toni Lastre Date: Sat, 4 Jul 2026 01:00:51 +0200 Subject: [PATCH 24/30] Chore: Update package.json --- package-lock.json | 5037 ++++++++++++++++++++++++++++----------------- package.json | 68 +- 2 files changed, 3155 insertions(+), 1950 deletions(-) diff --git a/package-lock.json b/package-lock.json index ac11942..9727a5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,75 +9,62 @@ "version": "1.0.0", "license": "Apache-2.0", "dependencies": { - "d3-drag": "3.0.0", - "d3-ease": "3.0.1", - "d3-force": "3.0.0", - "d3-selection": "3.0.0", - "d3-transition": "3.0.1", - "d3-zoom": "3.0.0", - "leaflet": "1.8.0" + "d3-drag": "^3.0.0", + "d3-ease": "^3.0.1", + "d3-force": "^3.0.0", + "d3-selection": "^3.0.0", + "d3-transition": "^3.0.1", + "d3-zoom": "^3.0.0", + "leaflet": "^1.9.4" }, "devDependencies": { - "@commitlint/cli": "17.0.0", - "@commitlint/config-conventional": "17.0.0", - "@semantic-release/changelog": "6.0.1", - "@semantic-release/git": "10.0.1", - "@types/d3-drag": "3.0.1", - "@types/d3-ease": "3.0.0", - "@types/d3-force": "3.0.3", - "@types/d3-selection": "3.0.1", - "@types/d3-transition": "3.0.1", - "@types/d3-zoom": "3.0.1", - "@types/jest": "29.5.12", - "@types/leaflet": "1.7.9", + "@commitlint/cli": "^17.0.0", + "@commitlint/config-conventional": "^17.0.0", + "@semantic-release/changelog": "^6.0.1", + "@semantic-release/git": "^10.0.1", + "@types/d3-drag": "^3.0.1", + "@types/d3-ease": "^3.0.0", + "@types/d3-force": "^3.0.3", + "@types/d3-selection": "^3.0.1", + "@types/d3-transition": "^3.0.1", + "@types/d3-zoom": "^3.0.1", + "@types/jest": "^29.5.12", + "@types/leaflet": "^1.9.4", "@types/resize-observer-browser": "^0.1.7", - "@typescript-eslint/eslint-plugin": "8.56.1", - "@typescript-eslint/parser": "8.56.1", - "conventional-changelog-eslint": "3.0.9", + "@typescript-eslint/eslint-plugin": "^8.56.1", + "@typescript-eslint/parser": "^8.56.1", + "conventional-changelog-eslint": "^3.0.9", "copy-webpack-plugin": "^11.0.0", - "eslint": "8.57.0", - "eslint-config-google": "0.14.0", - "eslint-config-prettier": "8.5.0", - "eslint-plugin-jest": "29.15.0", - "eslint-plugin-prettier": "5.5.5", + "eslint": "^8.57.0", + "eslint-config-google": "^0.14.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-jest": "^29.15.0", + "eslint-plugin-prettier": "^5.5.5", "http-server": "^14.1.1", "husky": "^8.0.1", - "jest": "29.7.0", - "prettier": "3.8.1", - "semantic-release": "19.0.3", - "ts-jest": "29.1.2", + "jest": "^29.7.0", + "prettier": "^3.8.1", + "semantic-release": "^19.0.3", + "ts-jest": "^29.1.2", "ts-loader": "^9.3.1", - "ts-node": "10.9.2", - "typescript": "5.9.3", + "ts-node": "^10.9.2", + "typescript": "^5.9.3", "webpack": "^5.73.0", "webpack-cli": "^4.10.0", - "webpack-dev-server": "5.2.0" + "webpack-dev-server": "^5.2.0" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "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" }, @@ -86,30 +73,32 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "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": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", - "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.9", - "@babel/parser": "^7.23.9", - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -129,34 +118,38 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "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/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "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.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", + "@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" }, @@ -164,87 +157,50 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "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/types": "^7.22.15" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "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-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -254,42 +210,19 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "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, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "license": "MIT", "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": { @@ -297,9 +230,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": { @@ -307,36 +240,37 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "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": { "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.29.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "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.29.0" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -350,6 +284,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -362,6 +297,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -374,6 +310,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -381,11 +318,44 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "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.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -398,6 +368,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -406,12 +377,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "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.22.5" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -425,6 +397,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -437,6 +410,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -449,6 +423,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -461,6 +436,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -473,6 +449,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -485,6 +462,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -492,11 +470,28 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -508,12 +503,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "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.22.5" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -523,59 +519,48 @@ } }, "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.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "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.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "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" @@ -585,30 +570,34 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.1.90" } }, "node_modules/@commitlint/cli": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.0.0.tgz", - "integrity": "sha512-Np6slCdVVG1XwMvwbZrXIzS1INPAD5QmN4L6al04AmCd4nAPU63gxgxC5Mz0Fmx7va23Uvb0S7yEFV1JPhvPUQ==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.8.1.tgz", + "integrity": "sha512-ay+WbzQesE0Rv4EQKfNbSMiJJ12KdKTDzIt0tcK4k11FdsWmtwP0Kp1NWMOUswfIWo6Eb7p7Ln721Nx9FLNBjg==", "dev": true, + "license": "MIT", "dependencies": { - "@commitlint/format": "^17.0.0", - "@commitlint/lint": "^17.0.0", - "@commitlint/load": "^17.0.0", - "@commitlint/read": "^17.0.0", - "@commitlint/types": "^17.0.0", - "lodash": "^4.17.19", + "@commitlint/format": "^17.8.1", + "@commitlint/lint": "^17.8.1", + "@commitlint/load": "^17.8.1", + "@commitlint/read": "^17.8.1", + "@commitlint/types": "^17.8.1", + "execa": "^5.0.0", + "lodash.isfunction": "^3.0.9", "resolve-from": "5.0.0", "resolve-global": "1.0.0", "yargs": "^17.0.0" @@ -621,24 +610,26 @@ } }, "node_modules/@commitlint/config-conventional": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.0.0.tgz", - "integrity": "sha512-jttJXBIq3AuQCvUVwxSctCwKfHxxbALE0IB9OIHYCu/eQdOzPxN72pugeZsWDo1VK/T9iFx+MZoPb6Rb1/ylsw==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.8.1.tgz", + "integrity": "sha512-NxCOHx1kgneig3VLauWJcDWS40DVjg7nKOpBEEK9E5fjJpQqLCilcnKkIIjdBH98kEO1q3NpE5NSrZ2kl/QGJg==", "dev": true, + "license": "MIT", "dependencies": { - "conventional-changelog-conventionalcommits": "^4.3.1" + "conventional-changelog-conventionalcommits": "^6.1.0" }, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/config-validator": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.4.4.tgz", - "integrity": "sha512-bi0+TstqMiqoBAQDvdEP4AFh0GaKyLFlPPEObgI29utoKEYoPQTvF0EYqIwYYLEoJYhj5GfMIhPHJkTJhagfeg==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.8.1.tgz", + "integrity": "sha512-UUgUC+sNiiMwkyiuIFR7JG2cfd9t/7MV8VB4TZ+q02ZFkHoduUS4tJGsCBWvBOGD9Btev6IecPMvlWUfJorkEA==", "dev": true, + "license": "MIT", "dependencies": { - "@commitlint/types": "^17.4.4", + "@commitlint/types": "^17.8.1", "ajv": "^8.11.0" }, "engines": { @@ -646,34 +637,41 @@ } }, "node_modules/@commitlint/ensure": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.0.0.tgz", - "integrity": "sha512-M2hkJnNXvEni59S0QPOnqCKIK52G1XyXBGw51mvh7OXDudCmZ9tZiIPpU882p475Mhx48Ien1MbWjCP1zlyC0A==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.8.1.tgz", + "integrity": "sha512-xjafwKxid8s1K23NFpL8JNo6JnY/ysetKo8kegVM7c8vs+kWLP8VrQq+NbhgVlmCojhEDbzQKp4eRXSjVOGsow==", "dev": true, + "license": "MIT", "dependencies": { - "@commitlint/types": "^17.0.0", - "lodash": "^4.17.19" + "@commitlint/types": "^17.8.1", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" }, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/execute-rule": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.4.0.tgz", - "integrity": "sha512-LIgYXuCSO5Gvtc0t9bebAMSwd68ewzmqLypqI2Kke1rqOqqDbMpYcYfoPfFlv9eyLIh4jocHWwCK5FS7z9icUA==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.8.1.tgz", + "integrity": "sha512-JHVupQeSdNI6xzA9SqMF+p/JjrHTcrJdI02PwesQIDCIGUrv04hicJgCcws5nzaoZbROapPs0s6zeVHoxpMwFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=v14" } }, "node_modules/@commitlint/format": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.0.0.tgz", - "integrity": "sha512-MZzJv7rBp/r6ZQJDEodoZvdRM0vXu1PfQvMTNWFb8jFraxnISMTnPBWMMjr2G/puoMashwaNM//fl7j8gGV5lA==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.8.1.tgz", + "integrity": "sha512-f3oMTyZ84M9ht7fb93wbCKmWxO5/kKSbwuYvS867duVomoOsgrgljkGGIztmT/srZnaiGbaK8+Wf8Ik2tSr5eg==", "dev": true, + "license": "MIT", "dependencies": { - "@commitlint/types": "^17.0.0", + "@commitlint/types": "^17.8.1", "chalk": "^4.1.0" }, "engines": { @@ -681,44 +679,47 @@ } }, "node_modules/@commitlint/is-ignored": { - "version": "17.6.7", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.6.7.tgz", - "integrity": "sha512-vqyNRqtbq72P2JadaoWiuoLtXIs9SaAWDqdtef6G2zsoXqKFc7vqj1f+thzVgosXG3X/5K9jNp+iYijmvOfc/g==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.8.1.tgz", + "integrity": "sha512-UshMi4Ltb4ZlNn4F7WtSEugFDZmctzFpmbqvpyxD3la510J+PLcnyhf9chs7EryaRFJMdAKwsEKfNK0jL/QM4g==", "dev": true, + "license": "MIT", "dependencies": { - "@commitlint/types": "^17.4.4", - "semver": "7.5.2" + "@commitlint/types": "^17.8.1", + "semver": "7.5.4" }, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/lint": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.0.3.tgz", - "integrity": "sha512-2o1fk7JUdxBUgszyt41sHC/8Nd5PXNpkmuOo9jvGIjDHzOwXyV0PSdbEVTH3xGz9NEmjohFHr5l+N+T9fcxong==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.8.1.tgz", + "integrity": "sha512-aQUlwIR1/VMv2D4GXSk7PfL5hIaFSfy6hSHV94O8Y27T5q+DlDEgd/cZ4KmVI+MWKzFfCTiTuWqjfRSfdRllCA==", "dev": true, + "license": "MIT", "dependencies": { - "@commitlint/is-ignored": "^17.0.3", - "@commitlint/parse": "^17.0.0", - "@commitlint/rules": "^17.0.0", - "@commitlint/types": "^17.0.0" + "@commitlint/is-ignored": "^17.8.1", + "@commitlint/parse": "^17.8.1", + "@commitlint/rules": "^17.8.1", + "@commitlint/types": "^17.8.1" }, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/load": { - "version": "17.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.5.0.tgz", - "integrity": "sha512-l+4W8Sx4CD5rYFsrhHH8HP01/8jEP7kKf33Xlx2Uk2out/UKoKPYMOIRcDH5ppT8UXLMV+x6Wm5osdRKKgaD1Q==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.8.1.tgz", + "integrity": "sha512-iF4CL7KDFstP1kpVUkT8K2Wl17h2yx9VaR1ztTc8vzByWWcbO/WaKwxsnCOqow9tVAlzPfo1ywk9m2oJ9ucMqA==", "dev": true, + "license": "MIT", "dependencies": { - "@commitlint/config-validator": "^17.4.4", - "@commitlint/execute-rule": "^17.4.0", - "@commitlint/resolve-extends": "^17.4.4", - "@commitlint/types": "^17.4.4", - "@types/node": "*", + "@commitlint/config-validator": "^17.8.1", + "@commitlint/execute-rule": "^17.8.1", + "@commitlint/resolve-extends": "^17.8.1", + "@commitlint/types": "^17.8.1", + "@types/node": "20.5.1", "chalk": "^4.1.0", "cosmiconfig": "^8.0.0", "cosmiconfig-typescript-loader": "^4.0.0", @@ -727,76 +728,70 @@ "lodash.uniq": "^4.5.0", "resolve-from": "^5.0.0", "ts-node": "^10.8.1", - "typescript": "^4.6.4 || ^5.0.0" + "typescript": "^4.6.4 || ^5.2.2" }, "engines": { "node": ">=v14" } }, - "node_modules/@commitlint/load/node_modules/cosmiconfig": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", - "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", + "node_modules/@commitlint/load/node_modules/@types/node": { + "version": "20.5.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz", + "integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==", "dev": true, - "dependencies": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - } + "license": "MIT" }, "node_modules/@commitlint/message": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.0.0.tgz", - "integrity": "sha512-LpcwYtN+lBlfZijHUdVr8aNFTVpHjuHI52BnfoV01TF7iSLnia0jttzpLkrLmI8HNQz6Vhr9UrxDWtKZiMGsBw==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.8.1.tgz", + "integrity": "sha512-6bYL1GUQsD6bLhTH3QQty8pVFoETfFQlMn2Nzmz3AOLqRVfNNtXBaSY0dhZ0dM6A2MEq4+2d7L/2LP8TjqGRkA==", "dev": true, + "license": "MIT", "engines": { "node": ">=v14" } }, "node_modules/@commitlint/parse": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.0.0.tgz", - "integrity": "sha512-cKcpfTIQYDG1ywTIr5AG0RAiLBr1gudqEsmAGCTtj8ffDChbBRxm6xXs2nv7GvmJN7msOt7vOKleLvcMmRa1+A==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.8.1.tgz", + "integrity": "sha512-/wLUickTo0rNpQgWwLPavTm7WbwkZoBy3X8PpkUmlSmQJyWQTj0m6bDjiykMaDt41qcUbfeFfaCvXfiR4EGnfw==", "dev": true, + "license": "MIT", "dependencies": { - "@commitlint/types": "^17.0.0", - "conventional-changelog-angular": "^5.0.11", - "conventional-commits-parser": "^3.2.2" + "@commitlint/types": "^17.8.1", + "conventional-changelog-angular": "^6.0.0", + "conventional-commits-parser": "^4.0.0" }, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/read": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.0.0.tgz", - "integrity": "sha512-zkuOdZayKX3J6F6mPnVMzohK3OBrsEdOByIqp4zQjA9VLw1hMsDEFQ18rKgUc2adkZar+4S01QrFreDCfZgbxA==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.8.1.tgz", + "integrity": "sha512-Fd55Oaz9irzBESPCdMd8vWWgxsW3OWR99wOntBDHgf9h7Y6OOHjWEdS9Xzen1GFndqgyoaFplQS5y7KZe0kO2w==", "dev": true, + "license": "MIT", "dependencies": { - "@commitlint/top-level": "^17.0.0", - "@commitlint/types": "^17.0.0", - "fs-extra": "^10.0.0", - "git-raw-commits": "^2.0.0" + "@commitlint/top-level": "^17.8.1", + "@commitlint/types": "^17.8.1", + "fs-extra": "^11.0.0", + "git-raw-commits": "^2.0.11", + "minimist": "^1.2.6" }, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/resolve-extends": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.4.4.tgz", - "integrity": "sha512-znXr1S0Rr8adInptHw0JeLgumS11lWbk5xAWFVno+HUFVN45875kUtqjrI6AppmD3JI+4s0uZlqqlkepjJd99A==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.8.1.tgz", + "integrity": "sha512-W/ryRoQ0TSVXqJrx5SGkaYuAaE/BUontL1j1HsKckvM6e5ZaG0M9126zcwL6peKSuIetJi7E87PRQF8O86EW0Q==", "dev": true, + "license": "MIT", "dependencies": { - "@commitlint/config-validator": "^17.4.4", - "@commitlint/types": "^17.4.4", + "@commitlint/config-validator": "^17.8.1", + "@commitlint/types": "^17.8.1", "import-fresh": "^3.0.0", "lodash.mergewith": "^4.6.2", "resolve-from": "^5.0.0", @@ -807,15 +802,16 @@ } }, "node_modules/@commitlint/rules": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.0.0.tgz", - "integrity": "sha512-45nIy3dERKXWpnwX9HeBzK5SepHwlDxdGBfmedXhL30fmFCkJOdxHyOJsh0+B0RaVsLGT01NELpfzJUmtpDwdQ==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.8.1.tgz", + "integrity": "sha512-2b7OdVbN7MTAt9U0vKOYKCDsOvESVXxQmrvuVUZ0rGFMCrCPJWWP1GJ7f0lAypbDAhaGb8zqtdOr47192LBrIA==", "dev": true, + "license": "MIT", "dependencies": { - "@commitlint/ensure": "^17.0.0", - "@commitlint/message": "^17.0.0", - "@commitlint/to-lines": "^17.0.0", - "@commitlint/types": "^17.0.0", + "@commitlint/ensure": "^17.8.1", + "@commitlint/message": "^17.8.1", + "@commitlint/to-lines": "^17.8.1", + "@commitlint/types": "^17.8.1", "execa": "^5.0.0" }, "engines": { @@ -823,19 +819,21 @@ } }, "node_modules/@commitlint/to-lines": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.0.0.tgz", - "integrity": "sha512-nEi4YEz04Rf2upFbpnEorG8iymyH7o9jYIVFBG1QdzebbIFET3ir+8kQvCZuBE5pKCtViE4XBUsRZz139uFrRQ==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.8.1.tgz", + "integrity": "sha512-LE0jb8CuR/mj6xJyrIk8VLz03OEzXFgLdivBytoooKO5xLt5yalc8Ma5guTWobw998sbR3ogDd+2jed03CFmJA==", "dev": true, + "license": "MIT", "engines": { "node": ">=v14" } }, "node_modules/@commitlint/top-level": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.0.0.tgz", - "integrity": "sha512-dZrEP1PBJvodNWYPOYiLWf6XZergdksKQaT6i1KSROLdjf5Ai0brLOv5/P+CPxBeoj3vBxK4Ax8H1Pg9t7sHIQ==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.8.1.tgz", + "integrity": "sha512-l6+Z6rrNf5p333SHfEte6r+WkOxGlWK4bLuZKbtf/2TXRN+qhrvn1XE63VhD8Oe9oIHQ7F7W1nG2k/TJFhx2yA==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^5.0.0" }, @@ -844,10 +842,11 @@ } }, "node_modules/@commitlint/types": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.4.4.tgz", - "integrity": "sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.8.1.tgz", + "integrity": "sha512-PXDQXkAmiMEG162Bqdh9ChML/GJZo6vU+7F03ALKDK8zYc6SuAr47LjG7hGYRqUOz+WK0dU7bQ0xzuqFMdxzeQ==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0" }, @@ -860,6 +859,7 @@ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -872,6 +872,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -882,6 +883,7 @@ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -940,9 +942,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -956,6 +958,34 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/@eslint/eslintrc/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -963,10 +993,23 @@ "dev": true, "license": "MIT" }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "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" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, "license": "MIT", "engines": { @@ -974,14 +1017,14 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "deprecated": "Use @eslint/config-array instead", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -989,6 +1032,37 @@ "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "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" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -1016,6 +1090,7 @@ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -1032,6 +1107,7 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } @@ -1041,6 +1117,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -1050,9 +1127,9 @@ } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.0.tgz", + "integrity": "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==", "dev": true, "license": "MIT", "dependencies": { @@ -1068,6 +1145,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -1075,11 +1153,28 @@ "node": ">=8" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -1088,10 +1183,11 @@ } }, "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", + "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1101,6 +1197,7 @@ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -1113,11 +1210,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/console/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@jest/core": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/reporters": "^29.7.0", @@ -1160,12 +1268,23 @@ } } }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "dependencies": { + "node_modules/@jest/core/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", @@ -1180,6 +1299,7 @@ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, + "license": "MIT", "dependencies": { "expect": "^29.7.0", "jest-snapshot": "^29.7.0" @@ -1193,6 +1313,7 @@ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, + "license": "MIT", "dependencies": { "jest-get-type": "^29.6.3" }, @@ -1205,6 +1326,7 @@ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", @@ -1222,6 +1344,7 @@ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", @@ -1237,6 +1360,7 @@ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, + "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.7.0", @@ -1275,34 +1399,14 @@ } } }, - "node_modules/@jest/reporters/node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/@jest/reporters/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=8" } }, "node_modules/@jest/schemas": { @@ -1310,6 +1414,7 @@ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, + "license": "MIT", "dependencies": { "@sinclair/typebox": "^0.27.8" }, @@ -1322,6 +1427,7 @@ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", @@ -1336,6 +1442,7 @@ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/types": "^29.6.3", @@ -1351,6 +1458,7 @@ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", @@ -1361,11 +1469,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/test-sequencer/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@jest/transform": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -1387,11 +1506,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/transform/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@jest/types": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", @@ -1415,11 +1545,23 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@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==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -1505,14 +1647,14 @@ } }, "node_modules/@jsonjoy.com/fs-core": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.56.11.tgz", - "integrity": "sha512-wThHjzUp01ImIjfCwhs+UnFkeGPFAymwLEkOtenHewaKe2pTP12p6r1UuwikA9NEvNf9Vlck92r8fb8n/MWM5w==", + "version": "4.57.8", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.57.8.tgz", + "integrity": "sha512-YzVbwggV9452VCeHgo0bjsTaUt1O7JE0XpEsPar93nn/+RAwXk0mb1Y+f5EDJ3TRtRCFe+Ck5RuojdfB4jeHVw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-node-builtins": "4.56.11", - "@jsonjoy.com/fs-node-utils": "4.56.11", + "@jsonjoy.com/fs-node-builtins": "4.57.8", + "@jsonjoy.com/fs-node-utils": "4.57.8", "thingies": "^2.5.0" }, "engines": { @@ -1527,15 +1669,15 @@ } }, "node_modules/@jsonjoy.com/fs-fsa": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.56.11.tgz", - "integrity": "sha512-ZYlF3XbMayyp97xEN8ZvYutU99PCHjM64mMZvnCseXkCJXJDVLAwlF8Q/7q/xiWQRsv3pQBj1WXHd9eEyYcaCQ==", + "version": "4.57.8", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.57.8.tgz", + "integrity": "sha512-vmClyvCQMxgqz7uamDiGtRfp4MjzOznk3pcQjCxlIwJcw7TWeyr+bF30hI0x8NxdtNOGMg1pHM74VDIXOeyjuw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-core": "4.56.11", - "@jsonjoy.com/fs-node-builtins": "4.56.11", - "@jsonjoy.com/fs-node-utils": "4.56.11", + "@jsonjoy.com/fs-core": "4.57.8", + "@jsonjoy.com/fs-node-builtins": "4.57.8", + "@jsonjoy.com/fs-node-utils": "4.57.8", "thingies": "^2.5.0" }, "engines": { @@ -1550,17 +1692,17 @@ } }, "node_modules/@jsonjoy.com/fs-node": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.56.11.tgz", - "integrity": "sha512-D65YrnP6wRuZyEWoSFnBJSr5zARVpVBGctnhie4rCsMuGXNzX7IHKaOt85/Aj7SSoG1N2+/xlNjWmkLvZ2H3Tg==", + "version": "4.57.8", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.57.8.tgz", + "integrity": "sha512-IPEOlDYSnTDYpjQlQg2F8h+eqxKQN3sdbroI0WrteRiQZ462HzVpBo9ZZX485njz4nAacoe3fd4iDiIhk+k5Hg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-core": "4.56.11", - "@jsonjoy.com/fs-node-builtins": "4.56.11", - "@jsonjoy.com/fs-node-utils": "4.56.11", - "@jsonjoy.com/fs-print": "4.56.11", - "@jsonjoy.com/fs-snapshot": "4.56.11", + "@jsonjoy.com/fs-core": "4.57.8", + "@jsonjoy.com/fs-node-builtins": "4.57.8", + "@jsonjoy.com/fs-node-utils": "4.57.8", + "@jsonjoy.com/fs-print": "4.57.8", + "@jsonjoy.com/fs-snapshot": "4.57.8", "glob-to-regex.js": "^1.0.0", "thingies": "^2.5.0" }, @@ -1576,9 +1718,9 @@ } }, "node_modules/@jsonjoy.com/fs-node-builtins": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.56.11.tgz", - "integrity": "sha512-CNmt3a0zMCIhniFLXtzPWuUxXFU+U+2VyQiIrgt/rRVeEJNrMQUABaRbVxR0Ouw1LyR9RjaEkPM6nYpED+y43A==", + "version": "4.57.8", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.57.8.tgz", + "integrity": "sha512-mxXSXw8zZwRVakcjLqR2I/psy4gURFSASZS10kKJ2kJw05GC2nXGroGrWVHxwgkxXgQLsFQnB74QaLzsxzdL/w==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1593,15 +1735,15 @@ } }, "node_modules/@jsonjoy.com/fs-node-to-fsa": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.56.11.tgz", - "integrity": "sha512-5OzGdvJDgZVo+xXWEYo72u81zpOWlxlbG4d4nL+hSiW+LKlua/dldNgPrpWxtvhgyntmdFQad2UTxFyGjJAGhA==", + "version": "4.57.8", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.57.8.tgz", + "integrity": "sha512-AWZcT/4+H+iDl4XCukbXrarvwEgOrf/prFI5/7eg4ix9FxqVsZysIDJd1Kjd+AjlCeHKHJOaRqjLd5HiGSCJEw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-fsa": "4.56.11", - "@jsonjoy.com/fs-node-builtins": "4.56.11", - "@jsonjoy.com/fs-node-utils": "4.56.11" + "@jsonjoy.com/fs-fsa": "4.57.8", + "@jsonjoy.com/fs-node-builtins": "4.57.8", + "@jsonjoy.com/fs-node-utils": "4.57.8" }, "engines": { "node": ">=10.0" @@ -1615,13 +1757,13 @@ } }, "node_modules/@jsonjoy.com/fs-node-utils": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.56.11.tgz", - "integrity": "sha512-JADOZFDA3wRfsuxkT0+MYc4F9hJO2PYDaY66kRTG6NqGX3+bqmKu66YFYAbII/tEmQWPZeHoClUB23rtQM9UPg==", + "version": "4.57.8", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.57.8.tgz", + "integrity": "sha512-E/bJ7sQAb4pu9nbeJhbULU3WnqWrswte4N9Js/oHt7aHB746S8/XBqKlcbrqIgnD3095XluovNEZuu5ONT230g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-node-builtins": "4.56.11" + "@jsonjoy.com/fs-node-builtins": "4.57.8" }, "engines": { "node": ">=10.0" @@ -1635,13 +1777,13 @@ } }, "node_modules/@jsonjoy.com/fs-print": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.56.11.tgz", - "integrity": "sha512-rnaKRgCRIn8JGTjxhS0JPE38YM3Pj/H7SW4/tglhIPbfKEkky7dpPayNKV2qy25SZSL15oFVgH/62dMZ/z7cyA==", + "version": "4.57.8", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.57.8.tgz", + "integrity": "sha512-DfzhOBpmvNu5P/KSe4NNQaOnvNliTdcf0qrh/4EReErF/XUQXYkd0vZl/OiJCm/qjEEo8DWRstliw2/JNS84dA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-node-utils": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.57.8", "tree-dump": "^1.1.0" }, "engines": { @@ -1656,14 +1798,14 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.56.11.tgz", - "integrity": "sha512-IIldPX+cIRQuUol9fQzSS3hqyECxVpYMJQMqdU3dCKZFRzEl1rkIkw4P6y7Oh493sI7YdxZlKr/yWdzEWZ1wGQ==", + "version": "4.57.8", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.57.8.tgz", + "integrity": "sha512-L+eqKaWOHLDaiMv1dh/EWQ4hA+o6xAhWSumTo3Teg7OM18jU/KE13/e8Mfal+eAZ/pSl4wIhKHcDiwapJzC8Wg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@jsonjoy.com/buffers": "^17.65.0", - "@jsonjoy.com/fs-node-utils": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.57.8", "@jsonjoy.com/json-pack": "^17.65.0", "@jsonjoy.com/util": "^17.65.0" }, @@ -1890,11 +2032,25 @@ "dev": true, "license": "MIT" }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1908,6 +2064,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -1917,6 +2074,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -2092,14 +2250,183 @@ "@octokit/openapi-types": "^18.0.0" } }, + "node_modules/@peculiar/asn1-cms": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.8.0.tgz", + "integrity": "sha512-NgekZOrSJFSBFLFoLfwePguAWAx7z1+f2TEsWFUMyiqqfntZ4+S/S5hzqME3q4pCA0iOsFKdwiQ35dwY24eVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "@peculiar/asn1-x509-attr": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-csr": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.8.0.tgz", + "integrity": "sha512-akbF8+uvleHs8sejNPQxwmVFuInAg6FMNHOwMILXfP518YfFJwdR3jr6oNUPOaEJfuEhn/vkNOCIT6ASUd4mbg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-ecc": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.8.0.tgz", + "integrity": "sha512-ohwlk+u9Rv2NOAY1c6MfHj45ATVF8R1DUN/WCgABiRtLi2ZftlZWZX7KvpAbU8v9xPcmoILfELeEABj/rn18AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pfx": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.8.0.tgz", + "integrity": "sha512-5yof1ytoB++RQtaFbqSUJ8pxDJtZT6vbVqZ8XoJ61ph7UjNVvfFwAilnCodqkNsAodpy13gDhoxZXw00pghnyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.8.0", + "@peculiar/asn1-pkcs8": "^2.8.0", + "@peculiar/asn1-rsa": "^2.8.0", + "@peculiar/asn1-schema": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs8": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.8.0.tgz", + "integrity": "sha512-qAKXtLpBEw9LqhKpjw3ajZSXlBur+ipW+y2ivVBQAG6F6qRx94yO+1ZR4mvw+YaCfKSaOzLeYEzsPaBp4SJELA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs9": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.8.0.tgz", + "integrity": "sha512-b5nDWCnkV60+cQ141D6sVVwK9nz64R5n3zSVnklGd+ECdkW2Ol3U1a6yYFlalpSOaD557yuJB64A+q42jG7lUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.8.0", + "@peculiar/asn1-pfx": "^2.8.0", + "@peculiar/asn1-pkcs8": "^2.8.0", + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "@peculiar/asn1-x509-attr": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-rsa": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.8.0.tgz", + "integrity": "sha512-zHEUlCqB2mk7x2lxDwHHJy7hWZOPdGHVlsmITWKB5/PbQo61atbu9PJ/0r9dQNMwFzbKPXZ8uK8/91eUhRznSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.8.0.tgz", + "integrity": "sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.8.0.tgz", + "integrity": "sha512-N0CMuhWUzsWEVq6F1q9X6+VKUnWzSW+cSVg+aPaGGwDdbFoFWTYgin5MHwXgpWd6y9COMBxnfy/Qc+Xc7F0Zwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509-attr": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.8.0.tgz", + "integrity": "sha512-tHjkfS/qhMnmrlB2J9NhflQlQ7In3khO3CfmVrriOlpTeErY9ZIKOso1hQ5JQiyrJ7ShvqVPk7E5fQmbclkSKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@peculiar/utils/-/utils-2.0.3.tgz", + "integrity": "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/x509": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.3.tgz", + "integrity": "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.6.0", + "@peculiar/asn1-csr": "^2.6.0", + "@peculiar/asn1-ecc": "^2.6.0", + "@peculiar/asn1-pkcs9": "^2.6.0", + "@peculiar/asn1-rsa": "^2.6.0", + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "pvtsutils": "^1.3.6", + "reflect-metadata": "^0.2.2", + "tslib": "^2.8.1", + "tsyringe": "^4.10.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@pkgr/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", - "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", + "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", "dev": true, "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "node": "^14.18.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/pkgr" @@ -2110,6 +2437,7 @@ "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.22.0" } @@ -2119,6 +2447,7 @@ "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "4.2.10" }, @@ -2126,11 +2455,19 @@ "node": ">=12.22.0" } }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "license": "ISC" + }, "node_modules/@pnpm/npm-conf": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", - "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-3.0.3.tgz", + "integrity": "sha512-//0sR/cow/s4ICQaYoAobOl4aU8cjU6x/V24V7XkKotb9+O+3zySIYp146vpaobYHnxa4pZX8NkV54Z5AwbDKA==", "dev": true, + "license": "MIT", "dependencies": { "@pnpm/config.env-replace": "^1.1.0", "@pnpm/network.ca-file": "^1.0.1", @@ -2141,14 +2478,15 @@ } }, "node_modules/@semantic-release/changelog": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@semantic-release/changelog/-/changelog-6.0.1.tgz", - "integrity": "sha512-FT+tAGdWHr0RCM3EpWegWnvXJ05LQtBkQUaQRIExONoXjVjLuOILNm4DEKNaV+GAQyJjbLRVs57ti//GypH6PA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@semantic-release/changelog/-/changelog-6.0.3.tgz", + "integrity": "sha512-dZuR5qByyfe3Y03TpmCvAxCyTnp7r5XwtHRf/8vD9EAn4ZWbavUX8adMtXYzE86EVh0gyLA7lm5yW4IV30XUag==", "dev": true, + "license": "MIT", "dependencies": { "@semantic-release/error": "^3.0.0", "aggregate-error": "^3.0.0", - "fs-extra": "^9.0.0", + "fs-extra": "^11.0.0", "lodash": "^4.17.4" }, "engines": { @@ -2158,26 +2496,12 @@ "semantic-release": ">=18.0.0" } }, - "node_modules/@semantic-release/changelog/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@semantic-release/commit-analyzer": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-9.0.2.tgz", "integrity": "sha512-E+dr6L+xIHZkX4zNMe6Rnwg4YQrWNXK+rNsvwOPpdFppvZO1olE2fIgWhv89TkQErygevbjsZFSIxp+u6w2e5g==", "dev": true, + "license": "MIT", "dependencies": { "conventional-changelog-angular": "^5.0.0", "conventional-commits-filter": "^2.0.0", @@ -2194,11 +2518,47 @@ "semantic-release": ">=18.0.0-beta.1" } }, + "node_modules/@semantic-release/commit-analyzer/node_modules/conventional-changelog-angular": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", + "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@semantic-release/commit-analyzer/node_modules/conventional-commits-parser": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", + "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@semantic-release/error": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-3.0.0.tgz", "integrity": "sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.17" } @@ -2208,6 +2568,7 @@ "resolved": "https://registry.npmjs.org/@semantic-release/git/-/git-10.0.1.tgz", "integrity": "sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==", "dev": true, + "license": "MIT", "dependencies": { "@semantic-release/error": "^3.0.0", "aggregate-error": "^3.0.0", @@ -2257,19 +2618,35 @@ "semantic-release": ">=18.0.0-beta.1" } }, - "node_modules/@semantic-release/github/node_modules/fs-extra": { - "version": "11.3.4", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", - "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", + "node_modules/@semantic-release/github/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=14.14" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/github/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" } }, "node_modules/@semantic-release/github/node_modules/mime": { @@ -2277,6 +2654,7 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", "dev": true, + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -2284,11 +2662,22 @@ "node": ">=10.0.0" } }, + "node_modules/@semantic-release/github/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@semantic-release/npm": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-9.0.2.tgz", "integrity": "sha512-zgsynF6McdzxPnFet+a4iO9HpAlARXOM5adz7VGVCvj0ne8wtL2ZOQoDV2wZPDmdEotDIbVeJjafhelZjs9j6g==", "dev": true, + "license": "MIT", "dependencies": { "@semantic-release/error": "^3.0.0", "aggregate-error": "^3.0.0", @@ -2311,25 +2700,12 @@ "semantic-release": ">=19.0.0" } }, - "node_modules/@semantic-release/npm/node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/@semantic-release/release-notes-generator": { "version": "10.0.3", "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-10.0.3.tgz", "integrity": "sha512-k4x4VhIKneOWoBGHkx0qZogNjCldLPRiAjnIpMnlUh6PtaWXp/T+C9U7/TaNDDtgDa5HMbHl4WlREdxHio6/3w==", "dev": true, + "license": "MIT", "dependencies": { "conventional-changelog-angular": "^5.0.0", "conventional-changelog-writer": "^5.0.0", @@ -2349,17 +2725,54 @@ "semantic-release": ">=18.0.0-beta.1" } }, + "node_modules/@semantic-release/release-notes-generator/node_modules/conventional-changelog-angular": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", + "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/conventional-commits-parser": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", + "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "dev": true, + "license": "MIT" }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } @@ -2369,39 +2782,45 @@ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0" } }, "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -2411,10 +2830,11 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" } @@ -2424,25 +2844,28 @@ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", - "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.20.7" + "@babel/types": "^7.28.2" } }, "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", "dev": true, + "license": "MIT", "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -2459,10 +2882,11 @@ } }, "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -2479,92 +2903,78 @@ } }, "node_modules/@types/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==", - "dev": true + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "dev": true, + "license": "MIT" }, "node_modules/@types/d3-drag": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.1.tgz", - "integrity": "sha512-o1Va7bLwwk6h03+nSM8dpaGEYnoIG19P0lKqlic8Un36ymh9NSkNFX1yiXMKNMx8rJ0Kfnn2eovuFaL6Jvj0zA==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/d3-selection": "*" } }, "node_modules/@types/d3-ease": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.0.tgz", - "integrity": "sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==", - "dev": true + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/d3-force": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.3.tgz", - "integrity": "sha512-z8GteGVfkWJMKsx6hwC3SiTSLspL98VNpmvLpEFJQpZPq6xpA1I8HNBDNSpukfK0Vb0l64zGFhzunLgEAcBWSA==", - "dev": true + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "dev": true, + "license": "MIT" }, "node_modules/@types/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", "dev": true, + "license": "MIT", "dependencies": { "@types/d3-color": "*" } }, "node_modules/@types/d3-selection": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.1.tgz", - "integrity": "sha512-aJ1d1SCUtERHH65bB8NNoLpUOI3z8kVcfg2BGm4rMMUwuZF4x6qnIEKjT60Vt0o7gP/a/xkRVs4D9CpDifbyRA==", - "dev": true + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "dev": true, + "license": "MIT" }, "node_modules/@types/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-Sv4qEI9uq3bnZwlOANvYK853zvpdKEm1yz9rcc8ZTsxvRklcs9Fx4YFuGA3gXoQN/c/1T6QkVNjhaRO/cWj94g==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", "dev": true, + "license": "MIT", "dependencies": { "@types/d3-selection": "*" } }, "node_modules/@types/d3-zoom": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.1.tgz", - "integrity": "sha512-7s5L9TjfqIYQmQQEUcpMAcBOahem7TRoSO/+Gkz02GbMVuULiZzjF2BOdw291dbO2aNon4m2OdFsRGaCq2caLQ==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", "dev": true, + "license": "MIT", "dependencies": { "@types/d3-interpolate": "*", "@types/d3-selection": "*" } }, - "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" }, @@ -2595,16 +3005,18 @@ } }, "node_modules/@types/geojson": { - "version": "7946.0.10", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz", - "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==", - "dev": true + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "dev": true, + "license": "MIT" }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -2617,10 +3029,11 @@ "license": "MIT" }, "node_modules/@types/http-proxy": { - "version": "1.17.9", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", - "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==", + "version": "1.17.17", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz", + "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -2629,13 +3042,15 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, + "license": "MIT", "dependencies": { "@types/istanbul-lib-coverage": "*" } @@ -2645,15 +3060,17 @@ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/jest": { - "version": "29.5.12", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", - "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", "dev": true, + "license": "MIT", "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" @@ -2667,10 +3084,11 @@ "license": "MIT" }, "node_modules/@types/leaflet": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.9.tgz", - "integrity": "sha512-H8vPgD49HKzqM41ArHGZM70g/tfhp8W+JcPxfnF+5H/Xvp+xiP+KQOUNWU8U89fqS1Jj3cpRY/+nbnaHFzwnFA==", + "version": "1.9.21", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.21.tgz", + "integrity": "sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==", "dev": true, + "license": "MIT", "dependencies": { "@types/geojson": "*" } @@ -2683,56 +3101,56 @@ "license": "MIT" }, "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { - "version": "18.0.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.6.tgz", - "integrity": "sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==", - "dev": true - }, - "node_modules/@types/node-forge": { - "version": "1.3.14", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", - "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.0.tgz", + "integrity": "sha512-O0A1G3xPGy4w7AgQdAQYUlQ+BKk2Oovw8eRpofyp5KdBZULnbe+WqaOVNrm705SHphCiG4XHsACrSmPu1f+Kgw==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*" + "undici-types": "~8.3.0" } }, "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "dev": true, + "license": "MIT" }, "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", + "dev": true, + "license": "MIT" }, "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" }, "node_modules/@types/resize-observer-browser": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@types/resize-observer-browser/-/resize-observer-browser-0.1.7.tgz", - "integrity": "sha512-G9eN0Sn0ii9PWQ3Vl72jDPgeJwRWhv2Qk/nQkJuWmRmOB4HX3/BhD5SE1dZs/hzPZL/WKnvF0RHdTSG54QJFyg==", - "dev": true + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@types/resize-observer-browser/-/resize-observer-browser-0.1.11.tgz", + "integrity": "sha512-cNw5iH8JkMkb3QkCoe7DaZiawbDQEUX8t7iuQaRTyLOyQCR2h+ibBD4GJt7p5yhUHrlOeL7ZtbxNHeipqNsBzQ==", + "dev": true, + "license": "MIT" }, "node_modules/@types/retry": { "version": "0.12.2", @@ -2798,7 +3216,8 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/ws": { "version": "8.18.1", @@ -2811,10 +3230,11 @@ } }, "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", "dev": true, + "license": "MIT", "dependencies": { "@types/yargs-parser": "*" } @@ -2823,23 +3243,24 @@ "version": "21.0.3", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.1.tgz", - "integrity": "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.62.1.tgz", + "integrity": "sha512-4EQM77WgVNxj7OkL/5b/D/xZsw00G577+UriYTC7JF5opcF3T2AuoeY7ueLaZgSVjSgCS6yOAJB5bRGLPSJUzA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/type-utils": "8.56.1", - "@typescript-eslint/utils": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", + "@typescript-eslint/scope-manager": "8.62.1", + "@typescript-eslint/type-utils": "8.62.1", + "@typescript-eslint/utils": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.4.0" + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2849,32 +3270,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.56.1", + "@typescript-eslint/parser": "^8.62.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz", - "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.62.1.tgz", + "integrity": "sha512-sPhE4iHuJDSvoAiec+Ro8JyXw8f0ql13HFR82P99nCm9GwTEKG0KYLvDe6REk8BCXuit6vJAv/Yxg5ABaNS2rA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", + "@typescript-eslint/scope-manager": "8.62.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/typescript-estree": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1", "debug": "^4.4.3" }, "engines": { @@ -2886,18 +3297,18 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", - "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.62.1.tgz", + "integrity": "sha512-yQ3RgY5RkSBpsNS1Bx/JQEcA24FOSdfGktoyprAr5u18390UQdtVcfnEv4nIrIshNnavlVyZBKxQwT1fIAE6cg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.56.1", - "@typescript-eslint/types": "^8.56.1", + "@typescript-eslint/tsconfig-utils": "^8.62.1", + "@typescript-eslint/types": "^8.62.1", "debug": "^4.4.3" }, "engines": { @@ -2908,18 +3319,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz", - "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.62.1.tgz", + "integrity": "sha512-r4d249KbQ1SFdpeStvob8Ih6aPPIzfqllPVOtvhve6ZcpuVcYo5/7zUWckKpHE7StASX4kTKZTLf0WQm/wPkcg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1" + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2930,9 +3341,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", - "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.1.tgz", + "integrity": "sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g==", "dev": true, "license": "MIT", "engines": { @@ -2943,21 +3354,21 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz", - "integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.62.1.tgz", + "integrity": "sha512-aXM5xlqXiTxPibXB93cLAURfT3rlizf7uMXISCXy66Isr/9hISJx3yDsKl0L7lKa51b8JpFuNKby0/O0pEm9jg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1", - "@typescript-eslint/utils": "8.56.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/typescript-estree": "8.62.1", + "@typescript-eslint/utils": "8.62.1", "debug": "^4.4.3", - "ts-api-utils": "^2.4.0" + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2968,13 +3379,13 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz", - "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.62.1.tgz", + "integrity": "sha512-ooCzJFaf+Hg+uG6fA3NRFGuFjlfNlDhBthbv4ZPU/0elCAFUfnyXUvf/WOpHz/jYwSmvU2GkR2LtyUfy1AxZ1Q==", "dev": true, "license": "MIT", "engines": { @@ -2986,21 +3397,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", - "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.1.tgz", + "integrity": "sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.56.1", - "@typescript-eslint/tsconfig-utils": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", + "@typescript-eslint/project-service": "8.62.1", + "@typescript-eslint/tsconfig-utils": "8.62.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.4.0" + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3010,52 +3421,13 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/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, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, "license": "ISC", "bin": { @@ -3066,16 +3438,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz", - "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.62.1.tgz", + "integrity": "sha512-sHtbPfuKNZCG+ih8SyjjucqRntSVmp8XgL5u6o9mAhiSn8ds5o/M/XdM0abweme2Tln3szOstOrZ9OXitvPh0g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1" + "@typescript-eslint/scope-manager": "8.62.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/typescript-estree": "8.62.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3086,17 +3458,17 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz", - "integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.62.1.tgz", + "integrity": "sha512-4g3BLxfdTMy8iZG0MaBkadnlRrCJ74cQiFbyEVMrkwIoqdyaXXQM22cotDvrl4x28wgIZ9rEJRoM+mmhSJpJ1g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/types": "8.62.1", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -3121,9 +3493,9 @@ } }, "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.2.tgz", + "integrity": "sha512-5jsZFwgR5rTdKwidH9Qmat75RKwqfpKlWWB1frDkljN127mwqBu8K0PYo7/hFpF03IEJpfVPpCQDY/eDx3iHvA==", "dev": true, "license": "ISC" }, @@ -3293,6 +3665,7 @@ "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", "dev": true, + "license": "MIT", "peerDependencies": { "webpack": "4.x.x || 5.x.x", "webpack-cli": "4.x.x" @@ -3303,6 +3676,7 @@ "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", "dev": true, + "license": "MIT", "dependencies": { "envinfo": "^7.7.3" }, @@ -3315,6 +3689,7 @@ "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", "dev": true, + "license": "MIT", "peerDependencies": { "webpack-cli": "4.x.x" }, @@ -3343,6 +3718,7 @@ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -3351,10 +3727,20 @@ "node": ">= 0.6" } }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "dev": true, "license": "MIT", "bin": { @@ -3387,6 +3773,19 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -3402,6 +3801,7 @@ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, + "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -3411,9 +3811,9 @@ } }, "node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", "dependencies": { @@ -3432,6 +3832,7 @@ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^8.0.0" }, @@ -3449,6 +3850,7 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -3461,6 +3863,7 @@ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, @@ -3476,6 +3879,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -3491,6 +3895,7 @@ "engines": [ "node >= 0.8.0" ], + "license": "Apache-2.0", "bin": { "ansi-html": "bin/ansi-html" } @@ -3500,6 +3905,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3509,6 +3915,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -3523,13 +3930,15 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -3542,31 +3951,43 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/argv-formatter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/argv-formatter/-/argv-formatter-1.0.0.tgz", "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true, + "license": "MIT" }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3576,33 +3997,39 @@ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "node_modules/asn1js": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.10.tgz", + "integrity": "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "lodash": "^4.17.14" + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.5", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=12.0.0" } }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "dev": true, - "engines": { - "node": ">= 4.0.0" - } + "license": "MIT" }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", @@ -3619,11 +4046,22 @@ "@babel/core": "^7.8.0" } }, + "node_modules/babel-jest/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/babel-plugin-istanbul": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -3640,6 +4078,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -3656,6 +4095,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -3665,6 +4105,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -3676,26 +4117,30 @@ } }, "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0 || ^8.0.0-0" } }, "node_modules/babel-preset-jest": { @@ -3703,6 +4148,7 @@ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" @@ -3715,15 +4161,19 @@ } }, "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } }, "node_modules/baseline-browser-mapping": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", - "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", + "version": "2.10.41", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.41.tgz", + "integrity": "sha512-WwS7MHhqGHHlaVsqRZnhvCEMS0owDX+SxRlve7JkuH7My1Ara3ZriTmCQupPfYjxMZ8I/tgxtJYr2t7taHaH4A==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3738,6 +4188,7 @@ "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "5.1.2" }, @@ -3749,7 +4200,8 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/before-after-hook": { "version": "2.2.3", @@ -3772,9 +4224,9 @@ } }, "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": { @@ -3786,7 +4238,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" @@ -3814,9 +4266,9 @@ "license": "MIT" }, "node_modules/bonjour-service": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", - "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.4.2.tgz", + "integrity": "sha512-lMskhnsW70yWHr4PhPeh2rvaIkLSaDpp+nmtbXBZaNKTXwxL73QOkW6HhbzqTImXjevn9TreGT4GACGBCGP9nQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3832,14 +4284,16 @@ "license": "MIT" }, "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": "5.0.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", + "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/braces": { @@ -3856,9 +4310,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "version": "4.28.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", + "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", "dev": true, "funding": [ { @@ -3876,11 +4330,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" + "baseline-browser-mapping": "^2.10.38", + "caniuse-lite": "^1.0.30001799", + "electron-to-chromium": "^1.5.376", + "node-releases": "^2.0.48", + "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" @@ -3894,6 +4348,7 @@ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, + "license": "MIT", "dependencies": { "fast-json-stable-stringify": "2.x" }, @@ -3906,6 +4361,7 @@ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "node-int64": "^0.4.0" } @@ -3914,7 +4370,8 @@ "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 + "dev": true, + "license": "MIT" }, "node_modules/bundle-name": { "version": "4.1.0", @@ -3942,6 +4399,16 @@ "node": ">= 0.8" } }, + "node_modules/bytestreamjs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bytestreamjs/-/bytestreamjs-2.0.1.tgz", + "integrity": "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -3978,6 +4445,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3987,6 +4455,7 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3996,6 +4465,7 @@ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", "dev": true, + "license": "MIT", "dependencies": { "camelcase": "^5.3.1", "map-obj": "^4.0.0", @@ -4009,9 +4479,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001776", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001776.tgz", - "integrity": "sha512-sg01JDPzZ9jGshqKSckOQthXnYwOEP50jeVFhaSFbZcOy05TiuuaffDOfcwtCisJ9kNQuLBFibYywv2Bgm9osw==", + "version": "1.0.30001800", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001800.tgz", + "integrity": "sha512-MMHtuAz9Ys840zAY5F4k6fV5GaivZ9sPk+nz0mY+GYVzRBnYkN0mpqkSR92oWRQ19yQWo4HvBV/FnC16AJX8MA==", "dev": true, "funding": [ { @@ -4034,6 +4504,7 @@ "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", "dev": true, + "license": "MIT", "dependencies": { "ansicolors": "~0.3.2", "redeyed": "~2.1.0" @@ -4047,6 +4518,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4063,6 +4535,7 @@ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -4106,10 +4579,11 @@ } }, "node_modules/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==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0" } @@ -4125,30 +4599,34 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/cli-table3": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz", - "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dev": true, + "license": "MIT", "dependencies": { "string-width": "^4.2.0" }, @@ -4160,14 +4638,18 @@ } }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/clone-deep": { @@ -4175,6 +4657,7 @@ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", @@ -4189,6 +4672,7 @@ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, + "license": "MIT", "dependencies": { "isobject": "^3.0.1" }, @@ -4201,22 +4685,25 @@ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, + "license": "MIT", "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" } }, "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -4228,13 +4715,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "dev": true + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" }, "node_modules/commander": { "version": "2.20.3", @@ -4248,6 +4737,7 @@ "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, + "license": "MIT", "dependencies": { "array-ify": "^1.0.0", "dot-prop": "^5.1.0" @@ -4258,6 +4748,7 @@ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": ">= 1.43.0 < 2" }, @@ -4289,6 +4780,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -4297,17 +4789,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/compression/node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } + "license": "MIT" }, "node_modules/compression/node_modules/safe-buffer": { "version": "5.2.1", @@ -4334,13 +4817,15 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/config-chain": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dev": true, + "license": "MIT", "dependencies": { "ini": "^1.3.4", "proto-list": "~1.2.1" @@ -4351,6 +4836,7 @@ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8" } @@ -4360,6 +4846,7 @@ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -4385,7 +4872,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/content-type": { "version": "1.0.5", @@ -4398,37 +4886,38 @@ } }, "node_modules/conventional-changelog-angular": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", + "integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==", "dev": true, + "license": "ISC", "dependencies": { - "compare-func": "^2.0.0", - "q": "^1.5.1" + "compare-func": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=14" } }, "node_modules/conventional-changelog-conventionalcommits": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz", - "integrity": "sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-6.1.0.tgz", + "integrity": "sha512-3cS3GEtR78zTfMzk0AizXKKIdN4OvSh7ibNz6/DPbhWWQu7LqE/8+/GqSodV+sywUR2gpJAdP/1JFf4XtN7Zpw==", "dev": true, + "license": "ISC", "dependencies": { - "compare-func": "^2.0.0", - "lodash": "^4.17.15", - "q": "^1.5.1" + "compare-func": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=14" } }, "node_modules/conventional-changelog-eslint": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", + "deprecated": "This preset is deprecated. Please use conventional-changelog-conventionalcommits or conventional-changelog-angular instead.", "dev": true, + "license": "ISC", "dependencies": { "q": "^1.5.1" }, @@ -4441,6 +4930,7 @@ "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", "dev": true, + "license": "MIT", "dependencies": { "conventional-commits-filter": "^2.0.7", "dateformat": "^3.0.0", @@ -4464,6 +4954,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -4473,6 +4964,7 @@ "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", "dev": true, + "license": "MIT", "dependencies": { "lodash.ismatch": "^4.4.0", "modify-values": "^1.0.0" @@ -4482,30 +4974,30 @@ } }, "node_modules/conventional-commits-parser": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", - "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz", + "integrity": "sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==", "dev": true, + "license": "MIT", "dependencies": { "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" + "JSONStream": "^1.3.5", + "meow": "^8.1.2", + "split2": "^3.2.2" }, "bin": { "conventional-commits-parser": "cli.js" }, "engines": { - "node": ">=10" + "node": ">=14" } }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cookie": { "version": "0.7.2", @@ -4518,16 +5010,18 @@ } }, "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "dev": true, + "license": "MIT" }, "node_modules/copy-webpack-plugin": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", "dev": true, + "license": "MIT", "dependencies": { "fast-glob": "^3.2.11", "glob-parent": "^6.0.1", @@ -4547,82 +5041,64 @@ "webpack": "^5.1.0" } }, - "node_modules/copy-webpack-plugin/node_modules/globby": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz", - "integrity": "sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==", - "dev": true, - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "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 + "dev": true, + "license": "MIT" }, "node_modules/corser": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4.0" } }, "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, + "license": "MIT", "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/cosmiconfig-typescript-loader": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.3.0.tgz", - "integrity": "sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.4.0.tgz", + "integrity": "sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=12", - "npm": ">=6" + "node": ">=v14.21.3" }, "peerDependencies": { "@types/node": "*", "cosmiconfig": ">=7", "ts-node": ">=10", - "typescript": ">=3" + "typescript": ">=4" } }, "node_modules/create-jest": { @@ -4630,6 +5106,7 @@ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", @@ -4650,7 +5127,8 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.6", @@ -4672,6 +5150,7 @@ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4680,6 +5159,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", "engines": { "node": ">=12" } @@ -4688,6 +5168,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", "engines": { "node": ">=12" } @@ -4696,6 +5177,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", "d3-selection": "3" @@ -4708,6 +5190,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", "engines": { "node": ">=12" } @@ -4716,6 +5199,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", "d3-quadtree": "1 - 3", @@ -4729,6 +5213,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", "dependencies": { "d3-color": "1 - 3" }, @@ -4740,6 +5225,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", "engines": { "node": ">=12" } @@ -4748,6 +5234,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", "engines": { "node": ">=12" } @@ -4756,6 +5243,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", "engines": { "node": ">=12" } @@ -4764,6 +5252,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", "dependencies": { "d3-color": "1 - 3", "d3-dispatch": "1 - 3", @@ -4782,6 +5271,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", @@ -4798,6 +5288,7 @@ "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4807,6 +5298,7 @@ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -4834,21 +5326,26 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, + "license": "MIT", "dependencies": { "decamelize": "^1.1.0", "map-obj": "^1.0.0" }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/decamelize-keys/node_modules/map-obj": { @@ -4856,15 +5353,17 @@ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", "dev": true, + "license": "MIT", "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, @@ -4879,6 +5378,7 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4.0.0" } @@ -4895,6 +5395,7 @@ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -4947,6 +5448,7 @@ "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", "dev": true, + "license": "MIT", "dependencies": { "globby": "^11.0.1", "graceful-fs": "^4.2.4", @@ -4964,11 +5466,43 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/del/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/del/node_modules/p-map": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, + "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, @@ -4979,10 +5513,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/del/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "license": "MIT", "engines": { @@ -5012,6 +5556,7 @@ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -5020,7 +5565,8 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/diff": { "version": "4.0.4", @@ -5037,6 +5583,7 @@ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -5046,6 +5593,7 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -5071,6 +5619,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -5083,6 +5632,7 @@ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, + "license": "MIT", "dependencies": { "is-obj": "^2.0.0" }, @@ -5110,6 +5660,7 @@ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "readable-stream": "^2.0.2" } @@ -5122,9 +5673,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.307", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", - "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", + "version": "1.5.386", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.386.tgz", + "integrity": "sha512-f9yJE+9dJy+B4QC1iTu+mVP/KWLZviG5u/qtRwdBF0zPt3etWa1HSY1lMuWw0Nt8/KpLCY6ok+XlKHOs6ZhxSA==", "dev": true, "license": "ISC" }, @@ -5133,6 +5684,7 @@ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -5144,7 +5696,8 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/encodeurl": { "version": "2.0.0", @@ -5157,14 +5710,14 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", - "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", + "version": "5.24.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.1.tgz", + "integrity": "sha512-7DdUaTjmNwMcH2gLr1qycesKII3BK4RLy/mdAb7x10Lq7bR4aNKHt1BR1ZALSv0rPM/hF5wYF0PhGop/rJm8vw==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" + "tapable": "^2.3.3" }, "engines": { "node": ">=10.13.0" @@ -5175,6 +5728,7 @@ "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-5.5.0.tgz", "integrity": "sha512-o0JdWIbOLP+WJKIUt36hz1ImQQFuN92nhsfTkHHap+J8CiI8WgGpH/a9jEGHh4/TU5BUUGjlnKXNoDb57+ne+A==", "dev": true, + "license": "MIT", "dependencies": { "execa": "^5.0.0", "fromentries": "^1.3.2", @@ -5185,10 +5739,11 @@ } }, "node_modules/envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.21.0.tgz", + "integrity": "sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow==", "dev": true, + "license": "MIT", "bin": { "envinfo": "dist/cli.js" }, @@ -5197,10 +5752,11 @@ } }, "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } @@ -5226,16 +5782,16 @@ } }, "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.3.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.0.tgz", + "integrity": "sha512-KLdwQm2NvGLDkQDCGvmiQrhkd0JbMzXthwQAUgWjQuQdBLFa3eiBP5arXZyA+f8x+x7OXgud6bq2rxjGtHV2tw==", "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "dev": true, "license": "MIT", "dependencies": { @@ -5259,13 +5815,15 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -5274,9 +5832,9 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", @@ -5284,8 +5842,8 @@ "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -5335,6 +5893,7 @@ "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=0.10.0" }, @@ -5343,10 +5902,11 @@ } }, "node_modules/eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.2.tgz", + "integrity": "sha512-/IGJ6+Dka158JnP5n5YFMOszjDWrXggGz1LaK/guZq9vZTmniaKlHcsscvkAhn9y4U+BU3JuUdYvtAMcv30y4A==", "dev": true, + "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -5355,9 +5915,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "29.15.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.15.0.tgz", - "integrity": "sha512-ZCGr7vTH2WSo2hrK5oM2RULFmMruQ7W3cX7YfwoTiPfzTGTFBMmrVIz45jZHd++cGKj/kWf02li/RhTGcANJSA==", + "version": "29.15.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.15.4.tgz", + "integrity": "sha512-6ln5i9Nkrb27X4w91ZPt/xHDsVQnvxTS2ntgq6r32u+8gymdUrp88TdcBXSveZW0Dl+M5v2H6K75kJhMvUGhjg==", "dev": true, "license": "MIT", "dependencies": { @@ -5370,7 +5930,7 @@ "@typescript-eslint/eslint-plugin": "^8.0.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "jest": "*", - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <7.0.0" }, "peerDependenciesMeta": { "@typescript-eslint/eslint-plugin": { @@ -5385,14 +5945,14 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.5.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz", - "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==", + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.6.tgz", + "integrity": "sha512-ifetmTcxWfz+4qRW3pH/ujdTq2jQIj59AxJMIN26K5avYgU8dxycUETQonWiW+wPrYXA0j3Try0l1CnwVQtDqQ==", "dev": true, "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.1", - "synckit": "^0.11.12" + "synckit": "^0.11.13" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -5416,16 +5976,20 @@ } }, "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { @@ -5442,9 +6006,9 @@ } }, "node_modules/eslint/node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -5458,38 +6022,53 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT" + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">= 4" } }, "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/minimatch": { + "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" + }, + "engines": { + "node": "*" + } }, "node_modules/espree": { "version": "9.6.1", @@ -5514,6 +6093,7 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -5535,21 +6115,12 @@ "node": ">=0.10" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, "node_modules/esrecurse": { "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, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -5557,20 +6128,12 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { + "node_modules/estraverse": { "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" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -5580,6 +6143,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -5598,13 +6162,15 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.x" } @@ -5614,6 +6180,7 @@ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -5646,6 +6213,7 @@ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/expect-utils": "^29.7.0", "jest-get-type": "^29.6.3", @@ -5658,15 +6226,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", @@ -5685,7 +6253,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", @@ -5704,17 +6272,12 @@ "url": "https://opencollective.com/express" } }, - "node_modules/express/node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -5723,7 +6286,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/express/node_modules/safe-buffer": { "version": "5.2.1", @@ -5743,13 +6307,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "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 + "dev": true, + "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", @@ -5759,16 +6325,17 @@ "license": "Apache-2.0" }, "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -5779,6 +6346,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -5790,7 +6358,8 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -5800,9 +6369,9 @@ "license": "MIT" }, "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.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz", + "integrity": "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==", "dev": true, "funding": [ { @@ -5817,19 +6386,21 @@ "license": "BSD-3-Clause" }, "node_modules/fastest-levenshtein": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.14.tgz", - "integrity": "sha512-tFfWHjnuUfKE186Tfgr+jtaFc0mZTApEgKDOeyN+FwOqRkO/zK/3h1AiRd8u8CY53owL3CUmGr/oI9p/RdyLTA==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.9.1" } }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -5839,6 +6410,7 @@ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", "dev": true, + "license": "Apache-2.0", "dependencies": { "websocket-driver": ">=0.5.1" }, @@ -5851,6 +6423,7 @@ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "bser": "2.1.1" } @@ -5860,6 +6433,7 @@ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -5875,6 +6449,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -5884,6 +6459,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -5945,6 +6521,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -5961,6 +6538,7 @@ "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", "dev": true, + "license": "MIT", "dependencies": { "semver-regex": "^3.1.2" }, @@ -5971,13 +6549,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, + "license": "MIT", "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { @@ -5985,15 +6575,16 @@ } }, "node_modules/flatted": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", - "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", - "dev": true + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "dev": true, "funding": [ { @@ -6001,6 +6592,7 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -6015,6 +6607,7 @@ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -6034,6 +6627,7 @@ "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" @@ -6057,34 +6651,38 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "version": "11.3.6", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.6.tgz", + "integrity": "sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=14.14" } }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -6108,6 +6706,7 @@ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -6117,6 +6716,7 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -6151,6 +6751,7 @@ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0.0" } @@ -6174,6 +6775,7 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6182,17 +6784,18 @@ } }, "node_modules/git-log-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", - "integrity": "sha512-rnCVNfkTL8tdNryFuaY0fYiBWEBcgF748O6ZI61rslBvr2o7U65c2/6npCRqH40vuAhtgtDiqLTJjBVdrejCzA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.1.tgz", + "integrity": "sha512-PI+sPDvHXNPl5WNOErAK05s3j0lgwUzMN6o8cyQrDaKfT3qd7TmNJKeXX+SknI5I0QhG5fVPAEwSY4tRGDtYoQ==", "dev": true, + "license": "MIT", "dependencies": { "argv-formatter": "~1.0.0", "spawn-error-forwarder": "~1.0.0", "split2": "~1.0.0", "stream-combiner2": "~1.1.1", "through2": "~2.0.0", - "traverse": "~0.6.6" + "traverse": "0.6.8" } }, "node_modules/git-log-parser/node_modules/split2": { @@ -6200,6 +6803,7 @@ "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", "integrity": "sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==", "dev": true, + "license": "ISC", "dependencies": { "through2": "~2.0.0" } @@ -6209,6 +6813,7 @@ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, + "license": "MIT", "dependencies": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" @@ -6218,7 +6823,9 @@ "version": "2.0.11", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "deprecated": "Deprecated and no longer maintained. Use @conventional-changelog/git-client instead.", "dev": true, + "license": "MIT", "dependencies": { "dargs": "^7.0.0", "lodash": "^4.17.15", @@ -6237,7 +6844,9 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "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": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -6258,6 +6867,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -6282,18 +6892,43 @@ "tslib": "2" } }, - "node_modules/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==", + "node_modules/glob/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, - "license": "BSD-2-Clause" + "license": "MIT" + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "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" + }, + "engines": { + "node": "*" + } }, "node_modules/global-dirs": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", "dev": true, + "license": "MIT", "dependencies": { "ini": "^1.3.4" }, @@ -6318,25 +6953,35 @@ } }, "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", "dev": true, + "license": "MIT", "dependencies": { - "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", "merge2": "^1.4.1", - "slash": "^3.0.0" + "slash": "^4.0.0" }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globby/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -6351,10 +6996,11 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true + "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, + "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", @@ -6367,16 +7013,18 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "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.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, @@ -6395,27 +7043,17 @@ "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/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, + "license": "MIT", "engines": { "node": ">=8" } @@ -6434,9 +7072,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "dev": true, "license": "MIT", "dependencies": { @@ -6451,6 +7089,7 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, + "license": "MIT", "bin": { "he": "bin/he" } @@ -6460,6 +7099,7 @@ "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-2.0.0.tgz", "integrity": "sha512-zZ6T5WcuBMIUVh49iPQS9t977t7C0l7OtHrpeMb5uk48JdflRX0NSFvCekfYNmGQETnLq9W/isMyHl69kxGi8g==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -6469,6 +7109,7 @@ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -6476,11 +7117,32 @@ "node": ">=10" } }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.1", "obuf": "^1.0.0", @@ -6488,17 +7150,32 @@ "wbuf": "^1.1.0" } }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/http-errors": { "version": "2.0.1", @@ -6522,16 +7199,18 @@ } }, "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", + "dev": true, + "license": "MIT" }, "node_modules/http-proxy": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, + "license": "MIT", "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", @@ -6556,9 +7235,9 @@ } }, "node_modules/http-proxy-middleware": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", - "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.10.tgz", + "integrity": "sha512-RKzRWNPxUZqbuk3BC5mGVJbBnWgr+diEnjJexIOytFbBzDy88Fbh/YvBr3DsNrl1jYAfjWfpATEv0NO35FDuPQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6585,6 +7264,7 @@ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6597,6 +7277,7 @@ "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", "dev": true, + "license": "MIT", "dependencies": { "basic-auth": "^2.0.1", "chalk": "^4.1.2", @@ -6619,42 +7300,6 @@ "node": ">=12" } }, - "node_modules/http-server/node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/http-server/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/http-server/node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/https-proxy-agent": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", @@ -6674,15 +7319,17 @@ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } }, "node_modules/husky": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", - "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", "dev": true, + "license": "MIT", "bin": { "husky": "lib/bin.js" }, @@ -6717,19 +7364,21 @@ } }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -6746,6 +7395,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -6755,6 +7405,7 @@ "resolved": "https://registry.npmjs.org/import-from/-/import-from-4.0.0.tgz", "integrity": "sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.2" }, @@ -6763,10 +7414,11 @@ } }, "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, + "license": "MIT", "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -6781,60 +7433,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-local/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -6844,6 +7448,7 @@ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -6852,7 +7457,9 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -6862,19 +7469,22 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/interpret": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -6884,6 +7494,7 @@ "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-6.0.0.tgz", "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==", "dev": true, + "license": "MIT", "dependencies": { "from2": "^2.3.0", "p-is-promise": "^3.0.0" @@ -6896,9 +7507,9 @@ } }, "node_modules/ipaddr.js": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.3.0.tgz", - "integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz", + "integrity": "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==", "dev": true, "license": "MIT", "engines": { @@ -6909,7 +7520,8 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-binary-path": { "version": "2.1.0", @@ -6925,12 +7537,16 @@ } }, "node_modules/is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", "dev": true, + "license": "MIT", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6957,6 +7573,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6966,6 +7583,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -6975,6 +7593,7 @@ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -6984,6 +7603,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -7011,9 +7631,9 @@ } }, "node_modules/is-network-error": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.1.tgz", - "integrity": "sha512-6QCxa49rQbmUWLfk0nuGqzql9U8uaV2H6279bRErPBHe/109hCzsLUBUHfbEtvLIHBd6hyXbgedBSHevm43Edw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.2.tgz", + "integrity": "sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==", "dev": true, "license": "MIT", "engines": { @@ -7038,6 +7658,7 @@ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -7047,6 +7668,7 @@ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -7056,6 +7678,7 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -7065,6 +7688,7 @@ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7084,6 +7708,7 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -7096,6 +7721,7 @@ "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", "dev": true, + "license": "MIT", "dependencies": { "text-extensions": "^1.0.0" }, @@ -7123,19 +7749,22 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7145,6 +7774,7 @@ "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz", "integrity": "sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==", "dev": true, + "license": "MIT", "dependencies": { "lodash.capitalize": "^4.2.1", "lodash.escaperegexp": "^4.1.2", @@ -7161,15 +7791,17 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-instrument": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", - "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.23.9", "@babel/parser": "^7.23.9", @@ -7181,26 +7813,12 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/istanbul-lib-report": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", @@ -7215,6 +7833,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -7225,10 +7844,11 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -7242,6 +7862,7 @@ "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-1.0.2.tgz", "integrity": "sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6.0" } @@ -7251,6 +7872,7 @@ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -7277,6 +7899,7 @@ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, + "license": "MIT", "dependencies": { "execa": "^5.0.0", "jest-util": "^29.7.0", @@ -7286,26 +7909,12 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-changed-files/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/jest-circus": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", @@ -7332,19 +7941,14 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-circus/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/jest-circus/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/jest-cli": { @@ -7352,6 +7956,7 @@ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/core": "^29.7.0", "@jest/test-result": "^29.7.0", @@ -7385,6 +7990,7 @@ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.7.0", @@ -7425,11 +8031,22 @@ } } }, + "node_modules/jest-config/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", @@ -7445,6 +8062,7 @@ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, + "license": "MIT", "dependencies": { "detect-newline": "^3.0.0" }, @@ -7457,6 +8075,7 @@ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", @@ -7473,6 +8092,7 @@ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", @@ -7490,6 +8110,7 @@ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -7499,6 +8120,7 @@ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -7519,44 +8141,15 @@ "fsevents": "^2.3.2" } }, - "node_modules/jest-haste-map/node_modules/jest-worker": { + "node_modules/jest-leak-detector": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map/node_modules/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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -7567,6 +8160,7 @@ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.7.0", @@ -7582,6 +8176,7 @@ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.6.3", @@ -7597,11 +8192,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-message-util/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/jest-mock": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -7616,6 +8222,7 @@ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -7633,6 +8240,7 @@ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -7642,6 +8250,7 @@ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", @@ -7662,6 +8271,7 @@ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, + "license": "MIT", "dependencies": { "jest-regex-util": "^29.6.3", "jest-snapshot": "^29.7.0" @@ -7670,11 +8280,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-resolve/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/jest-runner": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/environment": "^29.7.0", @@ -7702,66 +8323,12 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runner/node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-runner/node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/jest-runner/node_modules/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, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/jest-runtime": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", @@ -7790,11 +8357,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-runtime/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/jest-snapshot": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", @@ -7821,26 +8399,12 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -7858,6 +8422,7 @@ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "camelcase": "^6.2.0", @@ -7875,6 +8440,7 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -7887,6 +8453,7 @@ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, + "license": "MIT", "dependencies": { "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", @@ -7902,18 +8469,19 @@ } }, "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-worker/node_modules/supports-color": { @@ -7940,10 +8508,20 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -7953,52 +8531,66 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true + "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 + "dev": true, + "license": "MIT" }, "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 + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -8007,10 +8599,11 @@ } }, "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -8025,13 +8618,15 @@ "dev": true, "engines": [ "node >= 0.2.0" - ] + ], + "license": "MIT" }, "node_modules/JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, + "license": "(MIT OR Apache-2.0)", "dependencies": { "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" @@ -8043,11 +8638,22 @@ "node": "*" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8057,31 +8663,34 @@ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/launch-editor": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.13.1.tgz", - "integrity": "sha512-lPSddlAAluRKJ7/cjRFoXUFzaX7q/YKI7yPHuEvSJVqoXvFnJov1/Ud87Aa4zULIbA9Nja4mSPK8l0z/7eV2wA==", + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.14.1.tgz", + "integrity": "sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==", "dev": true, "license": "MIT", "dependencies": { "picocolors": "^1.1.1", - "shell-quote": "^1.8.3" + "shell-quote": "^1.8.4" } }, "node_modules/leaflet": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.8.0.tgz", - "integrity": "sha512-gwhMjFCQiYs3x/Sf+d49f10ERXaEFCPr+nVTryhAW8DWbMGqJqt9G4XuIaHmFW08zYvhgdzqXGr8AlW8v8dQkA==" + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", + "license": "BSD-2-Clause" }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -8104,13 +8713,15 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.1.2", "parse-json": "^4.0.0", @@ -8126,6 +8737,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, + "license": "MIT", "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" @@ -8134,28 +8746,20 @@ "node": ">=4" } }, - "node_modules/load-json-file/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/load-json-file/node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "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": { @@ -8171,6 +8775,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -8182,9 +8787,16 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true, "license": "MIT" }, @@ -8192,72 +8804,115 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.escaperegexp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", + "dev": true, + "license": "MIT" }, "node_modules/lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true, + "license": "MIT" }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.mergewith": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true, + "license": "MIT" }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.uniqby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "dev": true, + "license": "MIT" }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "version": "5.1.1", + "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": "^4.0.0" - }, - "engines": { - "node": ">=10" + "yallist": "^3.0.2" } }, "node_modules/make-dir": { @@ -8265,6 +8920,7 @@ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.5.3" }, @@ -8275,32 +8931,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "tmpl": "1.0.5" } @@ -8310,6 +8953,7 @@ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -8318,10 +8962,11 @@ } }, "node_modules/marked": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.18.tgz", - "integrity": "sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, + "license": "MIT", "bin": { "marked": "bin/marked.js" }, @@ -8330,45 +8975,45 @@ } }, "node_modules/marked-terminal": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.1.1.tgz", - "integrity": "sha512-+cKTOx9P4l7HwINYhzbrBSyzgxO2HaHKGZGuB1orZsMIgXYaJyfidT81VXRdpelW/PcHEWxywscePVgI/oUF6g==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.2.0.tgz", + "integrity": "sha512-Piv6yNwAQXGFjZSaiNljyNFw7jKDdGrw70FSbtxEyldLsyeuV5ZHm/1wW++kWbrOF1VPnUgYOhB2oLL0ZpnekA==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-escapes": "^5.0.0", + "ansi-escapes": "^6.2.0", "cardinal": "^2.1.1", - "chalk": "^5.0.0", - "cli-table3": "^0.6.1", + "chalk": "^5.2.0", + "cli-table3": "^0.6.3", "node-emoji": "^1.11.0", - "supports-hyperlinks": "^2.2.0" + "supports-hyperlinks": "^2.3.0" }, "engines": { "node": ">=14.13.1 || >=16.0.0" }, "peerDependencies": { - "marked": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0" + "marked": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" } }, "node_modules/marked-terminal/node_modules/ansi-escapes": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", - "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", "dev": true, - "dependencies": { - "type-fest": "^1.0.2" - }, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/marked-terminal/node_modules/chalk": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", - "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -8376,18 +9021,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/marked-terminal/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -8409,20 +9042,20 @@ } }, "node_modules/memfs": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.56.11.tgz", - "integrity": "sha512-/GodtwVeKVIHZKLUSr2ZdOxKBC5hHki4JNCU22DoCGPEHr5o2PD5U721zvESKyWwCfTfavFl9WZYgA13OAYK0g==", + "version": "4.57.8", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.57.8.tgz", + "integrity": "sha512-bApYhn8BLpFAnAQmFfEl/NPN+8qx5Ar3V4Qt3ek23mVwBEElzV7c6XoPkb/PCG8ZFpowCEpHcPwMFTwHS7tSMA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-core": "4.56.11", - "@jsonjoy.com/fs-fsa": "4.56.11", - "@jsonjoy.com/fs-node": "4.56.11", - "@jsonjoy.com/fs-node-builtins": "4.56.11", - "@jsonjoy.com/fs-node-to-fsa": "4.56.11", - "@jsonjoy.com/fs-node-utils": "4.56.11", - "@jsonjoy.com/fs-print": "4.56.11", - "@jsonjoy.com/fs-snapshot": "4.56.11", + "@jsonjoy.com/fs-core": "4.57.8", + "@jsonjoy.com/fs-fsa": "4.57.8", + "@jsonjoy.com/fs-node": "4.57.8", + "@jsonjoy.com/fs-node-builtins": "4.57.8", + "@jsonjoy.com/fs-node-to-fsa": "4.57.8", + "@jsonjoy.com/fs-node-utils": "4.57.8", + "@jsonjoy.com/fs-print": "4.57.8", + "@jsonjoy.com/fs-snapshot": "4.57.8", "@jsonjoy.com/json-pack": "^1.11.0", "@jsonjoy.com/util": "^1.9.0", "glob-to-regex.js": "^1.0.1", @@ -8443,6 +9076,7 @@ "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, + "license": "MIT", "dependencies": { "@types/minimist": "^1.2.0", "camelcase-keys": "^6.2.2", @@ -8468,6 +9102,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -8489,13 +9124,15 @@ "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 + "dev": true, + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -8505,6 +9142,7 @@ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8528,6 +9166,7 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -8536,10 +9175,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==", + "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" } @@ -8549,6 +9189,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -8556,11 +9197,22 @@ "node": ">= 0.6" } }, + "node_modules/mime-types/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, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -8570,59 +9222,149 @@ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minimizer-webpack-plugin": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-DoeAZz8Q1C1znwsUzej1fdoi4jCf7/+Em27ouLqfK/+3m8G+D7yDhUwrc3CNhjSzGUN1kn7Iv4sWmjflQHenpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "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/minimizer-webpack-plugin/node_modules/jest-worker": { + "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": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": "*" + "node": ">= 10.13.0" } }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "node_modules/minimizer-webpack-plugin/node_modules/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, + "license": "MIT", "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" + "node": ">=10" }, - "bin": { - "mkdirp": "bin/cmd.js" + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/modify-values": { @@ -8630,6 +9372,7 @@ "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8659,13 +9402,15 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8674,19 +9419,22 @@ "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 + "dev": true, + "license": "MIT" }, "node_modules/nerf-dart": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", "dev": true, + "license": "MIT", "dependencies": { "lodash": "^4.17.21" } @@ -8712,34 +9460,29 @@ } } }, - "node_modules/node-forge": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz", - "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==", - "dev": true, - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } - }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.36", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", - "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "version": "2.0.50", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz", + "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/normalize-package-data": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", @@ -8755,6 +9498,7 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8764,6 +9508,7 @@ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -8851,6 +9596,12 @@ "write-file-atomic" ], "dev": true, + "license": "Artistic-2.0", + "workspaces": [ + "docs", + "smoke-tests", + "workspaces/*" + ], "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/arborist": "^5.6.3", @@ -8939,6 +9690,7 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.0.0" }, @@ -11366,7 +12118,8 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/on-finished": { "version": "2.4.1", @@ -11396,6 +12149,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -11405,6 +12159,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -11439,6 +12194,7 @@ "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", "dev": true, + "license": "(WTFPL OR MIT)", "bin": { "opener": "bin/opener-bin.js" } @@ -11466,6 +12222,7 @@ "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -11478,6 +12235,7 @@ "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", "dev": true, + "license": "MIT", "dependencies": { "p-map": "^2.0.0" }, @@ -11490,20 +12248,22 @@ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11514,6 +12274,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -11524,26 +12285,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-map": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -11553,6 +12300,7 @@ "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz", "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -11580,6 +12328,7 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -11589,6 +12338,7 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -11601,6 +12351,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -11619,6 +12370,7 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -11628,6 +12380,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -11637,6 +12390,7 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11646,6 +12400,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -11654,12 +12409,13 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "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==", + "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, "license": "MIT" }, @@ -11668,6 +12424,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -11680,10 +12437,11 @@ "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" }, @@ -11691,11 +12449,22 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } @@ -11705,6 +12474,7 @@ "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^2.0.0", "load-json-file": "^4.0.0" @@ -11718,6 +12488,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^2.0.0" }, @@ -11730,6 +12501,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -11743,6 +12515,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^1.0.0" }, @@ -11755,6 +12528,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^1.1.0" }, @@ -11767,6 +12541,7 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -11776,31 +12551,110 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/portfinder": { - "version": "1.0.28", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", - "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "license": "MIT", "dependencies": { - "async": "^2.6.2", - "debug": "^3.1.1", - "mkdirp": "^0.5.5" + "find-up": "^4.0.0" }, "engines": { - "node": ">= 0.12.0" + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkijs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.4.0.tgz", + "integrity": "sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@noble/hashes": "1.4.0", + "asn1js": "^3.0.6", + "bytestreamjs": "^2.0.1", + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.3", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/portfinder/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/portfinder": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.38.tgz", + "integrity": "sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "async": "^3.2.6", + "debug": "^4.3.6" + }, + "engines": { + "node": ">= 10.12" } }, "node_modules/prelude-ls": { @@ -11814,9 +12668,9 @@ } }, "node_modules/prettier": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", - "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.4.tgz", + "integrity": "sha512-yWG/o/4oJfo036EKAfK6ACAoDOfHeRHx4tuxkfBZiauURiaSmYwlpOr5LQqKtIkRD2z1PLteme2WoxEnj4tHTg==", "dev": true, "license": "MIT", "bin": { @@ -11847,6 +12701,7 @@ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -11861,6 +12716,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -11872,13 +12728,15 @@ "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 + "dev": true, + "license": "MIT" }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, + "license": "MIT", "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" @@ -11891,13 +12749,15 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -11911,23 +12771,25 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/pure-rand": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", - "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, "funding": [ { @@ -11938,26 +12800,50 @@ "type": "opencollective", "url": "https://opencollective.com/fast-check" } - ] + ], + "license": "MIT" + }, + "node_modules/pvtsutils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz", + "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } }, "node_modules/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", "dev": true, + "license": "MIT", "engines": { "node": ">=0.6.0", "teleport": ">=0.2.0" } }, "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.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.1.0" + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" }, "engines": { "node": ">=0.6" @@ -11984,13 +12870,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -12000,6 +12888,7 @@ "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" } @@ -12009,6 +12898,7 @@ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -12034,6 +12924,7 @@ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -12049,21 +12940,24 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, + "license": "MIT", "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", @@ -12079,6 +12973,7 @@ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", @@ -12096,6 +12991,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -12109,6 +13005,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -12116,11 +13013,28 @@ "node": ">=8" } }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/read-pkg-up/node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -12133,6 +13047,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } @@ -12141,13 +13056,15 @@ "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/read-pkg/node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -12160,6 +13077,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -12169,15 +13087,17 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } }, "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -12206,6 +13126,7 @@ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", "dev": true, + "license": "MIT", "dependencies": { "resolve": "^1.9.0" }, @@ -12218,6 +13139,7 @@ "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, + "license": "MIT", "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" @@ -12231,17 +13153,26 @@ "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", "dev": true, + "license": "MIT", "dependencies": { "esprima": "~4.0.0" } }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/registry-auth-token": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", - "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.1.tgz", + "integrity": "sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q==", "dev": true, + "license": "MIT", "dependencies": { - "@pnpm/npm-conf": "^2.1.0" + "@pnpm/npm-conf": "^3.0.2" }, "engines": { "node": ">=14" @@ -12252,6 +13183,7 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -12261,6 +13193,7 @@ "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, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -12269,21 +13202,27 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "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.9.0", + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -12293,6 +13232,7 @@ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, + "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, @@ -12305,6 +13245,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -12314,6 +13255,7 @@ "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", "dev": true, + "license": "MIT", "dependencies": { "global-dirs": "^0.1.1" }, @@ -12322,10 +13264,11 @@ } }, "node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -12341,10 +13284,11 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -12354,7 +13298,9 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -12397,6 +13343,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -12405,13 +13352,15 @@ "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 + "dev": true, + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/schema-utils": { "version": "4.3.3", @@ -12437,33 +13386,36 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-5.5.0.tgz", + "integrity": "sha512-ftnu3TW4+3eBfLRFnDEkzGxSF/10BJBkaLJuBHZX0kiPS7bRdlpZGu6YGt4KngMkdTwJE6MbjavFpqHvqVt+Ew==", "dev": true, "license": "MIT", "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" + "@peculiar/x509": "^1.14.2", + "pkijs": "^3.3.3" }, "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/semantic-release": { - "version": "19.0.3", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-19.0.3.tgz", - "integrity": "sha512-HaFbydST1cDKZHuFZxB8DTrBLJVK/AnDExpK0s3EqLIAAUAHUgnd+VSJCUtTYQKkAkauL8G9CucODrVCc7BuAA==", + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-19.0.5.tgz", + "integrity": "sha512-NMPKdfpXTnPn49FDogMBi36SiBfXkSOJqCkk0E4iWOY1tusvvgBwqUmxTX1kmlT6kIYed9YwNKD1sfPpqa5yaA==", "dev": true, + "license": "MIT", "dependencies": { "@semantic-release/commit-analyzer": "^9.0.2", "@semantic-release/error": "^3.0.0", @@ -12501,20 +13453,41 @@ "node": ">=16 || ^14.17" } }, - "node_modules/semantic-release/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "node_modules/semantic-release/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/semantic-release/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, "engines": { "node": ">=10" } }, "node_modules/semantic-release/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "16.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.2.tgz", + "integrity": "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -12529,10 +13502,11 @@ } }, "node_modules/semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -12548,6 +13522,7 @@ "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^6.3.0" }, @@ -12560,6 +13535,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -12569,6 +13545,7 @@ "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -12576,6 +13553,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/send": { "version": "0.19.2", "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", @@ -12629,21 +13626,26 @@ } }, "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.2.tgz", + "integrity": "sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==", "dev": true, + "license": "MIT", "dependencies": { - "accepts": "~1.3.4", + "accepts": "~1.3.8", "batch": "0.6.1", "debug": "2.6.9", "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" + "http-errors": "~1.8.0", + "mime-types": "~2.1.35", + "parseurl": "~1.3.3" }, "engines": { "node": ">= 0.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/serve-index/node_modules/debug": { @@ -12651,6 +13653,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -12660,48 +13663,41 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "dev": true, + "license": "MIT", "dependencies": { "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" }, "engines": { "node": ">= 0.6" } }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, "node_modules/serve-index/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/serve-index/node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -12734,6 +13730,7 @@ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, + "license": "MIT", "dependencies": { "kind-of": "^6.0.2" }, @@ -12746,6 +13743,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -12758,14 +13756,15 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.9.0.tgz", + "integrity": "sha512-Iov+JwFv/2HcTpcwNMKd8+IWNb8tboQJNQTkAY/LLVK7gGH9jy+LGkVqPxfekHl+yMmiqXszdGWXgkfml7hjqA==", "dev": true, "license": "MIT", "engines": { @@ -12776,15 +13775,15 @@ } }, "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" }, @@ -12796,14 +13795,14 @@ } }, "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==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "object-inspect": "^1.13.4" }, "engines": { "node": ">= 0.4" @@ -12855,13 +13854,15 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/signale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz", "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^2.3.2", "figures": "^2.0.0", @@ -12876,6 +13877,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -12888,6 +13890,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -12902,6 +13905,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } @@ -12910,13 +13914,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/signale/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -12926,6 +13932,7 @@ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -12938,6 +13945,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -12947,6 +13955,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -12958,15 +13967,20 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/sockjs": { @@ -12974,6 +13988,7 @@ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", "dev": true, + "license": "MIT", "dependencies": { "faye-websocket": "^0.11.3", "uuid": "^8.3.2", @@ -12985,14 +14000,15 @@ "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" } }, "node_modules/source-map-support": { - "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==", + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "license": "MIT", "dependencies": { @@ -13004,45 +14020,51 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", "integrity": "sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "dev": true, + "license": "CC0-1.0" }, "node_modules/spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.0", "handle-thing": "^2.0.0", @@ -13059,6 +14081,7 @@ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.0", "detect-node": "^2.0.4", @@ -13069,10 +14092,11 @@ } }, "node_modules/spdy-transport/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -13087,6 +14111,7 @@ "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, + "license": "MIT", "dependencies": { "through": "2" }, @@ -13099,15 +14124,17 @@ "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "dev": true, + "license": "ISC", "dependencies": { "readable-stream": "^3.0.0" } }, "node_modules/split2/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -13121,13 +14148,15 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^2.0.0" }, @@ -13140,6 +14169,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -13159,6 +14189,7 @@ "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", "dev": true, + "license": "MIT", "dependencies": { "duplexer2": "~0.1.0", "readable-stream": "^2.0.2" @@ -13169,6 +14200,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } @@ -13178,6 +14210,7 @@ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, + "license": "MIT", "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -13191,6 +14224,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13205,6 +14239,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -13217,6 +14252,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -13226,6 +14262,7 @@ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -13235,6 +14272,7 @@ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, + "license": "MIT", "dependencies": { "min-indent": "^1.0.0" }, @@ -13247,6 +14285,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -13259,6 +14298,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -13267,10 +14307,11 @@ } }, "node_modules/supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" @@ -13284,6 +14325,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -13292,13 +14334,13 @@ } }, "node_modules/synckit": { - "version": "0.11.12", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", - "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.13.tgz", + "integrity": "sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.2.9" + "@pkgr/core": "^0.3.6" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -13308,9 +14350,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": { @@ -13326,6 +14368,7 @@ "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -13335,6 +14378,7 @@ "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", "dev": true, + "license": "MIT", "dependencies": { "del": "^6.0.0", "is-stream": "^2.0.0", @@ -13354,6 +14398,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -13362,9 +14407,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": { @@ -13379,39 +14424,16 @@ "engines": { "node": ">=10" } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.17", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.17.tgz", - "integrity": "sha512-YR7PtUp6GMU91BgSJmlaX/rS2lGDbAF7D+Wtq7hRO+MiljNmodYvqslzCFiYVAgW+Qoaaia/QUIP4lGXufjdZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "terser": "^5.31.1" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } + }, + "node_modules/terser/node_modules/source-map-support": { + "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", + "source-map": "^0.6.0" } }, "node_modules/test-exclude": { @@ -13419,6 +14441,7 @@ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -13428,11 +14451,43 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "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" + }, + "engines": { + "node": "*" + } + }, "node_modules/text-extensions": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10" } @@ -13441,12 +14496,13 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/thingies": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz", - "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.6.0.tgz", + "integrity": "sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==", "dev": true, "license": "MIT", "engines": { @@ -13464,22 +14520,25 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/through2": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, + "license": "MIT", "dependencies": { "readable-stream": "3" } }, "node_modules/through2/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -13497,14 +14556,14 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -13532,9 +14591,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.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, "license": "MIT", "engines": { @@ -13548,7 +14607,8 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/to-regex-range": { "version": "5.0.1", @@ -13581,10 +14641,17 @@ "license": "MIT" }, "node_modules/traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha512-kdf4JKs8lbARxWdp7RKdNzoJBhGUcIalSYibuGyHJbmk40pOysQ0+QPvlkCOICOivDWU2IJo2rkrxyTK2AH4fw==", - "dev": true + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.8.tgz", + "integrity": "sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/tree-dump": { "version": "1.1.0", @@ -13608,14 +14675,15 @@ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/ts-api-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", - "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { @@ -13626,37 +14694,44 @@ } }, "node_modules/ts-jest": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", - "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "dev": true, + "license": "MIT", "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.9", "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.8.0", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" }, "bin": { "ts-jest": "cli.js" }, "engines": { - "node": "^16.10.0 || ^18.0.0 || >=20.0.0" + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", - "typescript": ">=4.3 <6" + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <7" }, "peerDependenciesMeta": { "@babel/core": { "optional": true }, + "@jest/transform": { + "optional": true + }, "@jest/types": { "optional": true }, @@ -13665,17 +14740,18 @@ }, "esbuild": { "optional": true + }, + "jest-util": { + "optional": true } } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -13683,32 +14759,75 @@ "node": ">=10" } }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ts-jest/node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/ts-loader": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.3.1.tgz", - "integrity": "sha512-OkyShkcZTsTwyS3Kt7a4rsT/t2qvEVQuKCTg4LJmpj9fhFR7ukGdZwV6Qq3tRUkqcXtfGpPR7+hFKHCG/0d3Lw==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.6.2.tgz", + "integrity": "sha512-R4iuczmtgxvtuI556s+hTZ6/7Ee03VCAk/l/M8LY1OAsUgB7YydsCxkgq9D9pKRaD7GJqUi2u8fp9zZP/ufjKA==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" + "picomatch": "^4.0.0", + "source-map": "^0.7.4" }, "engines": { "node": ">=12.0.0" }, "peerDependencies": { + "loader-utils": "*", "typescript": "*", - "webpack": "^5.0.0" + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "loader-utils": { + "optional": true + } + } + }, + "node_modules/ts-loader/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" } }, "node_modules/ts-node": { @@ -13755,15 +14874,6 @@ } } }, - "node_modules/ts-node/node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -13771,6 +14881,26 @@ "dev": true, "license": "0BSD" }, + "node_modules/tsyringe": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz", + "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/tsyringe/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -13789,6 +14919,7 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -13835,10 +14966,11 @@ } }, "node_modules/uglify-js": { - "version": "3.16.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.16.2.tgz", - "integrity": "sha512-AaQNokTNgExWrkEYA24BTNMSjyqEXPSfhqoS0AxmHkCJ4U+Dyy5AvbGV/sqxuxficEfGGoX3zWw9R7QpLFfEsg==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, + "license": "BSD-2-Clause", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -13847,6 +14979,13 @@ "node": ">=0.8.0" } }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "dev": true, + "license": "MIT" + }, "node_modules/union": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", @@ -13864,6 +15003,7 @@ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", "dev": true, + "license": "MIT", "dependencies": { "crypto-random-string": "^2.0.0" }, @@ -13879,10 +15019,11 @@ "license": "ISC" }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -13933,6 +15074,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -13941,19 +15083,22 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4.0" } @@ -13962,7 +15107,9 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "dev": true, + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } @@ -13971,13 +15118,15 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/v8-to-istanbul": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", - "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, + "license": "ISC", "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -13992,6 +15141,7 @@ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -14002,6 +15152,7 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -14011,18 +15162,18 @@ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "makeerror": "1.0.12" } }, "node_modules/watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz", + "integrity": "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==", "dev": true, "license": "MIT", "dependencies": { - "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" }, "engines": { @@ -14034,6 +15185,7 @@ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "dev": true, + "license": "MIT", "dependencies": { "minimalistic-assert": "^1.0.0" } @@ -14046,13 +15198,12 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.105.4", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.4.tgz", - "integrity": "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==", + "version": "5.108.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.108.3.tgz", + "integrity": "sha512-hOpaCHmQVVY66IVTjofnH14IgSdmod2aquSGHGuYig/OIdWge01Hk2Wt988DZcwXumFUT4+FvJY5N+ikl8o/ww==", "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", @@ -14062,21 +15213,19 @@ "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.20.0", - "es-module-lexer": "^2.0.0", + "enhanced-resolve": "^5.22.2", + "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", + "minimizer-webpack-plugin": "^5.6.1", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.17", - "watchpack": "^2.5.1", - "webpack-sources": "^3.3.4" + "watchpack": "^2.5.2", + "webpack-sources": "^3.5.0" }, "bin": { "webpack": "bin/webpack.js" @@ -14099,6 +15248,7 @@ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", "dev": true, + "license": "MIT", "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^1.2.0", @@ -14146,6 +15296,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10" } @@ -14180,16 +15331,6 @@ } } }, - "node_modules/webpack-dev-middleware/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/webpack-dev-middleware/node_modules/mime-types": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", @@ -14208,15 +15349,16 @@ } }, "node_modules/webpack-dev-server": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.0.tgz", - "integrity": "sha512-90SqqYXA2SK36KcT6o1bvwvZfJFcmoamqeJY7+boioffX9g9C0wjjJRGUrQIuh43pb0ttX7+ssavmj/WN2RHtA==", + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.6.tgz", + "integrity": "sha512-HNLRmamRvVavZQ+avceZifmv8hmdUjg43t6MI4SqJDwFdW7RPQwH5vzGhDRZSX59SgfbeHhLnq3g+uooWo7pVw==", "dev": true, "license": "MIT", "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", - "@types/express": "^4.17.21", + "@types/express": "^4.17.25", + "@types/express-serve-static-core": "^4.17.21", "@types/serve-index": "^1.9.4", "@types/serve-static": "^1.15.5", "@types/sockjs": "^0.3.36", @@ -14225,17 +15367,17 @@ "bonjour-service": "^1.2.1", "chokidar": "^3.6.0", "colorette": "^2.0.10", - "compression": "^1.7.4", + "compression": "^1.8.1", "connect-history-api-fallback": "^2.0.0", - "express": "^4.21.2", + "express": "^4.22.1", "graceful-fs": "^4.2.6", - "http-proxy-middleware": "^2.0.7", + "http-proxy-middleware": "^2.0.9", "ipaddr.js": "^2.1.0", - "launch-editor": "^2.6.1", + "launch-editor": "^2.14.1", "open": "^10.0.3", "p-retry": "^6.2.0", "schema-utils": "^4.2.0", - "selfsigned": "^2.4.1", + "selfsigned": "^5.5.0", "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", @@ -14265,12 +15407,14 @@ } }, "node_modules/webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "dev": true, + "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", + "flat": "^5.0.2", "wildcard": "^2.0.0" }, "engines": { @@ -14278,27 +15422,45 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.4.tgz", - "integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==", + "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": { "node": ">=10.13.0" } }, - "node_modules/webpack/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==", + "node_modules/webpack/node_modules/eslint-scope": { + "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, - "license": "ISC" + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } }, "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.5.tgz", + "integrity": "sha512-ZL2+3c7kMBdIRCMz6l8jQMHyGVxj+UL+xVk74Ombiciboca8rHa15L86B19E5oh1pL9Ii/uj54gtsIrZGMo6zA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "http-parser-js": ">=0.5.1", "safe-buffer": ">=5.1.0", @@ -14313,10 +15475,38 @@ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=0.8.0" } }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -14333,6 +15523,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -14344,10 +15535,11 @@ } }, "node_modules/wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true, + "license": "MIT" }, "node_modules/word-wrap": { "version": "1.2.5", @@ -14363,13 +15555,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -14386,13 +15580,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" @@ -14402,9 +15598,9 @@ } }, "node_modules/ws": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", - "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "dev": true, "license": "MIT", "engines": { @@ -14444,38 +15640,52 @@ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" }, "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", "dev": true, + "license": "ISC", "engines": { "node": ">= 6" } }, "node_modules/yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", "dev": true, + "license": "MIT", "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" }, "engines": { "node": ">=12" @@ -14486,24 +15696,17 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } @@ -14513,6 +15716,7 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -14522,6 +15726,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index bfb4610..bb95dab 100644 --- a/package.json +++ b/package.json @@ -37,13 +37,13 @@ "prepare": "husky install" }, "dependencies": { - "d3-drag": "3.0.0", - "d3-ease": "3.0.1", - "d3-force": "3.0.0", - "d3-selection": "3.0.0", - "d3-transition": "3.0.1", - "d3-zoom": "3.0.0", - "leaflet": "1.8.0" + "d3-drag": "^3.0.0", + "d3-ease": "^3.0.1", + "d3-force": "^3.0.0", + "d3-selection": "^3.0.0", + "d3-transition": "^3.0.1", + "d3-zoom": "^3.0.0", + "leaflet": "^1.9.4" }, "files": [ "dist", @@ -54,40 +54,40 @@ "registry": "https://registry.npmjs.org/" }, "devDependencies": { - "@commitlint/cli": "17.0.0", - "@commitlint/config-conventional": "17.0.0", - "@semantic-release/changelog": "6.0.1", - "@semantic-release/git": "10.0.1", - "@types/d3-drag": "3.0.1", - "@types/d3-ease": "3.0.0", - "@types/d3-force": "3.0.3", - "@types/d3-selection": "3.0.1", - "@types/d3-transition": "3.0.1", - "@types/d3-zoom": "3.0.1", - "@types/jest": "29.5.12", - "@types/leaflet": "1.7.9", + "@commitlint/cli": "^17.0.0", + "@commitlint/config-conventional": "^17.0.0", + "@semantic-release/changelog": "^6.0.1", + "@semantic-release/git": "^10.0.1", + "@types/d3-drag": "^3.0.1", + "@types/d3-ease": "^3.0.0", + "@types/d3-force": "^3.0.3", + "@types/d3-selection": "^3.0.1", + "@types/d3-transition": "^3.0.1", + "@types/d3-zoom": "^3.0.1", + "@types/jest": "^29.5.12", + "@types/leaflet": "^1.9.4", "@types/resize-observer-browser": "^0.1.7", - "@typescript-eslint/eslint-plugin": "8.56.1", - "@typescript-eslint/parser": "8.56.1", - "conventional-changelog-eslint": "3.0.9", + "@typescript-eslint/eslint-plugin": "^8.56.1", + "@typescript-eslint/parser": "^8.56.1", + "conventional-changelog-eslint": "^3.0.9", "copy-webpack-plugin": "^11.0.0", - "eslint": "8.57.0", - "eslint-config-google": "0.14.0", - "eslint-config-prettier": "8.5.0", - "eslint-plugin-jest": "29.15.0", - "eslint-plugin-prettier": "5.5.5", + "eslint": "^8.57.0", + "eslint-config-google": "^0.14.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-jest": "^29.15.0", + "eslint-plugin-prettier": "^5.5.5", "http-server": "^14.1.1", "husky": "^8.0.1", - "jest": "29.7.0", - "prettier": "3.8.1", - "semantic-release": "19.0.3", - "ts-jest": "29.1.2", + "jest": "^29.7.0", + "prettier": "^3.8.1", + "semantic-release": "^19.0.3", + "ts-jest": "^29.1.2", "ts-loader": "^9.3.1", - "ts-node": "10.9.2", - "typescript": "5.9.3", + "ts-node": "^10.9.2", + "typescript": "^5.9.3", "webpack": "^5.73.0", "webpack-cli": "^4.10.0", - "webpack-dev-server": "5.2.0" + "webpack-dev-server": "^5.2.0" }, "jest": { "moduleFileExtensions": [ From 01f31943984a3dc472205ca10e57cd966e81477a Mon Sep 17 00:00:00 2001 From: Oleksandr Ichenskyi <55350107+AlexIchenskiy@users.noreply.github.com> Date: Thu, 16 Jul 2026 09:17:01 +0200 Subject: [PATCH 25/30] New: Add SVG export (#111) * New: Add SVG export * Chore: Refactor code quality --- src/index.ts | 1 + src/renderer/svg/defs.ts | 35 +++++++ src/renderer/svg/edge.ts | 154 ++++++++++++++++++++++++++++ src/renderer/svg/image.ts | 78 +++++++++++++++ src/renderer/svg/index.ts | 199 +++++++++++++++++++++++++++++++++++++ src/renderer/svg/label.ts | 83 ++++++++++++++++ src/renderer/svg/node.ts | 87 ++++++++++++++++ src/renderer/svg/shadow.ts | 87 ++++++++++++++++ src/renderer/svg/shapes.ts | 94 ++++++++++++++++++ src/renderer/svg/utils.ts | 39 ++++++++ src/views/orb-map-view.ts | 4 + src/views/orb-view.ts | 8 ++ src/views/shared.ts | 2 + 13 files changed, 871 insertions(+) create mode 100644 src/renderer/svg/defs.ts create mode 100644 src/renderer/svg/edge.ts create mode 100644 src/renderer/svg/image.ts create mode 100644 src/renderer/svg/index.ts create mode 100644 src/renderer/svg/label.ts create mode 100644 src/renderer/svg/node.ts create mode 100644 src/renderer/svg/shadow.ts create mode 100644 src/renderer/svg/shapes.ts create mode 100644 src/renderer/svg/utils.ts diff --git a/src/index.ts b/src/index.ts index b81444b..eed0b34 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,3 +22,4 @@ export { IEdge, IEdgeBase, IEdgePosition, IEdgeStyle, isEdge, EdgeType } from '. export { IGraphStyle, getDefaultGraphStyle } from './models/style'; export { ICircle, IPosition, IRectangle, Color, IColorRGB } from './common'; export { OrbView, OrbMapView, IOrbView, IOrbMapViewSettings, IOrbViewSettings } from './views'; +export { graphToSVG, ISVGExportOptions } from './renderer/svg'; diff --git a/src/renderer/svg/defs.ts b/src/renderer/svg/defs.ts new file mode 100644 index 0000000..1587b5e --- /dev/null +++ b/src/renderer/svg/defs.ts @@ -0,0 +1,35 @@ +import { IRectangle } from '../../common'; + +export interface ISVGDefs { + readonly filterRegion?: IRectangle; + add(signature: string, build: (id: string) => string): string; + toSVG(): string; +} + +export class SVGDefs implements ISVGDefs { + private _idBySignature = new Map(); + private _entries: string[] = []; + private _counter = 0; + + constructor(public readonly filterRegion?: IRectangle) {} + + add(signature: string, build: (id: string) => string): string { + const existing = this._idBySignature.get(signature); + if (existing !== undefined) { + return existing; + } + + const id = `orb-def-${this._counter}`; + this._counter += 1; + this._idBySignature.set(signature, id); + this._entries.push(build(id)); + return id; + } + + toSVG(): string { + if (!this._entries.length) { + return ''; + } + return `${this._entries.join('')}`; + } +} diff --git a/src/renderer/svg/edge.ts b/src/renderer/svg/edge.ts new file mode 100644 index 0000000..aca9cfe --- /dev/null +++ b/src/renderer/svg/edge.ts @@ -0,0 +1,154 @@ +import { INodeBase } from '../../models/node'; +import { IEdge, IEdgeBase, EdgeStraight, EdgeCurved, EdgeLoopback } from '../../models/edge'; +import { IPosition } from '../../common'; +import { LabelTextBaseline } from '../canvas/label'; +import { IEdgeArrow } from '../canvas/edge/shared'; +import { getStraightArrowShape } from '../canvas/edge/types/edge-straight'; +import { getCurvedArrowShape } from '../canvas/edge/types/edge-curved'; +import { getLoopbackArrowShape } from '../canvas/edge/types/edge-loopback'; +import { labelToSVG } from './label'; +import { shadowFilterId, toShadow } from './shadow'; +import { ISVGDefs } from './defs'; +import { formatNumber, svgElement, ISVGAttributes } from './utils'; + +const DEFAULT_EDGE_COLOR = '#000000'; + +const ARROW_KEY_POINTS: IPosition[] = [ + { x: 0, y: 0 }, + { x: -1, y: 0.4 }, + { x: -1, y: -0.4 }, +]; + +export interface IEdgeToSVGOptions { + isLabelEnabled: boolean; + isShadowEnabled: boolean; +} + +export const edgeToSVG = ( + edge: IEdge, + defs: ISVGDefs, + options?: Partial, +): string => { + const width = edge.getWidth(); + if (!width) { + return ''; + } + + const isLabelEnabled = options?.isLabelEnabled ?? true; + const isShadowEnabled = options?.isShadowEnabled ?? true; + const color = (edge.getColor() ?? DEFAULT_EDGE_COLOR).toString(); + + const arrow = edgeArrowToSVG(edge, color); + const line = edgeLineToSVG(edge, width, color); + + const shadow = isShadowEnabled && edge.hasShadow() ? toShadow(edge.getStyle()) : null; + + let content = `${arrow}${line}`; + if (shadow) { + content = svgElement('g', { filter: `url(#${shadowFilterId(defs, shadow)})` }, content); + } + + const label = isLabelEnabled ? edgeLabelToSVG(edge) : ''; + + return svgElement('g', {}, `${content}${label}`); +}; + +const edgeLineToSVG = ( + edge: IEdge, + width: number, + color: string, +): string => { + const dashPattern = edge.getLineDashPattern(); + const strokeAttributes: ISVGAttributes = { + stroke: color, + 'stroke-width': width, + fill: 'none', + 'stroke-dasharray': dashPattern ? dashPattern.join(' ') : undefined, + }; + + if (edge instanceof EdgeStraight) { + const source = edge.startNode.getCenter(); + const target = edge.endNode.getCenter(); + const d = `M ${formatNumber(source.x)} ${formatNumber(source.y)} L ${formatNumber(target.x)} ${formatNumber( + target.y, + )}`; + return svgElement('path', { d, ...strokeAttributes }); + } + + if (edge instanceof EdgeCurved) { + const source = edge.startNode.getCenter(); + const target = edge.endNode.getCenter(); + const control = edge.getCurvedControlPoint(); + const d = `M ${formatNumber(source.x)} ${formatNumber(source.y)} Q ${formatNumber(control.x)} ${formatNumber( + control.y, + )} ${formatNumber(target.x)} ${formatNumber(target.y)}`; + return svgElement('path', { d, ...strokeAttributes }); + } + + if (edge instanceof EdgeLoopback) { + const { x, y, radius } = edge.getCircularData(); + return svgElement('circle', { cx: x, cy: y, r: radius, ...strokeAttributes }); + } + + return ''; +}; + +const edgeArrowToSVG = (edge: IEdge, color: string): string => { + if (edge.getStyle().arrowSize === 0) { + return ''; + } + + const arrowShape = getArrowShape(edge); + if (!arrowShape) { + return ''; + } + + const points = transformArrowPoints(ARROW_KEY_POINTS, arrowShape); + const pointsAttribute = points.map((point) => `${formatNumber(point.x)},${formatNumber(point.y)}`).join(' '); + + return svgElement('polygon', { points: pointsAttribute, fill: color }); +}; + +const getArrowShape = (edge: IEdge): IEdgeArrow | null => { + if (edge instanceof EdgeStraight) { + return getStraightArrowShape(edge); + } + if (edge instanceof EdgeCurved) { + return getCurvedArrowShape(edge); + } + if (edge instanceof EdgeLoopback) { + return getLoopbackArrowShape(edge); + } + return null; +}; + +const transformArrowPoints = (points: IPosition[], arrow: IEdgeArrow): IPosition[] => { + return points.map((point) => { + const xt = point.x * Math.cos(arrow.angle) - point.y * Math.sin(arrow.angle); + const yt = point.x * Math.sin(arrow.angle) + point.y * Math.cos(arrow.angle); + return { + x: arrow.point.x + arrow.length * xt, + y: arrow.point.y + arrow.length * yt, + }; + }); +}; + +const edgeLabelToSVG = (edge: IEdge): string => { + const edgeLabel = edge.getLabel(); + if (!edgeLabel) { + return ''; + } + + const edgeStyle = edge.getStyle(); + + return labelToSVG(edgeLabel, { + position: edge.getCenter(), + textBaseline: LabelTextBaseline.MIDDLE, + properties: { + fontBackgroundColor: edgeStyle.fontBackgroundColor, + fontColor: edgeStyle.fontColor, + fontFamily: edgeStyle.fontFamily, + fontSize: edgeStyle.fontSize, + }, + }); +}; diff --git a/src/renderer/svg/image.ts b/src/renderer/svg/image.ts new file mode 100644 index 0000000..4bffb97 --- /dev/null +++ b/src/renderer/svg/image.ts @@ -0,0 +1,78 @@ +import { INodeBase, INode } from '../../models/node'; +import { IEdgeBase } from '../../models/edge'; +import { ISVGDefs } from './defs'; +import { ISVGShape } from './shapes'; +import { svgElement } from './utils'; + +export const nodeImageToSVG = ( + node: INode, + defs: ISVGDefs, + shape: ISVGShape, +): string => { + const image = node.getBackgroundImage(); + if (!image || !image.width || !image.height) { + return ''; + } + + const href = resolveImageHref(node, image); + if (!href) { + return ''; + } + + const center = node.getCenter(); + const radius = node.getRadius(); + + const clipGeometry = Object.keys(shape.attributes) + .map((key) => `${key}=${shape.attributes[key]}`) + .join(','); + const clipId = defs.add(`clip:${shape.tag}:${clipGeometry}`, (id) => + svgElement('clipPath', { id }, svgElement(shape.tag, shape.attributes)), + ); + + return svgElement('image', { + href, + 'xlink:href': href, + x: center.x - radius, + y: center.y - radius, + width: radius * 2, + height: radius * 2, + preserveAspectRatio: 'xMidYMid slice', + 'clip-path': `url(#${clipId})`, + }); +}; + +const resolveImageHref = ( + node: INode, + image: HTMLImageElement, +): string | undefined => { + const dataUrl = imageToDataURL(image); + if (dataUrl) { + return dataUrl; + } + + const style = node.getStyle(); + if (node.isSelected() && style.imageUrlSelected) { + return style.imageUrlSelected; + } + return style.imageUrl ?? image.src ?? undefined; +}; + +const imageToDataURL = (image: HTMLImageElement): string | undefined => { + if (typeof document === 'undefined') { + return undefined; + } + + try { + const canvas = document.createElement('canvas'); + canvas.width = image.naturalWidth || image.width; + canvas.height = image.naturalHeight || image.height; + const context = canvas.getContext('2d'); + if (!context) { + return undefined; + } + context.drawImage(image, 0, 0); + return canvas.toDataURL(); + } catch { + return undefined; + } +}; diff --git a/src/renderer/svg/index.ts b/src/renderer/svg/index.ts new file mode 100644 index 0000000..80afb92 --- /dev/null +++ b/src/renderer/svg/index.ts @@ -0,0 +1,199 @@ +import { INode, INodeBase } from '../../models/node'; +import { IEdge, IEdgeBase, EdgeCurved, EdgeLoopback } from '../../models/edge'; +import { IGraph } from '../../models/graph'; +import { Color, IRectangle } from '../../common'; +import { nodeToSVG } from './node'; +import { edgeToSVG } from './edge'; +import { SVGDefs } from './defs'; +import { formatNumber, svgElement } from './utils'; + +const DEFAULT_PADDING = 20; +const DEFAULT_FONT_SIZE = 4; +const LABEL_DISTANCE_RATIO = 0.2; +const FONT_LINE_SPACING = 1.2; +const FONT_BACKGROUND_MARGIN = 0.12; +const AVERAGE_GLYPH_WIDTH_RATIO = 0.6; + +export interface ISVGExportOptions { + backgroundColor?: Color | string | null; + padding?: number; + isLabelEnabled?: boolean; + isShadowEnabled?: boolean; + isImageEnabled?: boolean; +} + +export const graphToSVG = ( + graph: IGraph, + options: ISVGExportOptions = {}, +): string => { + const padding = options.padding ?? DEFAULT_PADDING; + const isLabelEnabled = options.isLabelEnabled ?? true; + const isShadowEnabled = options.isShadowEnabled ?? true; + const isImageEnabled = options.isImageEnabled ?? true; + + const nodes = graph.getNodes(); + const edges = graph.getEdges(); + + const content = computeContentBounds(nodes, edges, isLabelEnabled, isShadowEnabled); + const minX = content.x - padding; + const minY = content.y - padding; + const width = Math.max(content.width + padding * 2, 1); + const height = Math.max(content.height + padding * 2, 1); + const region: IRectangle = { x: minX, y: minY, width, height }; + + const defs = new SVGDefs(region); + const body: string[] = []; + + if (options.backgroundColor) { + body.push(svgElement('rect', { x: minX, y: minY, width, height, fill: options.backgroundColor.toString() })); + } + + for (let i = 0; i < edges.length; i++) { + body.push(edgeToSVG(edges[i], defs, { isLabelEnabled, isShadowEnabled })); + } + for (let i = 0; i < nodes.length; i++) { + body.push(nodeToSVG(nodes[i], defs, { isLabelEnabled, isShadowEnabled, isImageEnabled })); + } + + const viewBox = `${formatNumber(minX)} ${formatNumber(minY)} ${formatNumber(width)} ${formatNumber(height)}`; + + return svgElement( + 'svg', + { + xmlns: 'http://www.w3.org/2000/svg', + 'xmlns:xlink': 'http://www.w3.org/1999/xlink', + viewBox, + width, + height, + }, + `${defs.toSVG()}${body.join('')}`, + ); +}; + +interface IMutableBounds { + minX: number; + minY: number; + maxX: number; + maxY: number; +} + +const computeContentBounds = ( + nodes: INode[], + edges: IEdge[], + isLabelEnabled: boolean, + isShadowEnabled: boolean, +): IRectangle => { + const bounds: IMutableBounds = { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity }; + + for (let i = 0; i < nodes.length; i++) { + includeNode(bounds, nodes[i], isLabelEnabled, isShadowEnabled); + } + for (let i = 0; i < edges.length; i++) { + includeEdge(bounds, edges[i], isLabelEnabled, isShadowEnabled); + } + + if (!isFinite(bounds.minX)) { + return { x: 0, y: 0, width: 0, height: 0 }; + } + return { x: bounds.minX, y: bounds.minY, width: bounds.maxX - bounds.minX, height: bounds.maxY - bounds.minY }; +}; + +const includePoint = (bounds: IMutableBounds, x: number, y: number): void => { + if (x < bounds.minX) { + bounds.minX = x; + } + if (y < bounds.minY) { + bounds.minY = y; + } + if (x > bounds.maxX) { + bounds.maxX = x; + } + if (y > bounds.maxY) { + bounds.maxY = y; + } +}; + +const includeBox = (bounds: IMutableBounds, cx: number, cy: number, halfWidth: number, halfHeight: number): void => { + includePoint(bounds, cx - halfWidth, cy - halfHeight); + includePoint(bounds, cx + halfWidth, cy + halfHeight); +}; + +const includeNode = ( + bounds: IMutableBounds, + node: INode, + isLabelEnabled: boolean, + isShadowEnabled: boolean, +): void => { + if (node.getRadius() <= 0) { + return; + } + + const center = node.getCenter(); + const radius = node.getBorderedRadius(); + const pad = isShadowEnabled ? shadowReach(node.hasShadow(), node.getStyle()) : 0; + includeBox(bounds, center.x, center.y, radius + pad, radius + pad); + + if (isLabelEnabled && node.getLabel()) { + const style = node.getStyle(); + const top = center.y + node.getBorderedRadius() * (1 + LABEL_DISTANCE_RATIO); + includeLabelBox(bounds, node.getLabel() as string, center.x, top, style.fontSize ?? DEFAULT_FONT_SIZE, false); + } +}; + +const includeEdge = ( + bounds: IMutableBounds, + edge: IEdge, + isLabelEnabled: boolean, + isShadowEnabled: boolean, +): void => { + if (!edge.getWidth()) { + return; + } + + const style = edge.getStyle(); + const pad = isShadowEnabled ? shadowReach(edge.hasShadow(), style) : 0; + + if (edge instanceof EdgeLoopback) { + const circle = edge.getCircularData(); + includeBox(bounds, circle.x, circle.y, circle.radius + pad, circle.radius + pad); + } else if (edge instanceof EdgeCurved) { + const control = edge.getCurvedControlPoint(); + includeBox(bounds, control.x, control.y, pad, pad); + } + + if (isLabelEnabled && edge.getLabel()) { + const center = edge.getCenter(); + includeLabelBox(bounds, edge.getLabel() as string, center.x, center.y, style.fontSize ?? DEFAULT_FONT_SIZE, true); + } +}; + +const includeLabelBox = ( + bounds: IMutableBounds, + text: string, + cx: number, + y: number, + fontSize: number, + isCentered: boolean, +): void => { + if (fontSize <= 0) { + return; + } + const lines = `${text}`.split('\n'); + const maxLength = lines.reduce((max, line) => Math.max(max, line.trim().length), 0); + const margin = fontSize * FONT_BACKGROUND_MARGIN; + const width = maxLength * fontSize * AVERAGE_GLYPH_WIDTH_RATIO + 2 * margin; + const height = lines.length * fontSize * FONT_LINE_SPACING + 2 * margin; + const top = isCentered ? y - height / 2 : y; + includePoint(bounds, cx - width / 2, top); + includePoint(bounds, cx + width / 2, top + height); +}; + +const shadowReach = ( + hasShadow: boolean, + style: { shadowColor?: Color | string; shadowSize?: number; shadowOffsetX?: number; shadowOffsetY?: number }, +): number => { + if (!hasShadow || !style.shadowColor) { + return 0; + } + return (style.shadowSize ?? 0) + Math.max(Math.abs(style.shadowOffsetX ?? 0), Math.abs(style.shadowOffsetY ?? 0)); +}; diff --git a/src/renderer/svg/label.ts b/src/renderer/svg/label.ts new file mode 100644 index 0000000..3a52a79 --- /dev/null +++ b/src/renderer/svg/label.ts @@ -0,0 +1,83 @@ +import { IPosition } from '../../common'; +import { Label, LabelTextBaseline, ILabelProperties } from '../canvas/label'; +import { escapeXML, svgElement } from './utils'; + +const DEFAULT_FONT_FAMILY = 'Roboto, sans-serif'; +const DEFAULT_FONT_COLOR = '#000000'; +const FONT_LINE_SPACING = 1.2; +const FONT_BACKGROUND_MARGIN = 0.12; +const AVERAGE_GLYPH_WIDTH_RATIO = 0.6; + +export interface ILabelToSVGData { + position: IPosition; + textBaseline: LabelTextBaseline; + properties: Partial; +} + +export const labelToSVG = (text: string | undefined, data: ILabelToSVGData): string => { + if (text === undefined || text === null || `${text}` === '') { + return ''; + } + + const label = new Label(text, { + position: data.position, + textBaseline: data.textBaseline, + properties: data.properties, + }); + + if (!label.textLines.length || label.fontSize <= 0) { + return ''; + } + + const fontFamily = data.properties.fontFamily ?? DEFAULT_FONT_FAMILY; + const fontColor = (data.properties.fontColor ?? DEFAULT_FONT_COLOR).toString(); + const lineHeight = label.fontSize * FONT_LINE_SPACING; + const dominantBaseline = data.textBaseline === LabelTextBaseline.MIDDLE ? 'middle' : 'text-before-edge'; + + const background = labelBackgroundToSVG(label, lineHeight); + + const tspans = label.textLines + .map((line, i) => svgElement('tspan', { x: label.position.x, dy: i === 0 ? 0 : lineHeight }, escapeXML(line))) + .join(''); + + const textElement = svgElement( + 'text', + { + x: label.position.x, + y: label.position.y, + 'font-size': label.fontSize, + 'font-family': fontFamily, + fill: fontColor, + 'text-anchor': 'middle', + 'dominant-baseline': dominantBaseline, + }, + tspans, + ); + + return `${background}${textElement}`; +}; + +const labelBackgroundToSVG = (label: Label, lineHeight: number): string => { + const backgroundColor = label.properties.fontBackgroundColor; + if (!backgroundColor) { + return ''; + } + + const margin = label.fontSize * FONT_BACKGROUND_MARGIN; + const height = label.fontSize + 2 * margin; + const baselineHeight = label.textBaseline === LabelTextBaseline.MIDDLE ? label.fontSize / 2 : 0; + const color = backgroundColor.toString(); + + return label.textLines + .map((line, i) => { + const width = line.length * label.fontSize * AVERAGE_GLYPH_WIDTH_RATIO + 2 * margin; + return svgElement('rect', { + x: label.position.x - width / 2, + y: label.position.y - baselineHeight - margin + i * lineHeight, + width, + height, + fill: color, + }); + }) + .join(''); +}; diff --git a/src/renderer/svg/node.ts b/src/renderer/svg/node.ts new file mode 100644 index 0000000..8eaf016 --- /dev/null +++ b/src/renderer/svg/node.ts @@ -0,0 +1,87 @@ +import { INodeBase, INode } from '../../models/node'; +import { IEdgeBase } from '../../models/edge'; +import { LabelTextBaseline } from '../canvas/label'; +import { shapeToSVGShape } from './shapes'; +import { labelToSVG } from './label'; +import { nodeImageToSVG } from './image'; +import { shadowFilterId, toShadow } from './shadow'; +import { ISVGDefs } from './defs'; +import { svgElement, ISVGAttributes } from './utils'; + +const DEFAULT_LABEL_DISTANCE_SIZE_FROM_NODE = 0.2; +const DEFAULT_NODE_COLOR = '#000000'; +const DEFAULT_BORDER_COLOR = '#000000'; + +export interface INodeToSVGOptions { + isLabelEnabled: boolean; + isShadowEnabled: boolean; + isImageEnabled: boolean; +} + +export const nodeToSVG = ( + node: INode, + defs: ISVGDefs, + options?: Partial, +): string => { + const isLabelEnabled = options?.isLabelEnabled ?? true; + const isShadowEnabled = options?.isShadowEnabled ?? true; + const isImageEnabled = options?.isImageEnabled ?? true; + + const center = node.getCenter(); + const radius = node.getRadius(); + if (radius <= 0) { + return ''; + } + + const shape = shapeToSVGShape(node.getStyle().shape, center.x, center.y, radius); + const color = (node.getColor() ?? DEFAULT_NODE_COLOR).toString(); + + const hasBorder = node.hasBorder(); + const borderAttributes: ISVGAttributes = {}; + if (hasBorder) { + borderAttributes.stroke = node.getBorderColor()?.toString() ?? DEFAULT_BORDER_COLOR; + borderAttributes['stroke-width'] = node.getBorderWidth(); + } + + const image = isImageEnabled ? nodeImageToSVG(node, defs, shape) : ''; + const shadow = isShadowEnabled && node.hasShadow() ? toShadow(node.getStyle()) : null; + + let content: string; + if (!image && !shadow) { + content = svgElement(shape.tag, { ...shape.attributes, fill: color, ...borderAttributes }); + } else { + const fill = svgElement(shape.tag, { ...shape.attributes, fill: color }); + let shadowed = `${fill}${image}`; + if (shadow) { + shadowed = svgElement('g', { filter: `url(#${shadowFilterId(defs, shadow)})` }, shadowed); + } + const border = hasBorder ? svgElement(shape.tag, { ...shape.attributes, fill: 'none', ...borderAttributes }) : ''; + content = `${shadowed}${border}`; + } + + const label = isLabelEnabled ? nodeLabelToSVG(node) : ''; + + return svgElement('g', {}, `${content}${label}`); +}; + +const nodeLabelToSVG = (node: INode): string => { + const nodeLabel = node.getLabel(); + if (!nodeLabel) { + return ''; + } + + const center = node.getCenter(); + const distance = node.getBorderedRadius() * (1 + DEFAULT_LABEL_DISTANCE_SIZE_FROM_NODE); + const nodeStyle = node.getStyle(); + + return labelToSVG(nodeLabel, { + position: { x: center.x, y: center.y + distance }, + textBaseline: LabelTextBaseline.TOP, + properties: { + fontBackgroundColor: nodeStyle.fontBackgroundColor, + fontColor: nodeStyle.fontColor, + fontFamily: nodeStyle.fontFamily, + fontSize: nodeStyle.fontSize, + }, + }); +}; diff --git a/src/renderer/svg/shadow.ts b/src/renderer/svg/shadow.ts new file mode 100644 index 0000000..18eb127 --- /dev/null +++ b/src/renderer/svg/shadow.ts @@ -0,0 +1,87 @@ +import { Color, IRectangle } from '../../common'; +import { INodeStyle } from '../../models/node'; +import { IEdgeStyle } from '../../models/edge'; +import { ISVGDefs } from './defs'; +import { escapeXML, formatNumber } from './utils'; + +const SHADOW_STD_DEVIATION_RATIO = 0.5; + +export interface IShadow { + color: Color | string; + size: number; + offsetX: number; + offsetY: number; +} + +export const toShadow = (style: INodeStyle | IEdgeStyle): IShadow | null => { + if (!style.shadowColor) { + return null; + } + return { + color: style.shadowColor, + size: style.shadowSize ?? 0, + offsetX: style.shadowOffsetX ?? 0, + offsetY: style.shadowOffsetY ?? 0, + }; +}; + +export const shadowFilterId = (defs: ISVGDefs, shadow: IShadow): string => { + const { color, opacity } = parseColorAlpha(shadow.color.toString()); + const stdDeviation = Math.max(shadow.size * SHADOW_STD_DEVIATION_RATIO, 0); + const signature = `shadow:${color}:${opacity}:${stdDeviation}:${shadow.offsetX}:${shadow.offsetY}`; + + return defs.add(signature, (id) => + buildShadowFilter(id, color, opacity, stdDeviation, shadow.offsetX, shadow.offsetY, defs.filterRegion), + ); +}; + +const buildShadowFilter = ( + id: string, + color: string, + opacity: number, + stdDeviation: number, + offsetX: number, + offsetY: number, + region?: IRectangle, +): string => { + const regionAttributes = region + ? `filterUnits="userSpaceOnUse" x="${formatNumber(region.x)}" y="${formatNumber(region.y)}" ` + + `width="${formatNumber(region.width)}" height="${formatNumber(region.height)}"` + : 'filterUnits="objectBoundingBox" x="-50%" y="-50%" width="200%" height="200%"'; + + return ( + `` + + `` + + `` + + `` + + `` + + `` + + `` + ); +}; + +const parseColorAlpha = (color: string): { color: string; opacity: number } => { + const rgba = color.match(/^rgba\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*\)$/i); + if (rgba) { + return { color: `rgb(${rgba[1]}, ${rgba[2]}, ${rgba[3]})`, opacity: clamp01(Number(rgba[4])) }; + } + + const hex8 = color.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i); + if (hex8) { + return { color: `#${hex8[1]}${hex8[2]}${hex8[3]}`, opacity: parseInt(hex8[4], 16) / 255 }; + } + + const hex4 = color.match(/^#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])$/i); + if (hex4) { + return { color: `#${hex4[1]}${hex4[2]}${hex4[3]}`, opacity: parseInt(hex4[4], 16) / 15 }; + } + + return { color, opacity: 1 }; +}; + +const clamp01 = (value: number): number => { + if (!isFinite(value)) { + return 1; + } + return Math.min(Math.max(value, 0), 1); +}; diff --git a/src/renderer/svg/shapes.ts b/src/renderer/svg/shapes.ts new file mode 100644 index 0000000..9d17c31 --- /dev/null +++ b/src/renderer/svg/shapes.ts @@ -0,0 +1,94 @@ +import { NodeShapeType } from '../../models/node'; +import { IPosition } from '../../common'; +import { formatNumber, ISVGAttributes } from './utils'; + +export interface ISVGShape { + tag: string; + attributes: ISVGAttributes; +} + +const toPointsAttribute = (points: IPosition[]): string => { + return points.map((point) => `${formatNumber(point.x)},${formatNumber(point.y)}`).join(' '); +}; + +const polygon = (points: IPosition[]): ISVGShape => { + return { tag: 'polygon', attributes: { points: toPointsAttribute(points) } }; +}; + +export const shapeToSVGShape = (shape: NodeShapeType | undefined, x: number, y: number, r: number): ISVGShape => { + switch (shape) { + case NodeShapeType.SQUARE: + return { tag: 'rect', attributes: { x: x - r, y: y - r, width: r * 2, height: r * 2 } }; + case NodeShapeType.DIAMOND: + return polygon([ + { x, y: y + r }, + { x: x + r, y }, + { x, y: y - r }, + { x: x - r, y }, + ]); + case NodeShapeType.TRIANGLE: + return polygon(triangleUpPoints(x, y, r)); + case NodeShapeType.TRIANGLE_DOWN: + return polygon(triangleDownPoints(x, y, r)); + case NodeShapeType.STAR: + return polygon(starPoints(x, y, r)); + case NodeShapeType.HEXAGON: + return polygon(ngonPoints(x, y, r, 6)); + default: + return { tag: 'circle', attributes: { cx: x, cy: y, r } }; + } +}; + +const triangleUpPoints = (x: number, y: number, r: number): IPosition[] => { + r *= 1.15; + y += 0.275 * r; + + const diameter = r * 2; + const innerRadius = (Math.sqrt(3) * diameter) / 6; + const height = Math.sqrt(diameter * diameter - r * r); + + return [ + { x, y: y - (height - innerRadius) }, + { x: x + r, y: y + innerRadius }, + { x: x - r, y: y + innerRadius }, + ]; +}; + +const triangleDownPoints = (x: number, y: number, r: number): IPosition[] => { + r *= 1.15; + y -= 0.275 * r; + + const diameter = r * 2; + const innerRadius = (Math.sqrt(3) * diameter) / 6; + const height = Math.sqrt(diameter * diameter - r * r); + + return [ + { x, y: y + (height - innerRadius) }, + { x: x + r, y: y - innerRadius }, + { x: x - r, y: y - innerRadius }, + ]; +}; + +const starPoints = (x: number, y: number, r: number): IPosition[] => { + r *= 0.82; + y += 0.1 * r; + + const points: IPosition[] = []; + for (let n = 0; n < 10; n++) { + const radius = r * (n % 2 === 0 ? 1.3 : 0.5); + points.push({ + x: x + radius * Math.sin((n * 2 * Math.PI) / 10), + y: y - radius * Math.cos((n * 2 * Math.PI) / 10), + }); + } + return points; +}; + +const ngonPoints = (x: number, y: number, r: number, sides: number): IPosition[] => { + const points: IPosition[] = []; + const arcSide = (Math.PI * 2) / sides; + for (let i = 0; i < sides; i++) { + points.push({ x: x + r * Math.cos(arcSide * i), y: y + r * Math.sin(arcSide * i) }); + } + return points; +}; diff --git a/src/renderer/svg/utils.ts b/src/renderer/svg/utils.ts new file mode 100644 index 0000000..fc31043 --- /dev/null +++ b/src/renderer/svg/utils.ts @@ -0,0 +1,39 @@ +export interface ISVGAttributes { + [key: string]: string | number | undefined | null; +} + +export const formatNumber = (value: number): string => { + if (!isFinite(value)) { + return '0'; + } + return `${Math.round(value * 1000) / 1000}`; +}; + +export const escapeXML = (value: string): string => { + return value + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +}; + +export const svgElement = (tag: string, attributes: ISVGAttributes, children?: string): string => { + const serializedAttributes = Object.keys(attributes) + .filter((key) => { + const value = attributes[key]; + return value !== undefined && value !== null && value !== ''; + }) + .map((key) => { + const value = attributes[key]; + const serializedValue = typeof value === 'number' ? formatNumber(value) : escapeXML(String(value)); + return `${key}="${serializedValue}"`; + }) + .join(' '); + + const openTag = serializedAttributes ? `${tag} ${serializedAttributes}` : tag; + if (children === undefined) { + return `<${openTag}/>`; + } + return `<${openTag}>${children}`; +}; diff --git a/src/views/orb-map-view.ts b/src/views/orb-map-view.ts index 5d59819..7039c7e 100644 --- a/src/views/orb-map-view.ts +++ b/src/views/orb-map-view.ts @@ -245,6 +245,10 @@ export class OrbMapView implements IOr onRendered?.(); } + getSVG(): string { + throw new Error('SVG export is not supported on OrbMapView.'); + } + destroy() { this._renderer.destroy(); this._leaflet.off(); diff --git a/src/views/orb-view.ts b/src/views/orb-view.ts index 61b1efc..04dc4bc 100644 --- a/src/views/orb-view.ts +++ b/src/views/orb-view.ts @@ -24,6 +24,7 @@ import { IFitZoomTransformOptions, } from '../renderer/shared'; import { RendererFactory } from '../renderer/factory'; +import { graphToSVG, ISVGExportOptions } from '../renderer/svg'; import { SimulatorEventType } from '../simulator/shared'; import { getDefaultGraphStyle } from '../models/style'; import { isBoolean } from '../utils/type.utils'; @@ -329,6 +330,13 @@ export class OrbView implements IOrbVi .on('end', () => this.render(onRendered)); } + getSVG(options?: ISVGExportOptions): string { + return graphToSVG(this._graph, { + backgroundColor: this._settings.render.backgroundColor, + ...options, + }); + } + destroy() { this._renderer.destroy(); this._simulator.terminate(); diff --git a/src/views/shared.ts b/src/views/shared.ts index 4578dde..b82bba3 100644 --- a/src/views/shared.ts +++ b/src/views/shared.ts @@ -3,6 +3,7 @@ import { IEdgeBase } from '../models/edge'; import { IGraph } from '../models/graph'; import { OrbEmitter } from '../events'; import { IGraphInteraction } from '../models/interaction'; +import { ISVGExportOptions } from '../renderer/svg'; export interface IOrbView { data: IGraph; @@ -12,5 +13,6 @@ export interface IOrbView { setSettings(settings: Partial): void; render(onRendered?: () => void): void; recenter(onRendered?: () => void): void; + getSVG(options?: ISVGExportOptions): string; destroy(): void; } From 617ba93ba841dfeb42d86abc444644e493b8bf9c Mon Sep 17 00:00:00 2001 From: Oleksandr Ichenskyi <55350107+AlexIchenskiy@users.noreply.github.com> Date: Thu, 16 Jul 2026 10:28:12 +0200 Subject: [PATCH 26/30] New: Add WebGL renderer (#109) * New: Add WebGL renderer * New: Add naive WebGL force layout computation * New: Add WebGL improved node/shape geometry options * New: Add labels and node images * Fix: GPU drag behavior * Chore: Remove leftover comments * Fix: WebGL renderer style invalidating * Chore: Refactor code quality * Chore: Add WebGL example and docs --- .gitignore | 1 + docs/view-default.md | 11 +- examples/example-webgl-renderer.html | 148 +++ examples/index.html | 8 + package.json | 6 +- src/glsl.d.ts | 14 + src/renderer/webgl/shaders/edge/edge.frag | 150 +++ src/renderer/webgl/shaders/edge/edge.vert | 94 ++ src/renderer/webgl/shaders/label/label.frag | 15 + src/renderer/webgl/shaders/label/label.vert | 25 + src/renderer/webgl/shaders/node/node.frag | 162 +++ src/renderer/webgl/shaders/node/node.vert | 64 ++ src/renderer/webgl/utils/image-atlas.ts | 180 +++ src/renderer/webgl/utils/label-cache.ts | 181 +++ src/renderer/webgl/webgl-renderer.ts | 928 ++++++++++++++- .../engines/dynamic/force-layout-engine.ts | 65 +- .../dynamic/gpu-force-layout-engine.ts | 1023 +++++++++++++++++ src/simulator/engine/factory.ts | 15 +- src/simulator/engine/shaders/force/force.frag | 197 ++++ src/simulator/engine/shaders/force/force.vert | 7 + src/simulator/engine/shared.ts | 5 +- .../engine/utils/adjacency-builder.ts | 105 ++ .../engine/utils/quadtree-builder.ts | 245 ++++ src/simulator/factory.ts | 9 +- src/utils/program.utils.ts | 31 + src/utils/shaders.utils.ts | 24 + src/views/orb-map-view.ts | 65 +- src/views/orb-view.ts | 34 +- webpack.config.js | 6 +- 29 files changed, 3779 insertions(+), 39 deletions(-) create mode 100644 examples/example-webgl-renderer.html create mode 100644 src/glsl.d.ts create mode 100644 src/renderer/webgl/shaders/edge/edge.frag create mode 100644 src/renderer/webgl/shaders/edge/edge.vert create mode 100644 src/renderer/webgl/shaders/label/label.frag create mode 100644 src/renderer/webgl/shaders/label/label.vert create mode 100644 src/renderer/webgl/shaders/node/node.frag create mode 100644 src/renderer/webgl/shaders/node/node.vert create mode 100644 src/renderer/webgl/utils/image-atlas.ts create mode 100644 src/renderer/webgl/utils/label-cache.ts create mode 100644 src/simulator/engine/engines/dynamic/gpu-force-layout-engine.ts create mode 100644 src/simulator/engine/shaders/force/force.frag create mode 100644 src/simulator/engine/shaders/force/force.vert create mode 100644 src/simulator/engine/utils/adjacency-builder.ts create mode 100644 src/simulator/engine/utils/quadtree-builder.ts create mode 100644 src/utils/program.utils.ts create mode 100644 src/utils/shaders.utils.ts diff --git a/.gitignore b/.gitignore index 2eba078..4b7568e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ node_modules/ # IDEs and editors .idea/ +.vscode/ # Optional npm cache directory .npm diff --git a/docs/view-default.md b/docs/view-default.md index 34b7659..f5e64bb 100644 --- a/docs/view-default.md +++ b/docs/view-default.md @@ -71,8 +71,9 @@ interface IOrbViewSettings { radius: number; } }; - // For canvas rendering and events + // For rendering and events render: { + type: 'canvas' | 'webgl'; devicePixelRatio: number | null; fps: number; minZoom: number; @@ -319,6 +320,7 @@ Each layout type has its own option list you can tweak in order to change the la - `isSimulatingOnDataUpdate` - Whether to run simulation when graph data is updated. Enabled by default (`true`). - `isSimulatingOnSettingsUpdate` - Whether to re-run simulation when settings are updated. Enabled by default (`true`). - `isSimulatingOnUnstick` - Whether to re-run simulation when a node is unstuck. Enabled by default (`true`). + - `useGPU` - Runs the force layout on the GPU (WebGL2) using a Barnes-Hut quadtree. Falls back to the CPU engine automatically if WebGL2 is unavailable. Disabled by default (`false`). - `alpha` - Fine-grained control over the simulation's annealing process. - `alpha` - Current alpha value. Default `1`. - `alphaMin` - Minimum alpha threshold below which simulation stops. Default `0.001`. @@ -352,6 +354,13 @@ Each layout type has its own option list you can tweak in order to change the la Optional property `render` has several rendering options that you can tweak. Read more about them on [Styling guide](./styles.md). +#### Property `render.type` + +Selects the rendering backend. `canvas` (default) draws with the HTML5 Canvas API, while `webgl` +uses a WebGL2 renderer that offloads drawing to the GPU for better performance on large graphs. +The backend is chosen when the view is created and cannot be changed afterwards — to switch, create +a new view. See the `example-webgl-renderer.html` example for a live comparison. + #### Property `render.devicePixelRatio` `devicePixelRatio` is useful when dealing with the difference between rendering on a standard diff --git a/examples/example-webgl-renderer.html b/examples/example-webgl-renderer.html new file mode 100644 index 0000000..b2b40cd --- /dev/null +++ b/examples/example-webgl-renderer.html @@ -0,0 +1,148 @@ + + + + + + Orb | WebGL renderer & GPU layout + + + + +
    +

    Example 9 - WebGL renderer & GPU layout

    +

    + Renders a generated graph and lets you switch between the Canvas and WebGL + renderers and the CPU and GPU force-layout engines across different graph + sizes. The GPU layout falls back to the CPU automatically if WebGL2 is + unavailable. +

    + +
    + + + + +
    + + +
    +
    + + + diff --git a/examples/index.html b/examples/index.html index 73edf37..57ff39c 100644 --- a/examples/index.html +++ b/examples/index.html @@ -77,5 +77,13 @@

    Orb Examples

    Renders a simple graph with hierarchical layout (tree-like).

    +
    +

  • Example 9 - WebGL renderer & GPU layout
  • +

    + Renders a generated graph and lets you switch between the Canvas and WebGL + renderers and the CPU and GPU force-layout engines across different graph + sizes. +

    +
    diff --git a/package.json b/package.json index bb95dab..cb2c279 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,10 @@ { "name": "Toni Lastre", "url": "https://github.com/tonilastre" + }, + { + "name": "Oleksandr Ichenskyi", + "url": "https://github.com/AlexIchenskiy" } ], "author": "Memgraph Ltd. ", @@ -109,4 +113,4 @@ "main" ] } -} \ No newline at end of file +} diff --git a/src/glsl.d.ts b/src/glsl.d.ts new file mode 100644 index 0000000..531b1d0 --- /dev/null +++ b/src/glsl.d.ts @@ -0,0 +1,14 @@ +declare module '*.glsl' { + const value: string; + export default value; +} + +declare module '*.vert' { + const value: string; + export default value; +} + +declare module '*.frag' { + const value: string; + export default value; +} diff --git a/src/renderer/webgl/shaders/edge/edge.frag b/src/renderer/webgl/shaders/edge/edge.frag new file mode 100644 index 0000000..514b07d --- /dev/null +++ b/src/renderer/webgl/shaders/edge/edge.frag @@ -0,0 +1,150 @@ +#version 300 es + +precision highp float; + +in vec2 vWorldPos; +in vec2 vStart; +in vec2 vEnd; +in vec2 vControl; +in float vHalfWidth; +in float vLoopbackRadius; +in float vArrowSize; +in vec2 vArrowTip; +in vec2 vArrowDir; +in vec4 vColor; +in vec4 vShadowColor; +in float vShadowSize; +in vec2 vShadowOffset; +flat in int vEdgeType; + +uniform bool uSimpleMode; + +out vec4 fragColor; + +float sdSegment(vec2 p, vec2 a, vec2 b) { + vec2 pa = p - a; + vec2 ba = b - a; + float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0); + return length(pa - ba * h); +} + +float sdBezier(vec2 pos, vec2 A, vec2 B, vec2 C) { + vec2 a = B - A; + vec2 b = A - 2.0 * B + C; + vec2 c = a * 2.0; + vec2 d = A - pos; + + float kk = 1.0 / max(dot(b, b), 0.0001); + float kx = kk * dot(a, b); + float ky = kk * (2.0 * dot(a, a) + dot(d, b)) / 3.0; + float kz = kk * dot(d, a); + + float p = ky - kx * kx; + float q = kx * (2.0 * kx * kx - 3.0 * ky) + kz; + float p3 = p * p * p; + float q2 = q * q; + float h = q2 + 4.0 * p3; + + float res; + if (h >= 0.0) { + h = sqrt(h); + vec2 x = (vec2(h, -h) - q) / 2.0; + vec2 uv = sign(x) * pow(abs(x), vec2(1.0 / 3.0)); + float t = clamp(uv.x + uv.y - kx, 0.0, 1.0); + vec2 qo = d + (c + b * t) * t; + res = dot(qo, qo); + } else { + float z = sqrt(-p); + float v = acos(q / (p * z * 2.0)) / 3.0; + float m = cos(v); + float n = sin(v) * 1.732050808; + vec3 t = clamp(vec3(m + m, -n - m, n - m) * z - kx, 0.0, 1.0); + vec2 qx = d + (c + b * t.x) * t.x; + float dx = dot(qx, qx); + vec2 qy = d + (c + b * t.y) * t.y; + float dy = dot(qy, qy); + res = min(dx, dy); + } + + return sqrt(res); +} + +float sdArrow(vec2 p, vec2 tip, vec2 dir, float size) { + if (size <= 0.0) return 1e6; + + vec2 perp = vec2(-dir.y, dir.x); + vec2 rel = p - tip; + float along = dot(rel, -dir); + float across = dot(rel, perp); + + if (along < 0.0) return length(rel); + if (along > size) { + float hw = size * 0.4; + float closest = clamp(across, -hw, hw); + vec2 pt = tip - dir * size + perp * closest; + return length(p - pt); + } + + float halfW = (along / size) * size * 0.4; + float d = abs(across) - halfW; + return d; +} + +void main() { + if (uSimpleMode && vEdgeType == 0) { + fragColor = vColor; + return; + } + + float dist; + if (vEdgeType == 0) { + dist = sdSegment(vWorldPos, vStart, vEnd); + } else if (vEdgeType == 1) { + dist = sdBezier(vWorldPos, vStart, vControl, vEnd); + } else { + dist = abs(length(vWorldPos - vControl) - vLoopbackRadius); + } + + float edgeSdf = dist - vHalfWidth; + float combinedSdf = edgeSdf; + + if (vArrowSize > 0.0) { + float arrowDist = sdArrow(vWorldPos, vArrowTip, vArrowDir, vArrowSize); + combinedSdf = min(edgeSdf, arrowDist); + } + + float shadowAlpha = 0.0; + if (vShadowSize > 0.0) { + vec2 shadowPos = vWorldPos - vShadowOffset; + float shadowDist; + if (vEdgeType == 0) { + shadowDist = sdSegment(shadowPos, vStart, vEnd); + } else if (vEdgeType == 1) { + shadowDist = sdBezier(shadowPos, vStart, vControl, vEnd); + } else { + shadowDist = abs(length(shadowPos - vControl) - vLoopbackRadius); + } + float shadowArrowDist = vArrowSize > 0.0 + ? sdArrow(shadowPos, vArrowTip, vArrowDir, vArrowSize) + : 1.0e6; + float shadowCombined = min(shadowDist - vHalfWidth, shadowArrowDist); + float t = max(shadowCombined, 0.0) / vShadowSize; + shadowAlpha = exp(-t * t * 1.5) * 0.5 * vShadowColor.a; + } + + float aa = fwidth(combinedSdf); + float edgeAlpha = 1.0 - smoothstep(-aa, aa, combinedSdf); + vec4 edgeColor = vColor; + edgeColor.a *= edgeAlpha; + + float finalAlpha = edgeColor.a + shadowAlpha * (1.0 - edgeColor.a); + + if (finalAlpha < 0.001) discard; + + if (shadowAlpha > 0.0) { + vec3 finalRGB = (edgeColor.rgb * edgeColor.a + vShadowColor.rgb * shadowAlpha * (1.0 - edgeColor.a)) / finalAlpha; + fragColor = vec4(finalRGB, finalAlpha); + } else { + fragColor = edgeColor; + } +} diff --git a/src/renderer/webgl/shaders/edge/edge.vert b/src/renderer/webgl/shaders/edge/edge.vert new file mode 100644 index 0000000..8a881e4 --- /dev/null +++ b/src/renderer/webgl/shaders/edge/edge.vert @@ -0,0 +1,94 @@ +#version 300 es + +precision highp float; + +in vec2 aQuadPosition; + +in vec2 aStart; +in vec2 aEnd; +in vec2 aControl; +in float aWidth; +in float aEdgeType; +in float aLoopbackRadius; +in float aArrowSize; +in vec2 aArrowTip; +in vec2 aArrowDir; +in vec4 aColor; +in vec4 aShadowColor; +in float aShadowSize; +in float aShadowOffsetX; +in float aShadowOffsetY; + +uniform vec2 uResolution; +uniform vec2 uTranslation; +uniform float uScale; +uniform vec2 uOriginOffset; + +out vec2 vWorldPos; +out vec2 vStart; +out vec2 vEnd; +out vec2 vControl; +out float vHalfWidth; +out float vLoopbackRadius; +out float vArrowSize; +out vec2 vArrowTip; +out vec2 vArrowDir; +out vec4 vColor; +out vec4 vShadowColor; +out float vShadowSize; +out vec2 vShadowOffset; +flat out int vEdgeType; + +void main() { + vEdgeType = int(aEdgeType + 0.5); + vStart = aStart; + vEnd = aEnd; + vControl = aControl; + float effectiveWidth = max(aWidth, 1.0 / uScale); + vHalfWidth = effectiveWidth * 0.5; + vLoopbackRadius = aLoopbackRadius; + vArrowSize = aArrowSize; + vArrowTip = aArrowTip; + vArrowDir = aArrowDir; + vColor = aColor; + vShadowColor = aShadowColor; + vShadowSize = aShadowSize; + vShadowOffset = vec2(aShadowOffsetX, aShadowOffsetY); + + float pad = vHalfWidth + aShadowSize + abs(aShadowOffsetX) + abs(aShadowOffsetY); + + vec2 worldPos; + + if (vEdgeType == 0) { + vec2 dir = aEnd - aStart; + float len = length(dir); + vec2 unitDir = dir / max(len, 0.0001); + vec2 perp = vec2(-unitDir.y, unitDir.x); + float totalHalf = pad + aArrowSize; + vec2 midpoint = (aStart + aEnd) * 0.5; + worldPos = midpoint + + unitDir * (len * 0.5 + totalHalf) * aQuadPosition.x + + perp * totalHalf * aQuadPosition.y; + } else if (vEdgeType == 1) { + float margin = pad + aArrowSize; + vec2 bboxMin = min(min(aStart, aEnd), aControl) - margin; + vec2 bboxMax = max(max(aStart, aEnd), aControl) + margin; + vec2 center = (bboxMin + bboxMax) * 0.5; + vec2 halfSize = (bboxMax - bboxMin) * 0.5; + worldPos = center + aQuadPosition * halfSize; + } else { + float margin = pad + aArrowSize; + vec2 ctr = aControl; + float r = aLoopbackRadius; + vec2 bboxMin = min(ctr - (r + margin), aStart - margin); + vec2 bboxMax = max(ctr + (r + margin), aStart + margin); + vec2 center = (bboxMin + bboxMax) * 0.5; + vec2 halfSize = (bboxMax - bboxMin) * 0.5; + worldPos = center + aQuadPosition * halfSize; + } + + vWorldPos = worldPos; + vec2 screenPos = (worldPos + uOriginOffset) * uScale + uTranslation; + vec2 clip = (screenPos / uResolution) * 2.0 - 1.0; + gl_Position = vec4(clip.x, -clip.y, 0.0, 1.0); +} diff --git a/src/renderer/webgl/shaders/label/label.frag b/src/renderer/webgl/shaders/label/label.frag new file mode 100644 index 0000000..707d3cf --- /dev/null +++ b/src/renderer/webgl/shaders/label/label.frag @@ -0,0 +1,15 @@ +#version 300 es + +precision highp float; + +uniform sampler2D uAtlas; + +in vec2 vAtlasUV; + +out vec4 fragColor; + +void main() { + vec4 texel = texture(uAtlas, vAtlasUV); + if (texel.a < 0.01) discard; + fragColor = texel; +} diff --git a/src/renderer/webgl/shaders/label/label.vert b/src/renderer/webgl/shaders/label/label.vert new file mode 100644 index 0000000..c85c0a0 --- /dev/null +++ b/src/renderer/webgl/shaders/label/label.vert @@ -0,0 +1,25 @@ +#version 300 es + +in vec2 aQuadPosition; + +in vec2 aLabelCenter; +in vec2 aLabelSize; +in vec2 aLabelUV0; +in vec2 aLabelUV1; + +uniform vec2 uResolution; +uniform vec2 uTranslation; +uniform float uScale; +uniform vec2 uOriginOffset; + +out vec2 vAtlasUV; + +void main() { + vec2 worldPos = aLabelCenter + aQuadPosition * aLabelSize; + vec2 screenPos = (worldPos + uOriginOffset) * uScale + uTranslation; + vec2 clip = (screenPos / uResolution) * 2.0 - 1.0; + gl_Position = vec4(clip.x, -clip.y, 0.0, 1.0); + + vec2 uv01 = aQuadPosition * 0.5 + 0.5; + vAtlasUV = mix(aLabelUV0, aLabelUV1, uv01); +} diff --git a/src/renderer/webgl/shaders/node/node.frag b/src/renderer/webgl/shaders/node/node.frag new file mode 100644 index 0000000..edce819 --- /dev/null +++ b/src/renderer/webgl/shaders/node/node.frag @@ -0,0 +1,162 @@ +#version 300 es + +precision highp float; + +in vec2 vUV; +in vec4 vColor; +in vec4 vBorderColor; +in float vBorderThreshold; +in vec4 vShadowColor; +in float vNodeRadius; +in vec2 vShadowOffset; +in float vShadowBlur; +flat in int vShapeType; +in vec2 vImageUV0; +in vec2 vImageUV1; +in float vImageAspect; + +uniform sampler2D uImageAtlas; + +out vec4 fragColor; + +const int SHAPE_CIRCLE = 0; +const int SHAPE_DOT = 1; +const int SHAPE_SQUARE = 2; +const int SHAPE_DIAMOND = 3; +const int SHAPE_TRIANGLE = 4; +const int SHAPE_TRIANGLE_DOWN = 5; +const int SHAPE_STAR = 6; +const int SHAPE_HEXAGON = 7; + +float sdCircle(vec2 p, float r) { + return length(p) - r; +} + +float sdSquare(vec2 p, float r) { + vec2 d = abs(p) - vec2(r); + return max(d.x, d.y); +} + +float sdDiamond(vec2 p, float r) { + return (abs(p.x) + abs(p.y)) - r; +} + +float sdTriangleDown(vec2 p, float r) { + float sr = r * 1.15; + vec2 q = vec2(p.x, p.y - 0.275 * sr); + + float k = sqrt(3.0); + q.x = abs(q.x) - sr; + q.y = q.y + sr / k; + if (q.x + k * q.y > 0.0) { + q = vec2(q.x - k * q.y, -k * q.x - q.y) / 2.0; + } + q.x -= clamp(q.x, -2.0 * sr, 0.0); + return -length(q) * sign(q.y); +} + +float sdTriangleUp(vec2 p, float r) { + return sdTriangleDown(vec2(p.x, -p.y), r); +} + +float sdStar(vec2 p, float r) { + float sr = r * 0.82; + vec2 q = vec2(p.x, p.y - 0.1 * sr); + + float outerR = sr * 1.3; + float innerR = sr * 0.5; + + float angle = atan(q.x, -q.y); + float sector = 6.2831853 / 5.0; + float a = mod(angle + sector * 0.5, sector) - sector * 0.5; + + float cosA = cos(a); + float sinA = abs(sin(a)); + + float halfSector = sector * 0.5; + vec2 outerPt = vec2(outerR, 0.0); + vec2 innerPt = vec2(innerR * cos(halfSector), innerR * sin(halfSector)); + + vec2 sp = vec2(cosA, sinA) * length(q); + + vec2 edge = innerPt - outerPt; + vec2 toP = sp - outerPt; + float t = clamp(dot(toP, edge) / dot(edge, edge), 0.0, 1.0); + float dist = length(toP - edge * t); + + float cross2d = edge.x * toP.y - edge.y * toP.x; + return cross2d > 0.0 ? -dist : dist; +} + +float sdHexagon(vec2 p, float r) { + vec2 q = abs(p); + float k = sqrt(3.0); + float d = max(q.x, (q.x * 0.5 + q.y * (k * 0.5))); + return d - r; +} + +float shapeSDF(vec2 p, float r, int shapeType) { + if (shapeType == SHAPE_SQUARE) return sdSquare(p, r); + if (shapeType == SHAPE_DIAMOND) return sdDiamond(p, r); + if (shapeType == SHAPE_TRIANGLE) return sdTriangleUp(p, r); + if (shapeType == SHAPE_TRIANGLE_DOWN) return sdTriangleDown(p, r); + if (shapeType == SHAPE_STAR) return sdStar(p, r); + if (shapeType == SHAPE_HEXAGON) return sdHexagon(p, r); + + return sdCircle(p, r); +} + +void main() { + // Body SDF - always needed. + float dist = shapeSDF(vUV, vNodeRadius, vShapeType); + + float aa = 0.02 * vNodeRadius; + float nodeAlpha = 1.0 - smoothstep(-aa, 0.0, dist); + + // Shadow SDF - skip entirely when no shadow. Avoids a second full shapeSDF() call + // (which is a cascade of ifs) and the exp() per fragment. + float shadowAlpha = 0.0; + if (vShadowBlur > 0.0) { + float shadowDist = shapeSDF(vUV - vShadowOffset, vNodeRadius, vShapeType); + float t = max(shadowDist, 0.0) / vShadowBlur; + shadowAlpha = exp(-t * t * 1.5) * 0.5 * vShadowColor.a; + } + + vec4 fillColor = vColor; + if (vImageAspect > 0.0 && dist < 0.0) { + vec2 uv01 = (vUV / vNodeRadius) * 0.5 + 0.5; + if (vImageAspect > 1.0) { + uv01.x = (uv01.x - 0.5) / vImageAspect + 0.5; + } else { + uv01.y = (uv01.y - 0.5) * vImageAspect + 0.5; + } + if (uv01.x >= 0.0 && uv01.x <= 1.0 && uv01.y >= 0.0 && uv01.y <= 1.0) { + vec2 atlasUV = mix(vImageUV0, vImageUV1, uv01); + vec4 imgTexel = texture(uImageAtlas, atlasUV); + fillColor = mix(fillColor, vec4(imgTexel.rgb, 1.0), imgTexel.a); + } + } + + vec4 nodeColor; + if (vBorderThreshold < vNodeRadius) { + float borderDist = shapeSDF(vUV, vBorderThreshold, vShapeType); + float borderMix = smoothstep(-aa, aa, borderDist); + nodeColor = mix(fillColor, vBorderColor, borderMix); + } else { + nodeColor = fillColor; + } + nodeColor.a *= nodeAlpha; + + float finalAlpha = nodeColor.a + shadowAlpha * (1.0 - nodeColor.a); + + if (finalAlpha < 0.001) { + discard; + } + + if (shadowAlpha > 0.0) { + vec3 finalRGB = (nodeColor.rgb * nodeColor.a + vShadowColor.rgb * shadowAlpha * (1.0 - nodeColor.a)) / finalAlpha; + fragColor = vec4(finalRGB, finalAlpha); + } else { + fragColor = nodeColor; + } +} diff --git a/src/renderer/webgl/shaders/node/node.vert b/src/renderer/webgl/shaders/node/node.vert new file mode 100644 index 0000000..96fb121 --- /dev/null +++ b/src/renderer/webgl/shaders/node/node.vert @@ -0,0 +1,64 @@ +#version 300 es + +precision highp float; + +in vec2 aQuadPosition; + +in vec2 aCenter; +in float aRadius; +in vec4 aColor; +in vec4 aBorderColor; +in float aBorderWidth; +in vec4 aShadowColor; +in float aShadowSize; +in float aShadowOffsetX; +in float aShadowOffsetY; +in float aShapeType; +in vec2 aImageUV0; +in vec2 aImageUV1; +in float aImageAspect; + +uniform vec2 uResolution; +uniform vec2 uTranslation; +uniform float uScale; +uniform vec2 uOriginOffset; + +out vec2 vUV; +out vec4 vColor; +out vec4 vBorderColor; +out float vBorderThreshold; +out vec4 vShadowColor; +out float vNodeRadius; +out vec2 vShadowOffset; +out float vShadowBlur; +flat out int vShapeType; +out vec2 vImageUV0; +out vec2 vImageUV1; +out float vImageAspect; + +void main() { + vShapeType = int(aShapeType + 0.5); + vColor = aColor; + vBorderColor = aBorderColor; + vShadowColor = aShadowColor; + vImageUV0 = aImageUV0; + vImageUV1 = aImageUV1; + vImageAspect = aImageAspect; + + float totalRadius = aRadius + aShadowSize + abs(aShadowOffsetX) + abs(aShadowOffsetY); + + vUV = aQuadPosition; + vNodeRadius = aRadius / totalRadius; + + vBorderThreshold = vNodeRadius * (1.0 - aBorderWidth / aRadius); + + vShadowOffset = vec2(aShadowOffsetX, aShadowOffsetY) / totalRadius; + + vShadowBlur = aShadowSize / totalRadius; + + vec2 worldPos = aCenter + aQuadPosition * totalRadius; + vec2 screenPos = (worldPos + uOriginOffset) * uScale + uTranslation; + + vec2 clip = (screenPos / uResolution) * 2.0 - 1.0; + gl_Position = vec4(clip.x, -clip.y, 0.0, 1.0); +} diff --git a/src/renderer/webgl/utils/image-atlas.ts b/src/renderer/webgl/utils/image-atlas.ts new file mode 100644 index 0000000..cdaafa6 --- /dev/null +++ b/src/renderer/webgl/utils/image-atlas.ts @@ -0,0 +1,180 @@ +const ATLAS_WIDTH = 2048; +const ATLAS_HEIGHT = 2048; +const MAX_CELL_SIZE = 128; +const PADDING = 2; + +export interface IImageAtlasEntry { + u0: number; + v0: number; + u1: number; + v1: number; + aspect: number; +} + +interface IShelf { + y: number; + height: number; + x: number; +} + +interface IPendingImage { + image: HTMLImageElement; + loaded: boolean; +} + +export class ImageAtlas { + private _gl: WebGL2RenderingContext; + private _canvas: HTMLCanvasElement; + private _ctx: CanvasRenderingContext2D; + private _texture: WebGLTexture | null = null; + private _cache = new Map(); + private _pending = new Map(); + private _shelves: IShelf[] = []; + private _isDirty = false; + private _isTextureAllocated = false; + + constructor(gl: WebGL2RenderingContext) { + this._gl = gl; + this._canvas = document.createElement('canvas'); + this._canvas.width = ATLAS_WIDTH; + this._canvas.height = ATLAS_HEIGHT; + this._ctx = this._canvas.getContext('2d', { willReadFrequently: false })!; + this._texture = gl.createTexture(); + + gl.bindTexture(gl.TEXTURE_2D, this._texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.bindTexture(gl.TEXTURE_2D, null); + } + + getOrCreate(url: string): IImageAtlasEntry | null { + const cached = this._cache.get(url); + if (cached) { + return cached; + } + + const pending = this._pending.get(url); + if (pending) { + if (!pending.loaded) { + return null; + } + return this._packImage(url, pending.image); + } + + const image = new Image(); + image.crossOrigin = 'anonymous'; + + const record: IPendingImage = { image, loaded: false }; + this._pending.set(url, record); + + image.onload = () => { + record.loaded = true; + }; + image.onerror = () => { + this._pending.delete(url); + }; + image.src = url; + + return null; + } + + bind(unit: number): void { + const gl = this._gl; + gl.activeTexture(gl.TEXTURE0 + unit); + gl.bindTexture(gl.TEXTURE_2D, this._texture); + } + + uploadIfDirty(): void { + if (!this._isDirty) { + return; + } + + const gl = this._gl; + gl.bindTexture(gl.TEXTURE_2D, this._texture); + + if (!this._isTextureAllocated) { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, ATLAS_WIDTH, ATLAS_HEIGHT, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + this._isTextureAllocated = true; + } + + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, this._canvas); + + gl.bindTexture(gl.TEXTURE_2D, null); + this._isDirty = false; + } + + clear(): void { + this._cache.clear(); + this._pending.clear(); + this._shelves = []; + this._isDirty = false; + this._ctx.clearRect(0, 0, ATLAS_WIDTH, ATLAS_HEIGHT); + } + + private _packImage(url: string, image: HTMLImageElement): IImageAtlasEntry | null { + if (!image.naturalWidth || !image.naturalHeight) { + return null; + } + + const aspect = image.naturalWidth / image.naturalHeight; + + let drawW: number; + let drawH: number; + if (image.naturalWidth >= image.naturalHeight) { + drawW = Math.min(image.naturalWidth, MAX_CELL_SIZE); + drawH = Math.round(drawW / aspect); + } else { + drawH = Math.min(image.naturalHeight, MAX_CELL_SIZE); + drawW = Math.round(drawH * aspect); + } + + const cellW = drawW + PADDING * 2; + const cellH = drawH + PADDING * 2; + + const slot = this._allocate(cellW, cellH); + if (!slot) { + return null; + } + + this._ctx.drawImage(image, slot.x + PADDING, slot.y + PADDING, drawW, drawH); + + const entry: IImageAtlasEntry = { + u0: (slot.x + PADDING) / ATLAS_WIDTH, + v0: (slot.y + PADDING) / ATLAS_HEIGHT, + u1: (slot.x + PADDING + drawW) / ATLAS_WIDTH, + v1: (slot.y + PADDING + drawH) / ATLAS_HEIGHT, + aspect, + }; + + this._cache.set(url, entry); + this._pending.delete(url); + this._isDirty = true; + return entry; + } + + private _allocate(w: number, h: number): { x: number; y: number } | null { + for (let i = 0; i < this._shelves.length; i++) { + const shelf = this._shelves[i]; + if (shelf.x + w <= ATLAS_WIDTH && h <= shelf.height) { + const pos = { x: shelf.x, y: shelf.y }; + shelf.x += w; + return pos; + } + } + + const shelfY = + this._shelves.length === 0 + ? 0 + : this._shelves[this._shelves.length - 1].y + this._shelves[this._shelves.length - 1].height; + + if (shelfY + h > ATLAS_HEIGHT) { + return null; + } + + const newShelf: IShelf = { y: shelfY, height: h, x: w }; + this._shelves.push(newShelf); + return { x: 0, y: shelfY }; + } +} diff --git a/src/renderer/webgl/utils/label-cache.ts b/src/renderer/webgl/utils/label-cache.ts new file mode 100644 index 0000000..19434ab --- /dev/null +++ b/src/renderer/webgl/utils/label-cache.ts @@ -0,0 +1,181 @@ +const ATLAS_WIDTH = 2048; +const ATLAS_HEIGHT = 2048; +const RASTER_FONT_PX = 48; +const FONT_LINE_SPACING = 1.2; +const FONT_BACKGROUND_MARGIN = 0.12; +const PADDING = 2; + +export interface ILabelAtlasEntry { + u0: number; + v0: number; + u1: number; + v1: number; + pxWidth: number; + pxHeight: number; +} + +interface IShelf { + y: number; + height: number; + x: number; +} + +export class LabelCache { + private _gl: WebGL2RenderingContext; + private _canvas: HTMLCanvasElement; + private _ctx: CanvasRenderingContext2D; + private _texture: WebGLTexture | null = null; + private _cache = new Map(); + private _shelves: IShelf[] = []; + private _isDirty = false; + private _isTextureAllocated = false; + + constructor(gl: WebGL2RenderingContext) { + this._gl = gl; + this._canvas = document.createElement('canvas'); + this._canvas.width = ATLAS_WIDTH; + this._canvas.height = ATLAS_HEIGHT; + this._ctx = this._canvas.getContext('2d', { willReadFrequently: false })!; + this._texture = gl.createTexture(); + + gl.bindTexture(gl.TEXTURE_2D, this._texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.bindTexture(gl.TEXTURE_2D, null); + } + + getOrCreate( + text: string, + fontSize: number, + fontFamily: string, + fontColor: string, + bgColor: string | null, + ): ILabelAtlasEntry | null { + const key = `${text}|${fontSize}|${fontFamily}|${fontColor}|${bgColor ?? ''}`; + const cached = this._cache.get(key); + if (cached) { + return cached; + } + + const lines = text.split('\n').map((l) => l.trim()); + if (lines.length === 0 || (lines.length === 1 && lines[0] === '')) { + return null; + } + + const ctx = this._ctx; + const fontStr = `${RASTER_FONT_PX}px ${fontFamily}`; + ctx.font = fontStr; + + let maxLineWidth = 0; + for (let i = 0; i < lines.length; i++) { + const w = ctx.measureText(lines[i]).width; + if (w > maxLineWidth) { + maxLineWidth = w; + } + } + + const margin = RASTER_FONT_PX * FONT_BACKGROUND_MARGIN; + const lineHeight = RASTER_FONT_PX * FONT_LINE_SPACING; + const textBlockHeight = RASTER_FONT_PX + (lines.length - 1) * lineHeight; + const pxWidth = Math.ceil(maxLineWidth + margin * 2) + PADDING * 2; + const pxHeight = Math.ceil(textBlockHeight + margin * 2) + PADDING * 2; + + const slot = this._allocate(pxWidth, pxHeight); + if (!slot) { + return null; + } + + const ox = slot.x + PADDING; + const oy = slot.y + PADDING; + + if (bgColor) { + ctx.fillStyle = bgColor; + ctx.fillRect(ox, oy, pxWidth - PADDING * 2, pxHeight - PADDING * 2); + } + + ctx.font = fontStr; + ctx.fillStyle = fontColor; + ctx.textBaseline = 'top'; + ctx.textAlign = 'center'; + + const centerX = ox + (pxWidth - PADDING * 2) / 2; + for (let i = 0; i < lines.length; i++) { + ctx.fillText(lines[i], centerX, oy + margin + i * lineHeight); + } + + const entry: ILabelAtlasEntry = { + u0: slot.x / ATLAS_WIDTH, + v0: slot.y / ATLAS_HEIGHT, + u1: (slot.x + pxWidth) / ATLAS_WIDTH, + v1: (slot.y + pxHeight) / ATLAS_HEIGHT, + pxWidth, + pxHeight, + }; + + this._cache.set(key, entry); + this._isDirty = true; + return entry; + } + + bind(unit: number): void { + const gl = this._gl; + gl.activeTexture(gl.TEXTURE0 + unit); + gl.bindTexture(gl.TEXTURE_2D, this._texture); + } + + uploadIfDirty(): void { + if (!this._isDirty) { + return; + } + + const gl = this._gl; + gl.bindTexture(gl.TEXTURE_2D, this._texture); + + if (!this._isTextureAllocated) { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, ATLAS_WIDTH, ATLAS_HEIGHT, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + this._isTextureAllocated = true; + } + + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, this._canvas); + + gl.bindTexture(gl.TEXTURE_2D, null); + this._isDirty = false; + } + + clear(): void { + this._cache.clear(); + this._shelves = []; + this._isDirty = false; + this._ctx.clearRect(0, 0, ATLAS_WIDTH, ATLAS_HEIGHT); + } + + get rasterFontPx(): number { + return RASTER_FONT_PX; + } + + private _allocate(w: number, h: number): { x: number; y: number } | null { + for (let i = 0; i < this._shelves.length; i++) { + const shelf = this._shelves[i]; + if (shelf.x + w <= ATLAS_WIDTH && h <= shelf.height) { + const pos = { x: shelf.x, y: shelf.y }; + shelf.x += w; + return pos; + } + } + + const shelfY = + this._shelves.length === 0 + ? 0 + : this._shelves[this._shelves.length - 1].y + this._shelves[this._shelves.length - 1].height; + + if (shelfY + h > ATLAS_HEIGHT) { + return null; + } + + const newShelf: IShelf = { y: shelfY, height: h, x: w }; + this._shelves.push(newShelf); + return { x: 0, y: shelfY }; + } +} diff --git a/src/renderer/webgl/webgl-renderer.ts b/src/renderer/webgl/webgl-renderer.ts index 52ba3a1..9ff12bc 100644 --- a/src/renderer/webgl/webgl-renderer.ts +++ b/src/renderer/webgl/webgl-renderer.ts @@ -1,8 +1,8 @@ import { zoomIdentity, ZoomTransform } from 'd3-zoom'; -import { INodeBase } from '../../models/node'; -import { IEdgeBase } from '../../models/edge'; +import { INode, INodeBase } from '../../models/node'; +import { IEdge, IEdgeBase, EdgeCurved, EdgeLoopback } from '../../models/edge'; import { IGraph } from '../../models/graph'; -import { IPosition, IRectangle } from '../../common'; +import { Color, IPosition, IRectangle } from '../../common'; import { Emitter } from '../../utils/emitter.utils'; import { DEFAULT_RENDERER_HEIGHT, @@ -11,35 +11,120 @@ import { IRenderer, RendererEvents as RE, IRendererSettings, + RenderEventType, } from '../shared'; import { copyObject } from '../../utils/object.utils'; import { appendCanvas, setupContainer } from '../../utils/html.utils'; import { OrbError } from '../../exceptions'; +import { createProgram } from '../../utils/program.utils'; +import { NodeShapeType } from '../../models/node'; +import nodeVertexSource from './shaders/node/node.vert'; +import nodeFragmentSource from './shaders/node/node.frag'; +import edgeVertexSource from './shaders/edge/edge.vert'; +import edgeFragmentSource from './shaders/edge/edge.frag'; +import labelVertexSource from './shaders/label/label.vert'; +import labelFragmentSource from './shaders/label/label.frag'; +import { LabelCache } from './utils/label-cache'; +import { ImageAtlas } from './utils/image-atlas'; + +const EDGE_TYPE_STRAIGHT = 0; +const EDGE_TYPE_CURVED = 1; +const EDGE_TYPE_LOOPBACK = 2; + +// Shared default color tuples — same array reused across all cache misses. +// Without this, every miss in the render loop allocated a fresh 4-element array +// (~hundreds of thousands of allocations per frame at scale). Must not be mutated. +const TRANSPARENT_RGBA: [number, number, number, number] = [0, 0, 0, 0]; +const EDGE_DEFAULT_RGBA: [number, number, number, number] = [0.6, 0.6, 0.6, 1]; +const NODE_DEFAULT_RGBA: [number, number, number, number] = [1, 0, 0, 1]; + +const SHAPE_TYPE_MAP: Record = { + [NodeShapeType.CIRCLE]: 0, + [NodeShapeType.DOT]: 1, + [NodeShapeType.SQUARE]: 2, + [NodeShapeType.DIAMOND]: 3, + [NodeShapeType.TRIANGLE]: 4, + [NodeShapeType.TRIANGLE_DOWN]: 5, + [NodeShapeType.STAR]: 6, + [NodeShapeType.HEXAGON]: 7, +}; + +const DEFAULT_FONT_SIZE = 4; +const DEFAULT_FONT_FAMILY = 'Roboto, sans-serif'; +const DEFAULT_FONT_COLOR = '#000000'; +const LABEL_LOD_MIN_SCREEN_PX = 6; +const IMAGE_LOD_MIN_SCREEN_PX = 4; +const EDGE_SIMPLE_LOD_ZOOM = 0.2; +const LABEL_DISTANCE_FROM_NODE = 0.2; +const FLOATS_PER_LABEL = 8; + +type RGBAFloats = [number, number, number, number]; export class WebGLRenderer extends Emitter implements IRenderer { private readonly _container: HTMLElement; private readonly _canvas: HTMLCanvasElement; // Contains the HTML5 Canvas element which is used for drawing nodes and edges. - private readonly _context: WebGL2RenderingContext; + private readonly _gl: WebGL2RenderingContext; private _width: number; private _height: number; private _settings: IRendererSettings; transform: ZoomTransform; + private _isOriginCentered = false; + private _isInitiallyRendered = false; + + private _nodeProgram: WebGLProgram | null = null; + private _edgeProgram: WebGLProgram | null = null; + private _labelProgram: WebGLProgram | null = null; + + private _nodeVao: WebGLVertexArrayObject | null = null; + private _edgeVao: WebGLVertexArrayObject | null = null; + private _labelVao: WebGLVertexArrayObject | null = null; + + private _nodeInstanceBuffer: WebGLBuffer | null = null; + private _edgeInstanceBuffer: WebGLBuffer | null = null; + private _labelInstanceBuffer: WebGLBuffer | null = null; + + private _labelCache: LabelCache | null = null; + private _imageAtlas: ImageAtlas | null = null; + + private _isColorCacheDirty = true; + private _nodeColorCache = new Map(); + private _nodeBorderColorCache = new Map(); + private _nodeShadowColorCache = new Map(); + + private _edgeColorCache = new Map(); + private _edgeShadowColorCache = new Map(); + + private _lastNodeCount = 0; + private _lastEdgeCount = 0; + + private _edgeInstanceData: Float32Array | null = null; + private _nodeInstanceData: Float32Array | null = null; + private _buffersAreCurrent = false; + private _bufferCacheStats = { hits: 0, misses: 0 }; + + private _timerExt: any = null; + private _timerEdgeQueries: WebGLQuery[] = []; + private _timerNodeQueries: WebGLQuery[] = []; + private _timerQueryIdx = 0; + private _lastEdgeGpuMs: number | null = null; + private _lastNodeGpuMs: number | null = null; + constructor(container: HTMLElement, settings?: Partial) { super(); setupContainer(container, settings?.areCollapsedContainerDimensionsAllowed); this._container = container; this._canvas = appendCanvas(container); - const context = this._canvas.getContext('webgl2'); + const gl = this._canvas.getContext('webgl2', { antialias: true }); - if (!context) { + if (!gl) { throw new OrbError('Failed to create WebGL context.'); } - this._context = context; + this._gl = gl; this._width = DEFAULT_RENDERER_WIDTH; this._height = DEFAULT_RENDERER_HEIGHT; this.transform = zoomIdentity; @@ -48,7 +133,256 @@ export class WebGLRenderer extends Emi ...settings, }; - console.log('context', this._context); + this._initShaders(); + this._initNodeBuffers(); + this._initEdgeBuffers(); + this._initLabelBuffers(); + this._labelCache = new LabelCache(this._gl); + this._imageAtlas = new ImageAtlas(this._gl); + + // GPU timer queries — async, polled lazily. Without this extension getGpuTimeStats + // returns nulls but render() runs identically. + this._timerExt = gl.getExtension('EXT_disjoint_timer_query_webgl2'); + if (this._timerExt) { + for (let i = 0; i < 4; i++) { + const eq = gl.createQuery(); + const nq = gl.createQuery(); + if (eq) { + this._timerEdgeQueries.push(eq); + } + if (nq) { + this._timerNodeQueries.push(nq); + } + } + } + } + + private _pollTimerQuery(query: WebGLQuery): number | null { + if (!this._timerExt) { + return null; + } + const gl = this._gl; + const available = gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE); + if (!available) { + return null; + } + if (gl.getParameter(this._timerExt.GPU_DISJOINT_EXT)) { + return null; + } + const ns = gl.getQueryParameter(query, gl.QUERY_RESULT) as number; + return ns / 1e6; + } + + getGpuTimeStats(): { edgeMs: number | null; nodeMs: number | null; supported: boolean } { + return { + edgeMs: this._lastEdgeGpuMs, + nodeMs: this._lastNodeGpuMs, + supported: this._timerExt !== null, + }; + } + + private _initShaders(): void { + this._nodeProgram = createProgram(this._gl, nodeVertexSource, nodeFragmentSource); + this._edgeProgram = createProgram(this._gl, edgeVertexSource, edgeFragmentSource); + this._labelProgram = createProgram(this._gl, labelVertexSource, labelFragmentSource); + } + + private _initNodeBuffers(): void { + if (!this._nodeProgram) { + throw new OrbError('Node program not initialized.'); + } + + const gl = this._gl; + + this._nodeVao = gl.createVertexArray(); + gl.bindVertexArray(this._nodeVao); + + const quadVerts = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]); + const quadBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer); + gl.bufferData(gl.ARRAY_BUFFER, quadVerts, gl.STATIC_DRAW); + + const posLoc = gl.getAttribLocation(this._nodeProgram, 'aQuadPosition'); + gl.enableVertexAttribArray(posLoc); + gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0); + + this._nodeInstanceBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, this._nodeInstanceBuffer); + + const INSTANCE_STRIDE = 25 * Float32Array.BYTES_PER_ELEMENT; + const attr = (name: string, size: number, offset: number) => { + const loc = gl.getAttribLocation(this._nodeProgram!, name); + gl.enableVertexAttribArray(loc); + gl.vertexAttribPointer(loc, size, gl.FLOAT, false, INSTANCE_STRIDE, offset * 4); + gl.vertexAttribDivisor(loc, 1); + }; + + attr('aCenter', 2, 0); + attr('aRadius', 1, 2); + attr('aColor', 4, 3); + attr('aBorderColor', 4, 7); + attr('aBorderWidth', 1, 11); + attr('aShadowColor', 4, 12); + attr('aShadowSize', 1, 16); + attr('aShadowOffsetX', 1, 17); + attr('aShadowOffsetY', 1, 18); + attr('aShapeType', 1, 19); + attr('aImageUV0', 2, 20); + attr('aImageUV1', 2, 22); + attr('aImageAspect', 1, 24); + + gl.bindVertexArray(null); + } + + private _initEdgeBuffers(): void { + if (!this._edgeProgram) { + throw new OrbError('Edge program not initialized.'); + } + + const gl = this._gl; + + this._edgeVao = gl.createVertexArray(); + gl.bindVertexArray(this._edgeVao); + + const quadVerts = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]); + const quadBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer); + gl.bufferData(gl.ARRAY_BUFFER, quadVerts, gl.STATIC_DRAW); + + const posLoc = gl.getAttribLocation(this._edgeProgram, 'aQuadPosition'); + gl.enableVertexAttribArray(posLoc); + gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0); + + this._edgeInstanceBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, this._edgeInstanceBuffer); + + const STRIDE = 25 * 4; + const attr = (name: string, size: number, offset: number) => { + const loc = gl.getAttribLocation(this._edgeProgram!, name); + gl.enableVertexAttribArray(loc); + gl.vertexAttribPointer(loc, size, gl.FLOAT, false, STRIDE, offset * 4); + gl.vertexAttribDivisor(loc, 1); + }; + + attr('aStart', 2, 0); + attr('aEnd', 2, 2); + attr('aControl', 2, 4); + attr('aWidth', 1, 6); + attr('aEdgeType', 1, 7); + attr('aLoopbackRadius', 1, 8); + attr('aArrowSize', 1, 9); + attr('aArrowTip', 2, 10); + attr('aArrowDir', 2, 12); + attr('aColor', 4, 14); + attr('aShadowColor', 4, 18); + attr('aShadowSize', 1, 22); + attr('aShadowOffsetX', 1, 23); + attr('aShadowOffsetY', 1, 24); + + gl.bindVertexArray(null); + } + + private _initLabelBuffers(): void { + if (!this._labelProgram) { + throw new OrbError('Label program not initialized.'); + } + + const gl = this._gl; + + this._labelVao = gl.createVertexArray(); + gl.bindVertexArray(this._labelVao); + + const quadVerts = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]); + const quadBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer); + gl.bufferData(gl.ARRAY_BUFFER, quadVerts, gl.STATIC_DRAW); + + const posLoc = gl.getAttribLocation(this._labelProgram, 'aQuadPosition'); + gl.enableVertexAttribArray(posLoc); + gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0); + + this._labelInstanceBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, this._labelInstanceBuffer); + + const STRIDE = FLOATS_PER_LABEL * 4; + const attr = (name: string, size: number, offset: number) => { + const loc = gl.getAttribLocation(this._labelProgram!, name); + gl.enableVertexAttribArray(loc); + gl.vertexAttribPointer(loc, size, gl.FLOAT, false, STRIDE, offset * 4); + gl.vertexAttribDivisor(loc, 1); + }; + + attr('aLabelCenter', 2, 0); + attr('aLabelSize', 2, 2); + attr('aLabelUV0', 2, 4); + attr('aLabelUV1', 2, 6); + + gl.bindVertexArray(null); + } + + private _resolveColor(raw: Color | string | undefined): RGBAFloats { + if (!raw) { + return [1, 0, 0, 1]; + } + + if (raw instanceof Color) { + return [raw.rgb.r / 255, raw.rgb.g / 255, raw.rgb.b / 255, 1.0]; + } + + const rgbaMatch = raw.match(/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+))?\s*\)$/); + if (rgbaMatch) { + return [ + parseInt(rgbaMatch[1]) / 255, + parseInt(rgbaMatch[2]) / 255, + parseInt(rgbaMatch[3]) / 255, + rgbaMatch[4] !== undefined ? parseFloat(rgbaMatch[4]) : 1.0, + ]; + } + + const c = new Color(raw); + return [c.rgb.r / 255, c.rgb.g / 255, c.rgb.b / 255, 1.0]; + } + + private _buildNodeColorCache(nodes: INode[]): void { + this._nodeColorCache.clear(); + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + this._nodeColorCache.set(node.id, this._resolveColor(node.getColor())); + } + } + + private _buildNodeBorderColorCache(nodes: INode[]): void { + this._nodeBorderColorCache.clear(); + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + this._nodeBorderColorCache.set(node.id, this._resolveColor(node.getBorderColor())); + } + } + + private _buildNodeShadowColorCache(nodes: INode[]): void { + this._nodeShadowColorCache.clear(); + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + const raw = node.getStyle().shadowColor; + this._nodeShadowColorCache.set(node.id, raw ? this._resolveColor(raw) : [0, 0, 0, 0]); + } + } + + private _buildEdgeColorCache(edges: IEdge[]): void { + this._edgeColorCache.clear(); + for (let i = 0; i < edges.length; i++) { + const edge = edges[i]; + this._edgeColorCache.set(edge.id, this._resolveColor(edge.getColor())); + } + } + + private _buildEdgeShadowColorCache(edges: IEdge[]): void { + this._edgeShadowColorCache.clear(); + for (let i = 0; i < edges.length; i++) { + const edge = edges[i]; + const raw = edge.getStyle().shadowColor; + this._edgeShadowColorCache.set(edge.id, raw ? this._resolveColor(raw) : [0, 0, 0, 0]); + } } get width(): number { @@ -68,7 +402,20 @@ export class WebGLRenderer extends Emi } get isInitiallyRendered(): boolean { - throw new Error('Method not implemented.'); + return this._isInitiallyRendered; + } + + invalidateBuffers(): void { + this._buffersAreCurrent = false; + } + + invalidateStyles(): void { + this._buffersAreCurrent = false; + this._isColorCacheDirty = true; + } + + getRenderCacheStats(): { hits: number; misses: number } { + return { ...this._bufferCacheStats }; } getSettings(): IRendererSettings { @@ -83,34 +430,579 @@ export class WebGLRenderer extends Emi } render(graph: IGraph): void { - console.log('graph:', graph); - throw new Error('Method not implemented.'); + if (!this._nodeProgram || !this._edgeProgram || !this._labelProgram) { + throw new OrbError('Shader programs not initialized.'); + } + + this.emit(RenderEventType.RENDER_START, undefined); + const renderStartedAt = performance.now(); + + const gl = this._gl; + + const rect = this._container.getBoundingClientRect(); + if (rect.width !== this._width || rect.height !== this._height) { + this._canvas.width = rect.width; + this._canvas.height = rect.height; + this._width = rect.width; + this._height = rect.height; + } + + gl.viewport(0, 0, this._width, this._height); + + gl.clearColor(0.0, 0.0, 0.0, 0.0); + gl.clear(gl.COLOR_BUFFER_BIT); + + gl.enable(gl.BLEND); + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + + const edges = graph.getEdges(); + const FLOATS_PER_EDGE = 25; + const edgeBufferLen = edges.length * FLOATS_PER_EDGE; + const edgeBufferSizeChanged = this._edgeInstanceData === null || this._edgeInstanceData.length !== edgeBufferLen; + if (edgeBufferSizeChanged) { + this._edgeInstanceData = new Float32Array(edgeBufferLen); + } + const edgeData = this._edgeInstanceData!; + + const canSkipRebuild = this._buffersAreCurrent && !edgeBufferSizeChanged; + if (canSkipRebuild) { + this._bufferCacheStats.hits++; + } else { + this._bufferCacheStats.misses++; + } + + let nodeCxCache: Float64Array | null = null; + let nodeCyCache: Float64Array | null = null; + let nodeBorderCache: Float64Array | null = null; + let nodeIdToIndex: Map | null = null; + if (!canSkipRebuild) { + const allNodes = graph.getNodes(); + nodeCxCache = new Float64Array(allNodes.length); + nodeCyCache = new Float64Array(allNodes.length); + nodeBorderCache = new Float64Array(allNodes.length); + nodeIdToIndex = new Map(); + for (let i = 0; i < allNodes.length; i++) { + const n = allNodes[i]; + const c = n.getCenter(); + nodeCxCache[i] = c.x; + nodeCyCache[i] = c.y; + nodeBorderCache[i] = n.getDistanceToBorder(); + nodeIdToIndex.set(n.id, i); + } + } + + if (!canSkipRebuild && (edges.length !== this._lastEdgeCount || this._isColorCacheDirty)) { + this._buildEdgeColorCache(edges); + this._buildEdgeShadowColorCache(edges); + this._isColorCacheDirty = false; + this._lastEdgeCount = edges.length; + } + + if (!canSkipRebuild) { + for (let i = 0; i < edges.length; i++) { + const edge = edges[i]; + const startIdx = nodeIdToIndex!.get(edge.startNode.id); + const endIdx = nodeIdToIndex!.get(edge.endNode.id); + let startX: number; + let startY: number; + let endX: number; + let endY: number; + let endBorderDist: number; + let startBorderDist: number; + if (startIdx !== undefined) { + startX = nodeCxCache![startIdx]; + startY = nodeCyCache![startIdx]; + startBorderDist = nodeBorderCache![startIdx]; + } else { + const c = edge.startNode.getCenter(); + startX = c.x; + startY = c.y; + startBorderDist = edge.startNode.getDistanceToBorder(); + } + if (endIdx !== undefined) { + endX = nodeCxCache![endIdx]; + endY = nodeCyCache![endIdx]; + endBorderDist = nodeBorderCache![endIdx]; + } else { + const c = edge.endNode.getCenter(); + endX = c.x; + endY = c.y; + endBorderDist = edge.endNode.getDistanceToBorder(); + } + const edgeStyle = edge.getStyle(); + const shadowSize = edgeStyle.shadowSize || 0; + const shadowOffsetX = edgeStyle.shadowOffsetX || 0; + const shadowOffsetY = edgeStyle.shadowOffsetY || 0; + const shadowColor = this._edgeShadowColorCache.get(edge.id) || TRANSPARENT_RGBA; + const off = i * FLOATS_PER_EDGE; + + const width = edge.getWidth(); + const rgba = + edge.isHovered() || edge.isSelected() + ? this._resolveColor(edge.getColor()) + : this._edgeColorCache.get(edge.id) || EDGE_DEFAULT_RGBA; + + let edgeType = EDGE_TYPE_STRAIGHT; + let controlX = 0; + let controlY = 0; + let loopbackRadius = 0; + let arrowSize = 0; + let arrowTipX = 0; + let arrowTipY = 0; + let arrowDirX = 0; + let arrowDirY = 0; + + if (edge.isCurved()) { + edgeType = EDGE_TYPE_CURVED; + const cp = (edge as EdgeCurved).getCurvedControlPoint(); + controlX = cp.x; + controlY = cp.y; + } else if (edge.isLoopback()) { + edgeType = EDGE_TYPE_LOOPBACK; + const circle = (edge as EdgeLoopback).getCircularData(); + controlX = circle.x; + controlY = circle.y; + loopbackRadius = circle.radius; + } + + const scaleFactor = edgeStyle.arrowSize ?? 1; + if (scaleFactor > 0) { + const lineWidth = width || 1; + arrowSize = 1.5 * scaleFactor + 3 * lineWidth; + + if (edgeType === EDGE_TYPE_STRAIGHT) { + const dx = endX - startX; + const dy = endY - startY; + const len = Math.sqrt(dx * dx + dy * dy); + if (len > 0) { + arrowDirX = dx / len; + arrowDirY = dy / len; + arrowTipX = endX - arrowDirX * endBorderDist; + arrowTipY = endY - arrowDirY * endBorderDist; + } + } else if (edgeType === EDGE_TYPE_CURVED) { + // End node's center is (endX, endY); border distance cached above. + let bestT = 1.0; + let low = 0.5; + let high = 1.0; + + for (let iter = 0; iter < 8; iter++) { + const mid = (low + high) * 0.5; + const mt = 1 - mid; + const px = mt * mt * startX + 2 * mid * mt * controlX + mid * mid * endX; + const py = mt * mt * startY + 2 * mid * mt * controlY + mid * mid * endY; + const d = Math.sqrt((px - endX) ** 2 + (py - endY) ** 2); + if (Math.abs(d - endBorderDist) < 0.1) { + bestT = mid; + break; + } + if (d > endBorderDist) { + low = mid; + } else { + high = mid; + } + bestT = mid; + } + + const mt = 1 - bestT; + arrowTipX = mt * mt * startX + 2 * bestT * mt * controlX + bestT * bestT * endX; + arrowTipY = mt * mt * startY + 2 * bestT * mt * controlY + bestT * bestT * endY; + const tx = 2 * mt * (controlX - startX) + 2 * bestT * (endX - controlX); + const ty = 2 * mt * (controlY - startY) + 2 * bestT * (endY - controlY); + const tLen = Math.sqrt(tx * tx + ty * ty); + if (tLen > 0) { + arrowDirX = tx / tLen; + arrowDirY = ty / tLen; + } + } else { + let bestT = 0.8; + let low = 0.6; + let high = 1.0; + for (let iter = 0; iter < 8; iter++) { + const mid = (low + high) * 0.5; + const angle = mid * 2 * Math.PI; + const px = controlX + loopbackRadius * Math.cos(angle); + const py = controlY - loopbackRadius * Math.sin(angle); + const d = Math.sqrt((px - startX) ** 2 + (py - startY) ** 2); + if (Math.abs(d - startBorderDist) < 0.1) { + bestT = mid; + break; + } + if (d > startBorderDist) { + high = mid; + } else { + low = mid; + } + bestT = mid; + } + const angle = bestT * 2 * Math.PI; + arrowTipX = controlX + loopbackRadius * Math.cos(angle); + arrowTipY = controlY - loopbackRadius * Math.sin(angle); + const arrowAngle = bestT * -2 * Math.PI + 0.45 * Math.PI; + arrowDirX = Math.cos(arrowAngle); + arrowDirY = Math.sin(arrowAngle); + } + } + + edgeData[off] = startX; + edgeData[off + 1] = startY; + edgeData[off + 2] = endX; + edgeData[off + 3] = endY; + edgeData[off + 4] = controlX; + edgeData[off + 5] = controlY; + edgeData[off + 6] = width; + edgeData[off + 7] = edgeType; + edgeData[off + 8] = loopbackRadius; + edgeData[off + 9] = arrowSize; + edgeData[off + 10] = arrowTipX; + edgeData[off + 11] = arrowTipY; + edgeData[off + 12] = arrowDirX; + edgeData[off + 13] = arrowDirY; + edgeData[off + 14] = rgba[0]; + edgeData[off + 15] = rgba[1]; + edgeData[off + 16] = rgba[2]; + edgeData[off + 17] = rgba[3]; + edgeData[off + 18] = shadowColor[0]; + edgeData[off + 19] = shadowColor[1]; + edgeData[off + 20] = shadowColor[2]; + edgeData[off + 21] = shadowColor[3]; + edgeData[off + 22] = shadowSize; + edgeData[off + 23] = shadowOffsetX; + edgeData[off + 24] = shadowOffsetY; + } + } + + gl.useProgram(this._edgeProgram); + this._setViewUniforms(this._edgeProgram); + gl.bindBuffer(gl.ARRAY_BUFFER, this._edgeInstanceBuffer); + if (!canSkipRebuild) { + gl.bufferData(gl.ARRAY_BUFFER, edgeData.byteLength, gl.STREAM_DRAW); + gl.bufferSubData(gl.ARRAY_BUFFER, 0, edgeData); + } + + const isSimpleEdgeMode = this.transform.k <= EDGE_SIMPLE_LOD_ZOOM; + const uSimpleModeLoc = gl.getUniformLocation(this._edgeProgram, 'uSimpleMode'); + gl.uniform1i(uSimpleModeLoc, isSimpleEdgeMode ? 1 : 0); + + gl.bindVertexArray(this._edgeVao); + + if (this._timerExt && this._timerEdgeQueries.length > 0) { + const slot = this._timerEdgeQueries[this._timerQueryIdx]; + const ms = this._pollTimerQuery(slot); + if (ms !== null) { + this._lastEdgeGpuMs = ms; + } + gl.beginQuery(this._timerExt.TIME_ELAPSED_EXT, slot); + } + + gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, edges.length); + + if (this._timerExt && this._timerEdgeQueries.length > 0) { + gl.endQuery(this._timerExt.TIME_ELAPSED_EXT); + } + gl.bindVertexArray(null); + + if (isSimpleEdgeMode) { + gl.enable(gl.BLEND); + } + + gl.useProgram(this._nodeProgram); + this._setViewUniforms(this._nodeProgram); + + if (this._imageAtlas) { + this._imageAtlas.uploadIfDirty(); + this._imageAtlas.bind(0); + gl.uniform1i(gl.getUniformLocation(this._nodeProgram, 'uImageAtlas'), 0); + } + + const nodes = graph.getNodes(); + const zoom = this.transform.k; + const FLOATS_PER_NODE = 25; + const nodeBufferLen = nodes.length * FLOATS_PER_NODE; + const nodeBufferSizeChanged = this._nodeInstanceData === null || this._nodeInstanceData.length !== nodeBufferLen; + if (nodeBufferSizeChanged) { + this._nodeInstanceData = new Float32Array(nodeBufferLen); + } + const instanceData = this._nodeInstanceData!; + const canSkipNodeRebuild = canSkipRebuild && !nodeBufferSizeChanged; + + if (!canSkipNodeRebuild && (nodes.length !== this._lastNodeCount || this._isColorCacheDirty)) { + this._buildNodeColorCache(nodes); + this._buildNodeBorderColorCache(nodes); + this._buildNodeShadowColorCache(nodes); + this._isColorCacheDirty = false; + this._lastNodeCount = nodes.length; + } + + if (!canSkipNodeRebuild) { + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + const center = node.getCenter(); + const radius = node.getRadius(); + const nodeStyle = node.getStyle(); + const shadowSize = nodeStyle.shadowSize || 0; + const shadowOffsetX = nodeStyle.shadowOffsetX || 0; + const shadowOffsetY = nodeStyle.shadowOffsetY || 0; + const shadowColor = this._nodeShadowColorCache.get(node.id) || TRANSPARENT_RGBA; + const off = i * FLOATS_PER_NODE; + + let rgba: RGBAFloats; + let borderColor: RGBAFloats; + let borderWidth: number; + + if (node.isHovered() || node.isSelected()) { + rgba = this._resolveColor(node.getColor()); + borderColor = this._resolveColor(node.getBorderColor()); + borderWidth = node.getBorderWidth(); + } else { + rgba = this._nodeColorCache.get(node.id) || NODE_DEFAULT_RGBA; + borderColor = this._nodeBorderColorCache.get(node.id) || TRANSPARENT_RGBA; + borderWidth = node.getBorderWidth(); + } + + instanceData[off] = center.x; + instanceData[off + 1] = center.y; + instanceData[off + 2] = radius; + instanceData[off + 3] = rgba[0]; + instanceData[off + 4] = rgba[1]; + instanceData[off + 5] = rgba[2]; + instanceData[off + 6] = rgba[3]; + instanceData[off + 7] = borderColor[0]; + instanceData[off + 8] = borderColor[1]; + instanceData[off + 9] = borderColor[2]; + instanceData[off + 10] = borderColor[3]; + instanceData[off + 11] = borderWidth; + instanceData[off + 12] = shadowColor[0]; + instanceData[off + 13] = shadowColor[1]; + instanceData[off + 14] = shadowColor[2]; + instanceData[off + 15] = shadowColor[3]; + instanceData[off + 16] = shadowSize; + instanceData[off + 17] = shadowOffsetX; + instanceData[off + 18] = shadowOffsetY; + instanceData[off + 19] = SHAPE_TYPE_MAP[nodeStyle.shape ?? NodeShapeType.CIRCLE] ?? 0; + + let imgU0 = 0; + let imgV0 = 0; + let imgU1 = 0; + let imgV1 = 0; + let imgAspect = 0; + if (radius * zoom >= IMAGE_LOD_MIN_SCREEN_PX) { + const imageUrl = node.isSelected() ? nodeStyle.imageUrlSelected || nodeStyle.imageUrl : nodeStyle.imageUrl; + if (imageUrl && this._imageAtlas) { + const entry = this._imageAtlas.getOrCreate(imageUrl); + if (entry) { + imgU0 = entry.u0; + imgV0 = entry.v0; + imgU1 = entry.u1; + imgV1 = entry.v1; + imgAspect = entry.aspect; + } + } + } + instanceData[off + 20] = imgU0; + instanceData[off + 21] = imgV0; + instanceData[off + 22] = imgU1; + instanceData[off + 23] = imgV1; + instanceData[off + 24] = imgAspect; + } + } + + gl.bindBuffer(gl.ARRAY_BUFFER, this._nodeInstanceBuffer); + if (!canSkipNodeRebuild) { + gl.bufferData(gl.ARRAY_BUFFER, instanceData.byteLength, gl.STREAM_DRAW); + gl.bufferSubData(gl.ARRAY_BUFFER, 0, instanceData); + } + this._buffersAreCurrent = true; + + gl.bindVertexArray(this._nodeVao); + + if (this._timerExt && this._timerNodeQueries.length > 0) { + const slot = this._timerNodeQueries[this._timerQueryIdx]; + const ms = this._pollTimerQuery(slot); + if (ms !== null) { + this._lastNodeGpuMs = ms; + } + gl.beginQuery(this._timerExt.TIME_ELAPSED_EXT, slot); + } + + gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, nodes.length); + + if (this._timerExt && this._timerNodeQueries.length > 0) { + gl.endQuery(this._timerExt.TIME_ELAPSED_EXT); + this._timerQueryIdx = (this._timerQueryIdx + 1) % this._timerNodeQueries.length; + } + gl.bindVertexArray(null); + + if (this._labelProgram && this._labelCache && this._settings.labelsIsEnabled) { + const labelCache = this._labelCache; + const rasterPx = labelCache.rasterFontPx; + let labelCount = 0; + + const maxLabels = nodes.length + edges.length; + const labelData = new Float32Array(maxLabels * FLOATS_PER_LABEL); + + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + const text = node.getLabel(); + if (!text) { + continue; + } + + const style = node.getStyle(); + const fontSize = style.fontSize || DEFAULT_FONT_SIZE; + if (fontSize * zoom < LABEL_LOD_MIN_SCREEN_PX) { + continue; + } + + const fontFamily = style.fontFamily || DEFAULT_FONT_FAMILY; + const fontColor = (style.fontColor ?? DEFAULT_FONT_COLOR).toString(); + const bgColor = style.fontBackgroundColor ? style.fontBackgroundColor.toString() : null; + + const entry = labelCache.getOrCreate(text, fontSize, fontFamily, fontColor, bgColor); + if (!entry) { + continue; + } + + const center = node.getCenter(); + const borderedRadius = node.getBorderedRadius(); + const worldW = (entry.pxWidth / rasterPx) * fontSize; + const worldH = (entry.pxHeight / rasterPx) * fontSize; + + const off = labelCount * FLOATS_PER_LABEL; + labelData[off] = center.x; + labelData[off + 1] = center.y + borderedRadius * (1 + LABEL_DISTANCE_FROM_NODE) + worldH / 2; + labelData[off + 2] = worldW / 2; + labelData[off + 3] = worldH / 2; + labelData[off + 4] = entry.u0; + labelData[off + 5] = entry.v0; + labelData[off + 6] = entry.u1; + labelData[off + 7] = entry.v1; + labelCount++; + } + + for (let i = 0; i < edges.length; i++) { + const edge = edges[i]; + const text = edge.getLabel(); + if (!text) { + continue; + } + + const style = edge.getStyle(); + const fontSize = style.fontSize || DEFAULT_FONT_SIZE; + if (fontSize * zoom < LABEL_LOD_MIN_SCREEN_PX) { + continue; + } + + const fontFamily = style.fontFamily || DEFAULT_FONT_FAMILY; + const fontColor = (style.fontColor ?? DEFAULT_FONT_COLOR).toString(); + const bgColor = style.fontBackgroundColor ? style.fontBackgroundColor.toString() : null; + + const entry = labelCache.getOrCreate(text, fontSize, fontFamily, fontColor, bgColor); + if (!entry) { + continue; + } + + const edgeCenter = edge.getCenter(); + const worldW = (entry.pxWidth / rasterPx) * fontSize; + const worldH = (entry.pxHeight / rasterPx) * fontSize; + + const off = labelCount * FLOATS_PER_LABEL; + labelData[off] = edgeCenter.x; + labelData[off + 1] = edgeCenter.y; + labelData[off + 2] = worldW / 2; + labelData[off + 3] = worldH / 2; + labelData[off + 4] = entry.u0; + labelData[off + 5] = entry.v0; + labelData[off + 6] = entry.u1; + labelData[off + 7] = entry.v1; + labelCount++; + } + + if (labelCount > 0) { + labelCache.uploadIfDirty(); + + gl.useProgram(this._labelProgram); + this._setViewUniforms(this._labelProgram); + + labelCache.bind(0); + gl.uniform1i(gl.getUniformLocation(this._labelProgram, 'uAtlas'), 0); + + gl.bindBuffer(gl.ARRAY_BUFFER, this._labelInstanceBuffer); + gl.bufferData(gl.ARRAY_BUFFER, labelData.subarray(0, labelCount * FLOATS_PER_LABEL), gl.DYNAMIC_DRAW); + + gl.bindVertexArray(this._labelVao); + gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, labelCount); + gl.bindVertexArray(null); + } + } + + this._isInitiallyRendered = true; + this.emit(RenderEventType.RENDER_END, { durationMs: performance.now() - renderStartedAt }); } reset(): void { - throw new Error('Method not implemented.'); + this.transform = zoomIdentity; + const gl = this._gl; + gl.clearColor(0.0, 0.0, 0.0, 0.0); + gl.clear(gl.COLOR_BUFFER_BIT); } getFitZoomTransform(graph: IGraph): ZoomTransform { - console.log('graph:', graph); - throw new Error('Method not implemented.'); + const graphView = graph.getBoundingBox(); + const graphMiddleX = graphView.x + graphView.width / 2; + const graphMiddleY = graphView.y + graphView.height / 2; + + const simulationView = this.getSimulationViewRectangle(); + + const heightScale = simulationView.height / (graphView.height * (1 + this._settings.fitZoomMargin)); + const widthScale = simulationView.width / (graphView.width * (1 + this._settings.fitZoomMargin)); + const scale = Math.min(heightScale, widthScale); + + const previousZoom = this.transform.k; + const newZoom = Math.max(Math.min(scale * previousZoom, this._settings.maxZoom), this._settings.minZoom); + + const newX = (simulationView.width / 2) * previousZoom * (1 - newZoom) - graphMiddleX * newZoom; + const newY = (simulationView.height / 2) * previousZoom * (1 - newZoom) - graphMiddleY * newZoom; + + return zoomIdentity.translate(newX, newY).scale(newZoom); } getSimulationPosition(canvasPoint: IPosition): IPosition { - console.log('canvasPoint:', canvasPoint); - throw new Error('Method not implemented.'); + const [x, y] = this.transform.invert([canvasPoint.x, canvasPoint.y]); + return { + x: x - this._width / 2, + y: y - this._height / 2, + }; } getSimulationViewRectangle(): IRectangle { - throw new Error('Method not implemented.'); + const topLeftPosition = this.getSimulationPosition({ x: 0, y: 0 }); + const bottomRightPosition = this.getSimulationPosition({ x: this._width, y: this._height }); + return { + x: topLeftPosition.x, + y: topLeftPosition.y, + width: bottomRightPosition.x - topLeftPosition.x, + height: bottomRightPosition.y - topLeftPosition.y, + }; } translateOriginToCenter(): void { - throw new Error('Method not implemented.'); + this._isOriginCentered = true; } destroy(): void { this.removeAllListeners(); this._canvas.outerHTML = ''; } + + private _setViewUniforms(program: WebGLProgram): void { + const gl = this._gl; + const originX = this._isOriginCentered ? this._width / 2 : 0; + const originY = this._isOriginCentered ? this._height / 2 : 0; + + gl.uniform2f(gl.getUniformLocation(program, 'uResolution'), this._width, this._height); + gl.uniform2f(gl.getUniformLocation(program, 'uTranslation'), this.transform.x, this.transform.y); + gl.uniform1f(gl.getUniformLocation(program, 'uScale'), this.transform.k); + gl.uniform2f(gl.getUniformLocation(program, 'uOriginOffset'), originX, originY); + } } diff --git a/src/simulator/engine/engines/dynamic/force-layout-engine.ts b/src/simulator/engine/engines/dynamic/force-layout-engine.ts index 40dd4f8..fb9d824 100644 --- a/src/simulator/engine/engines/dynamic/force-layout-engine.ts +++ b/src/simulator/engine/engines/dynamic/force-layout-engine.ts @@ -11,7 +11,13 @@ import { SimulationLinkDatum, } from 'd3-force'; import { IPosition } from '../../../../common'; -import { ISimulationNode, ISimulationGraph, ISimulationIds, SimulatorEventType } from '../../../shared'; +import { + ISimulationNode, + ISimulationEdge, + ISimulationGraph, + ISimulationIds, + SimulatorEventType, +} from '../../../shared'; import { isObjectEqual, copyObject } from '../../../../utils/object.utils'; import { IEngineSettingsUpdate, IForceLayoutOptions, DEFAULT_FORCE_LAYOUT_OPTIONS, LayoutType } from '../../shared'; import { BaseLayoutEngine } from '../base-layout-engine'; @@ -23,6 +29,49 @@ interface IRunSimulationOptions { isUpdatingSettings: boolean; } +function forceEdgeMidpointRepulsion(strength: number, distanceMax: number, getEdges: () => ISimulationEdge[]) { + let nodes: ISimulationNode[] = []; + const distanceMax2 = distanceMax * distanceMax; + + function force(alpha: number) { + const edges = getEdges(); + for (let e = 0; e < edges.length; e++) { + const src = edges[e].source as ISimulationNode; + const tgt = edges[e].target as ISimulationNode; + if (!src || !tgt) { + continue; + } + + const mx = ((src.x ?? 0) + (tgt.x ?? 0)) * 0.5; + const my = ((src.y ?? 0) + (tgt.y ?? 0)) * 0.5; + + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + const dx = (node.x ?? 0) - mx; + const dy = (node.y ?? 0) - my; + let distSq = dx * dx + dy * dy; + + if (distSq === 0 || distSq >= distanceMax2) { + continue; + } + if (distSq < 1) { + distSq = 1; + } + + const f = (-strength * alpha) / distSq; + node.vx! += dx * f; + node.vy! += dy * f; + } + } + } + + force.initialize = (initNodes: ISimulationNode[]) => { + nodes = initNodes; + }; + + return force; +} + export class ForceLayoutEngine extends BaseLayoutEngine { private _linkForce!: ForceLink>; private _simulation!: Simulation; @@ -470,10 +519,24 @@ export class ForceLayoutEngine extends BaseLayoutEngine { .distanceMin(settings.manyBody.distanceMin) .distanceMax(settings.manyBody.distanceMax); this._simulation.force('charge', manyBody); + + if (settings.manyBody.edgeMidpointRepulsion) { + this._simulation.force( + 'edgeMidpointRepulsion', + forceEdgeMidpointRepulsion( + settings.manyBody.strength, + settings.manyBody.distanceMax, + () => this._edges, + ) as any, + ); + } else { + this._simulation.force('edgeMidpointRepulsion', null); + } } if (settings.manyBody === null) { this._simulation.force('charge', null); + this._simulation.force('edgeMidpointRepulsion', null); } if (settings.positioning?.forceX) { diff --git a/src/simulator/engine/engines/dynamic/gpu-force-layout-engine.ts b/src/simulator/engine/engines/dynamic/gpu-force-layout-engine.ts new file mode 100644 index 0000000..e0dc538 --- /dev/null +++ b/src/simulator/engine/engines/dynamic/gpu-force-layout-engine.ts @@ -0,0 +1,1023 @@ +import { IPosition } from '../../../../common'; +import { ISimulationNode, ISimulationGraph, ISimulationIds, SimulatorEventType } from '../../../shared'; +import { copyObject, isObjectEqual } from '../../../../utils/object.utils'; +import { + IEngineSettingsUpdate, + IForceLayoutOptions, + DEFAULT_FORCE_LAYOUT_OPTIONS, + LayoutType, + getManyBodyMaxDistance, +} from '../../shared'; +import { BaseLayoutEngine } from '../base-layout-engine'; +import { compileShader, ShaderType } from '../../../../utils/shaders.utils'; +import forceVertSource from '../../shaders/force/force.vert'; +import forceFragSource from '../../shaders/force/force.frag'; +import { OrbError } from '../../../../exceptions'; +import { buildQuadTree } from '../../utils/quadtree-builder'; +import { buildAdjacency, IAdjacencyResult } from '../../utils/adjacency-builder'; + +const MAX_SIMULATION_STEPS = 500; +const CHUNK_SIZE = 1; + +export class GPUForceLayoutEngine extends BaseLayoutEngine { + private readonly _gl: WebGL2RenderingContext; + + private _settings: IForceLayoutOptions; + private _initialSettings: IForceLayoutOptions | undefined; + + private _isStabilizing = false; + private _isDragging = false; + private _dragLoopRunning = false; + private _pendingRestart = false; + private _simulationGeneration = 0; + + private _currentAlpha = 0; + private _currentStep = 0; + private _totalSteps = 0; + + private _dragAlpha = 0; + private _dragNeedsReheat = false; + + private _dirtyNodes: Set = new Set(); + + private _forceProgram: WebGLProgram | null = null; + private _quadBuffer: WebGLBuffer | null = null; + private _quadVAO: WebGLVertexArrayObject | null = null; + + private _stateTexA: WebGLTexture | null = null; + private _stateTexB: WebGLTexture | null = null; + private _fixedTex: WebGLTexture | null = null; + private _fboA: WebGLFramebuffer | null = null; + private _fboB: WebGLFramebuffer | null = null; + private _texWidth = 0; + + private _treeDataTexture: WebGLTexture | null = null; + private _treeChildrenTexture: WebGLTexture | null = null; + private _treeGeometryTexture: WebGLTexture | null = null; + private _adjOffsetsTexture: WebGLTexture | null = null; + private _adjEdgesTexture: WebGLTexture | null = null; + + private _cachedAdjacency: IAdjacencyResult | null = null; + private _treeTexWidth = 1; + private _treeNodeCount = 0; + + private _pingPong = true; + + private _uniforms: Record = {}; + + readonly type: LayoutType = 'force'; + + constructor(options?: IForceLayoutOptions) { + super(); + this._settings = { + ...DEFAULT_FORCE_LAYOUT_OPTIONS, + ...options, + }; + + const gl = document.createElement('canvas').getContext('webgl2'); + if (!gl) { + throw new OrbError('Failed to create WebGL2 context for GPU force layout engine.'); + } + this._gl = gl; + + this._initGPU(); + this.clearData(); + } + + setSettings(settings: IEngineSettingsUpdate) { + const forceSettings = settings as Partial; + + if (!this._initialSettings) { + this._initialSettings = Object.assign(copyObject(DEFAULT_FORCE_LAYOUT_OPTIONS), forceSettings); + } + + const previousSettings = copyObject(this._settings); + Object.assign(this._settings, forceSettings); + + if (isObjectEqual(this._settings, previousSettings)) { + return; + } + + this.emit(SimulatorEventType.SETTINGS_UPDATE, { + settings: { type: 'force', options: this._settings }, + }); + + const hasPhysicsBeenDisabled = previousSettings.isPhysicsEnabled && !forceSettings.isPhysicsEnabled; + + if (hasPhysicsBeenDisabled) { + this.stopSimulation(); + } else if (this._settings.isSimulatingOnSettingsUpdate && this._nodes.length > 0) { + this.activateSimulation(); + } + } + + setupData(data: ISimulationGraph) { + this.clearData(); + this._initializeNewData(data); + + if (this._settings.isSimulatingOnDataUpdate) { + this._runSimulation(); + } + } + + mergeData(data: ISimulationGraph) { + this._initializeNewData(data); + + if (!this._settings.isPhysicsEnabled) { + this._pinNodes(); + } + + if (this._settings.isSimulatingOnDataUpdate) { + this.activateSimulation(); + } + } + + updateData(data: ISimulationGraph) { + const newNodeIds = new Set(data.nodes.map((node) => node.id)); + const oldNodes = this._nodes.filter((node) => newNodeIds.has(node.id)); + const newNodes = data.nodes.filter((node) => this._nodeIndexByNodeId[node.id] === undefined); + + this._nodes = [...oldNodes, ...newNodes]; + this._rebuildNodeIndex(); + this._edges = data.edges; + this._cachedAdjacency = null; + + if (this._settings.isSimulatingOnSettingsUpdate) { + this.activateSimulation(); + } + } + + deleteData(data: Partial) { + if (data.nodeIds) { + const nodeIds = new Set(data.nodeIds); + this._nodes = this._nodes.filter((node) => !nodeIds.has(node.id)); + } + if (data.edgeIds) { + const edgeIds = new Set(data.edgeIds); + this._edges = this._edges.filter((edge) => !edgeIds.has(edge.id)); + } + this._rebuildNodeIndex(); + this._cachedAdjacency = null; + + if (this._settings.isSimulatingOnDataUpdate) { + this.activateSimulation(); + } + } + + patchData(data: Partial) { + if (data.nodes) { + const nodeIds: { [id: number]: number } = {}; + + for (let i = 0; i < this._nodes.length; i++) { + nodeIds[this._nodes[i].id] = i; + } + + for (let i = 0; i < data.nodes.length; i += 1) { + const nodeId: number = data.nodes[i].id; + + if (nodeId in nodeIds) { + const index = nodeIds[nodeId]; + this._nodeIndexByNodeId[nodeId] = index; + this._nodes[index] = data.nodes[i]; + } else { + this._nodes.push(data.nodes[i]); + } + } + } + + if (data.edges) { + const edgeIds: { [id: number]: number } = {}; + for (let i = 0; i < this._edges.length; i++) { + edgeIds[this._edges[i].id] = i; + } + for (let i = 0; i < data.edges.length; i++) { + const edgeId = data.edges[i].id; + if (edgeId in edgeIds) { + this._edges[edgeIds[edgeId]] = data.edges[i]; + } else { + this._edges.push(data.edges[i]); + } + } + } + } + + clearData() { + this._nodes = []; + this._edges = []; + this._rebuildNodeIndex(); + this._cachedAdjacency = null; + } + + activateSimulation() { + if (this._settings.isPhysicsEnabled) { + this._unpinNodes(); + } else { + this._pinNodes(); + } + + if (this._isStabilizing) { + this._pendingRestart = true; + return; + } + + this._ensurePositions(); + this._uploadDataToGPU(); + if (!this._cachedAdjacency) { + this._buildAndUploadAdjacency(); + } + + this._startSimulationLoop(); + } + + stopSimulation() { + if (this._isStabilizing) { + this._cancelSimulation = true; + } + // Don't set flag when nothing is running — it would linger and block future simulations + } + + startDragNode() { + this._isDragging = true; + + // Stop the full simulation if running — drag uses its own lightweight loop + if (this._isStabilizing) { + this._cancelSimulation = true; + } + + if (this._settings.isPhysicsEnabled) { + this._startDragLoop(); + } + } + + dragNode(nodeId: number, position: IPosition) { + const nodeIndex = this._nodeIndexByNodeId[nodeId]; + const node = this._nodes[nodeIndex]; + if (!node) { + return; + } + + if (!this._isDragging) { + this.startDragNode(); + } + + node.fx = position.x; + node.fy = position.y; + + if (!this._settings.isPhysicsEnabled) { + node.x = position.x; + node.y = position.y; + } + + this._dirtyNodes.add(nodeIndex); + this._dragNeedsReheat = true; + + this.emit(SimulatorEventType.NODE_DRAG, { nodes: this._nodes, edges: this._edges }); + } + + endDragNode(nodeId: number) { + this._isDragging = false; + + const node = this._nodes[this._nodeIndexByNodeId[nodeId]]; + if (node && this._settings.isPhysicsEnabled) { + this._unpinNode(node); + const nodeIndex = this._nodeIndexByNodeId[nodeId]; + this._dirtyNodes.add(nodeIndex); + } + } + + fixNodes(nodes?: ISimulationNode[]) { + if (!nodes) { + nodes = this._nodes; + } + for (let i = 0; i < nodes.length; i++) { + this._stickNode(nodes[i]); + } + } + + releaseNodes(nodes?: ISimulationNode[]) { + if (!nodes) { + nodes = this._nodes; + } + for (let i = 0; i < nodes.length; i++) { + this._unstickNode(nodes[i]); + } + + if (this._settings.isSimulatingOnUnstick && this._nodes.length > 0) { + this.activateSimulation(); + } + } + + terminate(): void { + super.terminate(); + + const gl = this._gl; + if (!gl) { + return; + } + + gl.deleteBuffer(this._quadBuffer); + gl.deleteVertexArray(this._quadVAO); + gl.deleteProgram(this._forceProgram); + gl.deleteTexture(this._stateTexA); + gl.deleteTexture(this._stateTexB); + gl.deleteTexture(this._fixedTex); + gl.deleteTexture(this._treeDataTexture); + gl.deleteTexture(this._treeChildrenTexture); + gl.deleteTexture(this._treeGeometryTexture); + gl.deleteTexture(this._adjOffsetsTexture); + gl.deleteTexture(this._adjEdgesTexture); + gl.deleteFramebuffer(this._fboA); + gl.deleteFramebuffer(this._fboB); + gl.getExtension('WEBGL_lose_context')?.loseContext(); + } + + reheat() { + const alphaSettings = this._settings.alpha; + + this._currentAlpha = alphaSettings.alpha; + this._totalSteps = Math.min( + MAX_SIMULATION_STEPS, + Math.ceil(Math.log(alphaSettings.alphaMin) / Math.log(1 - alphaSettings.alphaDecay)), + ); + this._currentStep = 0; + + if (this._isStabilizing) { + return; + } + + this._ensurePositions(); + this._uploadDataToGPU(); + if (!this._cachedAdjacency) { + this._buildAndUploadAdjacency(); + } + this._startSimulationLoop(); + } + + private _runSimulation(): void { + if (this._isStabilizing || this._cancelSimulation) { + return; + } + + this._ensurePositions(); + this._uploadDataToGPU(); + this._buildAndUploadAdjacency(); + this._startSimulationLoop(); + } + + private _startDragLoop(): void { + if (this._dragLoopRunning) { + return; + } + this._dragLoopRunning = true; + + const alphaDecay = this._settings.alpha.alphaDecay; + const alphaMin = this._settings.alpha.alphaMin; + + this._dragAlpha = 0.3; + this._dragNeedsReheat = false; + + const tick = () => { + if (!this._isDragging) { + this._dragLoopRunning = false; + return; + } + + if (this._dragNeedsReheat) { + this._dragAlpha = 0.3; + this._dragNeedsReheat = false; + } + + this._dragAlpha += (0 - this._dragAlpha) * alphaDecay; + + if (this._dragAlpha < alphaMin) { + requestAnimationFrame(tick); + return; + } + + this._readbackFromGPU(); + this._flushDirtyNodes(); + this._buildAndUploadQuadTree(); + + this._simulateGPUStep(this._dragAlpha); + + this._readbackFromGPU(); + this._applyCentering(); + + this.emit(SimulatorEventType.NODE_DRAG, { nodes: this._nodes, edges: this._edges }); + + requestAnimationFrame(tick); + }; + + requestAnimationFrame(tick); + } + + private _startSimulationLoop(): void { + if (this._isStabilizing || this._cancelSimulation) { + return; + } + + this.emit(SimulatorEventType.SIMULATION_START, undefined); + this._isStabilizing = true; + this._pendingRestart = false; + const generation = ++this._simulationGeneration; + + const alphaSettings = this._settings.alpha; + const alphaMin = alphaSettings.alphaMin; + const alphaDecay = alphaSettings.alphaDecay; + + this._currentAlpha = alphaSettings.alpha; + this._totalSteps = Math.min(MAX_SIMULATION_STEPS, Math.ceil(Math.log(alphaMin) / Math.log(1 - alphaDecay))); + this._currentStep = 0; + + let lastProgress = -1; + + const runChunk = () => { + if (generation !== this._simulationGeneration) { + return; + } + + if (this._cancelSimulation) { + this._isStabilizing = false; + this._cancelSimulation = false; + this.emit(SimulatorEventType.SIMULATION_END, { nodes: this._nodes, edges: this._edges }); + return; + } + + this._readbackFromGPU(); + + if (this._pendingRestart) { + this._isStabilizing = false; + this._pendingRestart = false; + this._ensurePositions(); + this._uploadDataToGPU(); + if (!this._cachedAdjacency) { + this._buildAndUploadAdjacency(); + } + this._startSimulationLoop(); + return; + } + + this._flushDirtyNodes(); + this._buildAndUploadQuadTree(); + + const end = Math.min(this._currentStep + CHUNK_SIZE, this._totalSteps); + + for (; this._currentStep < end; this._currentStep++) { + this._currentAlpha += (alphaSettings.alphaTarget - this._currentAlpha) * alphaDecay; + if (this._currentAlpha < alphaMin || this._cancelSimulation) { + this._currentStep = this._totalSteps; + break; + } + this._simulateGPUStep(this._currentAlpha); + } + + this._readbackFromGPU(); + this._applyCentering(); + + const currentProgress = Math.round((this._currentStep * 100) / this._totalSteps); + if (currentProgress > lastProgress) { + lastProgress = currentProgress; + this.emit(SimulatorEventType.SIMULATION_PROGRESS, { + nodes: this._nodes, + edges: this._edges, + progress: currentProgress / 100, + }); + } + + if (this._currentStep < this._totalSteps && !this._cancelSimulation) { + this._scheduleNext(runChunk); + } else { + if (!this._settings.isPhysicsEnabled) { + this._pinNodes(); + } + + this._isStabilizing = false; + this._cancelSimulation = false; + this.emit(SimulatorEventType.SIMULATION_END, { nodes: this._nodes, edges: this._edges }); + } + }; + + this._scheduleNext(runChunk); + } + + private _ensurePositions(): void { + const linkDist = this._settings.links?.distance ?? 50; + const spread = linkDist * Math.sqrt(this._nodes.length); + for (const node of this._nodes) { + if (node.x === undefined || node.x === null) { + node.x = (Math.random() - 0.5) * spread; + } + if (node.y === undefined || node.y === null) { + node.y = (Math.random() - 0.5) * spread; + } + } + } + + private _applyCentering(): void { + const c = this._settings.centering; + if (!c) { + return; + } + const N = this._nodes.length; + if (N === 0) { + return; + } + let sx = 0; + let sy = 0; + for (let i = 0; i < N; i++) { + sx += this._nodes[i].x ?? 0; + sy += this._nodes[i].y ?? 0; + } + const dx = (sx / N - c.x) * c.strength; + const dy = (sy / N - c.y) * c.strength; + if (Math.abs(dx) < 1e-6 && Math.abs(dy) < 1e-6) { + return; + } + for (let i = 0; i < N; i++) { + const node = this._nodes[i]; + // Don't shift fixed/dragged nodes — their position must stay at fx/fy + if (node.fx !== null && node.fx !== undefined) { + continue; + } + node.x = (node.x ?? 0) - dx; + node.y = (node.y ?? 0) - dy; + } + + this._syncStateToGPU(); + } + + private _syncStateToGPU(): void { + const N = this._nodes.length; + if (N === 0) { + return; + } + + const texSize = this._texWidth * this._texWidth; + const stateData = new Float32Array(texSize * 4); + + for (let i = 0; i < N; i++) { + const node = this._nodes[i]; + const off = i * 4; + stateData[off] = node.x ?? 0; + stateData[off + 1] = node.y ?? 0; + stateData[off + 2] = node.vx ?? 0; + stateData[off + 3] = node.vy ?? 0; + } + + this._uploadTexture(this._stateTexA!, stateData, this._texWidth); + this._uploadTexture(this._stateTexB!, stateData, this._texWidth); + this._pingPong = true; + } + + private _flushDirtyNodes(): void { + if (this._dirtyNodes.size === 0) { + return; + } + + const gl = this._gl; + + for (const nodeIndex of this._dirtyNodes) { + const node = this._nodes[nodeIndex]; + if (!node) { + continue; + } + + const col = nodeIndex % this._texWidth; + const row = Math.floor(nodeIndex / this._texWidth); + + const statePixel = new Float32Array([node.x ?? 0, node.y ?? 0, node.vx ?? 0, node.vy ?? 0]); + + gl.bindTexture(gl.TEXTURE_2D, this._stateTexA); + gl.texSubImage2D(gl.TEXTURE_2D, 0, col, row, 1, 1, gl.RGBA, gl.FLOAT, statePixel); + gl.bindTexture(gl.TEXTURE_2D, this._stateTexB); + gl.texSubImage2D(gl.TEXTURE_2D, 0, col, row, 1, 1, gl.RGBA, gl.FLOAT, statePixel); + + const fixedPixel = new Float32Array([ + node.fx !== null && node.fx !== undefined ? 1.0 : 0.0, + node.fx ?? node.x ?? 0, + node.fy ?? node.y ?? 0, + 0.0, + ]); + + gl.bindTexture(gl.TEXTURE_2D, this._fixedTex); + gl.texSubImage2D(gl.TEXTURE_2D, 0, col, row, 1, 1, gl.RGBA, gl.FLOAT, fixedPixel); + } + + this._dirtyNodes.clear(); + } + + private _buildAndUploadQuadTree(): void { + const N = this._nodes.length; + if (N === 0) { + return; + } + + const strength = this._settings.manyBody?.strength ?? -100; + + let positions: { x: number; y: number }[] = this._nodes as { x: number; y: number }[]; + if (this._settings.manyBody?.edgeMidpointRepulsion) { + const edgeMidpoints = this._getEdgeMidpoints(); + if (edgeMidpoints.length > 0) { + positions = positions.concat(edgeMidpoints); + } + } + + const tree = buildQuadTree(positions, strength); + + this._uploadTexture(this._treeDataTexture!, tree.treeData, tree.texWidth); + this._uploadTexture(this._treeChildrenTexture!, tree.treeChildren, tree.texWidth); + this._uploadTexture(this._treeGeometryTexture!, tree.treeGeometry, tree.texWidth); + + this._treeTexWidth = tree.texWidth; + this._treeNodeCount = tree.nodeCount; + } + + private _getEdgeMidpoints(): { x: number; y: number }[] { + const midpoints: { x: number; y: number }[] = []; + for (let i = 0; i < this._edges.length; i++) { + const edge = this._edges[i]; + const srcId = typeof edge.source === 'object' ? (edge.source as ISimulationNode).id : (edge.source as number); + const tgtId = typeof edge.target === 'object' ? (edge.target as ISimulationNode).id : (edge.target as number); + const srcIdx = this._nodeIndexByNodeId[srcId]; + const tgtIdx = this._nodeIndexByNodeId[tgtId]; + if (srcIdx === undefined || tgtIdx === undefined) { + continue; + } + const src = this._nodes[srcIdx]; + const tgt = this._nodes[tgtIdx]; + midpoints.push({ + x: ((src.x ?? 0) + (tgt.x ?? 0)) * 0.5, + y: ((src.y ?? 0) + (tgt.y ?? 0)) * 0.5, + }); + } + return midpoints; + } + + private _buildAndUploadAdjacency(): void { + const N = this._nodes.length; + if (N === 0) { + return; + } + + const linkDist = this._settings.links?.distance ?? 50; + const adj = buildAdjacency(this._nodes, this._edges, linkDist, undefined); + this._cachedAdjacency = adj; + + this._uploadTexture(this._adjOffsetsTexture!, adj.offsets, adj.offsetsTexWidth); + this._uploadTexture(this._adjEdgesTexture!, adj.edges, adj.edgesTexWidth); + } + + private _pinNodes(nodes?: ISimulationNode[]) { + if (!nodes) { + nodes = this._nodes; + } + for (let i = 0; i < nodes.length; i++) { + this._pinNode(this._nodes[i]); + } + } + + private _unpinNodes(nodes?: ISimulationNode[]) { + if (!nodes) { + nodes = this._nodes; + } + for (let i = 0; i < nodes.length; i++) { + this._unpinNode(this._nodes[i]); + } + } + + private _pinNode(node: ISimulationNode) { + if (node.sx === null || node.sx === undefined) { + node.fx = node.x; + } + if (node.sy === null || node.sy === undefined) { + node.fy = node.y; + } + } + + private _unpinNode(node: ISimulationNode) { + if (node.sx === null || node.sx === undefined) { + node.fx = null; + } + if (node.sy === null || node.sy === undefined) { + node.fy = null; + } + } + + private _stickNode(node: ISimulationNode) { + node.sx = node.x; + node.fx = node.x; + node.sy = node.y; + node.fy = node.y; + } + + private _unstickNode(node: ISimulationNode) { + node.sx = null; + node.sy = null; + + if (this._settings.isPhysicsEnabled) { + node.fx = null; + node.fy = null; + } + } + + private _initializeNewData(data: Partial) { + if (data.nodes) { + for (let i = 0; i < data.nodes.length; i += 1) { + const nodeId = data.nodes[i].id; + + if (this._nodeIndexByNodeId[nodeId] !== undefined) { + this._nodeIndexByNodeId[nodeId] = i; + } else { + this._nodes.push(data.nodes[i]); + } + } + } else { + this._nodes = []; + } + + if (data.edges) { + const edgeIds: { [id: number]: number } = {}; + for (let i = 0; i < this._edges.length; i++) { + edgeIds[this._edges[i].id] = i; + } + for (let i = 0; i < data.edges.length; i++) { + const edgeId = data.edges[i].id; + if (edgeId in edgeIds) { + this._edges[edgeIds[edgeId]] = data.edges[i]; + } else { + this._edges.push(data.edges[i]); + } + } + } else { + this._edges = []; + } + + this._rebuildNodeIndex(); + this._cachedAdjacency = null; + } + + private _initGPU(): void { + const gl = this._gl; + + gl.getExtension('EXT_color_buffer_float'); + + const vs = compileShader(gl, forceVertSource, ShaderType.VERTEX); + const fs = compileShader(gl, forceFragSource, ShaderType.FRAGMENT); + const program = gl.createProgram(); + if (!program) { + throw new OrbError('Failed to create program.'); + } + this._forceProgram = program; + + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + const info = gl.getProgramInfoLog(program); + throw new OrbError(`Failed to link force program: ${info}`); + } + + this._cacheUniformLocations(program); + + this._quadBuffer = gl.createBuffer(); + const quadVerts = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]); + gl.bindBuffer(gl.ARRAY_BUFFER, this._quadBuffer); + gl.bufferData(gl.ARRAY_BUFFER, quadVerts, gl.STATIC_DRAW); + + this._quadVAO = gl.createVertexArray(); + gl.bindVertexArray(this._quadVAO); + const posLoc = gl.getAttribLocation(program, 'aPosition'); + gl.enableVertexAttribArray(posLoc); + gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0); + gl.bindVertexArray(null); + + this._stateTexA = gl.createTexture(); + this._stateTexB = gl.createTexture(); + this._fixedTex = gl.createTexture(); + this._treeDataTexture = gl.createTexture(); + this._treeChildrenTexture = gl.createTexture(); + this._treeGeometryTexture = gl.createTexture(); + this._adjOffsetsTexture = gl.createTexture(); + this._adjEdgesTexture = gl.createTexture(); + + this._fboA = gl.createFramebuffer(); + this._fboB = gl.createFramebuffer(); + } + + private _cacheUniformLocations(program: WebGLProgram): void { + const gl = this._gl; + const names = [ + 'uState', + 'uFixed', + 'uTreeData', + 'uTreeChildren', + 'uTreeGeometry', + 'uAdjOffsets', + 'uAdjEdges', + 'uNodeCount', + 'uTexWidth', + 'uAlpha', + 'uDamping', + 'uManyBodyStrength', + 'uTheta2', + 'uDistanceMin2', + 'uDistanceMax2', + 'uTreeNodeCount', + 'uTreeTexWidth', + 'uAdjOffsetsTexWidth', + 'uAdjEdgesTexWidth', + 'uCenter', + 'uCenterStrength', + 'uCollisionRadius', + 'uCollisionStrength', + 'uForceXTarget', + 'uForceXStrength', + 'uForceYTarget', + 'uForceYStrength', + 'uHasManyBody', + 'uHasLinks', + 'uHasCentering', + 'uHasCollision', + 'uHasPositioning', + ]; + for (const name of names) { + this._uniforms[name] = gl.getUniformLocation(program, name); + } + } + + private _uploadDataToGPU(): void { + const gl = this._gl; + const N = this._nodes.length; + + this._texWidth = Math.max(1, Math.ceil(Math.sqrt(N))); + const texSize = this._texWidth * this._texWidth; + + const stateData = new Float32Array(texSize * 4); + const fixedData = new Float32Array(texSize * 4); + + for (let i = 0; i < N; i++) { + const node = this._nodes[i]; + const off = i * 4; + stateData[off] = node.x ?? 0; + stateData[off + 1] = node.y ?? 0; + stateData[off + 2] = node.vx ?? 0; + stateData[off + 3] = node.vy ?? 0; + + fixedData[off] = node.fx !== null && node.fx !== undefined ? 1.0 : 0.0; + fixedData[off + 1] = node.fx ?? node.x ?? 0; + fixedData[off + 2] = node.fy ?? node.y ?? 0; + fixedData[off + 3] = 0.0; + } + + this._uploadTexture(this._stateTexA!, stateData, this._texWidth); + this._uploadTexture(this._stateTexB!, stateData, this._texWidth); + this._uploadTexture(this._fixedTex!, fixedData, this._texWidth); + + gl.bindFramebuffer(gl.FRAMEBUFFER, this._fboA); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._stateTexA, 0); + gl.bindFramebuffer(gl.FRAMEBUFFER, this._fboB); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._stateTexB, 0); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + this._pingPong = true; + } + + private _uploadTexture(texture: WebGLTexture, data: Float32Array, texWidth: number): void { + const gl = this._gl; + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, texWidth, texWidth, 0, gl.RGBA, gl.FLOAT, data); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + + private _simulateGPUStep(alpha: number): void { + const gl = this._gl; + const program = this._forceProgram; + if (!program) { + throw new OrbError('Force program not initialized.'); + } + const N = this._nodes.length; + if (N === 0) { + return; + } + + gl.useProgram(program); + + const u = this._uniforms; + + gl.uniform1i(u['uNodeCount'], N); + gl.uniform1i(u['uTexWidth'], this._texWidth); + gl.uniform1f(u['uAlpha'], alpha); + gl.uniform1f(u['uDamping'], 0.6); + + const hasManyBody = this._settings.manyBody !== null && this._settings.manyBody !== undefined; + gl.uniform1f(u['uHasManyBody'], hasManyBody ? 1.0 : 0.0); + if (hasManyBody) { + const mb = this._settings.manyBody!; + gl.uniform1f(u['uManyBodyStrength'], mb.strength); + const theta = mb.theta; + gl.uniform1f(u['uTheta2'], theta * theta); + gl.uniform1f(u['uDistanceMin2'], mb.distanceMin * mb.distanceMin); + const dMax = mb.distanceMax > 0 ? mb.distanceMax : getManyBodyMaxDistance(this._settings.links?.distance ?? 50); + gl.uniform1f(u['uDistanceMax2'], dMax * dMax); + gl.uniform1i(u['uTreeNodeCount'], this._treeNodeCount); + gl.uniform1i(u['uTreeTexWidth'], this._treeTexWidth); + } + + const hasLinks = this._cachedAdjacency !== null && this._edges.length > 0; + gl.uniform1f(u['uHasLinks'], hasLinks ? 1.0 : 0.0); + if (hasLinks) { + gl.uniform1i(u['uAdjOffsetsTexWidth'], this._cachedAdjacency!.offsetsTexWidth); + gl.uniform1i(u['uAdjEdgesTexWidth'], this._cachedAdjacency!.edgesTexWidth); + } + + gl.uniform1f(u['uHasCentering'], 0.0); + + const hasCollision = this._settings.collision !== null && this._settings.collision !== undefined; + gl.uniform1f(u['uHasCollision'], hasCollision ? 1.0 : 0.0); + if (hasCollision) { + gl.uniform1f(u['uCollisionRadius'], this._settings.collision!.radius); + gl.uniform1f(u['uCollisionStrength'], this._settings.collision!.strength); + } + + const hasPositioning = this._settings.positioning !== null && this._settings.positioning !== undefined; + gl.uniform1f(u['uHasPositioning'], hasPositioning ? 1.0 : 0.0); + if (hasPositioning) { + const pos = this._settings.positioning!; + gl.uniform1f(u['uForceXTarget'], pos.forceX?.x ?? 0); + gl.uniform1f(u['uForceXStrength'], pos.forceX?.strength ?? 0); + gl.uniform1f(u['uForceYTarget'], pos.forceY?.y ?? 0); + gl.uniform1f(u['uForceYStrength'], pos.forceY?.strength ?? 0); + } + + const readStateTex = this._pingPong ? this._stateTexA : this._stateTexB; + const writeFBO = this._pingPong ? this._fboB : this._fboA; + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, readStateTex); + gl.uniform1i(u['uState'], 0); + + gl.activeTexture(gl.TEXTURE1); + gl.bindTexture(gl.TEXTURE_2D, this._fixedTex); + gl.uniform1i(u['uFixed'], 1); + + gl.activeTexture(gl.TEXTURE2); + gl.bindTexture(gl.TEXTURE_2D, this._treeDataTexture); + gl.uniform1i(u['uTreeData'], 2); + + gl.activeTexture(gl.TEXTURE3); + gl.bindTexture(gl.TEXTURE_2D, this._treeChildrenTexture); + gl.uniform1i(u['uTreeChildren'], 3); + + gl.activeTexture(gl.TEXTURE4); + gl.bindTexture(gl.TEXTURE_2D, this._adjOffsetsTexture); + gl.uniform1i(u['uAdjOffsets'], 4); + + gl.activeTexture(gl.TEXTURE5); + gl.bindTexture(gl.TEXTURE_2D, this._adjEdgesTexture); + gl.uniform1i(u['uAdjEdges'], 5); + + gl.activeTexture(gl.TEXTURE6); + gl.bindTexture(gl.TEXTURE_2D, this._treeGeometryTexture); + gl.uniform1i(u['uTreeGeometry'], 6); + + gl.bindFramebuffer(gl.FRAMEBUFFER, writeFBO); + gl.viewport(0, 0, this._texWidth, this._texWidth); + + gl.bindVertexArray(this._quadVAO); + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); + gl.bindVertexArray(null); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + this._pingPong = !this._pingPong; + } + + private _readbackFromGPU(): void { + const gl = this._gl; + const N = this._nodes.length; + if (N === 0) { + return; + } + + const readFBO = this._pingPong ? this._fboA : this._fboB; + const texSize = this._texWidth * this._texWidth; + const data = new Float32Array(texSize * 4); + + gl.bindFramebuffer(gl.FRAMEBUFFER, readFBO); + gl.readPixels(0, 0, this._texWidth, this._texWidth, gl.RGBA, gl.FLOAT, data); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + for (let i = 0; i < N; i++) { + const node = this._nodes[i]; + const off = i * 4; + node.x = data[off]; + node.y = data[off + 1]; + node.vx = data[off + 2]; + node.vy = data[off + 3]; + } + } +} diff --git a/src/simulator/engine/factory.ts b/src/simulator/engine/factory.ts index aa1e058..2897d64 100644 --- a/src/simulator/engine/factory.ts +++ b/src/simulator/engine/factory.ts @@ -7,6 +7,7 @@ import { IForceLayoutOptions, } from './shared'; import { ForceLayoutEngine } from './engines/dynamic/force-layout-engine'; +import { GPUForceLayoutEngine } from './engines/dynamic/gpu-force-layout-engine'; import { CircularLayoutEngine } from './engines/static/circular-layout-engine'; import { GridLayoutEngine } from './engines/static/grid-layout-engine'; import { HierarchicalLayoutEngine } from './engines/static/hierarchical-layout-engine'; @@ -22,8 +23,18 @@ export class LayoutEngineFactory { case 'hierarchical': return new HierarchicalLayoutEngine(settings.options as IHierarchicalLayoutOptions); case 'force': - default: - return new ForceLayoutEngine(settings?.options as IForceLayoutOptions); + default: { + const forceOptions = settings?.options as IForceLayoutOptions | undefined; + if (forceOptions?.useGPU) { + try { + return new GPUForceLayoutEngine(forceOptions); + } catch { + console.warn('WebGL2 unavailable, falling back to CPU force layout engine.'); + return new ForceLayoutEngine(forceOptions); + } + } + return new ForceLayoutEngine(forceOptions); + } } } } diff --git a/src/simulator/engine/shaders/force/force.frag b/src/simulator/engine/shaders/force/force.frag new file mode 100644 index 0000000..b7bb64b --- /dev/null +++ b/src/simulator/engine/shaders/force/force.frag @@ -0,0 +1,197 @@ +#version 300 es + +precision highp float; + +uniform sampler2D uState; +uniform sampler2D uFixed; +uniform sampler2D uTreeData; +uniform sampler2D uTreeChildren; +uniform sampler2D uTreeGeometry; +uniform sampler2D uAdjOffsets; +uniform sampler2D uAdjEdges; + +uniform int uNodeCount; +uniform int uTexWidth; +uniform float uAlpha; +uniform float uDamping; + +uniform float uManyBodyStrength; +uniform float uTheta2; +uniform float uDistanceMin2; +uniform float uDistanceMax2; +uniform int uTreeNodeCount; +uniform int uTreeTexWidth; + +uniform int uAdjOffsetsTexWidth; +uniform int uAdjEdgesTexWidth; + +uniform vec2 uCenter; +uniform float uCenterStrength; + +uniform float uCollisionRadius; +uniform float uCollisionStrength; + +uniform float uForceXTarget; +uniform float uForceXStrength; +uniform float uForceYTarget; +uniform float uForceYStrength; + +uniform float uHasManyBody; +uniform float uHasLinks; +uniform float uHasCentering; +uniform float uHasCollision; +uniform float uHasPositioning; + +out vec4 fragColor; + +ivec2 texCoord(int idx, int tw) { + return ivec2(idx % tw, idx / tw); +} + +void main() { + ivec2 fc = ivec2(gl_FragCoord.xy); + int nodeId = fc.y * uTexWidth + fc.x; + + if (nodeId >= uNodeCount) { + fragColor = vec4(0.0); + return; + } + + vec4 fixedData = texelFetch(uFixed, fc, 0); + if (fixedData.x > 0.5) { + fragColor = vec4(fixedData.yz, 0.0, 0.0); + return; + } + + vec4 state = texelFetch(uState, fc, 0); + vec2 pos = state.xy; + vec2 vel = state.zw; + + if (uHasManyBody > 0.5 && uTreeNodeCount > 0) { + int stack[128]; + int top = 0; + stack[top++] = 0; + + while (top > 0) { + int idx = stack[--top]; + vec4 data = texelFetch(uTreeData, texCoord(idx, uTreeTexWidth), 0); + float w = data.w; + + if (w < -0.5) { + int bodyIdx = int(-w - 0.5); + if (bodyIdx != nodeId) { + vec2 delta = data.xy - pos; + float distSq = dot(delta, delta); + + if (distSq < 1e-8) { + delta = vec2(float(nodeId) * 1e-4 - float(bodyIdx) * 1e-4 + 1e-4, 1e-4); + distSq = dot(delta, delta); + } + + if (distSq < uDistanceMax2) { + float l = distSq; + if (l < uDistanceMin2) l = sqrt(uDistanceMin2 * l); + vel += delta * (data.z * uAlpha / max(l, 1e-6)); + } + } + } else { + vec2 delta = data.xy - pos; + float distSq = dot(delta, delta); + + if (distSq > 0.0 && w * w / distSq < uTheta2) { + if (distSq < uDistanceMax2) { + float l = distSq; + if (l < uDistanceMin2) l = sqrt(uDistanceMin2 * l); + vel += delta * (data.z * uAlpha / max(l, 1e-6)); + } + } else { + vec4 ch = texelFetch(uTreeChildren, texCoord(idx, uTreeTexWidth), 0); + if (ch.w >= 0.0 && top < 64) stack[top++] = int(ch.w + 0.5); + if (ch.z >= 0.0 && top < 64) stack[top++] = int(ch.z + 0.5); + if (ch.y >= 0.0 && top < 64) stack[top++] = int(ch.y + 0.5); + if (ch.x >= 0.0 && top < 64) stack[top++] = int(ch.x + 0.5); + } + } + } + } + + if (uHasCollision > 0.5 && uCollisionRadius > 0.0 && uTreeNodeCount > 0) { + float collisionDiam = uCollisionRadius * 2.0; + vec2 predictedPos = state.xy + state.zw; + int stack[64]; + int top = 0; + stack[top++] = 0; + + while (top > 0) { + int idx = stack[--top]; + vec4 data = texelFetch(uTreeData, texCoord(idx, uTreeTexWidth), 0); + float w = data.w; + + if (w < -0.5) { + int bodyIdx = int(-w - 0.5); + if (bodyIdx != nodeId && bodyIdx < uNodeCount) { + vec2 delta = data.xy - predictedPos; + float dist = length(delta); + + if (dist < collisionDiam && dist > 0.0) { + float push = (collisionDiam - dist) * uCollisionStrength; + vel -= (delta / dist) * push * 0.5; + } + } + } else { + vec4 geo = texelFetch(uTreeGeometry, texCoord(idx, uTreeTexWidth), 0); + float cellSize = geo.z; + vec2 nearest = clamp(predictedPos, geo.xy, geo.xy + cellSize); + float distToCell = length(nearest - predictedPos); + + if (distToCell < collisionDiam) { + vec4 ch = texelFetch(uTreeChildren, texCoord(idx, uTreeTexWidth), 0); + if (ch.w >= 0.0 && top < 64) stack[top++] = int(ch.w + 0.5); + if (ch.z >= 0.0 && top < 64) stack[top++] = int(ch.z + 0.5); + if (ch.y >= 0.0 && top < 64) stack[top++] = int(ch.y + 0.5); + if (ch.x >= 0.0 && top < 64) stack[top++] = int(ch.x + 0.5); + } + } + } + } + + if (uHasLinks > 0.5) { + vec4 offData = texelFetch(uAdjOffsets, texCoord(nodeId, uAdjOffsetsTexWidth), 0); + int start = int(offData.x + 0.5); + int count = int(offData.y + 0.5); + + for (int e = 0; e < count; e++) { + vec4 edgeData = texelFetch(uAdjEdges, texCoord(start + e, uAdjEdgesTexWidth), 0); + int targetId = int(edgeData.x + 0.5); + float restDist = edgeData.y; + float strength = edgeData.z; + float dirBias = edgeData.w; + + vec4 targetState = texelFetch(uState, texCoord(targetId, uTexWidth), 0); + vec2 delta = (targetState.xy + targetState.zw) - (state.xy + state.zw); + float d = length(delta); + + if (d < 1e-6) { + delta = vec2(1e-3, 1e-3); + d = length(delta); + } + + float scale = (d - restDist) / d * uAlpha * strength; + vel += delta * scale * dirBias; + } + } + + if (uHasCentering > 0.5) { + vel += (uCenter - pos) * uCenterStrength * uAlpha; + } + + if (uHasPositioning > 0.5) { + vel.x += (uForceXTarget - pos.x) * uForceXStrength * uAlpha; + vel.y += (uForceYTarget - pos.y) * uForceYStrength * uAlpha; + } + + vel *= uDamping; + pos += vel; + + fragColor = vec4(pos, vel); +} diff --git a/src/simulator/engine/shaders/force/force.vert b/src/simulator/engine/shaders/force/force.vert new file mode 100644 index 0000000..63bfe79 --- /dev/null +++ b/src/simulator/engine/shaders/force/force.vert @@ -0,0 +1,7 @@ +#version 300 es + +in vec2 aPosition; + +void main() { + gl_Position = vec4(aPosition, 0.0, 1.0); +} diff --git a/src/simulator/engine/shared.ts b/src/simulator/engine/shared.ts index 4bf5ac1..477d836 100644 --- a/src/simulator/engine/shared.ts +++ b/src/simulator/engine/shared.ts @@ -23,6 +23,7 @@ export const DEFAULT_CIRCULAR_LAYOUT_OPTIONS: ICircularLayoutOptions = { }; export interface IForceLayoutOptions extends ILayoutOptionsBase { + useGPU?: boolean; isSimulatingOnDataUpdate: boolean; isSimulatingOnSettingsUpdate: boolean; isSimulatingOnUnstick: boolean; @@ -44,6 +45,7 @@ export const getManyBodyMaxDistance = (linkDistance: number) => { }; export const DEFAULT_FORCE_LAYOUT_OPTIONS: IForceLayoutOptions = { + useGPU: false, isSimulatingOnDataUpdate: true, isSimulatingOnSettingsUpdate: true, isSimulatingOnUnstick: true, @@ -72,7 +74,7 @@ export const DEFAULT_FORCE_LAYOUT_OPTIONS: IForceLayoutOptions = { manyBody: { strength: -100, theta: 0.9, - distanceMin: 0, + distanceMin: 1, distanceMax: getManyBodyMaxDistance(DEFAULT_LINK_DISTANCE), }, positioning: { @@ -159,6 +161,7 @@ export interface IForceLayoutManyBody { theta: number; distanceMin: number; distanceMax: number; + edgeMidpointRepulsion?: boolean; } export interface IForceLayoutPositioning { diff --git a/src/simulator/engine/utils/adjacency-builder.ts b/src/simulator/engine/utils/adjacency-builder.ts new file mode 100644 index 0000000..3ddfba8 --- /dev/null +++ b/src/simulator/engine/utils/adjacency-builder.ts @@ -0,0 +1,105 @@ +import { ISimulationEdge, ISimulationNode } from '../../shared'; + +export interface IAdjacencyResult { + offsets: Float32Array; + edges: Float32Array; + offsetsTexWidth: number; + edgesTexWidth: number; +} + +export function buildAdjacency( + nodes: ISimulationNode[], + edges: ISimulationEdge[], + linkDistance: number, + linkStrength: number | undefined, +): IAdjacencyResult { + const N = nodes.length; + const nodeIndexById: Record = {}; + for (let i = 0; i < N; i++) { + nodeIndexById[nodes[i].id] = i; + } + + const degree = new Uint32Array(N); + + const resolvedEdges: { srcIdx: number; tgtIdx: number }[] = []; + for (let i = 0; i < edges.length; i++) { + const edge = edges[i]; + const srcId = typeof edge.source === 'object' ? (edge.source as ISimulationNode).id : (edge.source as number); + const tgtId = typeof edge.target === 'object' ? (edge.target as ISimulationNode).id : (edge.target as number); + const srcIdx = nodeIndexById[srcId]; + const tgtIdx = nodeIndexById[tgtId]; + if (srcIdx === undefined || tgtIdx === undefined) { + continue; + } + resolvedEdges.push({ srcIdx, tgtIdx }); + degree[srcIdx]++; + degree[tgtIdx]++; + } + + const totalDirectedEdges = resolvedEdges.length * 2; + + const adjCounts = new Uint32Array(N); + const adjStarts = new Uint32Array(N); + + const tempCounts = new Uint32Array(N); + for (const { srcIdx, tgtIdx } of resolvedEdges) { + tempCounts[srcIdx]++; + tempCounts[tgtIdx]++; + } + + let offset = 0; + for (let i = 0; i < N; i++) { + adjStarts[i] = offset; + adjCounts[i] = tempCounts[i]; + offset += tempCounts[i]; + } + + const edgesData = new Float32Array(totalDirectedEdges * 4); + const writePos = new Uint32Array(N); + for (let i = 0; i < N; i++) { + writePos[i] = adjStarts[i]; + } + + for (const { srcIdx, tgtIdx } of resolvedEdges) { + const bias = degree[srcIdx] / (degree[srcIdx] + degree[tgtIdx]); + const str = linkStrength !== undefined ? linkStrength : 1 / Math.min(degree[srcIdx], degree[tgtIdx]); + + { + const off = writePos[srcIdx] * 4; + edgesData[off] = tgtIdx; + edgesData[off + 1] = linkDistance; + edgesData[off + 2] = str; + edgesData[off + 3] = 1 - bias; + writePos[srcIdx]++; + } + + { + const off = writePos[tgtIdx] * 4; + edgesData[off] = srcIdx; + edgesData[off + 1] = linkDistance; + edgesData[off + 2] = str; + edgesData[off + 3] = bias; + writePos[tgtIdx]++; + } + } + + const offsetsTexWidth = Math.max(1, Math.ceil(Math.sqrt(N))); + const offsetsTexSize = offsetsTexWidth * offsetsTexWidth; + const offsetsData = new Float32Array(offsetsTexSize * 4); + for (let i = 0; i < N; i++) { + offsetsData[i * 4] = adjStarts[i]; + offsetsData[i * 4 + 1] = adjCounts[i]; + } + + const edgesTexWidth = Math.max(1, Math.ceil(Math.sqrt(totalDirectedEdges))); + const edgesTexSize = edgesTexWidth * edgesTexWidth; + const paddedEdges = new Float32Array(edgesTexSize * 4); + paddedEdges.set(edgesData); + + return { + offsets: offsetsData, + edges: paddedEdges, + offsetsTexWidth, + edgesTexWidth, + }; +} diff --git a/src/simulator/engine/utils/quadtree-builder.ts b/src/simulator/engine/utils/quadtree-builder.ts new file mode 100644 index 0000000..9d104a9 --- /dev/null +++ b/src/simulator/engine/utils/quadtree-builder.ts @@ -0,0 +1,245 @@ +export interface IQuadTreeResult { + treeData: Float32Array; + treeChildren: Float32Array; + treeGeometry: Float32Array; + nodeCount: number; + texWidth: number; +} + +interface ITreeNode { + cx: number; + cy: number; + charge: number; + size: number; + bodyIndex: number; + children: (number | null)[]; +} + +export function buildQuadTree(positions: { x: number; y: number }[], strength: number): IQuadTreeResult { + const N = positions.length; + if (N === 0) { + return { + treeData: new Float32Array(0), + treeChildren: new Float32Array(0), + treeGeometry: new Float32Array(0), + nodeCount: 0, + texWidth: 1, + }; + } + + let minX = Infinity; + let minY = Infinity; + let maxX = -Infinity; + let maxY = -Infinity; + for (let i = 0; i < N; i++) { + const x = positions[i].x; + const y = positions[i].y; + if (x < minX) { + minX = x; + } + if (y < minY) { + minY = y; + } + if (x > maxX) { + maxX = x; + } + if (y > maxY) { + maxY = y; + } + } + + let size = Math.max(maxX - minX, maxY - minY); + if (size < 1e-6) { + size = 1; + } + size *= 1.01; + const cx = (minX + maxX) * 0.5; + const cy = (minY + maxY) * 0.5; + const halfSize = size * 0.5; + const rootX0 = cx - halfSize; + const rootY0 = cy - halfSize; + + const nodes: ITreeNode[] = []; + + function allocNode(sz: number): number { + const idx = nodes.length; + nodes.push({ + cx: 0, + cy: 0, + charge: 0, + size: sz, + bodyIndex: -1, + children: [null, null, null, null], + }); + return idx; + } + + const rootIdx = allocNode(size); + + const nodeX0: number[] = [rootX0]; + const nodeY0: number[] = [rootY0]; + + function getQuadrant(px: number, py: number, x0: number, y0: number, sz: number): number { + const midX = x0 + sz * 0.5; + const midY = y0 + sz * 0.5; + const right = px >= midX ? 1 : 0; + const bottom = py >= midY ? 1 : 0; + return bottom * 2 + right; + } + + function childBounds(q: number, x0: number, y0: number, sz: number): { cx0: number; cy0: number; csz: number } { + const half = sz * 0.5; + const cx0 = q & 1 ? x0 + half : x0; + const cy0 = q & 2 ? y0 + half : y0; + return { cx0, cy0, csz: half }; + } + + function insertBody(bodyIdx: number, bx: number, by: number): void { + let nodeIdx = rootIdx; + let x0 = rootX0; + let y0 = rootY0; + let sz = size; + + for (let depth = 0; depth < 50; depth++) { + const node = nodes[nodeIdx]; + + if ( + node.bodyIndex === -1 && + node.children[0] === null && + node.children[1] === null && + node.children[2] === null && + node.children[3] === null + ) { + node.bodyIndex = bodyIdx; + node.cx = bx; + node.cy = by; + node.charge = strength; + return; + } + + if (node.bodyIndex >= 0) { + const existingBody = node.bodyIndex; + const ex = node.cx; + const ey = node.cy; + node.bodyIndex = -1; + + const eq = getQuadrant(ex, ey, x0, y0, sz); + const { cx0: ecx0, cy0: ecy0, csz: ecsz } = childBounds(eq, x0, y0, sz); + const childIdx = allocNode(ecsz); + nodeX0[childIdx] = ecx0; + nodeY0[childIdx] = ecy0; + node.children[eq] = childIdx; + nodes[childIdx].bodyIndex = existingBody; + nodes[childIdx].cx = ex; + nodes[childIdx].cy = ey; + nodes[childIdx].charge = strength; + } + + const q = getQuadrant(bx, by, x0, y0, sz); + if (node.children[q] === null) { + const { cx0, cy0, csz } = childBounds(q, x0, y0, sz); + const childIdx = allocNode(csz); + nodeX0[childIdx] = cx0; + nodeY0[childIdx] = cy0; + node.children[q] = childIdx; + nodes[childIdx].bodyIndex = bodyIdx; + nodes[childIdx].cx = bx; + nodes[childIdx].cy = by; + nodes[childIdx].charge = strength; + return; + } + + const { cx0, cy0, csz } = childBounds(q, x0, y0, sz); + nodeIdx = node.children[q]!; + x0 = cx0; + y0 = cy0; + sz = csz; + } + } + + for (let i = 0; i < N; i++) { + insertBody(i, positions[i].x, positions[i].y); + } + + function computeAggregates(idx: number): void { + const node = nodes[idx]; + if (node.bodyIndex >= 0) { + return; + } + + let totalCharge = 0; + let wcx = 0; + let wcy = 0; + let totalWeight = 0; + + for (let q = 0; q < 4; q++) { + const childIdx = node.children[q]; + if (childIdx === null) { + continue; + } + computeAggregates(childIdx); + const child = nodes[childIdx]; + const w = Math.abs(child.charge); + totalCharge += child.charge; + wcx += child.cx * w; + wcy += child.cy * w; + totalWeight += w; + } + + if (totalWeight > 0) { + node.cx = wcx / totalWeight; + node.cy = wcy / totalWeight; + } + node.charge = totalCharge; + } + + computeAggregates(rootIdx); + + const treeNodeCount = nodes.length; + const texWidth = Math.ceil(Math.sqrt(treeNodeCount)); + const texSize = texWidth * texWidth; + + const treeData = new Float32Array(texSize * 4); + const treeChildren = new Float32Array(texSize * 4); + const treeGeometry = new Float32Array(texSize * 4); + + for (let i = 0; i < treeNodeCount; i++) { + const node = nodes[i]; + const off = i * 4; + + treeData[off] = node.cx; + treeData[off + 1] = node.cy; + treeData[off + 2] = node.charge; + + if (node.bodyIndex >= 0) { + treeData[off + 3] = -(node.bodyIndex + 1); + } else { + treeData[off + 3] = node.size; + } + + treeChildren[off] = node.children[0] !== null ? node.children[0] : -1; + treeChildren[off + 1] = node.children[1] !== null ? node.children[1] : -1; + treeChildren[off + 2] = node.children[2] !== null ? node.children[2] : -1; + treeChildren[off + 3] = node.children[3] !== null ? node.children[3] : -1; + + treeGeometry[off] = nodeX0[i] ?? 0; + treeGeometry[off + 1] = nodeY0[i] ?? 0; + treeGeometry[off + 2] = node.size; + treeGeometry[off + 3] = 0; + } + + for (let i = treeNodeCount; i < texSize; i++) { + const off = i * 4; + treeData[off + 3] = 0; + treeChildren[off] = -1; + treeChildren[off + 1] = -1; + treeChildren[off + 2] = -1; + treeChildren[off + 3] = -1; + treeGeometry[off] = 0; + treeGeometry[off + 1] = 0; + treeGeometry[off + 2] = 0; + treeGeometry[off + 3] = 0; + } + + return { treeData, treeChildren, treeGeometry, nodeCount: treeNodeCount, texWidth }; +} diff --git a/src/simulator/factory.ts b/src/simulator/factory.ts index 4470442..57ed25c 100644 --- a/src/simulator/factory.ts +++ b/src/simulator/factory.ts @@ -1,5 +1,5 @@ import { DeepPartial } from '../utils/type.utils'; -import { ILayoutSettings } from './engine/shared'; +import { IForceLayoutOptions, ILayoutSettings } from './engine/shared'; import { ISimulator } from './shared'; import { MainThreadSimulator } from './types/main-thread-simulator'; import { WebWorkerSimulator } from './types/web-worker-simulator/web-worker-simulator'; @@ -8,6 +8,13 @@ import { WebWorkerSimulator } from './types/web-worker-simulator/web-worker-simu export class SimulatorFactory { static getSimulator(settings?: DeepPartial): ISimulator { const layoutSettings: DeepPartial = { type: 'force', ...settings }; + + // GPU engine requires main thread (needs WebGL context, cannot run in Web Worker) + const forceOptions = layoutSettings.options as Partial | undefined; + if (layoutSettings.type === 'force' && forceOptions?.useGPU) { + return new MainThreadSimulator(layoutSettings); + } + try { if (typeof Worker !== 'undefined') { return new WebWorkerSimulator(layoutSettings); diff --git a/src/utils/program.utils.ts b/src/utils/program.utils.ts new file mode 100644 index 0000000..b0ae62d --- /dev/null +++ b/src/utils/program.utils.ts @@ -0,0 +1,31 @@ +import { OrbError } from '../exceptions'; +import { compileShader, ShaderType } from './shaders.utils'; + +export const createProgram = ( + gl: WebGL2RenderingContext, + vertexSource: string, + fragmentSource: string, +): WebGLProgram => { + const vertexShader = compileShader(gl, vertexSource, ShaderType.VERTEX); + const fragmentShader = compileShader(gl, fragmentSource, ShaderType.FRAGMENT); + + const program = gl.createProgram(); + if (!program) { + throw new OrbError('Failed to create GL program.'); + } + + gl.attachShader(program, vertexShader); + gl.attachShader(program, fragmentShader); + gl.linkProgram(program); + + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + const info = gl.getProgramInfoLog(program); + gl.deleteProgram(program); + throw new OrbError(`Failed to link GL program: ${info}`); + } + + gl.deleteShader(vertexShader); + gl.deleteShader(fragmentShader); + + return program; +}; diff --git a/src/utils/shaders.utils.ts b/src/utils/shaders.utils.ts new file mode 100644 index 0000000..60d966c --- /dev/null +++ b/src/utils/shaders.utils.ts @@ -0,0 +1,24 @@ +import { OrbError } from '../exceptions'; + +export enum ShaderType { + VERTEX = 'vertex', + FRAGMENT = 'fragment', +} + +export const compileShader = (gl: WebGL2RenderingContext, source: string, type: ShaderType): WebGLShader => { + const shader = gl.createShader(type === ShaderType.VERTEX ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER); + if (!shader) { + throw new OrbError('Failed to create shader.'); + } + + gl.shaderSource(shader, source); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + const info = gl.getShaderInfoLog(shader); + gl.deleteShader(shader); + throw new OrbError(`Failed to compile shader: ${info}`); + } + + return shader; +}; diff --git a/src/views/orb-map-view.ts b/src/views/orb-map-view.ts index 7039c7e..58a13fb 100644 --- a/src/views/orb-map-view.ts +++ b/src/views/orb-map-view.ts @@ -42,9 +42,12 @@ const getDefaultMapTile = () => { const DEFAULT_ZOOM_LEVEL = 2; +export type INodeSizeMode = 'fixed' | 'geographic'; + export interface IMapSettings { zoomLevel: number; tile: ILeafletMapTile; + nodeSizeMode: INodeSizeMode; } export interface IOrbMapViewSettings { @@ -100,6 +103,7 @@ export class OrbMapView implements IOr map: { zoomLevel: settings.map?.zoomLevel ?? DEFAULT_ZOOM_LEVEL, tile: settings.map?.tile ?? getDefaultMapTile(), + nodeSizeMode: settings.map?.nodeSizeMode ?? 'geographic', }, render: { type: RendererType.CANVAS, @@ -188,6 +192,15 @@ export class OrbMapView implements IOr this._settings.map.tile = settings.map.tile; this._handleTileChange(); } + + if (settings.map.nodeSizeMode && settings.map.nodeSizeMode !== this._settings.map.nodeSizeMode) { + this._settings.map.nodeSizeMode = settings.map.nodeSizeMode; + this._updateGraphPositions(); + const leafletPos = (this._leaflet as any)._mapPane._leaflet_pos; + const k = this._getStyleScale(); + this._renderer.transform = { ...leafletPos, k }; + this._renderer.render(this._graph); + } } if (settings.render) { @@ -234,8 +247,12 @@ export class OrbMapView implements IOr recenter(onRendered?: () => void) { const view = this._graph.getBoundingBox(); - const topRightCoordinate = this._leaflet.layerPointToLatLng([view.x, view.y]); - const bottomLeftCoordinate = this._leaflet.layerPointToLatLng([view.x + view.width, view.y + view.height]); + const k = this._getStyleScale(); + const topRightCoordinate = this._leaflet.layerPointToLatLng([view.x * k, view.y * k]); + const bottomLeftCoordinate = this._leaflet.layerPointToLatLng([ + (view.x + view.width) * k, + (view.y + view.height) * k, + ]); this._leaflet.fitBounds(L.latLngBounds(topRightCoordinate, bottomLeftCoordinate)); onRendered?.(); } @@ -256,7 +273,12 @@ export class OrbMapView implements IOr this._leaflet.getContainer().outerHTML = ''; } + private _invalidateStyles = (): void => { + (this._renderer as any).invalidateStyles?.(); + }; + private _update: IObserver = (): void => { + this._invalidateStyles(); this.render(); }; @@ -284,13 +306,16 @@ export class OrbMapView implements IOr leaflet.on('zoom', (event) => { this._updateGraphPositions(); + (this._renderer as any).invalidateBuffers?.(); + const leafletPos = event.target._mapPane._leaflet_pos; + const k = this._getStyleScale(); + this._renderer.transform = { ...leafletPos, k }; this._renderer.render(this._graph); - const transform = { ...event.target._mapPane._leaflet_pos, k: event.target._zoom }; - this._events.emit(OrbEventType.TRANSFORM, { transform }); + this._events.emit(OrbEventType.TRANSFORM, { transform: { ...leafletPos, k } }); }); leaflet.on('mousemove', (event: ILeafletEvent) => { - const point: IPosition = { x: event.layerPoint.x, y: event.layerPoint.y }; + const point: IPosition = this._toSimulationPoint(event.layerPoint); const containerPoint: IPosition = { x: event.containerPoint.x, y: event.containerPoint.y }; const response = this._strategy.onMouseMove(this._graph, point); @@ -323,6 +348,7 @@ export class OrbMapView implements IOr }); if (response.isStateChanged) { + this._invalidateStyles(); this._renderer.render(this._graph); } }); @@ -330,7 +356,7 @@ export class OrbMapView implements IOr // Leaflet doesn't have a valid type definition for click event // @ts-ignore leaflet.on('click contextmenu dblclick', (event: ILeafletEvent) => { - const point: IPosition = { x: event.layerPoint.x, y: event.layerPoint.y }; + const point: IPosition = this._toSimulationPoint(event.layerPoint); const containerPoint: IPosition = { x: event.containerPoint.x, y: event.containerPoint.y }; if (event.type === 'contextmenu') { @@ -364,6 +390,7 @@ export class OrbMapView implements IOr }); if (response.isStateChanged) { + this._invalidateStyles(); this._renderer.render(this._graph); } } else if (event.type === 'click') { @@ -399,6 +426,7 @@ export class OrbMapView implements IOr }); if (response.isStateChanged || response.changedSubject) { + this._invalidateStyles(); this._renderer.render(this._graph); } } else if (event.type === 'dblclick') { @@ -438,6 +466,7 @@ export class OrbMapView implements IOr } if (response.isStateChanged || response.changedSubject) { + this._invalidateStyles(); this._renderer.render(this._graph); } } @@ -445,16 +474,17 @@ export class OrbMapView implements IOr leaflet.on('moveend', (event) => { const leafletPos = event.target._mapPane._leaflet_pos; - this._renderer.transform = { ...leafletPos, k: 1 }; + const k = this._getStyleScale(); + this._renderer.transform = { ...leafletPos, k }; this._renderer.render(this._graph); }); leaflet.on('drag', (event) => { const leafletPos = event.target._mapPane._leaflet_pos; - this._renderer.transform = { ...leafletPos, k: 1 }; + const k = this._getStyleScale(); + this._renderer.transform = { ...leafletPos, k }; this._renderer.render(this._graph); - const transform = { ...leafletPos, k: event.target._zoom }; - this._events.emit(OrbEventType.TRANSFORM, { transform }); + this._events.emit(OrbEventType.TRANSFORM, { transform: { ...leafletPos, k } }); }); return leaflet; @@ -462,6 +492,7 @@ export class OrbMapView implements IOr private _updateGraphPositions() { const nodes = this._graph.getNodes(); + const k = this._getStyleScale(); for (let i = 0; i < nodes.length; i++) { const coordinates = this._settings.getGeoPosition(nodes[i]); @@ -473,8 +504,20 @@ export class OrbMapView implements IOr } const layerPoint = this._leaflet.latLngToLayerPoint([coordinates.lat, coordinates.lng]); - nodes[i].setPosition(layerPoint, { isNotifySkipped: true }); + nodes[i].setPosition({ x: layerPoint.x / k, y: layerPoint.y / k }, { isNotifySkipped: true }); + } + } + + private _getStyleScale(): number { + if (this._settings.map.nodeSizeMode === 'fixed') { + return 1; } + return Math.pow(2, this._leaflet.getZoom() - this._settings.map.zoomLevel); + } + + private _toSimulationPoint(layerPoint: { x: number; y: number }): IPosition { + const k = this._getStyleScale(); + return { x: layerPoint.x / k, y: layerPoint.y / k }; } private _handleTileChange() { diff --git a/src/views/orb-view.ts b/src/views/orb-view.ts index 04dc4bc..f7f885e 100644 --- a/src/views/orb-view.ts +++ b/src/views/orb-view.ts @@ -62,7 +62,8 @@ export class OrbView implements IOrbVi private _interaction: IGraphInteraction; private readonly _renderer: IRenderer; - private readonly _simulator: ISimulator; + private _simulator: ISimulator; + private _simulatorUsesGPU = false; private _simulationStartedAt = Date.now(); private _d3Zoom: ZoomBehavior; @@ -162,6 +163,7 @@ export class OrbView implements IOrbVi .on('dblclick.zoom', this.mouseDoubleClicked); this._simulator = SimulatorFactory.getSimulator(this._settings.layout); + this._simulatorUsesGPU = OrbView._needsGPU(this._settings.layout); this._initializeSimulationEvents(); this._graph.setSettings({ @@ -222,6 +224,16 @@ export class OrbView implements IOrbVi ...settings.layout, }; + const needsGPU = OrbView._needsGPU(this._settings.layout); + if (needsGPU !== this._simulatorUsesGPU) { + this._simulator.terminate(); + this._simulator = SimulatorFactory.getSimulator(this._settings.layout); + this._simulatorUsesGPU = needsGPU; + this._initializeSimulationEvents(); + } else { + this._simulator.setSettings(this._settings.layout); + } + const nodePositions = this._graph.getNodePositions(); const edgePositions = this._graph.getEdgePositions(); @@ -232,7 +244,6 @@ export class OrbView implements IOrbVi } } - this._simulator.setSettings(this._settings.layout); this._simulator.releaseNodes(); if (shouldRecenter) { @@ -282,6 +293,10 @@ export class OrbView implements IOrbVi } } + private static _needsGPU(layout: Partial): boolean { + return layout.type === 'force' && !!(layout.options as any)?.useGPU; + } + private _assignPositions = (nodes: INode[]) => { if (this._settings.getPosition) { for (let i = 0; i < nodes.length; i++) { @@ -482,6 +497,7 @@ export class OrbView implements IOrbVi }); if (response.isStateChanged) { + this._invalidateStyles(); this.render(); } }; @@ -522,6 +538,7 @@ export class OrbView implements IOrbVi }); if (response.isStateChanged || response.changedSubject) { + this._invalidateStyles(); this.render(); } }; @@ -560,6 +577,7 @@ export class OrbView implements IOrbVi }); if (response.isStateChanged || response.changedSubject) { + this._invalidateStyles(); this.render(); } }; @@ -598,6 +616,7 @@ export class OrbView implements IOrbVi }); if (response.isStateChanged || response.changedSubject) { + this._invalidateStyles(); this.render(); } }; @@ -620,6 +639,10 @@ export class OrbView implements IOrbVi .on('end', () => this.render(onRendered)); }; + private _invalidateStyles = (): void => { + (this._renderer as any).invalidateStyles?.(); + }; + private _update: IObserver = (data?: IObserverDataPayload): void => { if (data && 'x' in data && 'y' in data && 'id' in data) { this._simulator.patchData({ @@ -637,6 +660,7 @@ export class OrbView implements IOrbVi edges: [], }); } + this._invalidateStyles(); this.render(); }; @@ -645,22 +669,28 @@ export class OrbView implements IOrbVi this._simulationStartedAt = Date.now(); this._events.emit(OrbEventType.SIMULATION_START, undefined); }); + + const invalidate = () => (this._renderer as any).invalidateBuffers?.(); this._simulator.on(SimulatorEventType.SIMULATION_PROGRESS, (data) => { this._graph.setNodePositions(data.nodes); + invalidate(); this._events.emit(OrbEventType.SIMULATION_STEP, { progress: data.progress }); this.render(); }); this._simulator.on(SimulatorEventType.SIMULATION_END, (data) => { this._graph.setNodePositions(data.nodes); + invalidate(); this.render(); this._events.emit(OrbEventType.SIMULATION_END, { durationMs: Date.now() - this._simulationStartedAt }); }); this._simulator.on(SimulatorEventType.SIMULATION_STEP, (data) => { this._graph.setNodePositions(data.nodes); + invalidate(); this.render(); }); this._simulator.on(SimulatorEventType.NODE_DRAG, (data) => { this._graph.setNodePositions(data.nodes); + invalidate(); this.render(); }); this._simulator.on(SimulatorEventType.SETTINGS_UPDATE, (data) => { diff --git a/webpack.config.js b/webpack.config.js index c09811a..94f4eb5 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -11,10 +11,14 @@ const commonConfiguration = { use: 'ts-loader', exclude: '/node_modules/', }, + { + test: /\.(glsl|vert|frag)$/, + type: 'asset/source', + }, ], }, resolve: { - extensions: ['.tsx', '.ts', '.js'], + extensions: ['.tsx', '.ts', '.js', '.glsl', '.vert', '.frag'], }, output: { chunkFilename(pathData) { From 4df0092e98e8df1c9fbe30815d4d57df1da62efc Mon Sep 17 00:00:00 2001 From: Oleksandr Ichenskyi <55350107+AlexIchenskiy@users.noreply.github.com> Date: Tue, 28 Jul 2026 12:47:02 +0200 Subject: [PATCH 27/30] New: Add docs page (#112) * New: Add docs page * New: Add more docs examples * Update .github/workflows/docs.yml --------- Co-authored-by: Toni --- .eslintignore | 1 + .github/workflows/docs.yml | 82 + README.md | 125 +- docs/assets/view-default-fixed.png | Bin 31300 -> 0 bytes docs/assets/view-default-simulated.png | Bin 31067 -> 0 bytes docs/assets/view-map-example.png | Bin 352127 -> 0 bytes docs/data.md | 326 --- docs/events.md | 482 ---- docs/site/.gitignore | 3 + docs/site/.vitepress/config.ts | 90 + docs/site/.vitepress/theme/Layout.vue | 15 + .../theme/components/ExampleGallery.vue | 149 + .../.vitepress/theme/components/HeroGraph.vue | 351 +++ .../.vitepress/theme/components/OrbDemo.vue | 72 + docs/site/.vitepress/theme/custom.css | 153 + docs/site/.vitepress/theme/index.ts | 15 + docs/site/concepts/data.md | 169 ++ docs/site/concepts/events.md | 118 + docs/site/concepts/interaction.md | 119 + docs/site/concepts/styling.md | 146 + docs/site/index.md | 36 + docs/site/introduction/getting-started.md | 100 + docs/site/introduction/what-is-orb.md | 38 + docs/site/layouts/force.md | 77 + docs/site/layouts/gpu.md | 37 + docs/site/layouts/overview.md | 58 + docs/site/layouts/static.md | 56 + docs/site/package-lock.json | 2559 +++++++++++++++++ docs/site/package.json | 16 + docs/site/public/demos/data.html | 119 + docs/site/public/demos/events.html | 101 + docs/site/public/demos/gpu.html | 183 ++ .../public/demos/interaction-showcase.html | 198 ++ docs/site/public/demos/interaction.html | 106 + docs/site/public/demos/layouts.html | 96 + docs/site/public/demos/map.html | 115 + docs/site/public/demos/metro.html | 225 ++ docs/site/public/demos/playground.html | 227 ++ docs/site/public/demos/styled.html | 213 ++ docs/site/public/demos/styles-showcase.html | 80 + docs/site/public/orb.min.js | 2 + docs/site/public/orb.worker.min.js | 1 + docs/site/public/orb.worker.vendor.min.js | 1 + docs/site/reference/api.md | 194 ++ docs/site/rendering/performance.md | 54 + docs/site/rendering/renderers.md | 56 + docs/site/rendering/svg-export.md | 78 + docs/site/views/default.md | 81 + docs/site/views/map.md | 74 + docs/styles.md | 401 --- docs/view-default.md | 520 ---- docs/view-map.md | 323 --- examples/example-webgl-renderer.html | 4 +- src/index.ts | 24 +- src/renderer/canvas/canvas-renderer.ts | 2 +- src/renderer/webgl/shaders/edge/edge.frag | 10 +- src/renderer/webgl/shaders/edge/edge.vert | 7 + src/renderer/webgl/webgl-renderer.ts | 46 +- src/views/orb-map-view.ts | 52 +- src/views/orb-view.ts | 91 +- src/views/shared.ts | 2 + 61 files changed, 6894 insertions(+), 2185 deletions(-) create mode 100644 .github/workflows/docs.yml delete mode 100644 docs/assets/view-default-fixed.png delete mode 100644 docs/assets/view-default-simulated.png delete mode 100644 docs/assets/view-map-example.png delete mode 100644 docs/data.md delete mode 100644 docs/events.md create mode 100644 docs/site/.gitignore create mode 100644 docs/site/.vitepress/config.ts create mode 100644 docs/site/.vitepress/theme/Layout.vue create mode 100644 docs/site/.vitepress/theme/components/ExampleGallery.vue create mode 100644 docs/site/.vitepress/theme/components/HeroGraph.vue create mode 100644 docs/site/.vitepress/theme/components/OrbDemo.vue create mode 100644 docs/site/.vitepress/theme/custom.css create mode 100644 docs/site/.vitepress/theme/index.ts create mode 100644 docs/site/concepts/data.md create mode 100644 docs/site/concepts/events.md create mode 100644 docs/site/concepts/interaction.md create mode 100644 docs/site/concepts/styling.md create mode 100644 docs/site/index.md create mode 100644 docs/site/introduction/getting-started.md create mode 100644 docs/site/introduction/what-is-orb.md create mode 100644 docs/site/layouts/force.md create mode 100644 docs/site/layouts/gpu.md create mode 100644 docs/site/layouts/overview.md create mode 100644 docs/site/layouts/static.md create mode 100644 docs/site/package-lock.json create mode 100644 docs/site/package.json create mode 100644 docs/site/public/demos/data.html create mode 100644 docs/site/public/demos/events.html create mode 100644 docs/site/public/demos/gpu.html create mode 100644 docs/site/public/demos/interaction-showcase.html create mode 100644 docs/site/public/demos/interaction.html create mode 100644 docs/site/public/demos/layouts.html create mode 100644 docs/site/public/demos/map.html create mode 100644 docs/site/public/demos/metro.html create mode 100644 docs/site/public/demos/playground.html create mode 100644 docs/site/public/demos/styled.html create mode 100644 docs/site/public/demos/styles-showcase.html create mode 100644 docs/site/public/orb.min.js create mode 100644 docs/site/public/orb.worker.min.js create mode 100644 docs/site/public/orb.worker.vendor.min.js create mode 100644 docs/site/reference/api.md create mode 100644 docs/site/rendering/performance.md create mode 100644 docs/site/rendering/renderers.md create mode 100644 docs/site/rendering/svg-export.md create mode 100644 docs/site/views/default.md create mode 100644 docs/site/views/map.md delete mode 100644 docs/styles.md delete mode 100644 docs/view-default.md delete mode 100644 docs/view-map.md diff --git a/.eslintignore b/.eslintignore index 457da68..1794051 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,4 +2,5 @@ coverage/ dist/ node_modules/ examples/ +docs/ webpack.config.js diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..7b2f944 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,82 @@ +name: Deploy docs to GitHub Pages + +on: + push: + # NOTE: `new/add-docs-page` is a TEMPORARY entry so the team can review a live + # deploy from the docs branch. Remove it before/at merge so main deploys only + # from main. + branches: [main] + # Validate the bundle + docs build on any PR that touches them, so reviewers + # get a green check without needing Pages enabled or a merge to main. The + # deploy job below is skipped for PRs. + pull_request: + paths: + - "docs/site/**" + - "src/**" + - ".github/workflows/docs.yml" + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +# One deploy at a time, but keep PR builds from cancelling a main deploy (and +# vice versa) by scoping the group per ref. +concurrency: + group: pages-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + # 1. Build the Orb browser bundle from source so the live demos stay in sync. + - name: Build Orb bundle + run: | + npm ci + npm run build:release + + # 2. Refresh the copies the docs site embeds. + - name: Sync bundle into docs site + run: | + cp dist/browser/orb.min.js docs/site/public/orb.min.js + cp dist/browser/orb.worker.min.js docs/site/public/orb.worker.min.js + # The module worker loads this shared vendor chunk as a sibling; without + # it the worker fails silently and layout simulation never runs. + cp dist/browser/orb.worker.vendor.min.js docs/site/public/orb.worker.vendor.min.js + + # 3. Build the VitePress site. + - name: Build docs + working-directory: docs/site + run: | + npm install + npm run build + + # 4. Package for Pages. Only needed for an actual deploy, so skip on PRs + # (where these steps would also fail until Pages is enabled). + - uses: actions/configure-pages@v5 + if: github.event_name != 'pull_request' + + - uses: actions/upload-pages-artifact@v3 + if: github.event_name != 'pull_request' + with: + path: docs/site/.vitepress/dist + + deploy: + needs: build + # Deploy only from main; PRs run the build job above for validation only. + if: github.event_name != 'pull_request' + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + uses: actions/deploy-pages@v4 diff --git a/README.md b/README.md index 2d5cd1a..34e3c2c 100644 --- a/README.md +++ b/README.md @@ -18,20 +18,28 @@ ![](./docs/assets/graph-example.png) -Orb is a graph visualization library. Read more about Orb in the following guides: +Orb is a graph visualization library. It renders interactive graphs on the 2D Canvas or on +WebGL, runs force-directed (CPU or GPU), circular, grid, and hierarchical layouts, plots +geo-located nodes on a map, and gives you full control over the style of every node and edge. -* [Handling nodes and edges](./docs/data.md) -* [Styling nodes and edges](./docs/styles.md) -* [Handling events](./docs/events.md) -* Using different views - * [Default view](./docs/view-default.md) - * [Map view](./docs/view-map.md) +## Documentation -## Install +Full guides, the API reference, and live interactive demos are on the documentation site: + +**https://memgraph.github.io/orb/** + +Some good places to start: + +* [Getting started](https://memgraph.github.io/orb/introduction/getting-started) +* [Graph data](https://memgraph.github.io/orb/concepts/data) - nodes, edges, and updates +* [Styling](https://memgraph.github.io/orb/concepts/styling) - colors, shapes, borders, labels +* [Events](https://memgraph.github.io/orb/concepts/events) and [Interaction](https://memgraph.github.io/orb/concepts/interaction) +* [Layouts](https://memgraph.github.io/orb/layouts/overview) - force, GPU, and static layouts +* [Canvas vs WebGL](https://memgraph.github.io/orb/rendering/renderers) +* [Map view](https://memgraph.github.io/orb/views/map) +* [API reference](https://memgraph.github.io/orb/reference/api) -> **Important note**: Please note that there might be breaking changes in minor version upgrades until -> the Orb reaches version 1.0.0, so we recommend to either set strict version (`@memgraph/orb: "0.x.y"`) -> of the Orb in your `package.json` or to allow only fix updates (`@memgraph/orb: "~0.x.y"`). +## Install ### With `npm` (recommended) @@ -39,24 +47,22 @@ Orb is a graph visualization library. Read more about Orb in the following guide npm install @memgraph/orb ``` -Below you can find a simple Typescript example using Orb to visualize a small graph. Feel -free to check other JavaScript examples in `examples/` directory. - ```typescript import { OrbView } from '@memgraph/orb'; + const container = document.getElementById('graph'); -const nodes: MyNode[] = [ +const nodes = [ { id: 1, label: 'Orb' }, { id: 2, label: 'Graph' }, { id: 3, label: 'Canvas' }, ]; -const edges: MyEdge[] = [ +const edges = [ { id: 1, start: 1, end: 2, label: 'DRAWS' }, { id: 2, start: 2, end: 3, label: 'ON' }, ]; -const orb = new OrbView(container); +const orb = new OrbView(container); // Initialize nodes and edges orb.data.setup({ nodes, edges }); @@ -73,69 +79,24 @@ orb.render(() => { > link. Graph simulation will use the main thread, which will affect performance. ```html - - - - - - - + ``` -Below you can find a simple JavaScript example using Orb to visualize a small graph. Feel -free to check other JavaScript examples in `examples/` directory. - -```html - - - - - Orb | Simple graph - - - - -
    - - - -``` +See the [getting started guide](https://memgraph.github.io/orb/introduction/getting-started) +for a complete runnable example. ## Build ``` -npm run build +npm run build # type-check + emit (tsc) +npm run build:release # tsc + webpack browser bundle (dist/browser/) ``` ## Test @@ -146,30 +107,38 @@ npm run test ## Development -If you want to experiment, contribute, or simply play with the Orb locally, you can -set up your local development environment with: +If you want to experiment, contribute, or simply play with Orb locally: -* Installation of all project dependencies +* Install dependencies ``` npm install ``` -* Running webpack build in the watch mode +* Rebuild the browser bundle on change ``` npm run webpack:watch ``` -* Running a local http server that will serve Orb and `examples/` directory on `localhost:8080` +* Serve the built bundle from `dist/browser/` on `localhost:8082` ``` npm run serve ``` +* Lint + + ``` + npm run lint + ``` + +To work on the documentation site itself, see `docs/site/` (a self-contained VitePress +project with its own `package.json`). + ## License -Copyright (c) 2016-2022 [Memgraph Ltd.](https://memgraph.com) +Copyright (c) 2016-present [Memgraph Ltd.](https://memgraph.com) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the diff --git a/docs/assets/view-default-fixed.png b/docs/assets/view-default-fixed.png deleted file mode 100644 index ce8c710185c0c7b43321f7d278abf6275ac72355..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31300 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 diff --git a/docs/assets/view-map-example.png b/docs/assets/view-map-example.png deleted file mode 100644 index cd5506ced9f4b2020cd381bdc1954ed7a3d34379..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 352127 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 e^`MDoVH}ghmv2u6(`gC(IzD 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 z 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

    Tpchx&Gq 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 diff --git a/docs/data.md b/docs/data.md deleted file mode 100644 index f07f26d..0000000 --- a/docs/data.md +++ /dev/null @@ -1,326 +0,0 @@ -# Handling graph data in Orb - -Graph data structure (nodes and edges) is the main part of Orb. Without the graph data -structure, there wouldn't be anything to render. Read the following guide to get to know -how to handle graph data in Orb. - -> Note: Please do not use `node.addEdge` and `node.removeEdge` because the general graph data -> structure might go out of sync. Always use `orb.data.(setup|merge|remove)` to change the -> graph data structure. - -## Setup nodes and edges - -To set up `nodes` and `edges`, there are a few requirements that Orb expects: - -- Node data object should be a JSON plain object with a defined unique `id`. The value of `id` can - be `any`. All other properties are up to you (e.g. `text` and `myField` in the above example). -- Edge data object should be a JSON plain object with defined unique `id`, `start` (id of - the source node), `end` (id of the target node). The value of `id` can be `any`. All other - properties are up to you. (e.g. `connects` in the above example). - -You can have your own `node` and `edge` types that satisfy those requirements: - -```typescript -export interface MyNode { - id: number; - text: string; - myField: number; -} - -export interface MyEdge { - id: number; - start: number; - end: number; - connects: string; -} -``` - -To initialize graph data structure use `orb.data.setup` function that receives `nodes` and -`edges`. Here is a simple example of it: - -```typescript -import { OrbView } from "@memgraph/orb"; - -const orb = new OrbView(container); - -const nodes: MyNode[] = [ - { id: 0, text: "Node A", myField: 12 }, - { id: 1, text: "Node B", myField: 77 }, -]; - -const edges: MyEdge[] = [ - { id: 0, start: 0, end: 1, connects: "A -> B" }, - { id: 1, start: 0, end: 0, connects: "A -> A" }, -]; - -orb.data.setup({ nodes, edges }); -``` - -Whenever `orb.data.setup` is called, any previous graph structure will be removed. - -### Node - -Node object (interface `INode`) is created on top of the node data that is provided via -`orb.data.setup` or `orb.data.merge` functions. - -#### Node information - -- `id` - Readonly unique `id` provided on init (same as `.getData().id`) -- `data` - User provided information on `orb.data.setup` or `orb.data.merge` -- `style` - Style properties like color, border, size (check more on [Styling guide](./styles.md)). -- `position` - Node `x` and `y` coordinate generated before first render -- `state` - Node state which can be selected (`GraphObjectState.SELECTED`), hovered - (`GraphObjectState.HOVERED`), or none (`GraphObjectState.NONE` - default) - -#### Node getters functions - -- `getId()` - Alias for `.id` -- `getData()` - Returns the node data -- `getPosition()` - Returns the node position -- `getStyle()` - Returns the node style -- `getState()` - Returns the node state -- `getCenter()` - Alias for `.position` -- `getRadius()` - Alias for `.getStyle().size` -- `getBorderedRadius()` - Alias for `.getStyle().size + .getStyle().borderWidth` -- `getInEdges()` - Returns a list of inbound edges connected to the node -- `getOutEdges()` - Returns a list of outbound edges connected to the node -- `getEdges()` - Returns a list of all edges connected to the node, inbound and outbound -- `getAdjacentNodes()` - Returns a list of adjacent nodes -- `getLabel()` - Returns the node label -- `getColor()` - Returns the node color - -#### Node setter/patch functions - -All of the setter/patch functions for nodes are able to accept the raw data of the corresponding type or the callback that returns this data. - -- `setData()` - Replaces the node data with the provided data -- `patchData()` - Replaces the node data entries with the provided ones -- `setPosition()` - Sets the node current position -- `setStyle()` - Sets the node current style -- `patchStyle()` - Replaces the node style entries with the provided ones -- `setState()` - Sets the node current state - -`position`, `style` and `state` setters can accept optional `options` argument. It can be used to skip the rerender on data change which can be useful for performance while changing the data of many nodes. - -Check the example to get to know node handling better: - -```typescript -import { OrbView } from "@memgraph/orb"; - -const orb = new OrbView(container); - -const nodes: MyNode[] = [ - { id: 0, text: "Node A", myField: 12 }, - { id: 1, text: "Node B", myField: 77 }, -]; - -orb.data.setup({ nodes }); - -const node = orb.data.getNodeById(0); -console.log(node.getId()); // Output: 0 -console.log(node.getData()); // Output: { id: 0, text: "Node A", myField: 12 } - -// Set node color to red -node.patchStyle({ color: "#FF0000" }); -console.log(node.getStyle()); // Output: { ..., color: '#FF0000' } -``` - -### Edge - -Edge object (interface `IEdge`) is created on top of the edge data that is provided via -`orb.data.setup` or `orb.data.merge` functions. - -#### Edge information - -- `id` - Readonly unique `id` provided on init (same as `.getData().id`) -- `data` - User provided information on `orb.data.setup` or `orb.data.merge` -- `start` - Readonly `start` provided on init (same as `.getData().start`) -- `end` - Readonly `end` provided on init (same as `.getData().end`) -- `startNode` - Reference to the start node (`INode`) that edge connects -- `endNode` - Reference to the end node (`INode`) that edge connects -- `style` - Style properties like color, border, size (check more on [Styling guide](./styles.md)). -- `state` - Edge state which can be selected (`GraphObjectState.SELECTED`), hovered - (`GraphObjectState.HOVERED`), or none (`GraphObjectState.NONE` - default) -- `type` - Edge line type which can be: - - straight (`EdgeType.STRAIGHT`) - if there are 1x, 3x, 5x, ... edges connecting nodes A and B, - one edge will be a straight line edge. If there are multiple edges, other edges will be curved - not to overlap with each other - - curved (`EdgeType.CURVED`) - if there is more than one edge connecting nodes A and B, some - of those edges will be curved, so they do not overlap with each other - - loopback (`EdgeType.LOOPBACK) - connects a node to itself - -#### Edge getters function - -- `getId()` - Alias for `.id` -- `getData()` - Getter for edge data -- `getPosition()` - Getter for edge position -- `getStyle()` - Getter for edge style -- `getState()` - Getter for edge state -- `getCenter()` - Gets the center edge position calculated by edge type and connected node positions -- `getWidth()` - Alias for `.style.width` -- `isLoopback()` - Checks if edge is a loopback type: connects a node to itself. -- `isStraight()` - Checks if edge is a straight line edge -- `isCurved()` - Checks if edge is a curved line edge. - -#### Edge setters/patch functions - -All of the setter/patch functions for edges are able to accept the raw data of the corresponding type or the callback that returns this data. - -- `setData()` - Replaces the edge data with the provided data -- `patchData()` - Replaces the edge data entries with the provided ones -- `setStyle()` - Sets the edge current style -- `patchStyle()` - Replaces the edge style entries with the provided ones -- `setState()` - Sets the edge current state - -`style` and `state` setters can accept optional `options` argument. It can be used to skip the rerender on data change which can be useful for performance while changing the data of many edges. - -Check the example to get to know edge handling better: - -```typescript -import { OrbView } from "@memgraph/orb"; - -const orb = new OrbView(container); - -const nodes: MyNode[] = [ - { id: 0, text: "Node A", myField: 12 }, - { id: 1, text: "Node B", myField: 77 }, -]; - -const edges: MyEdge[] = [ - { id: 0, start: 0, end: 1, connects: "A -> B" }, - { id: 1, start: 0, end: 0, connects: "A -> A" }, -]; - -orb.data.setup({ nodes, edges }); - -const edge = orb.data.geEdgeById(0); -console.log(edge.getId()); // Output: 0 -console.log(edge.getData()); // Output: { id: 0, start: 0, end: 1, connects: 'A -> B' } -console.log(edge.startNode.getData()); // Output: { id: 0, text: "Node A", myField: 12 } -console.log(edge.endNode.getData()); // Output: { id: 1, text: "Node B", myField: 77 } - -// Set edge line color to red -edge.patchStyle({ color: "#FF0000" }); -console.log(edge.getStyle()); // Output: { ..., color: '#FF0000' } -``` - -## Merge nodes and edges - -Merge `orb.data.merge` is a handy function to add new nodes and edges or even update the existing -ones. An update of a node or edge will happen if a node or edge with the same unique `id` already -exists in the graph structure. Check the example below: - -```typescript -import { OrbView } from "@memgraph/orb"; - -const orb = new OrbView(container); - -const nodes: MyNode[] = [ - { id: 0, text: "Node A", myField: 12 }, - { id: 1, text: "Node B", myField: 77 }, -]; - -const edges: MyEdge[] = [ - { id: 0, start: 0, end: 1, connects: "A -> B" }, - { id: 1, start: 0, end: 0, connects: "A -> A" }, -]; - -orb.data.setup({ nodes, edges }); -console.log(orb.data.getNodeCount()); // Output: 3 -console.log(orb.data.getNodeById(1)); // Output: { id: 1, text: "Node B", myField: 77 } - -orb.data.merge({ - nodes: [ - // This will be a new node in the graph because node with id = 2 doesn't exist - { id: 2, text: "Node C", myField: 82 }, - // This will update the node with id = 1 because it already exists. `node.data` will be updated. - { id: 1, text: "Node D", myField: 82 }, - ], - edges: [ - // This will update the edge with id = 1 because it already exists. `edge.data` will be updated, - // but also, edge will disconnect from previous nodes and connect to the new ones (0 -> 2). - { id: 1, start: 0, end: 2, connects: "A -> C" }, - // This will be a new edge in the graph because edge with id = 2 doesn't exist - { id: 2, start: 2, end: 1, connects: "C -> B" }, - // This edge will be dismissed because node with id = 7 doesn't exist - { id: 3, start: 2, end: 8, connects: "C -> ?" }, - ], -}); -console.log(orb.data.getNodeCount()); // Output: 3 -console.log(orb.data.getNodeById(1)); // Output: { id: 1, text: "Node D", myField: 82 } -``` - -## Remove nodes and edges - -To remove nodes or edges from a graph, you just need the `id`. Removing a node will also -remove all inbound and outbound edges to that node. Removing an edge will just remove that edge. - -```typescript -import { OrbView } from "@memgraph/orb"; - -const orb = new OrbView(container); - -const nodes: MyNode[] = [ - { id: 0, text: "Node A" }, - { id: 1, text: "Node B" }, -]; - -const edges: MyEdge[] = [ - { id: 0, start: 0, end: 1, text: "A -> B" }, - { id: 1, start: 0, end: 0, text: "A -> A" }, -]; - -orb.data.setup({ nodes, edges }); - -// After the removal of node with id 0, both edges will be removed too because they are -// connected to the removed edge -orb.data.remove({ nodeIds: [0] }); -``` - -You can remove just nodes, edges, or both: - -```typescript -// Remove just one node -orb.data.remove({ nodeIds: [0] }); - -// Remove multiple nodes and one edge -orb.data.remove({ nodeIds: [0, 1, 2], edgeIds: [0] }); - -// Remove just edges -orb.data.remove({ edgeIds: [0, 1, 2] }); -``` - -If you need to remove everything, you can do it with `remove` or even with `setup`: - -```typescript -const nodeIds = orb.data.getNodes().map((node) => node.getId()); -// No need to get edges because if we remove all the nodes, all the edges will be removed too -orb.data.remove({ nodeIds: nodeIds }); - -// Or use just setup with empty nodes and edges: -orb.data.setup({ nodes: [], edges: [] }); -``` - -## Other functions - -There are only three main functions to change the graph structure: `setup`, `merge`, and `remove`. -But couple more functions could be useful to you: - -```typescript -// Returns the list of all nodes/edges in the graph -const nodes = orb.data.getNodes(); -const edges = orb.data.getEdges(); - -// Returns the total number of nodes/edges in the graph -const nodeCount = orb.data.getNodeCount(); -const edgeCount = orb.data.getEdgeCount(); - -// Returns specific node or edge by id. If node or edge doesn't exist, it will return undefined -const node = orb.data.getNodeById(0); -const edge = orb.data.getEdgeById(0); - -// Get nearest node/edge to the position (x, y). Useful with events such as mouse click to -// check if node should be considered clicked or not -const nearestNode = orb.data.getNearestNode({ x: 0, y: 0 }); -const nearestEdge = orb.data.getNearestEdge({ x: 0, y: 0 }); -``` diff --git a/docs/events.md b/docs/events.md deleted file mode 100644 index 67a84bb..0000000 --- a/docs/events.md +++ /dev/null @@ -1,482 +0,0 @@ -Handling events in Orb -=== - -In the following section, you can find a list of all supported events that Orb emits along -with an example of each event type with its event data. - -# Events - -Below you can find all the event types (names) that Orb supports that you can -subscribe to: - -```typescript -export enum OrbEventType { - // Renderer events for drawing on canvas - RENDER_START = 'render-start', - RENDER_END = 'render-end', - // Simulation (D3) events for setting up node positions - SIMULATION_START = 'simulation-start', - SIMULATION_STEP = 'simulation-step', - SIMULATION_END = 'simulation-end', - // Mouse events: click, hover, move - NODE_CLICK = 'node-click', - NODE_HOVER = 'node-hover', - EDGE_CLICK = 'edge-click', - EDGE_HOVER = 'edge-hover', - MOUSE_CLICK = 'mouse-click', - MOUSE_MOVE = 'mouse-move', - // Zoom or pan (translate) change - TRANSFORM = 'transform', - // Mouse node drag events - NODE_DRAG_START = 'node-drag-start', - NODE_DRAG = 'node-drag', - NODE_DRAG_END = 'node-drag-end', - NODE_RIGHT_CLICK = 'node-right-click', - EDGE_RIGHT_CLICK = 'edge-right-click', - MOUSE_RIGHT_CLICK = 'mouse-right-click', - // DBL click events - NODE_DOUBLE_CLICK = 'node-double-click', - EDGE_DOUBLE_CLICK = 'edge-double-click', - MOUSE_DOUBLE_CLICK = 'mouse-double-click', -} -``` - -Subscribe to the events via `orb.events` in one of the two ways: - -```typescript -import { OrbEventType } from '@memgraph/orb'; - -orb.events.on(OrbEventType.RENDER_START, () => { - console.log('Render started'); -}); - -// Or use enum value directly -orb.events.on('render-start', () => { - console.log('Render started'); -}); -``` - -# Event examples - -In the following sections, you can find event subscription examples and what kind of data -you can get from each event. - -## Rendering events - -### Event `OrbEventType.RENDER_START` - -Event is emitted on each render call before the renderer starts drawing the graph on canvas. - -```typescript -import { OrbEventType } from '@memgraph/orb'; - -orb.events.on(OrbEventType.RENDER_START, () => { - console.log('Render started'); -}); -``` - -Event data for `OrbEventType.RENDER_START` is undefined. - -### Event `OrbEventType.RENDER_END` - -Event is emitted on each render call after the renderer completes drawing the graph on canvas. - -```typescript -import { OrbEventType, IOrbEventRenderEnd } from '@memgraph/orb'; - -orb.events.on(OrbEventType.RENDER_END, (event: IOrbEventRenderEnd) => { - console.log(`Render ended in ${event.durationMs} ms`); -}); -``` - -Event data for `OrbEventType.RENDER_END` has the following properties: - -```typescript -interface IOrbEventRenderEnd { - durationMs: number; -} -``` - -## Simulation events - -Simulation is a process where a view uses `d3` simulator to calculate node positions if positions -are not defined. The simulation could take some time to position all the nodes which is the reason -why there are three simulation events you can subscribe to: start, step (progress), and end. - -### Event `OrbEventType.SIMULATION_START` - -Event `OrbEventType.SIMULATION_START` is emitted once the simulator starts setting up node positions. - -```typescript -import { OrbEventType } from '@memgraph/orb'; - -orb.events.on(OrbEventType.SIMULATION_START, () => { - console.log(`Simulation started`); -}); -``` - -Event data for `OrbEventType.SIMULATION_START` is undefined. - -### Event `OrbEventType.SIMULATION_STEP` - -Event `OrbEventType.SIMULATION_STEP` is emitted on each simulation step. `d3` simulator runs -node positioning in iterations where each iteration is one simulation step. - -```typescript -import { OrbEventType, IOrbEventSimulationStep } from '@memgraph/orb'; - -orb.events.on(OrbEventType.SIMULATION_STEP, (event: IOrbEventSimulationStep) => { - console.log(`Simulation progress: ${event.progress}`); - // If you want to see each step of the simulation, add render here - orb.view.render(); -}); -``` - -Event data for `OrbEventType.SIMULATION_STEP` has the following properties: - -```typescript -interface IOrbEventSimulationStep { - progress: number; -} -``` - -### Event `OrbEventType.SIMULATION_END` - -Event `OrbEventType.SIMULATION_END` is emitted once the simulator ends with the final node positions. - -```typescript -import { OrbEventType, IOrbEventSimulationEnd } from '@memgraph/orb'; - -orb.events.on(OrbEventType.SIMULATION_END, (event: IOrbEventSimulationEnd) => { - console.log(`Simulation ended in ${event.durationMs} ms`); -}); -``` - -Event data for `OrbEventType.SIMULATION_END` has the following properties: - -```typescript -interface IOrbEventSimulationEnd { - durationMs: number; -} -``` - -## Mouse events - -### Event `OrbEventType.NODE_CLICK` - -Event is emitted on mouse click that selects the node. The event `OrbEventType.MOUSE_CLICK` will also be -triggered. - -```typescript -import { OrbEventType, IOrbEventNodeClick } from '@memgraph/orb'; - -orb.events.on(OrbEventType.NODE_CLICK, (event: IOrbEventNodeClick) => { - console.log(`Node clicked`, event.node); -}); -``` - -Event data for `OrbEventType.NODE_CLICK` has the following properties: - -```typescript -interface IOrbEventNodeClick { - node: INode; - event: PointerEvent; - localPoint: { x: number; y: number }; - globalPoint: { x: number; y: number }; -} -``` - -Property `localPoint` contains the coordinates in the system of node positions, while `globalPoint` -is the original mouse coordinate on the canvas. - -### Event `OrbEventType.NODE_HOVER` - -Event is emitted on mouse move that hovers the node. The event `OrbEventType.MOUSE_MOVE` will also be -triggered. - -```typescript -import { OrbEventType, IOrbEventNodeHover } from '@memgraph/orb'; - -orb.events.on(OrbEventType.NODE_HOVER, (event: IOrbEventNodeHover) => { - console.log(`Node hovered`, event.node); -}); -``` - -Event data for `OrbEventType.NODE_HOVER` has the following properties: - -```typescript -interface IOrbEventNodeHover { - node: INode; - event: MouseEvent; - localPoint: { x: number; y: number }; - globalPoint: { x: number; y: number }; -} -``` - -Property `localPoint` contains the coordinates in the system of node positions, while `globalPoint` -is the original mouse coordinate on the canvas. - -### Event `OrbEventType.EDGE_CLICK` - -Event is emitted on mouse click that selects the edge. The event `OrbEventType.MOUSE_CLICK` will also be -triggered. - -```typescript -import { OrbEventType, IOrbEventEdgeClick } from '@memgraph/orb'; - -orb.events.on(OrbEventType.EDGE_CLICK, (event: IOrbEventEdgeClick) => { - console.log(`Edge clicked`, event.edge); -}); -``` - -Event data for `OrbEventType.EDGE_CLICK` has the following properties: - -```typescript -interface IOrbEventEdgeClick { - edge: IEdge; - event: PointerEvent; - localPoint: { x: number; y: number }; - globalPoint: { x: number; y: number }; -} -``` - -Property `localPoint` contains the coordinates in the system of node positions, while `globalPoint` -is the original mouse coordinate on the canvas. - -### Event `OrbEventType.EDGE_HOVER` _(not supported currently)_ - -Event is emitted on mouse move that hovers the edge. The event `OrbEventType.MOUSE_MOVE` will also be -triggered. - -> Note: The following event is not supported because of the performance issue to calculate -> the distance to the closest edge to hover it. - -```typescript -import { OrbEventType, IOrbEventEdgeHover } from '@memgraph/orb'; - -orb.events.on(OrbEventType.EDGE_HOVER, (event: IOrbEventEdgeHover) => { - console.log(`Edge hovered`, event.node); -}); -``` - -Event data for `OrbEventType.EDGE_HOVER` has the following properties: - -```typescript -interface IOrbEventEdgeHover { - edge: IEdge; - event: MouseEvent; - localPoint: { x: number; y: number }; - globalPoint: { x: number; y: number }; -} -``` - -Property `localPoint` contains the coordinates in the system of node positions, while `globalPoint` -is the original mouse coordinate on the canvas. - -### Event `OrbEventType.MOUSE_CLICK` - -The event is emitted on a mouse click within the canvas. If there is a graph object (node or -edge) at the mouse click position, `OrbEventType.NODE_CLICK` and `OrbEventType.EDGE_CLICK` events -will be triggered too. - -```typescript -import { OrbEventType, IOrbEventMouseClick } from '@memgraph/orb'; - -orb.events.on(OrbEventType.MOUSE_CLICK, (event: IOrbEventMouseClick) => { - console.log(`Mouse clicked`, event); -}); -``` - -Event data for `OrbEventType.MOUSE_CLICK` has the following properties: - -```typescript -interface IOrbEventMouseClick { - subject?: INode | IEdge; - event: PointerEvent; - localPoint: { x: number; y: number }; - globalPoint: { x: number; y: number }; -} -``` - -Property `localPoint` contains the coordinates in the system of node positions, while `globalPoint` -is the original mouse coordinate on the canvas. Property `subject` will be filled with either `INode` -or `IEdge` if the mouse click position is on top of the node or edge. The same objects are received in -the events `OrbEventType.NODE_CLICK` and `OrbEventType.EDGE_CLICK`. - -If you need to check if `subject` is a `INode` or `IEdge` use type check functions from orb: - -```typescript -import { isNode, isEdge, OrbEventType, IOrbEventMouseClick } from '@memgraph/orb'; - -orb.events.on(OrbEventType.MOUSE_CLICK, (event: IOrbEventMouseClick) => { - if (event.subject && isNode(event.subject)) { - console.log(`Mouse clicked on top of the node`, event.subject); - } - if (event.subject && isEdge(event.subject)) { - console.log(`Mouse clicked on top of the edge`, event.subject); - } -}); -``` - -### Event `OrbEventType.MOUSE_MOVE` - -Event is emitted on any mouse movement within the canvas. If there is a graph object (node or -edge) at the mouse position, `OrbEventType.NODE_HOVER` and `OrbEventType.EDGE_HOVER` events will -be triggered too. - -```typescript -import { OrbEventType, IOrbEventMouseMove } from '@memgraph/orb'; - -orb.events.on(OrbEventType.MOUSE_MOVE, (event: IOrbEventMouseMove) => { - console.log(`Mouse moved`, event); -}); -``` - -Event data for `OrbEventType.MOUSE_MOVE` has the following properties: - -```typescript -interface IOrbEventMouseMove { - subject?: INode | IEdge; - event: MouseEvent; - localPoint: { x: number; y: number }; - globalPoint: { x: number; y: number }; -} -``` - -Property `localPoint` contains the coordinates in the system of node positions, while `globalPoint` -is the original mouse coordinate on the canvas. Property `subject` will be filled with either `INode` -or `IEdge` if the mouse position is on top of the node or edge. The same objects are received in the -events `OrbEventType.NODE_CLICK` and `OrbEventType.EDGE_CLICK`. - -If you need to check if `subject` is a `INode` or `IEdge` use type check functions from orb: - -```typescript -import { isNode, isEdge, OrbEventType, IOrbEventMouseMove } from '@memgraph/orb'; - -orb.events.on(OrbEventType.MOUSE_MOVE, (event: IOrbEventMouseMove) => { - if (event.subject && isNode(event.subject)) { - console.log(`Mouse moved over the node`, event.subject); - } - if (event.subject && isEdge(event.subject)) { - console.log(`Mouse moved over the edge`, event.subject); - } -}); -``` - -## Zoom and pan events - -### Event `OrbEventType.TRANSFORM` - -Event is emitted on any zoom or pan event. - -```typescript -import { OrbEventType, IOrbEventTransform } from '@memgraph/orb'; - -orb.events.on(OrbEventType.TRANSFORM, (event: IOrbEventTransform) => { - console.log(`Zoom or pan event`, event); -}); -``` - -Event data for `OrbEventType.TRANSFORM` has the following properties: - -```typescript -interface IOrbEventTransform { - transform: { x: number; y: number, k: number }; -} -``` - -Properties `x` and `y` are translation coordinates while `k` stands for zoom scale. If `OrbView` -is used, `transform` data is actually same as `ZoomTransform` type from `d3` library. - -## Node dragging events - -Node dragging events are events that are emitted on node dragging which starts with a mouse click and -hold, mouse movement, and ends with mouse click release. - -> Note: Node dragging events might not be enabled on some views, e.g. `OrbMapView` which currently -> has a fixed position for each node by `latitude` and `longitude` values. - -### Event `OrbEventType.NODE_DRAG_START` - -The event is emitted when node drag starts. If a user just clicks on a node, four events will be -triggered: `OrbEventType.NODE_DRAG_START`, `OrbEventType.NODE_DRAG_END`, `OrbEventType.NODE_CLICK`, -and `OrbEventType.MOUSE_CLICK`. If you want to listen just for drag then combine `OrbEventType.NODE_DRAG` -with `OrbEventType.NODE_DRAG_(START|END)`. - -```typescript -import { OrbEventType, IOrbEventNodeDragStart } from '@memgraph/orb'; - -orb.events.on(OrbEventType.NODE_DRAG_START, (event: IOrbEventNodeDragStart) => { - console.log(`Node drag started`, event); -}); -``` - -Event data for `OrbEventType.NODE_DRAG_START` has the following properties: - -```typescript -interface IOrbEventNodeDragStart { - node: INode; - event: MouseEvent; - localPoint: { x: number; y: number }; - globalPoint: { x: number; y: number }; -} -``` - -Property `localPoint` contains the coordinates in the system of node positions, while `globalPoint` -is the original mouse coordinate on the canvas. - -### Event `OrbEventType.NODE_DRAG` - -Event is emitted on every mouse movement which is dragging a node with it. Event `OrbEventType.MOUSE_MOVE` -will also be triggered. - -```typescript -import { OrbEventType, IOrbEventNodeDrag } from '@memgraph/orb'; - -orb.events.on(OrbEventType.NODE_DRAG, (event: IOrbEventNodeDrag) => { - console.log(`Node dragged`, event); -}); -``` - -Event data for `OrbEventType.NODE_DRAG` has the following properties: - -```typescript -interface IOrbEventNodeDrag { - node: INode; - event: MouseEvent; - localPoint: { x: number; y: number }; - globalPoint: { x: number; y: number }; -} -``` - -Property `localPoint` contains the coordinates in the system of node positions, while `globalPoint` -is the original mouse coordinate on the canvas. - -### Event `OrbEventType.NODE_DRAG_END` - -The event is emitted when node drag ends. If a user just clicks on a node, four events will -be triggered: `OrbEventType.NODE_DRAG_START`, `OrbEventType.NODE_DRAG_END`, `OrbEventType.NODE_CLICK`, -and `OrbEventType.MOUSE_CLICK`. If you want to listen just for drag then combine `OrbEventType.NODE_DRAG` -with `OrbEventType.NODE_DRAG_(START|END)`. - -```typescript -import { OrbEventType, IOrbEventNodeDragEnd } from '@memgraph/orb'; - -orb.events.on(OrbEventType.NODE_DRAG_END, (event: IOrbEventNodeDragEnd) => { - console.log(`Node drag ended`, event); -}); -``` - -Event data for `OrbEventType.NODE_DRAG_END` has the following properties: - -```typescript -interface IOrbEventNodeDragEnd { - node: INode; - event: MouseEvent; - localPoint: { x: number; y: number }; - globalPoint: { x: number; y: number }; -} -``` - -Property `localPoint` contains the coordinates in the system of node positions, while `globalPoint` -is the original mouse coordinate on the canvas. diff --git a/docs/site/.gitignore b/docs/site/.gitignore new file mode 100644 index 0000000..2c1fa99 --- /dev/null +++ b/docs/site/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +.vitepress/dist/ +.vitepress/cache/ diff --git a/docs/site/.vitepress/config.ts b/docs/site/.vitepress/config.ts new file mode 100644 index 0000000..b868261 --- /dev/null +++ b/docs/site/.vitepress/config.ts @@ -0,0 +1,90 @@ +import { defineConfig } from 'vitepress'; + +// https://vitepress.dev/reference/site-config +export default defineConfig({ + // Served from https://memgraph.github.io/orb/ on GitHub Pages. + base: '/orb/', + lang: 'en-US', + title: 'Orb', + description: 'A graph visualization library by Memgraph.', + cleanUrls: true, + + // Every page has real content now; fail the build on broken internal links. + ignoreDeadLinks: false, + + head: [ + ['link', { rel: 'preconnect', href: 'https://fonts.googleapis.com' }], + ['link', { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' }], + [ + 'link', + { + rel: 'stylesheet', + href: 'https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;500;600;700;800&family=Ubuntu+Mono:wght@400;700&display=swap', + }, + ], + ], + + themeConfig: { + nav: [ + { text: 'Guide', link: '/introduction/getting-started', activeMatch: '/(introduction|concepts|layouts|rendering|views)/' }, + { text: 'Reference', link: '/reference/api', activeMatch: '/reference/' }, + { text: 'npm', link: 'https://www.npmjs.com/package/@memgraph/orb' }, + ], + + sidebar: [ + { + text: 'Introduction', + items: [ + { text: 'What is Orb', link: '/introduction/what-is-orb' }, + { text: 'Getting started', link: '/introduction/getting-started' }, + ], + }, + { + text: 'Core concepts', + items: [ + { text: 'Graph data', link: '/concepts/data' }, + { text: 'Styling', link: '/concepts/styling' }, + { text: 'Events', link: '/concepts/events' }, + { text: 'Selection & interaction', link: '/concepts/interaction' }, + ], + }, + { + text: 'Layouts', + items: [ + { text: 'Overview', link: '/layouts/overview' }, + { text: 'Force layout', link: '/layouts/force' }, + { text: 'GPU layout', link: '/layouts/gpu' }, + { text: 'Static layouts', link: '/layouts/static' }, + ], + }, + { + text: 'Rendering', + items: [ + { text: 'Canvas vs WebGL', link: '/rendering/renderers' }, + { text: 'Performance', link: '/rendering/performance' }, + { text: 'SVG export', link: '/rendering/svg-export' }, + ], + }, + { + text: 'Views', + items: [ + { text: 'Default view', link: '/views/default' }, + { text: 'Map view', link: '/views/map' }, + ], + }, + { + text: 'Reference', + items: [{ text: 'API reference', link: '/reference/api' }], + }, + ], + + socialLinks: [{ icon: 'github', link: 'https://github.com/memgraph/orb' }], + + search: { provider: 'local' }, + + footer: { + message: 'Released under the Apache-2.0 License.', + copyright: 'Copyright © 2016-present Memgraph Ltd.', + }, + }, +}); diff --git a/docs/site/.vitepress/theme/Layout.vue b/docs/site/.vitepress/theme/Layout.vue new file mode 100644 index 0000000..336487c --- /dev/null +++ b/docs/site/.vitepress/theme/Layout.vue @@ -0,0 +1,15 @@ + + + diff --git a/docs/site/.vitepress/theme/components/ExampleGallery.vue b/docs/site/.vitepress/theme/components/ExampleGallery.vue new file mode 100644 index 0000000..5606084 --- /dev/null +++ b/docs/site/.vitepress/theme/components/ExampleGallery.vue @@ -0,0 +1,149 @@ + + +