@cryptotaxi247 / CoPilot / commits / 92312123

New indices page (#90)

* added new indices marquee component * added cluster health component * create index page backup * updated indices types * updated indices page * added index details component * added Unhealthy Indices component * updated dependencies * updated indices types * added indexIcon component * added index details component * added UnhealthyIndices component * added ClusterHealth component * added IndexCard component * updated indices page * added topIndex component * added NodeAllocation component * active index check and precommit fixes * add regex to requirements * updated index error message * check if index exists after delete and precommit fixes * precommit fixes and more modular --------- Co-authored-by: Davide Di Modica <webmaster.ddm@gmail.com>

taylor_socfortress committed Aug 29, 2023 at 13:41 UTC 92312123c719e0ee964e733208375c184ee472a8
19 files changed +15589 -15103
.flake8
+1 -1
@@ -1,6 +1,6 @@
1 [flake8]
2 #max-complexity = 18
3 -max-line-length = 140
3 +max-line-length = 170
4 #select = B,C,E,F,W,T4,B9
5 #ignore = E203, E266, E501, W503, F403, F401
6 ignore = E402, W503, E231, W605
backend/app/services/Graylog/index.py
+73 -54
@@ -1,4 +1,3 @@
1 -# from datetime import datetime
1 from typing import Dict
2 from typing import List
3 from typing import Union
@@ -11,115 +10,138 @@ from app.services.Graylog.universal import UniversalService
10
11 class IndexService:
12 """
14 - A service class that encapsulates the logic for pulling index data from Graylog
13 + A service class for interacting with Graylog's index management API.
14 """
15
16 HEADERS: Dict[str, str] = {"X-Requested-By": "CoPilot"}
17 + FAILED_DETAILS_MSG: str = "Failed to collect Graylog details"
18 + FAILED_INDEX_MSG: str = "Failed to collect managed indices"
19
19 - def __init__(self):
20 + def __init__(self) -> None:
21 """
21 - Initializes the IndexService by collecting Graylog details.
22 + Initialize the IndexService by collecting Graylog details.
23 """
23 - (
24 - self.connector_url,
25 - self.connector_username,
26 - self.connector_password,
27 - ) = UniversalService().collect_graylog_details("Graylog")
24 + self.connector_url, self.connector_username, self.connector_password = UniversalService().collect_graylog_details("Graylog")
25
29 - def collect_indices(self) -> Dict[str, Union[bool, str, Dict]]:
26 + def _check_graylog_details(self) -> bool:
27 + """
28 + Checks if Graylog details are available.
29 +
30 + Returns:
31 + bool: True if all Graylog details are available, False otherwise.
32 """
31 - Collects the indices that are managed by Graylog.
33 + return all([self.connector_url, self.connector_username, self.connector_password])
34 +
35 + def _index_exists(self, index_name: str, managed_indices: Dict) -> bool:
36 + """
37 + Checks if an index exists in Graylog.
38 +
39 + Args:
40 + index_name (str): The name of the index to check.
41 + managed_indices (Dict): The managed indices information.
42
43 Returns:
34 - dict: A dictionary containing the success status, a message, and potentially a dictionary with indices.
44 + bool: True if the index exists, False otherwise.
45 + """
46 + index_names = self._extract_index_names(managed_indices)
47 + return index_name in index_names
48 +
49 + def _is_index_deleted(self, index_name: str) -> bool:
50 """
36 - if self.connector_url is None or self.connector_username is None or self.connector_password is None:
37 - return {"message": "Failed to collect Graylog details", "success": False}
51 + Checks if an index has been deleted from Graylog.
52
53 + Args:
54 + index_name (str): The name of the index to check.
55 +
56 + Returns:
57 + bool: True if the index has been deleted, False otherwise.
58 + """
59 managed_indices = self._collect_managed_indices()
60 + return managed_indices["success"] and not self._index_exists(index_name, managed_indices)
61
41 - if managed_indices["success"]:
42 - index_names = self._extract_index_names(managed_indices)
43 - managed_indices["index_names"] = index_names
62 + def collect_indices(self) -> Dict[str, Union[bool, str, Dict]]:
63 + """
64 + Collects the indices managed by Graylog.
65
66 + Returns:
67 + Dict[str, Union[bool, str, Dict]]: A dictionary containing the success status, a message, and potentially a dictionary with indices.
68 + """
69 + if not self._check_graylog_details():
70 + return {"message": self.FAILED_DETAILS_MSG, "success": False}
71 +
72 + managed_indices = self._collect_managed_indices()
73 + if managed_indices["success"]:
74 + managed_indices["index_names"] = self._extract_index_names(managed_indices)
75 return managed_indices
76
77 def _collect_managed_indices(self) -> Dict[str, Union[bool, str, Dict]]:
78 """
49 - Collects the indices that are managed by Graylog.
79 + Fetches the indices managed by Graylog.
80
81 Returns:
52 - dict: A dictionary containing the success status, a message, and potentially a dictionary with indices.
82 + Dict[str, Union[bool, str, Dict]]: A dictionary containing the success status, a message, and potentially a dictionary with indices.
83 """
84 try:
55 - managed_indices = requests.get(
85 + response = requests.get(
86 f"{self.connector_url}/api/system/indexer/indices",
87 headers=self.HEADERS,
88 auth=(self.connector_username, self.connector_password),
89 verify=False,
90 )
61 - return {
62 - "message": "Successfully collected managed indices",
63 - "success": True,
64 - "indices": managed_indices.json()["all"]["indices"],
65 - }
91 + return {"message": "Successfully collected managed indices", "success": True, "indices": response.json()["all"]["indices"]}
92 except Exception as e:
67 - logger.error(f"Failed to collect managed indices: {e}")
68 - return {"message": "Failed to collect managed indices", "success": False}
93 + logger.error(f"{self.FAILED_INDEX_MSG}: {e}")
94 + return {"message": self.FAILED_INDEX_MSG, "success": False}
95
96 def _extract_index_names(self, response: Dict[str, object]) -> List[str]:
97 """
72 - Extracts index names from the provided response.
98 + Extracts the names of indices from the Graylog response.
99
100 Args:
75 - response (dict): The dictionary containing the response.
101 + response (Dict[str, object]): The Graylog API response.
102
103 Returns:
78 - list: A list containing the index names.
104 + List[str]: A list of index names.
105 """
80 - index_names = list(response.get("indices", {}).keys())
81 - return index_names
106 + return list(response.get("indices", {}).keys())
107
108 def delete_index(self, index_name: str) -> Dict[str, Union[bool, str]]:
109 """
85 - Deletes the specified index from Graylog.
110 + Deletes a specified index from Graylog.
111
112 Args:
113 index_name (str): The name of the index to delete.
114
115 Returns:
91 - dict: A dictionary containing the response.
116 + Dict[str, Union[bool, str]]: A dictionary containing the success status and a message.
117 """
118 logger.info(f"Deleting index {index_name} from Graylog")
94 - if self.connector_url is None or self.connector_username is None or self.connector_password is None:
95 - return {"message": "Failed to collect Graylog details", "success": False}
119
97 - # Check if the index exists in Graylog
120 + if not self._check_graylog_details():
121 + return {"message": self.FAILED_DETAILS_MSG, "success": False}
122 +
123 managed_indices = self._collect_managed_indices()
99 - if managed_indices["success"]:
100 - index_names = self._extract_index_names(managed_indices)
101 - if index_name not in index_names:
124 + if managed_indices["success"] and self._index_exists(index_name, managed_indices):
125 + self._delete_index(index_name)
126 + if self._is_index_deleted(index_name):
127 + return {"message": f"Successfully deleted index {index_name} from Graylog", "success": True}
128 + else:
129 return {
103 - "message": f"Index {index_name} is not managed by Graylog",
130 + "message": f"Failed to delete index {index_name} from Graylog. Please rotate the index via Graylog's WebUI and try again.",
131 "success": False,
132 }
106 - # Invoke _delete_index
107 - return self._delete_index(index_name)
133
109 - return {
110 - "message": f"Failed to delete index {index_name} from Graylog",
111 - "success": False,
112 - }
134 + return {"message": f"Failed to delete index {index_name} from Graylog", "success": False}
135
136 def _delete_index(self, index_name: str) -> Dict[str, Union[bool, str]]:
137 """
116 - Deletes the specified index from Graylog.
138 + Deletes a specified index from Graylog.
139
140 Args:
141 index_name (str): The name of the index to delete.
142
143 Returns:
122 - dict: A dictionary containing the response.
144 + Dict[str, Union[bool, str]]: A dictionary containing the success status and a message.
145 """
146 try:
147 requests.delete(
@@ -128,13 +150,10 @@ class IndexService:
150 auth=(self.connector_username, self.connector_password),
151 verify=False,
152 )
131 - return {
132 - "message": f"Successfully deleted index {index_name} from Graylog",
133 - "success": True,
134 - }
153 + return {"message": f"Successfully deleted index {index_name} from Graylog", "success": True}
154 except Exception as e:
155 logger.error(f"Failed to delete index {index_name} from Graylog: {e}")
156 return {
138 - "message": f"Failed to delete index {index_name} from Graylog. If this is the current index, " "it cannot be deleted.",
157 + "message": f"Failed to delete index {index_name} from Graylog. Please rotate the index via Graylog's WebUI and try again.",
158 "success": False,
159 }
backend/requirements.in
+1
@@ -18,6 +18,7 @@ pika
18 psycopg2-binary
19 pytest
20 pyvelociraptor~=0.1
21 +regex
22 reportlab
23 requests
24 xmltodict
package-lock.json
+13508 -13469
@@ -1,13471 +1,13510 @@
1 {
2 - "name": "pragmatic",
3 - "version": "5.0.0",
4 - "lockfileVersion": 2,
5 - "requires": true,
6 - "packages": {
7 - "": {
8 - "name": "pragmatic",
9 - "version": "5.0.0",
10 - "dependencies": {
11 - "@element-plus/icons-vue": "^2.1.0",
12 - "@fullcalendar/core": "^5.11.5",
13 - "@fullcalendar/daygrid": "^5.11.5",
14 - "@fullcalendar/interaction": "^5.11.5",
15 - "@fullcalendar/list": "^5.11.5",
16 - "@fullcalendar/timegrid": "^5.11.5",
17 - "@fullcalendar/vue3": "^5.11.5",
18 - "@mdi/font": "^7.2.96",
19 - "@vue-leaflet/vue-leaflet": "^0.10.1",
20 - "animate.css": "^4.1.1",
21 - "balloon-css": "^1.2.0",
22 - "chance": "^1.1.11",
23 - "cryptocoins-icons": "^2.9.0",
24 - "dayjs": "^1.11.9",
25 - "detect-browser": "^5.3.0",
26 - "drift-zoom": "^1.5.1",
27 - "echarts": "^5.4.3",
28 - "element-plus": "^2.3.9",
29 - "file-saver": "^2.0.5",
30 - "flag-icon-css": "^4.1.7",
31 - "flex.box": "^3.4.4",
32 - "leaflet": "^1.9.4",
33 - "lodash": "^4.17.21",
34 - "mapbox-gl": "^2.15.0",
35 - "marquee-infinite": "^0.0.4",
36 - "mavon-editor": "^3.0.1",
37 - "open-props": "^1.5.11",
38 - "papaparse": "^5.4.1",
39 - "pell": "^1.0.6",
40 - "perfect-scrollbar": "^1.5.5",
41 - "pinia": "2.0.22",
42 - "pinia-plugin-persistedstate": "^2.2.0",
43 - "quill": "^1.3.7",
44 - "tui-grid": "^4.21.15",
45 - "v-click-outside": "^3.2.0",
46 - "v-viewer": "3.0.11",
47 - "validator": "^13.11.0",
48 - "vue": "^3.3.4",
49 - "vue-chartkick": "^1.1.0",
50 - "vue-fullscreen": "^3.1.1",
51 - "vue-i18n": "^9.2.2",
52 - "vue-router": "^4.2.4",
53 - "vue-virtual-collection": "^1.5.0",
54 - "vue3-highlightjs": "^1.0.5",
55 - "vue3-marquee": "^4.0.0",
56 - "vue3-marquee-slider": "^1.0.5",
57 - "vue3-tui-grid": "^0.1.51"
58 - },
59 - "devDependencies": {
60 - "@rushstack/eslint-patch": "^1.3.3",
61 - "@types/jsdom": "^21.1.1",
62 - "@types/node": "^20.5.0",
63 - "@vitejs/plugin-vue": "^4.2.3",
64 - "@vue/eslint-config-prettier": "^8.0.0",
65 - "@vue/eslint-config-typescript": "^11.0.3",
66 - "@vue/test-utils": "^2.4.1",
67 - "@vue/tsconfig": "^0.4.0",
68 - "cypress": "^12.17.4",
69 - "eslint": "^8.47.0",
70 - "eslint-plugin-cypress": "^2.14.0",
71 - "eslint-plugin-vue": "^9.17.0",
72 - "jsdom": "^22.1.0",
73 - "npm-run-all": "^4.1.5",
74 - "prettier": "^3.0.2",
75 - "sass": "^1.65.1",
76 - "start-server-and-test": "^2.0.0",
77 - "typescript": "~5.1.6",
78 - "url": "^0.11.1",
79 - "vite": "^4.4.9",
80 - "vitest": "^0.34.1",
81 - "vue-tsc": "^1.8.8"
82 - }
83 - },
84 - "node_modules/@aashutoshrathi/word-wrap": {
85 - "version": "1.2.6",
86 - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
87 - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
88 - "dev": true,
89 - "engines": {
90 - "node": ">=0.10.0"
91 - }
92 - },
93 - "node_modules/@babel/parser": {
94 - "version": "7.22.10",
95 - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz",
96 - "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==",
97 - "bin": {
98 - "parser": "bin/babel-parser.js"
99 - },
100 - "engines": {
101 - "node": ">=6.0.0"
102 - }
103 - },
104 - "node_modules/@colors/colors": {
105 - "version": "1.5.0",
106 - "dev": true,
107 - "license": "MIT",
108 - "optional": true,
109 - "engines": {
110 - "node": ">=0.1.90"
111 - }
112 - },
113 - "node_modules/@ctrl/tinycolor": {
114 - "version": "3.4.1",
115 - "license": "MIT",
116 - "engines": {
117 - "node": ">=10"
118 - }
119 - },
120 - "node_modules/@cypress/request": {
121 - "version": "2.88.12",
122 - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.12.tgz",
123 - "integrity": "sha512-tOn+0mDZxASFM+cuAP9szGUGPI1HwWVSvdzm7V4cCsPdFTx6qMj29CwaQmRAMIEhORIUBFBsYROYJcveK4uOjA==",
124 - "dev": true,
125 - "dependencies": {
126 - "aws-sign2": "~0.7.0",
127 - "aws4": "^1.8.0",
128 - "caseless": "~0.12.0",
129 - "combined-stream": "~1.0.6",
130 - "extend": "~3.0.2",
131 - "forever-agent": "~0.6.1",
132 - "form-data": "~2.3.2",
133 - "http-signature": "~1.3.6",
134 - "is-typedarray": "~1.0.0",
135 - "isstream": "~0.1.2",
136 - "json-stringify-safe": "~5.0.1",
137 - "mime-types": "~2.1.19",
138 - "performance-now": "^2.1.0",
139 - "qs": "~6.10.3",
140 - "safe-buffer": "^5.1.2",
141 - "tough-cookie": "^4.1.3",
142 - "tunnel-agent": "^0.6.0",
143 - "uuid": "^8.3.2"
144 - },
145 - "engines": {
146 - "node": ">= 6"
147 - }
148 - },
149 - "node_modules/@cypress/xvfb": {
150 - "version": "1.2.4",
151 - "dev": true,
152 - "license": "MIT",
153 - "dependencies": {
154 - "debug": "^3.1.0",
155 - "lodash.once": "^4.1.1"
156 - }
157 - },
158 - "node_modules/@cypress/xvfb/node_modules/debug": {
159 - "version": "3.2.7",
160 - "dev": true,
161 - "license": "MIT",
162 - "dependencies": {
163 - "ms": "^2.1.1"
164 - }
165 - },
166 - "node_modules/@element-plus/icons-vue": {
167 - "version": "2.1.0",
168 - "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.1.0.tgz",
169 - "integrity": "sha512-PSBn3elNoanENc1vnCfh+3WA9fimRC7n+fWkf3rE5jvv+aBohNHABC/KAR5KWPecxWxDTVT1ERpRbOMRcOV/vA==",
170 - "peerDependencies": {
171 - "vue": "^3.2.0"
172 - }
173 - },
174 - "node_modules/@esbuild/android-arm": {
175 - "version": "0.18.20",
176 - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
177 - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
178 - "cpu": [
179 - "arm"
180 - ],
181 - "dev": true,
182 - "optional": true,
183 - "os": [
184 - "android"
185 - ],
186 - "engines": {
187 - "node": ">=12"
188 - }
189 - },
190 - "node_modules/@esbuild/android-arm64": {
191 - "version": "0.18.20",
192 - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
193 - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
194 - "cpu": [
195 - "arm64"
196 - ],
197 - "dev": true,
198 - "optional": true,
199 - "os": [
200 - "android"
201 - ],
202 - "engines": {
203 - "node": ">=12"
204 - }
205 - },
206 - "node_modules/@esbuild/android-x64": {
207 - "version": "0.18.20",
208 - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
209 - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
210 - "cpu": [
211 - "x64"
212 - ],
213 - "dev": true,
214 - "optional": true,
215 - "os": [
216 - "android"
217 - ],
218 - "engines": {
219 - "node": ">=12"
220 - }
221 - },
222 - "node_modules/@esbuild/darwin-arm64": {
223 - "version": "0.18.20",
224 - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
225 - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
226 - "cpu": [
227 - "arm64"
228 - ],
229 - "dev": true,
230 - "optional": true,
231 - "os": [
232 - "darwin"
233 - ],
234 - "engines": {
235 - "node": ">=12"
236 - }
237 - },
238 - "node_modules/@esbuild/darwin-x64": {
239 - "version": "0.18.20",
240 - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
241 - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
242 - "cpu": [
243 - "x64"
244 - ],
245 - "dev": true,
246 - "optional": true,
247 - "os": [
248 - "darwin"
249 - ],
250 - "engines": {
251 - "node": ">=12"
252 - }
253 - },
254 - "node_modules/@esbuild/freebsd-arm64": {
255 - "version": "0.18.20",
256 - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
257 - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
258 - "cpu": [
259 - "arm64"
260 - ],
261 - "dev": true,
262 - "optional": true,
263 - "os": [
264 - "freebsd"
265 - ],
266 - "engines": {
267 - "node": ">=12"
268 - }
269 - },
270 - "node_modules/@esbuild/freebsd-x64": {
271 - "version": "0.18.20",
272 - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
273 - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
274 - "cpu": [
275 - "x64"
276 - ],
277 - "dev": true,
278 - "optional": true,
279 - "os": [
280 - "freebsd"
281 - ],
282 - "engines": {
283 - "node": ">=12"
284 - }
285 - },
286 - "node_modules/@esbuild/linux-arm": {
287 - "version": "0.18.20",
288 - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
289 - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
290 - "cpu": [
291 - "arm"
292 - ],
293 - "dev": true,
294 - "optional": true,
295 - "os": [
296 - "linux"
297 - ],
298 - "engines": {
299 - "node": ">=12"
300 - }
301 - },
302 - "node_modules/@esbuild/linux-arm64": {
303 - "version": "0.18.20",
304 - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
305 - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
306 - "cpu": [
307 - "arm64"
308 - ],
309 - "dev": true,
310 - "optional": true,
311 - "os": [
312 - "linux"
313 - ],
314 - "engines": {
315 - "node": ">=12"
316 - }
317 - },
318 - "node_modules/@esbuild/linux-ia32": {
319 - "version": "0.18.20",
320 - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
321 - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
322 - "cpu": [
323 - "ia32"
324 - ],
325 - "dev": true,
326 - "optional": true,
327 - "os": [
328 - "linux"
329 - ],
330 - "engines": {
331 - "node": ">=12"
332 - }
333 - },
334 - "node_modules/@esbuild/linux-loong64": {
335 - "version": "0.18.20",
336 - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
337 - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
338 - "cpu": [
339 - "loong64"
340 - ],
341 - "dev": true,
342 - "optional": true,
343 - "os": [
344 - "linux"
345 - ],
346 - "engines": {
347 - "node": ">=12"
348 - }
349 - },
350 - "node_modules/@esbuild/linux-mips64el": {
351 - "version": "0.18.20",
352 - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
353 - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
354 - "cpu": [
355 - "mips64el"
356 - ],
357 - "dev": true,
358 - "optional": true,
359 - "os": [
360 - "linux"
361 - ],
362 - "engines": {
363 - "node": ">=12"
364 - }
365 - },
366 - "node_modules/@esbuild/linux-ppc64": {
367 - "version": "0.18.20",
368 - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
369 - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
370 - "cpu": [
371 - "ppc64"
372 - ],
373 - "dev": true,
374 - "optional": true,
375 - "os": [
376 - "linux"
377 - ],
378 - "engines": {
379 - "node": ">=12"
380 - }
381 - },
382 - "node_modules/@esbuild/linux-riscv64": {
383 - "version": "0.18.20",
384 - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
385 - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
386 - "cpu": [
387 - "riscv64"
388 - ],
389 - "dev": true,
390 - "optional": true,
391 - "os": [
392 - "linux"
393 - ],
394 - "engines": {
395 - "node": ">=12"
396 - }
397 - },
398 - "node_modules/@esbuild/linux-s390x": {
399 - "version": "0.18.20",
400 - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
401 - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
402 - "cpu": [
403 - "s390x"
404 - ],
405 - "dev": true,
406 - "optional": true,
407 - "os": [
408 - "linux"
409 - ],
410 - "engines": {
411 - "node": ">=12"
412 - }
413 - },
414 - "node_modules/@esbuild/linux-x64": {
415 - "version": "0.18.20",
416 - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
417 - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
418 - "cpu": [
419 - "x64"
420 - ],
421 - "dev": true,
422 - "optional": true,
423 - "os": [
424 - "linux"
425 - ],
426 - "engines": {
427 - "node": ">=12"
428 - }
429 - },
430 - "node_modules/@esbuild/netbsd-x64": {
431 - "version": "0.18.20",
432 - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
433 - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
434 - "cpu": [
435 - "x64"
436 - ],
437 - "dev": true,
438 - "optional": true,
439 - "os": [
440 - "netbsd"
441 - ],
442 - "engines": {
443 - "node": ">=12"
444 - }
445 - },
446 - "node_modules/@esbuild/openbsd-x64": {
447 - "version": "0.18.20",
448 - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
449 - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
450 - "cpu": [
451 - "x64"
452 - ],
453 - "dev": true,
454 - "optional": true,
455 - "os": [
456 - "openbsd"
457 - ],
458 - "engines": {
459 - "node": ">=12"
460 - }
461 - },
462 - "node_modules/@esbuild/sunos-x64": {
463 - "version": "0.18.20",
464 - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
465 - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
466 - "cpu": [
467 - "x64"
468 - ],
469 - "dev": true,
470 - "optional": true,
471 - "os": [
472 - "sunos"
473 - ],
474 - "engines": {
475 - "node": ">=12"
476 - }
477 - },
478 - "node_modules/@esbuild/win32-arm64": {
479 - "version": "0.18.20",
480 - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
481 - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
482 - "cpu": [
483 - "arm64"
484 - ],
485 - "dev": true,
486 - "optional": true,
487 - "os": [
488 - "win32"
489 - ],
490 - "engines": {
491 - "node": ">=12"
492 - }
493 - },
494 - "node_modules/@esbuild/win32-ia32": {
495 - "version": "0.18.20",
496 - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
497 - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
498 - "cpu": [
499 - "ia32"
500 - ],
501 - "dev": true,
502 - "optional": true,
503 - "os": [
504 - "win32"
505 - ],
506 - "engines": {
507 - "node": ">=12"
508 - }
509 - },
510 - "node_modules/@esbuild/win32-x64": {
511 - "version": "0.18.20",
512 - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
513 - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
514 - "cpu": [
515 - "x64"
516 - ],
517 - "dev": true,
518 - "optional": true,
519 - "os": [
520 - "win32"
521 - ],
522 - "engines": {
523 - "node": ">=12"
524 - }
525 - },
526 - "node_modules/@eslint-community/eslint-utils": {
527 - "version": "4.4.0",
528 - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
529 - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
530 - "dev": true,
531 - "dependencies": {
532 - "eslint-visitor-keys": "^3.3.0"
533 - },
534 - "engines": {
535 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
536 - },
537 - "peerDependencies": {
538 - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
539 - }
540 - },
541 - "node_modules/@eslint-community/regexpp": {
542 - "version": "4.6.2",
543 - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz",
544 - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==",
545 - "dev": true,
546 - "engines": {
547 - "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
548 - }
549 - },
550 - "node_modules/@eslint/eslintrc": {
551 - "version": "2.1.2",
552 - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz",
553 - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==",
554 - "dev": true,
555 - "dependencies": {
556 - "ajv": "^6.12.4",
557 - "debug": "^4.3.2",
558 - "espree": "^9.6.0",
559 - "globals": "^13.19.0",
560 - "ignore": "^5.2.0",
561 - "import-fresh": "^3.2.1",
562 - "js-yaml": "^4.1.0",
563 - "minimatch": "^3.1.2",
564 - "strip-json-comments": "^3.1.1"
565 - },
566 - "engines": {
567 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
568 - },
569 - "funding": {
570 - "url": "https://opencollective.com/eslint"
571 - }
572 - },
573 - "node_modules/@eslint/js": {
574 - "version": "8.47.0",
575 - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz",
576 - "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==",
577 - "dev": true,
578 - "engines": {
579 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
580 - }
581 - },
582 - "node_modules/@floating-ui/core": {
583 - "version": "1.0.1",
584 - "license": "MIT"
585 - },
586 - "node_modules/@floating-ui/dom": {
587 - "version": "1.0.1",
588 - "license": "MIT",
589 - "dependencies": {
590 - "@floating-ui/core": "^1.0.1"
591 - }
592 - },
593 - "node_modules/@fullcalendar/common": {
594 - "version": "5.11.5",
595 - "resolved": "https://registry.npmjs.org/@fullcalendar/common/-/common-5.11.5.tgz",
596 - "integrity": "sha512-3iAYiUbHXhjSVXnYWz27Od2cslztUPsOwiwKlfGvQxBixv2Kl6a8IPwaijKFYJHXdwYmfPoEgK7rvqAGVoIYwA==",
597 - "dependencies": {
598 - "tslib": "^2.1.0"
599 - }
600 - },
601 - "node_modules/@fullcalendar/core": {
602 - "version": "5.11.5",
603 - "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-5.11.5.tgz",
604 - "integrity": "sha512-M/WQuq1+uUHxFDEIu2ib/aaPZ70VsRk2ITECo/WCLSLTVWcHPXwEg83reyP3G8JrMM4gRL4vScEHhX0U5aoNSw==",
605 - "dependencies": {
606 - "@fullcalendar/common": "~5.11.5",
607 - "preact": "~10.12.1",
608 - "tslib": "^2.1.0"
609 - }
610 - },
611 - "node_modules/@fullcalendar/daygrid": {
612 - "version": "5.11.5",
613 - "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-5.11.5.tgz",
614 - "integrity": "sha512-hMpq0U3Nucys2jDD+crbkJCr+tVt3fDw04OE3fbpisuzqtrHxIzRmnUOdbWUjJQyToAAkt7UVUQ9E7hYdmvyGA==",
615 - "dependencies": {
616 - "@fullcalendar/common": "~5.11.5",
617 - "tslib": "^2.1.0"
618 - }
619 - },
620 - "node_modules/@fullcalendar/interaction": {
621 - "version": "5.11.5",
622 - "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-5.11.5.tgz",
623 - "integrity": "sha512-Vg9uw8zKXZc2RP7it88U8R/kxJIQsK4pyv+s+RhlvT5NBZ9KLOh5y2xGCS4A4hyY7qLrzugxnKYlu6NwNqJ/RQ==",
624 - "dependencies": {
625 - "@fullcalendar/common": "~5.11.5",
626 - "tslib": "^2.1.0"
627 - }
628 - },
629 - "node_modules/@fullcalendar/list": {
630 - "version": "5.11.5",
631 - "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-5.11.5.tgz",
632 - "integrity": "sha512-ZYMPT4CVt9tIYkVVNx7CKkB2xc+n9L56+vgXkurptgYgPsacXYkcpF/1Hy/B5LKlg0ROEF9Qfftjow8xjANqaA==",
633 - "dependencies": {
634 - "@fullcalendar/common": "~5.11.5",
635 - "tslib": "^2.1.0"
636 - }
637 - },
638 - "node_modules/@fullcalendar/timegrid": {
639 - "version": "5.11.5",
640 - "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-5.11.5.tgz",
641 - "integrity": "sha512-OEH5mrTclwxgUbb51N6qr7ifzNkR74ygUEFpiMLyyUjkp7a76N6BsAP5mBQnTOpTTUZBu9tAOmfcnvi7skUayQ==",
642 - "dependencies": {
643 - "@fullcalendar/common": "~5.11.5",
644 - "@fullcalendar/daygrid": "~5.11.5",
645 - "tslib": "^2.1.0"
646 - }
647 - },
648 - "node_modules/@fullcalendar/vue3": {
649 - "version": "5.11.5",
650 - "resolved": "https://registry.npmjs.org/@fullcalendar/vue3/-/vue3-5.11.5.tgz",
651 - "integrity": "sha512-813zzFAuW9/ysysLhjxFKIThUrT23qjf1EKymyj0tCnrFtfTrpbk1k/txRQ5dwITanHEU3iFxgE/d+PlswL/bg==",
652 - "dependencies": {
653 - "@fullcalendar/core": "~5.11.5",
654 - "tslib": "^2.1.0"
655 - },
656 - "peerDependencies": {
657 - "vue": "^3.0.11"
658 - }
659 - },
660 - "node_modules/@hapi/hoek": {
661 - "version": "9.3.0",
662 - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
663 - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==",
664 - "dev": true
665 - },
666 - "node_modules/@hapi/topo": {
667 - "version": "5.1.0",
668 - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz",
669 - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
670 - "dev": true,
671 - "dependencies": {
672 - "@hapi/hoek": "^9.0.0"
673 - }
674 - },
675 - "node_modules/@humanwhocodes/config-array": {
676 - "version": "0.11.10",
677 - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
678 - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
679 - "dev": true,
680 - "dependencies": {
681 - "@humanwhocodes/object-schema": "^1.2.1",
682 - "debug": "^4.1.1",
683 - "minimatch": "^3.0.5"
684 - },
685 - "engines": {
686 - "node": ">=10.10.0"
687 - }
688 - },
689 - "node_modules/@humanwhocodes/module-importer": {
690 - "version": "1.0.1",
691 - "dev": true,
692 - "license": "Apache-2.0",
693 - "engines": {
694 - "node": ">=12.22"
695 - },
696 - "funding": {
697 - "type": "github",
698 - "url": "https://github.com/sponsors/nzakas"
699 - }
700 - },
701 - "node_modules/@humanwhocodes/object-schema": {
702 - "version": "1.2.1",
703 - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
704 - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
705 - "dev": true
706 - },
707 - "node_modules/@intlify/core-base": {
708 - "version": "9.2.2",
709 - "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.2.2.tgz",
710 - "integrity": "sha512-JjUpQtNfn+joMbrXvpR4hTF8iJQ2sEFzzK3KIESOx+f+uwIjgw20igOyaIdhfsVVBCds8ZM64MoeNSx+PHQMkA==",
711 - "dependencies": {
712 - "@intlify/devtools-if": "9.2.2",
713 - "@intlify/message-compiler": "9.2.2",
714 - "@intlify/shared": "9.2.2",
715 - "@intlify/vue-devtools": "9.2.2"
716 - },
717 - "engines": {
718 - "node": ">= 14"
719 - }
720 - },
721 - "node_modules/@intlify/devtools-if": {
722 - "version": "9.2.2",
723 - "resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.2.2.tgz",
724 - "integrity": "sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==",
725 - "dependencies": {
726 - "@intlify/shared": "9.2.2"
727 - },
728 - "engines": {
729 - "node": ">= 14"
730 - }
731 - },
732 - "node_modules/@intlify/message-compiler": {
733 - "version": "9.2.2",
734 - "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.2.2.tgz",
735 - "integrity": "sha512-IUrQW7byAKN2fMBe8z6sK6riG1pue95e5jfokn8hA5Q3Bqy4MBJ5lJAofUsawQJYHeoPJ7svMDyBaVJ4d0GTtA==",
736 - "dependencies": {
737 - "@intlify/shared": "9.2.2",
738 - "source-map": "0.6.1"
739 - },
740 - "engines": {
741 - "node": ">= 14"
742 - }
743 - },
744 - "node_modules/@intlify/shared": {
745 - "version": "9.2.2",
746 - "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.2.2.tgz",
747 - "integrity": "sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==",
748 - "engines": {
749 - "node": ">= 14"
750 - }
751 - },
752 - "node_modules/@intlify/vue-devtools": {
753 - "version": "9.2.2",
754 - "resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.2.2.tgz",
755 - "integrity": "sha512-+dUyqyCHWHb/UcvY1MlIpO87munedm3Gn6E9WWYdWrMuYLcoIoOEVDWSS8xSwtlPU+kA+MEQTP6Q1iI/ocusJg==",
756 - "dependencies": {
757 - "@intlify/core-base": "9.2.2",
758 - "@intlify/shared": "9.2.2"
759 - },
760 - "engines": {
761 - "node": ">= 14"
762 - }
763 - },
764 - "node_modules/@jest/schemas": {
765 - "version": "29.6.0",
766 - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz",
767 - "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==",
768 - "dev": true,
769 - "dependencies": {
770 - "@sinclair/typebox": "^0.27.8"
771 - },
772 - "engines": {
773 - "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
774 - }
775 - },
776 - "node_modules/@jridgewell/gen-mapping": {
777 - "version": "0.3.2",
778 - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
779 - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
780 - "dev": true,
781 - "optional": true,
782 - "peer": true,
783 - "dependencies": {
784 - "@jridgewell/set-array": "^1.0.1",
785 - "@jridgewell/sourcemap-codec": "^1.4.10",
786 - "@jridgewell/trace-mapping": "^0.3.9"
787 - },
788 - "engines": {
789 - "node": ">=6.0.0"
790 - }
791 - },
792 - "node_modules/@jridgewell/resolve-uri": {
793 - "version": "3.1.0",
794 - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
795 - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
796 - "dev": true,
797 - "optional": true,
798 - "peer": true,
799 - "engines": {
800 - "node": ">=6.0.0"
801 - }
802 - },
803 - "node_modules/@jridgewell/set-array": {
804 - "version": "1.1.2",
805 - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
806 - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
807 - "dev": true,
808 - "optional": true,
809 - "peer": true,
810 - "engines": {
811 - "node": ">=6.0.0"
812 - }
813 - },
814 - "node_modules/@jridgewell/source-map": {
815 - "version": "0.3.2",
816 - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
817 - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
818 - "dev": true,
819 - "optional": true,
820 - "peer": true,
821 - "dependencies": {
822 - "@jridgewell/gen-mapping": "^0.3.0",
823 - "@jridgewell/trace-mapping": "^0.3.9"
824 - }
825 - },
826 - "node_modules/@jridgewell/sourcemap-codec": {
827 - "version": "1.4.15",
828 - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
829 - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
830 - },
831 - "node_modules/@jridgewell/trace-mapping": {
832 - "version": "0.3.15",
833 - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz",
834 - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==",
835 - "dev": true,
836 - "optional": true,
837 - "peer": true,
838 - "dependencies": {
839 - "@jridgewell/resolve-uri": "^3.0.3",
840 - "@jridgewell/sourcemap-codec": "^1.4.10"
841 - }
842 - },
843 - "node_modules/@mapbox/geojson-rewind": {
844 - "version": "0.5.2",
845 - "resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz",
846 - "integrity": "sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==",
847 - "dependencies": {
848 - "get-stream": "^6.0.1",
849 - "minimist": "^1.2.6"
850 - },
851 - "bin": {
852 - "geojson-rewind": "geojson-rewind"
853 - }
854 - },
855 - "node_modules/@mapbox/geojson-rewind/node_modules/get-stream": {
856 - "version": "6.0.1",
857 - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
858 - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
859 - "engines": {
860 - "node": ">=10"
861 - },
862 - "funding": {
863 - "url": "https://github.com/sponsors/sindresorhus"
864 - }
865 - },
866 - "node_modules/@mapbox/jsonlint-lines-primitives": {
867 - "version": "2.0.2",
868 - "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz",
869 - "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==",
870 - "engines": {
871 - "node": ">= 0.6"
872 - }
873 - },
874 - "node_modules/@mapbox/mapbox-gl-supported": {
875 - "version": "2.0.1",
876 - "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-2.0.1.tgz",
877 - "integrity": "sha512-HP6XvfNIzfoMVfyGjBckjiAOQK9WfX0ywdLubuPMPv+Vqf5fj0uCbgBQYpiqcWZT6cbyyRnTSXDheT1ugvF6UQ=="
878 - },
879 - "node_modules/@mapbox/point-geometry": {
880 - "version": "0.1.0",
881 - "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz",
882 - "integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ=="
883 - },
884 - "node_modules/@mapbox/tiny-sdf": {
885 - "version": "2.0.6",
886 - "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz",
887 - "integrity": "sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA=="
888 - },
889 - "node_modules/@mapbox/unitbezier": {
890 - "version": "0.0.1",
891 - "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz",
892 - "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw=="
893 - },
894 - "node_modules/@mapbox/vector-tile": {
895 - "version": "1.3.1",
896 - "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz",
897 - "integrity": "sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==",
898 - "dependencies": {
899 - "@mapbox/point-geometry": "~0.1.0"
900 - }
901 - },
902 - "node_modules/@mapbox/whoots-js": {
903 - "version": "3.1.0",
904 - "resolved": "https://registry.npmjs.org/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz",
905 - "integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==",
906 - "engines": {
907 - "node": ">=6.0.0"
908 - }
909 - },
910 - "node_modules/@mdi/font": {
911 - "version": "7.2.96",
912 - "resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.2.96.tgz",
913 - "integrity": "sha512-e//lmkmpFUMZKhmCY9zdjRe4zNXfbOIJnn6xveHbaV2kSw5aJ5dLXUxcRt1Gxfi7ZYpFLUWlkG2MGSFAiqAu7w=="
914 - },
915 - "node_modules/@nodelib/fs.scandir": {
916 - "version": "2.1.5",
917 - "dev": true,
918 - "license": "MIT",
919 - "dependencies": {
920 - "@nodelib/fs.stat": "2.0.5",
921 - "run-parallel": "^1.1.9"
922 - },
923 - "engines": {
924 - "node": ">= 8"
925 - }
926 - },
927 - "node_modules/@nodelib/fs.stat": {
928 - "version": "2.0.5",
929 - "dev": true,
930 - "license": "MIT",
931 - "engines": {
932 - "node": ">= 8"
933 - }
934 - },
935 - "node_modules/@nodelib/fs.walk": {
936 - "version": "1.2.8",
937 - "dev": true,
938 - "license": "MIT",
939 - "dependencies": {
940 - "@nodelib/fs.scandir": "2.1.5",
941 - "fastq": "^1.6.0"
942 - },
943 - "engines": {
944 - "node": ">= 8"
945 - }
946 - },
947 - "node_modules/@one-ini/wasm": {
948 - "version": "0.1.1",
949 - "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
950 - "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==",
951 - "dev": true
952 - },
953 - "node_modules/@pkgr/utils": {
954 - "version": "2.4.2",
955 - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz",
956 - "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==",
957 - "dev": true,
958 - "dependencies": {
959 - "cross-spawn": "^7.0.3",
960 - "fast-glob": "^3.3.0",
961 - "is-glob": "^4.0.3",
962 - "open": "^9.1.0",
963 - "picocolors": "^1.0.0",
964 - "tslib": "^2.6.0"
965 - },
966 - "engines": {
967 - "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
968 - },
969 - "funding": {
970 - "url": "https://opencollective.com/unts"
971 - }
972 - },
973 - "node_modules/@pkgr/utils/node_modules/tslib": {
974 - "version": "2.6.1",
975 - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
976 - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==",
977 - "dev": true
978 - },
979 - "node_modules/@popperjs/core": {
980 - "name": "@sxzz/popperjs-es",
981 - "version": "2.11.7",
982 - "license": "MIT",
983 - "funding": {
984 - "type": "opencollective",
985 - "url": "https://opencollective.com/popperjs"
986 - }
987 - },
988 - "node_modules/@rushstack/eslint-patch": {
989 - "version": "1.3.3",
990 - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.3.tgz",
991 - "integrity": "sha512-0xd7qez0AQ+MbHatZTlI1gu5vkG8r7MYRUJAHPAHJBmGLs16zpkrpAVLvjQKQOqaXPDUBwOiJzNc00znHSCVBw==",
992 - "dev": true
993 - },
994 - "node_modules/@sideway/address": {
995 - "version": "4.1.4",
996 - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
997 - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==",
998 - "dev": true,
999 - "dependencies": {
1000 - "@hapi/hoek": "^9.0.0"
1001 - }
1002 - },
1003 - "node_modules/@sideway/formula": {
1004 - "version": "3.0.1",
1005 - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz",
1006 - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==",
1007 - "dev": true
1008 - },
1009 - "node_modules/@sideway/pinpoint": {
1010 - "version": "2.0.0",
1011 - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
1012 - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==",
1013 - "dev": true
1014 - },
1015 - "node_modules/@sinclair/typebox": {
1016 - "version": "0.27.8",
1017 - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
1018 - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
1019 - "dev": true
1020 - },
1021 - "node_modules/@tootallnate/once": {
1022 - "version": "2.0.0",
1023 - "dev": true,
1024 - "license": "MIT",
1025 - "engines": {
1026 - "node": ">= 10"
1027 - }
1028 - },
1029 - "node_modules/@types/chai": {
1030 - "version": "4.3.5",
1031 - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz",
1032 - "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==",
1033 - "dev": true
1034 - },
1035 - "node_modules/@types/chai-subset": {
1036 - "version": "1.3.3",
1037 - "dev": true,
1038 - "license": "MIT",
1039 - "dependencies": {
1040 - "@types/chai": "*"
1041 - }
1042 - },
1043 - "node_modules/@types/geojson": {
1044 - "version": "7946.0.10",
1045 - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz",
1046 - "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==",
1047 - "optional": true,
1048 - "peer": true
1049 - },
1050 - "node_modules/@types/jsdom": {
1051 - "version": "21.1.1",
1052 - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.1.tgz",
1053 - "integrity": "sha512-cZFuoVLtzKP3gmq9eNosUL1R50U+USkbLtUQ1bYVgl/lKp0FZM7Cq4aIHAL8oIvQ17uSHi7jXPtfDOdjPwBE7A==",
1054 - "dev": true,
1055 - "dependencies": {
1056 - "@types/node": "*",
1057 - "@types/tough-cookie": "*",
1058 - "parse5": "^7.0.0"
1059 - }
1060 - },
1061 - "node_modules/@types/json-schema": {
1062 - "version": "7.0.12",
1063 - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
1064 - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==",
1065 - "dev": true
1066 - },
1067 - "node_modules/@types/leaflet": {
1068 - "version": "1.7.11",
1069 - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.11.tgz",
1070 - "integrity": "sha512-VwAYom2pfIAf/pLj1VR5aLltd4tOtHyvfaJlNYCoejzP2nu52PrMi1ehsLRMUS+bgafmIIKBV1cMfKeS+uJ0Vg==",
1071 - "optional": true,
1072 - "peer": true,
1073 - "dependencies": {
1074 - "@types/geojson": "*"
1075 - }
1076 - },
1077 - "node_modules/@types/lodash": {
1078 - "version": "4.14.184",
1079 - "license": "MIT"
1080 - },
1081 - "node_modules/@types/lodash-es": {
1082 - "version": "4.17.6",
1083 - "license": "MIT",
1084 - "dependencies": {
1085 - "@types/lodash": "*"
1086 - }
1087 - },
1088 - "node_modules/@types/node": {
1089 - "version": "20.5.0",
1090 - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz",
1091 - "integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==",
1092 - "dev": true
1093 - },
1094 - "node_modules/@types/semver": {
1095 - "version": "7.5.0",
1096 - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz",
1097 - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==",
1098 - "dev": true
1099 - },
1100 - "node_modules/@types/sinonjs__fake-timers": {
1101 - "version": "8.1.1",
1102 - "dev": true,
1103 - "license": "MIT"
1104 - },
1105 - "node_modules/@types/sizzle": {
1106 - "version": "2.3.3",
1107 - "dev": true,
1108 - "license": "MIT"
1109 - },
1110 - "node_modules/@types/tough-cookie": {
1111 - "version": "4.0.2",
1112 - "dev": true,
1113 - "license": "MIT"
1114 - },
1115 - "node_modules/@types/web-bluetooth": {
1116 - "version": "0.0.15",
1117 - "license": "MIT"
1118 - },
1119 - "node_modules/@types/yauzl": {
1120 - "version": "2.10.0",
1121 - "dev": true,
1122 - "license": "MIT",
1123 - "optional": true,
1124 - "dependencies": {
1125 - "@types/node": "*"
1126 - }
1127 - },
1128 - "node_modules/@typescript-eslint/eslint-plugin": {
1129 - "version": "5.62.0",
1130 - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz",
1131 - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==",
1132 - "dev": true,
1133 - "dependencies": {
1134 - "@eslint-community/regexpp": "^4.4.0",
1135 - "@typescript-eslint/scope-manager": "5.62.0",
1136 - "@typescript-eslint/type-utils": "5.62.0",
1137 - "@typescript-eslint/utils": "5.62.0",
1138 - "debug": "^4.3.4",
1139 - "graphemer": "^1.4.0",
1140 - "ignore": "^5.2.0",
1141 - "natural-compare-lite": "^1.4.0",
1142 - "semver": "^7.3.7",
1143 - "tsutils": "^3.21.0"
1144 - },
1145 - "engines": {
1146 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1147 - },
1148 - "funding": {
1149 - "type": "opencollective",
1150 - "url": "https://opencollective.com/typescript-eslint"
1151 - },
1152 - "peerDependencies": {
1153 - "@typescript-eslint/parser": "^5.0.0",
1154 - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
1155 - },
1156 - "peerDependenciesMeta": {
1157 - "typescript": {
1158 - "optional": true
1159 - }
1160 - }
1161 - },
1162 - "node_modules/@typescript-eslint/parser": {
1163 - "version": "5.62.0",
1164 - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz",
1165 - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==",
1166 - "dev": true,
1167 - "dependencies": {
1168 - "@typescript-eslint/scope-manager": "5.62.0",
1169 - "@typescript-eslint/types": "5.62.0",
1170 - "@typescript-eslint/typescript-estree": "5.62.0",
1171 - "debug": "^4.3.4"
1172 - },
1173 - "engines": {
1174 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1175 - },
1176 - "funding": {
1177 - "type": "opencollective",
1178 - "url": "https://opencollective.com/typescript-eslint"
1179 - },
1180 - "peerDependencies": {
1181 - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
1182 - },
1183 - "peerDependenciesMeta": {
1184 - "typescript": {
1185 - "optional": true
1186 - }
1187 - }
1188 - },
1189 - "node_modules/@typescript-eslint/scope-manager": {
1190 - "version": "5.62.0",
1191 - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz",
1192 - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==",
1193 - "dev": true,
1194 - "dependencies": {
1195 - "@typescript-eslint/types": "5.62.0",
1196 - "@typescript-eslint/visitor-keys": "5.62.0"
1197 - },
1198 - "engines": {
1199 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1200 - },
1201 - "funding": {
1202 - "type": "opencollective",
1203 - "url": "https://opencollective.com/typescript-eslint"
1204 - }
1205 - },
1206 - "node_modules/@typescript-eslint/type-utils": {
1207 - "version": "5.62.0",
1208 - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz",
1209 - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==",
1210 - "dev": true,
1211 - "dependencies": {
1212 - "@typescript-eslint/typescript-estree": "5.62.0",
1213 - "@typescript-eslint/utils": "5.62.0",
1214 - "debug": "^4.3.4",
1215 - "tsutils": "^3.21.0"
1216 - },
1217 - "engines": {
1218 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1219 - },
1220 - "funding": {
1221 - "type": "opencollective",
1222 - "url": "https://opencollective.com/typescript-eslint"
1223 - },
1224 - "peerDependencies": {
1225 - "eslint": "*"
1226 - },
1227 - "peerDependenciesMeta": {
1228 - "typescript": {
1229 - "optional": true
1230 - }
1231 - }
1232 - },
1233 - "node_modules/@typescript-eslint/types": {
1234 - "version": "5.62.0",
1235 - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz",
1236 - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==",
1237 - "dev": true,
1238 - "engines": {
1239 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1240 - },
1241 - "funding": {
1242 - "type": "opencollective",
1243 - "url": "https://opencollective.com/typescript-eslint"
1244 - }
1245 - },
1246 - "node_modules/@typescript-eslint/typescript-estree": {
1247 - "version": "5.62.0",
1248 - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz",
1249 - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==",
1250 - "dev": true,
1251 - "dependencies": {
1252 - "@typescript-eslint/types": "5.62.0",
1253 - "@typescript-eslint/visitor-keys": "5.62.0",
1254 - "debug": "^4.3.4",
1255 - "globby": "^11.1.0",
1256 - "is-glob": "^4.0.3",
1257 - "semver": "^7.3.7",
1258 - "tsutils": "^3.21.0"
1259 - },
1260 - "engines": {
1261 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1262 - },
1263 - "funding": {
1264 - "type": "opencollective",
1265 - "url": "https://opencollective.com/typescript-eslint"
1266 - },
1267 - "peerDependenciesMeta": {
1268 - "typescript": {
1269 - "optional": true
1270 - }
1271 - }
1272 - },
1273 - "node_modules/@typescript-eslint/utils": {
1274 - "version": "5.62.0",
1275 - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz",
1276 - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==",
1277 - "dev": true,
1278 - "dependencies": {
1279 - "@eslint-community/eslint-utils": "^4.2.0",
1280 - "@types/json-schema": "^7.0.9",
1281 - "@types/semver": "^7.3.12",
1282 - "@typescript-eslint/scope-manager": "5.62.0",
1283 - "@typescript-eslint/types": "5.62.0",
1284 - "@typescript-eslint/typescript-estree": "5.62.0",
1285 - "eslint-scope": "^5.1.1",
1286 - "semver": "^7.3.7"
1287 - },
1288 - "engines": {
1289 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1290 - },
1291 - "funding": {
1292 - "type": "opencollective",
1293 - "url": "https://opencollective.com/typescript-eslint"
1294 - },
1295 - "peerDependencies": {
1296 - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
1297 - }
1298 - },
1299 - "node_modules/@typescript-eslint/visitor-keys": {
1300 - "version": "5.62.0",
1301 - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz",
1302 - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==",
1303 - "dev": true,
1304 - "dependencies": {
1305 - "@typescript-eslint/types": "5.62.0",
1306 - "eslint-visitor-keys": "^3.3.0"
1307 - },
1308 - "engines": {
1309 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1310 - },
1311 - "funding": {
1312 - "type": "opencollective",
1313 - "url": "https://opencollective.com/typescript-eslint"
1314 - }
1315 - },
1316 - "node_modules/@vitejs/plugin-vue": {
1317 - "version": "4.2.3",
1318 - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.2.3.tgz",
1319 - "integrity": "sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==",
1320 - "dev": true,
1321 - "engines": {
1322 - "node": "^14.18.0 || >=16.0.0"
1323 - },
1324 - "peerDependencies": {
1325 - "vite": "^4.0.0",
1326 - "vue": "^3.2.25"
1327 - }
1328 - },
1329 - "node_modules/@vitest/expect": {
1330 - "version": "0.34.1",
1331 - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.1.tgz",
1332 - "integrity": "sha512-q2CD8+XIsQ+tHwypnoCk8Mnv5e6afLFvinVGCq3/BOT4kQdVQmY6rRfyKkwcg635lbliLPqbunXZr+L1ssUWiQ==",
1333 - "dev": true,
1334 - "dependencies": {
1335 - "@vitest/spy": "0.34.1",
1336 - "@vitest/utils": "0.34.1",
1337 - "chai": "^4.3.7"
1338 - },
1339 - "funding": {
1340 - "url": "https://opencollective.com/vitest"
1341 - }
1342 - },
1343 - "node_modules/@vitest/runner": {
1344 - "version": "0.34.1",
1345 - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.1.tgz",
1346 - "integrity": "sha512-YfQMpYzDsYB7yqgmlxZ06NI4LurHWfrH7Wy3Pvf/z/vwUSgq1zLAb1lWcItCzQG+NVox+VvzlKQrYEXb47645g==",
1347 - "dev": true,
1348 - "dependencies": {
1349 - "@vitest/utils": "0.34.1",
1350 - "p-limit": "^4.0.0",
1351 - "pathe": "^1.1.1"
1352 - },
1353 - "funding": {
1354 - "url": "https://opencollective.com/vitest"
1355 - }
1356 - },
1357 - "node_modules/@vitest/runner/node_modules/p-limit": {
1358 - "version": "4.0.0",
1359 - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
1360 - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
1361 - "dev": true,
1362 - "dependencies": {
1363 - "yocto-queue": "^1.0.0"
1364 - },
1365 - "engines": {
1366 - "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
1367 - },
1368 - "funding": {
1369 - "url": "https://github.com/sponsors/sindresorhus"
1370 - }
1371 - },
1372 - "node_modules/@vitest/runner/node_modules/yocto-queue": {
1373 - "version": "1.0.0",
1374 - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
1375 - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
1376 - "dev": true,
1377 - "engines": {
1378 - "node": ">=12.20"
1379 - },
1380 - "funding": {
1381 - "url": "https://github.com/sponsors/sindresorhus"
1382 - }
1383 - },
1384 - "node_modules/@vitest/snapshot": {
1385 - "version": "0.34.1",
1386 - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.1.tgz",
1387 - "integrity": "sha512-0O9LfLU0114OqdF8lENlrLsnn024Tb1CsS9UwG0YMWY2oGTQfPtkW+B/7ieyv0X9R2Oijhi3caB1xgGgEgclSQ==",
1388 - "dev": true,
1389 - "dependencies": {
1390 - "magic-string": "^0.30.1",
1391 - "pathe": "^1.1.1",
1392 - "pretty-format": "^29.5.0"
1393 - },
1394 - "funding": {
1395 - "url": "https://opencollective.com/vitest"
1396 - }
1397 - },
1398 - "node_modules/@vitest/spy": {
1399 - "version": "0.34.1",
1400 - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.1.tgz",
1401 - "integrity": "sha512-UT4WcI3EAPUNO8n6y9QoEqynGGEPmmRxC+cLzneFFXpmacivjHZsNbiKD88KUScv5DCHVDgdBsLD7O7s1enFcQ==",
1402 - "dev": true,
1403 - "dependencies": {
1404 - "tinyspy": "^2.1.1"
1405 - },
1406 - "funding": {
1407 - "url": "https://opencollective.com/vitest"
1408 - }
1409 - },
1410 - "node_modules/@vitest/utils": {
1411 - "version": "0.34.1",
1412 - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.1.tgz",
1413 - "integrity": "sha512-/ql9dsFi4iuEbiNcjNHQWXBum7aL8pyhxvfnD9gNtbjR9fUKAjxhj4AA3yfLXg6gJpMGGecvtF8Au2G9y3q47Q==",
1414 - "dev": true,
1415 - "dependencies": {
1416 - "diff-sequences": "^29.4.3",
1417 - "loupe": "^2.3.6",
1418 - "pretty-format": "^29.5.0"
1419 - },
1420 - "funding": {
1421 - "url": "https://opencollective.com/vitest"
1422 - }
1423 - },
1424 - "node_modules/@volar/language-core": {
1425 - "version": "1.10.0",
1426 - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.10.0.tgz",
1427 - "integrity": "sha512-ddyWwSYqcbEZNFHm+Z3NZd6M7Ihjcwl/9B5cZd8kECdimVXUFdFi60XHWD27nrWtUQIsUYIG7Ca1WBwV2u2LSQ==",
1428 - "dev": true,
1429 - "dependencies": {
1430 - "@volar/source-map": "1.10.0"
1431 - }
1432 - },
1433 - "node_modules/@volar/source-map": {
1434 - "version": "1.10.0",
1435 - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.10.0.tgz",
1436 - "integrity": "sha512-/ibWdcOzDGiq/GM1JU2eX8fH1bvAhl66hfe8yEgLEzg9txgr6qb5sQ/DEz5PcDL75tF5H5sCRRwn8Eu8ezi9mw==",
1437 - "dev": true,
1438 - "dependencies": {
1439 - "muggle-string": "^0.3.1"
1440 - }
1441 - },
1442 - "node_modules/@volar/typescript": {
1443 - "version": "1.10.0",
1444 - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.10.0.tgz",
1445 - "integrity": "sha512-OtqGtFbUKYC0pLNIk3mHQp5xWnvL1CJIUc9VE39VdZ/oqpoBh5jKfb9uJ45Y4/oP/WYTrif/Uxl1k8VTPz66Gg==",
1446 - "dev": true,
1447 - "dependencies": {
1448 - "@volar/language-core": "1.10.0"
1449 - }
1450 - },
1451 - "node_modules/@vue-leaflet/vue-leaflet": {
1452 - "version": "0.10.1",
1453 - "resolved": "https://registry.npmjs.org/@vue-leaflet/vue-leaflet/-/vue-leaflet-0.10.1.tgz",
1454 - "integrity": "sha512-RNEDk8TbnwrJl8ujdbKgZRFygLCxd0aBcWLQ05q/pGv4+d0jamE3KXQgQBqGAteE1mbQsk3xoNcqqUgaIGfWVg==",
1455 - "dependencies": {
1456 - "vue": "^3.2.25"
1457 - },
1458 - "peerDependencies": {
1459 - "@types/leaflet": "^1.5.7",
1460 - "leaflet": "^1.6.0"
1461 - },
1462 - "peerDependenciesMeta": {
1463 - "@types/leaflet": {
1464 - "optional": true
1465 - }
1466 - }
1467 - },
1468 - "node_modules/@vue/compiler-core": {
1469 - "version": "3.3.4",
1470 - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz",
1471 - "integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==",
1472 - "dependencies": {
1473 - "@babel/parser": "^7.21.3",
1474 - "@vue/shared": "3.3.4",
1475 - "estree-walker": "^2.0.2",
1476 - "source-map-js": "^1.0.2"
1477 - }
1478 - },
1479 - "node_modules/@vue/compiler-dom": {
1480 - "version": "3.3.4",
1481 - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz",
1482 - "integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==",
1483 - "dependencies": {
1484 - "@vue/compiler-core": "3.3.4",
1485 - "@vue/shared": "3.3.4"
1486 - }
1487 - },
1488 - "node_modules/@vue/compiler-sfc": {
1489 - "version": "3.3.4",
1490 - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz",
1491 - "integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==",
1492 - "dependencies": {
1493 - "@babel/parser": "^7.20.15",
1494 - "@vue/compiler-core": "3.3.4",
1495 - "@vue/compiler-dom": "3.3.4",
1496 - "@vue/compiler-ssr": "3.3.4",
1497 - "@vue/reactivity-transform": "3.3.4",
1498 - "@vue/shared": "3.3.4",
1499 - "estree-walker": "^2.0.2",
1500 - "magic-string": "^0.30.0",
1501 - "postcss": "^8.1.10",
1502 - "source-map-js": "^1.0.2"
1503 - }
1504 - },
1505 - "node_modules/@vue/compiler-ssr": {
1506 - "version": "3.3.4",
1507 - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz",
1508 - "integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==",
1509 - "dependencies": {
1510 - "@vue/compiler-dom": "3.3.4",
1511 - "@vue/shared": "3.3.4"
1512 - }
1513 - },
1514 - "node_modules/@vue/devtools-api": {
1515 - "version": "6.5.0",
1516 - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.0.tgz",
1517 - "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
1518 - },
1519 - "node_modules/@vue/eslint-config-prettier": {
1520 - "version": "8.0.0",
1521 - "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-8.0.0.tgz",
1522 - "integrity": "sha512-55dPqtC4PM/yBjhAr+yEw6+7KzzdkBuLmnhBrDfp4I48+wy+Giqqj9yUr5T2uD/BkBROjjmqnLZmXRdOx/VtQg==",
1523 - "dev": true,
1524 - "dependencies": {
1525 - "eslint-config-prettier": "^8.8.0",
1526 - "eslint-plugin-prettier": "^5.0.0"
1527 - },
1528 - "peerDependencies": {
1529 - "eslint": ">= 8.0.0",
1530 - "prettier": ">= 3.0.0"
1531 - }
1532 - },
1533 - "node_modules/@vue/eslint-config-typescript": {
1534 - "version": "11.0.3",
1535 - "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-11.0.3.tgz",
1536 - "integrity": "sha512-dkt6W0PX6H/4Xuxg/BlFj5xHvksjpSlVjtkQCpaYJBIEuKj2hOVU7r+TIe+ysCwRYFz/lGqvklntRkCAibsbPw==",
1537 - "dev": true,
1538 - "dependencies": {
1539 - "@typescript-eslint/eslint-plugin": "^5.59.1",
1540 - "@typescript-eslint/parser": "^5.59.1",
1541 - "vue-eslint-parser": "^9.1.1"
1542 - },
1543 - "engines": {
1544 - "node": "^14.17.0 || >=16.0.0"
1545 - },
1546 - "peerDependencies": {
1547 - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0",
1548 - "eslint-plugin-vue": "^9.0.0",
1549 - "typescript": "*"
1550 - },
1551 - "peerDependenciesMeta": {
1552 - "typescript": {
1553 - "optional": true
1554 - }
1555 - }
1556 - },
1557 - "node_modules/@vue/language-core": {
1558 - "version": "1.8.8",
1559 - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.8.tgz",
1560 - "integrity": "sha512-i4KMTuPazf48yMdYoebTkgSOJdFraE4pQf0B+FTOFkbB+6hAfjrSou/UmYWRsWyZV6r4Rc6DDZdI39CJwL0rWw==",
1561 - "dev": true,
1562 - "dependencies": {
1563 - "@volar/language-core": "~1.10.0",
1564 - "@volar/source-map": "~1.10.0",
1565 - "@vue/compiler-dom": "^3.3.0",
1566 - "@vue/reactivity": "^3.3.0",
1567 - "@vue/shared": "^3.3.0",
1568 - "minimatch": "^9.0.0",
1569 - "muggle-string": "^0.3.1",
1570 - "vue-template-compiler": "^2.7.14"
1571 - },
1572 - "peerDependencies": {
1573 - "typescript": "*"
1574 - },
1575 - "peerDependenciesMeta": {
1576 - "typescript": {
1577 - "optional": true
1578 - }
1579 - }
1580 - },
1581 - "node_modules/@vue/language-core/node_modules/brace-expansion": {
1582 - "version": "2.0.1",
1583 - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
1584 - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
1585 - "dev": true,
1586 - "dependencies": {
1587 - "balanced-match": "^1.0.0"
1588 - }
1589 - },
1590 - "node_modules/@vue/language-core/node_modules/minimatch": {
1591 - "version": "9.0.3",
1592 - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
1593 - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
1594 - "dev": true,
1595 - "dependencies": {
1596 - "brace-expansion": "^2.0.1"
1597 - },
1598 - "engines": {
1599 - "node": ">=16 || 14 >=14.17"
1600 - },
1601 - "funding": {
1602 - "url": "https://github.com/sponsors/isaacs"
1603 - }
1604 - },
1605 - "node_modules/@vue/reactivity": {
1606 - "version": "3.3.4",
1607 - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz",
1608 - "integrity": "sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==",
1609 - "dependencies": {
1610 - "@vue/shared": "3.3.4"
1611 - }
1612 - },
1613 - "node_modules/@vue/reactivity-transform": {
1614 - "version": "3.3.4",
1615 - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz",
1616 - "integrity": "sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==",
1617 - "dependencies": {
1618 - "@babel/parser": "^7.20.15",
1619 - "@vue/compiler-core": "3.3.4",
1620 - "@vue/shared": "3.3.4",
1621 - "estree-walker": "^2.0.2",
1622 - "magic-string": "^0.30.0"
1623 - }
1624 - },
1625 - "node_modules/@vue/runtime-core": {
1626 - "version": "3.3.4",
1627 - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.4.tgz",
1628 - "integrity": "sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==",
1629 - "dependencies": {
1630 - "@vue/reactivity": "3.3.4",
1631 - "@vue/shared": "3.3.4"
1632 - }
1633 - },
1634 - "node_modules/@vue/runtime-dom": {
1635 - "version": "3.3.4",
1636 - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz",
1637 - "integrity": "sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==",
1638 - "dependencies": {
1639 - "@vue/runtime-core": "3.3.4",
1640 - "@vue/shared": "3.3.4",
1641 - "csstype": "^3.1.1"
1642 - }
1643 - },
1644 - "node_modules/@vue/server-renderer": {
1645 - "version": "3.3.4",
1646 - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.4.tgz",
1647 - "integrity": "sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==",
1648 - "dependencies": {
1649 - "@vue/compiler-ssr": "3.3.4",
1650 - "@vue/shared": "3.3.4"
1651 - },
1652 - "peerDependencies": {
1653 - "vue": "3.3.4"
1654 - }
1655 - },
1656 - "node_modules/@vue/shared": {
1657 - "version": "3.3.4",
1658 - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
1659 - "integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ=="
1660 - },
1661 - "node_modules/@vue/test-utils": {
1662 - "version": "2.4.1",
1663 - "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.1.tgz",
1664 - "integrity": "sha512-VO8nragneNzUZUah6kOjiFmD/gwRjUauG9DROh6oaOeFwX1cZRUNHhdeogE8635cISigXFTtGLUQWx5KCb0xeg==",
1665 - "dev": true,
1666 - "dependencies": {
1667 - "js-beautify": "1.14.9",
1668 - "vue-component-type-helpers": "1.8.4"
1669 - },
1670 - "peerDependencies": {
1671 - "@vue/server-renderer": "^3.0.1",
1672 - "vue": "^3.0.1"
1673 - },
1674 - "peerDependenciesMeta": {
1675 - "@vue/server-renderer": {
1676 - "optional": true
1677 - }
1678 - }
1679 - },
1680 - "node_modules/@vue/tsconfig": {
1681 - "version": "0.4.0",
1682 - "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.4.0.tgz",
1683 - "integrity": "sha512-CPuIReonid9+zOG/CGTT05FXrPYATEqoDGNrEaqS4hwcw5BUNM2FguC0mOwJD4Jr16UpRVl9N0pY3P+srIbqmg==",
1684 - "dev": true
1685 - },
1686 - "node_modules/@vue/typescript": {
1687 - "version": "1.8.8",
1688 - "resolved": "https://registry.npmjs.org/@vue/typescript/-/typescript-1.8.8.tgz",
1689 - "integrity": "sha512-jUnmMB6egu5wl342eaUH236v8tdcEPXXkPgj+eI/F6JwW/lb+yAU6U07ZbQ3MVabZRlupIlPESB7ajgAGixhow==",
1690 - "dev": true,
1691 - "dependencies": {
1692 - "@volar/typescript": "~1.10.0",
1693 - "@vue/language-core": "1.8.8"
1694 - }
1695 - },
1696 - "node_modules/@vueuse/core": {
1697 - "version": "9.1.1",
1698 - "license": "MIT",
1699 - "dependencies": {
1700 - "@types/web-bluetooth": "^0.0.15",
1701 - "@vueuse/metadata": "9.1.1",
1702 - "@vueuse/shared": "9.1.1",
1703 - "vue-demi": "*"
1704 - },
1705 - "funding": {
1706 - "url": "https://github.com/sponsors/antfu"
1707 - }
1708 - },
1709 - "node_modules/@vueuse/core/node_modules/vue-demi": {
1710 - "version": "0.13.11",
1711 - "hasInstallScript": true,
1712 - "license": "MIT",
1713 - "bin": {
1714 - "vue-demi-fix": "bin/vue-demi-fix.js",
1715 - "vue-demi-switch": "bin/vue-demi-switch.js"
1716 - },
1717 - "engines": {
1718 - "node": ">=12"
1719 - },
1720 - "funding": {
1721 - "url": "https://github.com/sponsors/antfu"
1722 - },
1723 - "peerDependencies": {
1724 - "@vue/composition-api": "^1.0.0-rc.1",
1725 - "vue": "^3.0.0-0 || ^2.6.0"
1726 - },
1727 - "peerDependenciesMeta": {
1728 - "@vue/composition-api": {
1729 - "optional": true
1730 - }
1731 - }
1732 - },
1733 - "node_modules/@vueuse/metadata": {
1734 - "version": "9.1.1",
1735 - "license": "MIT",
1736 - "funding": {
1737 - "url": "https://github.com/sponsors/antfu"
1738 - }
1739 - },
1740 - "node_modules/@vueuse/shared": {
1741 - "version": "9.1.1",
1742 - "license": "MIT",
1743 - "dependencies": {
1744 - "vue-demi": "*"
1745 - },
1746 - "funding": {
1747 - "url": "https://github.com/sponsors/antfu"
1748 - }
1749 - },
1750 - "node_modules/@vueuse/shared/node_modules/vue-demi": {
1751 - "version": "0.13.11",
1752 - "hasInstallScript": true,
1753 - "license": "MIT",
1754 - "bin": {
1755 - "vue-demi-fix": "bin/vue-demi-fix.js",
1756 - "vue-demi-switch": "bin/vue-demi-switch.js"
1757 - },
1758 - "engines": {
1759 - "node": ">=12"
1760 - },
1761 - "funding": {
1762 - "url": "https://github.com/sponsors/antfu"
1763 - },
1764 - "peerDependencies": {
1765 - "@vue/composition-api": "^1.0.0-rc.1",
1766 - "vue": "^3.0.0-0 || ^2.6.0"
1767 - },
1768 - "peerDependenciesMeta": {
1769 - "@vue/composition-api": {
1770 - "optional": true
1771 - }
1772 - }
1773 - },
1774 - "node_modules/abab": {
1775 - "version": "2.0.6",
1776 - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
1777 - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
1778 - "dev": true
1779 - },
1780 - "node_modules/abbrev": {
1781 - "version": "1.1.1",
1782 - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
1783 - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
1784 - "dev": true
1785 - },
1786 - "node_modules/acorn": {
1787 - "version": "8.10.0",
1788 - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
1789 - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
1790 - "dev": true,
1791 - "bin": {
1792 - "acorn": "bin/acorn"
1793 - },
1794 - "engines": {
1795 - "node": ">=0.4.0"
1796 - }
1797 - },
1798 - "node_modules/acorn-jsx": {
1799 - "version": "5.3.2",
1800 - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
1801 - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
1802 - "dev": true,
1803 - "peerDependencies": {
1804 - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
1805 - }
1806 - },
1807 - "node_modules/acorn-walk": {
1808 - "version": "8.2.0",
1809 - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
1810 - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
1811 - "dev": true,
1812 - "engines": {
1813 - "node": ">=0.4.0"
1814 - }
1815 - },
1816 - "node_modules/adler-32": {
1817 - "version": "1.2.0",
1818 - "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz",
1819 - "integrity": "sha512-/vUqU/UY4MVeFsg+SsK6c+/05RZXIHZMGJA+PX5JyWI0ZRcBpupnRuPLU/NXXoFwMYCPCoxIfElM2eS+DUXCqQ==",
1820 - "dependencies": {
1821 - "exit-on-epipe": "~1.0.1",
1822 - "printj": "~1.1.0"
1823 - },
1824 - "bin": {
1825 - "adler32": "bin/adler32.njs"
1826 - },
1827 - "engines": {
1828 - "node": ">=0.8"
1829 - }
1830 - },
1831 - "node_modules/agent-base": {
1832 - "version": "6.0.2",
1833 - "dev": true,
1834 - "license": "MIT",
1835 - "dependencies": {
1836 - "debug": "4"
1837 - },
1838 - "engines": {
1839 - "node": ">= 6.0.0"
1840 - }
1841 - },
1842 - "node_modules/aggregate-error": {
1843 - "version": "3.1.0",
1844 - "dev": true,
1845 - "license": "MIT",
1846 - "dependencies": {
1847 - "clean-stack": "^2.0.0",
1848 - "indent-string": "^4.0.0"
1849 - },
1850 - "engines": {
1851 - "node": ">=8"
1852 - }
1853 - },
1854 - "node_modules/ajv": {
1855 - "version": "6.12.6",
1856 - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
1857 - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
1858 - "dev": true,
1859 - "dependencies": {
1860 - "fast-deep-equal": "^3.1.1",
1861 - "fast-json-stable-stringify": "^2.0.0",
1862 - "json-schema-traverse": "^0.4.1",
1863 - "uri-js": "^4.2.2"
1864 - },
1865 - "funding": {
1866 - "type": "github",
1867 - "url": "https://github.com/sponsors/epoberezkin"
1868 - }
1869 - },
1870 - "node_modules/animate.css": {
1871 - "version": "4.1.1",
1872 - "license": "MIT"
1873 - },
1874 - "node_modules/ansi-colors": {
1875 - "version": "4.1.3",
1876 - "dev": true,
1877 - "license": "MIT",
1878 - "engines": {
1879 - "node": ">=6"
1880 - }
1881 - },
1882 - "node_modules/ansi-escapes": {
1883 - "version": "4.3.2",
1884 - "dev": true,
1885 - "license": "MIT",
1886 - "dependencies": {
1887 - "type-fest": "^0.21.3"
1888 - },
1889 - "engines": {
1890 - "node": ">=8"
1891 - },
1892 - "funding": {
1893 - "url": "https://github.com/sponsors/sindresorhus"
1894 - }
1895 - },
1896 - "node_modules/ansi-escapes/node_modules/type-fest": {
1897 - "version": "0.21.3",
1898 - "dev": true,
1899 - "license": "(MIT OR CC0-1.0)",
1900 - "engines": {
1901 - "node": ">=10"
1902 - },
1903 - "funding": {
1904 - "url": "https://github.com/sponsors/sindresorhus"
1905 - }
1906 - },
1907 - "node_modules/ansi-regex": {
1908 - "version": "5.0.1",
1909 - "dev": true,
1910 - "license": "MIT",
1911 - "engines": {
1912 - "node": ">=8"
1913 - }
1914 - },
1915 - "node_modules/ansi-styles": {
1916 - "version": "4.3.0",
1917 - "dev": true,
1918 - "license": "MIT",
1919 - "dependencies": {
1920 - "color-convert": "^2.0.1"
1921 - },
1922 - "engines": {
1923 - "node": ">=8"
1924 - },
1925 - "funding": {
1926 - "url": "https://github.com/chalk/ansi-styles?sponsor=1"
1927 - }
1928 - },
1929 - "node_modules/anymatch": {
1930 - "version": "3.1.2",
1931 - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
1932 - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
1933 - "dev": true,
1934 - "dependencies": {
1935 - "normalize-path": "^3.0.0",
1936 - "picomatch": "^2.0.4"
1937 - },
1938 - "engines": {
1939 - "node": ">= 8"
1940 - }
1941 - },
1942 - "node_modules/arch": {
1943 - "version": "2.2.0",
1944 - "dev": true,
1945 - "funding": [
1946 - {
1947 - "type": "github",
1948 - "url": "https://github.com/sponsors/feross"
1949 - },
1950 - {
1951 - "type": "patreon",
1952 - "url": "https://www.patreon.com/feross"
1953 - },
1954 - {
1955 - "type": "consulting",
1956 - "url": "https://feross.org/support"
1957 - }
1958 - ],
1959 - "license": "MIT"
1960 - },
1961 - "node_modules/arg": {
1962 - "version": "5.0.2",
1963 - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
1964 - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
1965 - "dev": true
1966 - },
1967 - "node_modules/argparse": {
1968 - "version": "2.0.1",
1969 - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
1970 - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
1971 - "dev": true
1972 - },
1973 - "node_modules/array-union": {
1974 - "version": "2.1.0",
1975 - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
1976 - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
1977 - "dev": true,
1978 - "engines": {
1979 - "node": ">=8"
1980 - }
1981 - },
1982 - "node_modules/asn1": {
1983 - "version": "0.2.6",
1984 - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
1985 - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
1986 - "dev": true,
1987 - "dependencies": {
1988 - "safer-buffer": "~2.1.0"
1989 - }
1990 - },
1991 - "node_modules/assert-plus": {
1992 - "version": "1.0.0",
1993 - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
1994 - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
1995 - "dev": true,
1996 - "engines": {
1997 - "node": ">=0.8"
1998 - }
1999 - },
2000 - "node_modules/assertion-error": {
2001 - "version": "1.1.0",
2002 - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
2003 - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
2004 - "dev": true,
2005 - "engines": {
2006 - "node": "*"
2007 - }
2008 - },
2009 - "node_modules/astral-regex": {
2010 - "version": "2.0.0",
2011 - "dev": true,
2012 - "license": "MIT",
2013 - "engines": {
2014 - "node": ">=8"
2015 - }
2016 - },
2017 - "node_modules/async": {
2018 - "version": "3.2.4",
2019 - "dev": true,
2020 - "license": "MIT"
2021 - },
2022 - "node_modules/async-validator": {
2023 - "version": "4.2.5",
2024 - "license": "MIT"
2025 - },
2026 - "node_modules/asynckit": {
2027 - "version": "0.4.0",
2028 - "dev": true,
2029 - "license": "MIT"
2030 - },
2031 - "node_modules/at-least-node": {
2032 - "version": "1.0.0",
2033 - "dev": true,
2034 - "license": "ISC",
2035 - "engines": {
2036 - "node": ">= 4.0.0"
2037 - }
2038 - },
2039 - "node_modules/aws-sign2": {
2040 - "version": "0.7.0",
2041 - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
2042 - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
2043 - "dev": true,
2044 - "engines": {
2045 - "node": "*"
2046 - }
2047 - },
2048 - "node_modules/aws4": {
2049 - "version": "1.12.0",
2050 - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz",
2051 - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==",
2052 - "dev": true
2053 - },
2054 - "node_modules/axios": {
2055 - "version": "0.27.2",
2056 - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
2057 - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
2058 - "dev": true,
2059 - "dependencies": {
2060 - "follow-redirects": "^1.14.9",
2061 - "form-data": "^4.0.0"
2062 - }
2063 - },
2064 - "node_modules/axios/node_modules/form-data": {
2065 - "version": "4.0.0",
2066 - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
2067 - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
2068 - "dev": true,
2069 - "dependencies": {
2070 - "asynckit": "^0.4.0",
2071 - "combined-stream": "^1.0.8",
2072 - "mime-types": "^2.1.12"
2073 - },
2074 - "engines": {
2075 - "node": ">= 6"
2076 - }
2077 - },
2078 - "node_modules/balanced-match": {
2079 - "version": "1.0.2",
2080 - "dev": true,
2081 - "license": "MIT"
2082 - },
2083 - "node_modules/balloon-css": {
2084 - "version": "1.2.0",
2085 - "resolved": "https://registry.npmjs.org/balloon-css/-/balloon-css-1.2.0.tgz",
2086 - "integrity": "sha512-urXwkHgwp6GsXVF+it01485Z2Cj4pnW02ICnM0TemOlkKmCNnDLmyy+ZZiRXBpwldUXO+aRNr7Hdia4CBvXJ5A=="
2087 - },
2088 - "node_modules/base64-js": {
2089 - "version": "1.5.1",
2090 - "dev": true,
2091 - "funding": [
2092 - {
2093 - "type": "github",
2094 - "url": "https://github.com/sponsors/feross"
2095 - },
2096 - {
2097 - "type": "patreon",
2098 - "url": "https://www.patreon.com/feross"
2099 - },
2100 - {
2101 - "type": "consulting",
2102 - "url": "https://feross.org/support"
2103 - }
2104 - ],
2105 - "license": "MIT"
2106 - },
2107 - "node_modules/bcrypt-pbkdf": {
2108 - "version": "1.0.2",
2109 - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
2110 - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
2111 - "dev": true,
2112 - "dependencies": {
2113 - "tweetnacl": "^0.14.3"
2114 - }
2115 - },
2116 - "node_modules/big-integer": {
2117 - "version": "1.6.51",
2118 - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
2119 - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
2120 - "dev": true,
2121 - "engines": {
2122 - "node": ">=0.6"
2123 - }
2124 - },
2125 - "node_modules/binary-extensions": {
2126 - "version": "2.2.0",
2127 - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
2128 - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
2129 - "dev": true,
2130 - "engines": {
2131 - "node": ">=8"
2132 - }
2133 - },
2134 - "node_modules/blob-util": {
2135 - "version": "2.0.2",
2136 - "dev": true,
2137 - "license": "Apache-2.0"
2138 - },
2139 - "node_modules/bluebird": {
2140 - "version": "3.7.2",
2141 - "dev": true,
2142 - "license": "MIT"
2143 - },
2144 - "node_modules/boolbase": {
2145 - "version": "1.0.0",
2146 - "dev": true,
2147 - "license": "ISC"
2148 - },
2149 - "node_modules/bplist-parser": {
2150 - "version": "0.2.0",
2151 - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz",
2152 - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==",
2153 - "dev": true,
2154 - "dependencies": {
2155 - "big-integer": "^1.6.44"
2156 - },
2157 - "engines": {
2158 - "node": ">= 5.10.0"
2159 - }
2160 - },
2161 - "node_modules/brace-expansion": {
2162 - "version": "1.1.11",
2163 - "dev": true,
2164 - "license": "MIT",
2165 - "dependencies": {
2166 - "balanced-match": "^1.0.0",
2167 - "concat-map": "0.0.1"
2168 - }
2169 - },
2170 - "node_modules/braces": {
2171 - "version": "3.0.2",
2172 - "dev": true,
2173 - "license": "MIT",
2174 - "dependencies": {
2175 - "fill-range": "^7.0.1"
2176 - },
2177 - "engines": {
2178 - "node": ">=8"
2179 - }
2180 - },
2181 - "node_modules/buffer": {
2182 - "version": "5.7.1",
2183 - "dev": true,
2184 - "funding": [
2185 - {
2186 - "type": "github",
2187 - "url": "https://github.com/sponsors/feross"
2188 - },
2189 - {
2190 - "type": "patreon",
2191 - "url": "https://www.patreon.com/feross"
2192 - },
2193 - {
2194 - "type": "consulting",
2195 - "url": "https://feross.org/support"
2196 - }
2197 - ],
2198 - "license": "MIT",
2199 - "dependencies": {
2200 - "base64-js": "^1.3.1",
2201 - "ieee754": "^1.1.13"
2202 - }
2203 - },
2204 - "node_modules/buffer-crc32": {
2205 - "version": "0.2.13",
2206 - "dev": true,
2207 - "license": "MIT",
2208 - "engines": {
2209 - "node": "*"
2210 - }
2211 - },
2212 - "node_modules/buffer-from": {
2213 - "version": "1.1.2",
2214 - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
2215 - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
2216 - "dev": true,
2217 - "optional": true,
2218 - "peer": true
2219 - },
2220 - "node_modules/bundle-name": {
2221 - "version": "3.0.0",
2222 - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz",
2223 - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==",
2224 - "dev": true,
2225 - "dependencies": {
2226 - "run-applescript": "^5.0.0"
2227 - },
2228 - "engines": {
2229 - "node": ">=12"
2230 - },
2231 - "funding": {
2232 - "url": "https://github.com/sponsors/sindresorhus"
2233 - }
2234 - },
2235 - "node_modules/cac": {
2236 - "version": "6.7.14",
2237 - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
2238 - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
2239 - "dev": true,
2240 - "engines": {
2241 - "node": ">=8"
2242 - }
2243 - },
2244 - "node_modules/cachedir": {
2245 - "version": "2.3.0",
2246 - "dev": true,
2247 - "license": "MIT",
2248 - "engines": {
2249 - "node": ">=6"
2250 - }
2251 - },
2252 - "node_modules/call-bind": {
2253 - "version": "1.0.2",
2254 - "license": "MIT",
2255 - "dependencies": {
2256 - "function-bind": "^1.1.1",
2257 - "get-intrinsic": "^1.0.2"
2258 - },
2259 - "funding": {
2260 - "url": "https://github.com/sponsors/ljharb"
2261 - }
2262 - },
2263 - "node_modules/callsites": {
2264 - "version": "3.1.0",
2265 - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
2266 - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
2267 - "dev": true,
2268 - "engines": {
2269 - "node": ">=6"
2270 - }
2271 - },
2272 - "node_modules/caseless": {
2273 - "version": "0.12.0",
2274 - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
2275 - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
2276 - "dev": true
2277 - },
2278 - "node_modules/cfb": {
2279 - "version": "1.2.2",
2280 - "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
2281 - "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
2282 - "dependencies": {
2283 - "adler-32": "~1.3.0",
2284 - "crc-32": "~1.2.0"
2285 - },
2286 - "engines": {
2287 - "node": ">=0.8"
2288 - }
2289 - },
2290 - "node_modules/cfb/node_modules/adler-32": {
2291 - "version": "1.3.1",
2292 - "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
2293 - "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
2294 - "engines": {
2295 - "node": ">=0.8"
2296 - }
2297 - },
2298 - "node_modules/chai": {
2299 - "version": "4.3.7",
2300 - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz",
2301 - "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==",
2302 - "dev": true,
2303 - "dependencies": {
2304 - "assertion-error": "^1.1.0",
2305 - "check-error": "^1.0.2",
2306 - "deep-eql": "^4.1.2",
2307 - "get-func-name": "^2.0.0",
2308 - "loupe": "^2.3.1",
2309 - "pathval": "^1.1.1",
2310 - "type-detect": "^4.0.5"
2311 - },
2312 - "engines": {
2313 - "node": ">=4"
2314 - }
2315 - },
2316 - "node_modules/chalk": {
2317 - "version": "4.1.2",
2318 - "dev": true,
2319 - "license": "MIT",
2320 - "dependencies": {
2321 - "ansi-styles": "^4.1.0",
2322 - "supports-color": "^7.1.0"
2323 - },
2324 - "engines": {
2325 - "node": ">=10"
2326 - },
2327 - "funding": {
2328 - "url": "https://github.com/chalk/chalk?sponsor=1"
2329 - }
2330 - },
2331 - "node_modules/chalk/node_modules/supports-color": {
2332 - "version": "7.2.0",
2333 - "dev": true,
2334 - "license": "MIT",
2335 - "dependencies": {
2336 - "has-flag": "^4.0.0"
2337 - },
2338 - "engines": {
2339 - "node": ">=8"
2340 - }
2341 - },
2342 - "node_modules/chance": {
2343 - "version": "1.1.11",
2344 - "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.11.tgz",
2345 - "integrity": "sha512-kqTg3WWywappJPqtgrdvbA380VoXO2eu9VCV895JgbyHsaErXdyHK9LOZ911OvAk6L0obK7kDk9CGs8+oBawVA=="
2346 - },
2347 - "node_modules/chart.js": {
2348 - "version": "3.9.1",
2349 - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz",
2350 - "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==",
2351 - "optional": true
2352 - },
2353 - "node_modules/chartjs-adapter-date-fns": {
2354 - "version": "2.0.0",
2355 - "resolved": "https://registry.npmjs.org/chartjs-adapter-date-fns/-/chartjs-adapter-date-fns-2.0.0.tgz",
2356 - "integrity": "sha512-rmZINGLe+9IiiEB0kb57vH3UugAtYw33anRiw5kS2Tu87agpetDDoouquycWc9pRsKtQo5j+vLsYHyr8etAvFw==",
2357 - "optional": true,
2358 - "peerDependencies": {
2359 - "chart.js": "^3.0.0"
2360 - }
2361 - },
2362 - "node_modules/chartkick": {
2363 - "version": "4.2.0",
2364 - "resolved": "https://registry.npmjs.org/chartkick/-/chartkick-4.2.0.tgz",
2365 - "integrity": "sha512-7yYZyxeFhOh/LA7gc1VwDFgc6t4ZM9RrbBjgb4dJoFukk2+94QkK0yulYI2OUH1cjcfrf1qmj04FkjZx7kZDeg==",
2366 - "optionalDependencies": {
2367 - "chart.js": ">=3.0.2",
2368 - "chartjs-adapter-date-fns": ">=2.0.0",
2369 - "date-fns": ">=2.0.0"
2370 - }
2371 - },
2372 - "node_modules/check-error": {
2373 - "version": "1.0.2",
2374 - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
2375 - "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==",
2376 - "dev": true,
2377 - "engines": {
2378 - "node": "*"
2379 - }
2380 - },
2381 - "node_modules/check-more-types": {
2382 - "version": "2.24.0",
2383 - "dev": true,
2384 - "license": "MIT",
2385 - "engines": {
2386 - "node": ">= 0.8.0"
2387 - }
2388 - },
2389 - "node_modules/chokidar": {
2390 - "version": "3.5.3",
2391 - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
2392 - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
2393 - "dev": true,
2394 - "funding": [
2395 - {
2396 - "type": "individual",
2397 - "url": "https://paulmillr.com/funding/"
2398 - }
2399 - ],
2400 - "dependencies": {
2401 - "anymatch": "~3.1.2",
2402 - "braces": "~3.0.2",
2403 - "glob-parent": "~5.1.2",
2404 - "is-binary-path": "~2.1.0",
2405 - "is-glob": "~4.0.1",
2406 - "normalize-path": "~3.0.0",
2407 - "readdirp": "~3.6.0"
2408 - },
2409 - "engines": {
2410 - "node": ">= 8.10.0"
2411 - },
2412 - "optionalDependencies": {
2413 - "fsevents": "~2.3.2"
2414 - }
2415 - },
2416 - "node_modules/chokidar/node_modules/glob-parent": {
2417 - "version": "5.1.2",
2418 - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
2419 - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
2420 - "dev": true,
2421 - "dependencies": {
2422 - "is-glob": "^4.0.1"
2423 - },
2424 - "engines": {
2425 - "node": ">= 6"
2426 - }
2427 - },
2428 - "node_modules/ci-info": {
2429 - "version": "3.3.2",
2430 - "dev": true,
2431 - "license": "MIT"
2432 - },
2433 - "node_modules/clean-stack": {
2434 - "version": "2.2.0",
2435 - "dev": true,
2436 - "license": "MIT",
2437 - "engines": {
2438 - "node": ">=6"
2439 - }
2440 - },
2441 - "node_modules/cli-cursor": {
2442 - "version": "3.1.0",
2443 - "dev": true,
2444 - "license": "MIT",
2445 - "dependencies": {
2446 - "restore-cursor": "^3.1.0"
2447 - },
2448 - "engines": {
2449 - "node": ">=8"
2450 - }
2451 - },
2452 - "node_modules/cli-table3": {
2453 - "version": "0.6.2",
2454 - "dev": true,
2455 - "license": "MIT",
2456 - "dependencies": {
2457 - "string-width": "^4.2.0"
2458 - },
2459 - "engines": {
2460 - "node": "10.* || >= 12.*"
2461 - },
2462 - "optionalDependencies": {
2463 - "@colors/colors": "1.5.0"
2464 - }
2465 - },
2466 - "node_modules/cli-truncate": {
2467 - "version": "2.1.0",
2468 - "dev": true,
2469 - "license": "MIT",
2470 - "dependencies": {
2471 - "slice-ansi": "^3.0.0",
2472 - "string-width": "^4.2.0"
2473 - },
2474 - "engines": {
2475 - "node": ">=8"
2476 - },
2477 - "funding": {
2478 - "url": "https://github.com/sponsors/sindresorhus"
2479 - }
2480 - },
2481 - "node_modules/clone": {
2482 - "version": "2.1.2",
2483 - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
2484 - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
2485 - "engines": {
2486 - "node": ">=0.8"
2487 - }
2488 - },
2489 - "node_modules/codepage": {
2490 - "version": "1.15.0",
2491 - "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
2492 - "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
2493 - "engines": {
2494 - "node": ">=0.8"
2495 - }
2496 - },
2497 - "node_modules/color-convert": {
2498 - "version": "2.0.1",
2499 - "dev": true,
2500 - "license": "MIT",
2501 - "dependencies": {
2502 - "color-name": "~1.1.4"
2503 - },
2504 - "engines": {
2505 - "node": ">=7.0.0"
2506 - }
2507 - },
2508 - "node_modules/color-name": {
2509 - "version": "1.1.4",
2510 - "dev": true,
2511 - "license": "MIT"
2512 - },
2513 - "node_modules/colorette": {
2514 - "version": "2.0.19",
2515 - "dev": true,
2516 - "license": "MIT"
2517 - },
2518 - "node_modules/combined-stream": {
2519 - "version": "1.0.8",
2520 - "dev": true,
2521 - "license": "MIT",
2522 - "dependencies": {
2523 - "delayed-stream": "~1.0.0"
2524 - },
2525 - "engines": {
2526 - "node": ">= 0.8"
2527 - }
2528 - },
2529 - "node_modules/commander": {
2530 - "version": "6.2.1",
2531 - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
2532 - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
2533 - "dev": true,
2534 - "engines": {
2535 - "node": ">= 6"
2536 - }
2537 - },
2538 - "node_modules/common-tags": {
2539 - "version": "1.8.2",
2540 - "dev": true,
2541 - "license": "MIT",
2542 - "engines": {
2543 - "node": ">=4.0.0"
2544 - }
2545 - },
2546 - "node_modules/concat-map": {
2547 - "version": "0.0.1",
2548 - "dev": true,
2549 - "license": "MIT"
2550 - },
2551 - "node_modules/config-chain": {
2552 - "version": "1.1.13",
2553 - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
2554 - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
2555 - "dev": true,
2556 - "dependencies": {
2557 - "ini": "^1.3.4",
2558 - "proto-list": "~1.2.1"
2559 - }
2560 - },
2561 - "node_modules/config-chain/node_modules/ini": {
2562 - "version": "1.3.8",
2563 - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
2564 - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
2565 - "dev": true
2566 - },
2567 - "node_modules/core-util-is": {
2568 - "version": "1.0.2",
2569 - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
2570 - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
2571 - "dev": true
2572 - },
2573 - "node_modules/crc-32": {
2574 - "version": "1.2.2",
2575 - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
2576 - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
2577 - "bin": {
2578 - "crc32": "bin/crc32.njs"
2579 - },
2580 - "engines": {
2581 - "node": ">=0.8"
2582 - }
2583 - },
2584 - "node_modules/cross-spawn": {
2585 - "version": "7.0.3",
2586 - "dev": true,
2587 - "license": "MIT",
2588 - "dependencies": {
2589 - "path-key": "^3.1.0",
2590 - "shebang-command": "^2.0.0",
2591 - "which": "^2.0.1"
2592 - },
2593 - "engines": {
2594 - "node": ">= 8"
2595 - }
2596 - },
2597 - "node_modules/cryptocoins-icons": {
2598 - "version": "2.9.0",
2599 - "resolved": "https://registry.npmjs.org/cryptocoins-icons/-/cryptocoins-icons-2.9.0.tgz",
2600 - "integrity": "sha512-bfhtws/Hs4YOv7GXrCQfZ9yzgVLqkJsFzgsTFVFBY/D1qPIICQI0UjcoFxea8dlBlwerxNu3Shp0T0ucBLHwng=="
2601 - },
2602 - "node_modules/csscolorparser": {
2603 - "version": "1.0.3",
2604 - "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz",
2605 - "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w=="
2606 - },
2607 - "node_modules/cssesc": {
2608 - "version": "3.0.0",
2609 - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
2610 - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
2611 - "dev": true,
2612 - "bin": {
2613 - "cssesc": "bin/cssesc"
2614 - },
2615 - "engines": {
2616 - "node": ">=4"
2617 - }
2618 - },
2619 - "node_modules/cssfilter": {
2620 - "version": "0.0.10",
2621 - "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz",
2622 - "integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw=="
2623 - },
2624 - "node_modules/cssstyle": {
2625 - "version": "3.0.0",
2626 - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz",
2627 - "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==",
2628 - "dev": true,
2629 - "dependencies": {
2630 - "rrweb-cssom": "^0.6.0"
2631 - },
2632 - "engines": {
2633 - "node": ">=14"
2634 - }
2635 - },
2636 - "node_modules/csstype": {
2637 - "version": "3.1.2",
2638 - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
2639 - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
2640 - },
2641 - "node_modules/cypress": {
2642 - "version": "12.17.4",
2643 - "resolved": "https://registry.npmjs.org/cypress/-/cypress-12.17.4.tgz",
2644 - "integrity": "sha512-gAN8Pmns9MA5eCDFSDJXWKUpaL3IDd89N9TtIupjYnzLSmlpVr+ZR+vb4U/qaMp+lB6tBvAmt7504c3Z4RU5KQ==",
2645 - "dev": true,
2646 - "hasInstallScript": true,
2647 - "dependencies": {
2648 - "@cypress/request": "2.88.12",
2649 - "@cypress/xvfb": "^1.2.4",
2650 - "@types/node": "^16.18.39",
2651 - "@types/sinonjs__fake-timers": "8.1.1",
2652 - "@types/sizzle": "^2.3.2",
2653 - "arch": "^2.2.0",
2654 - "blob-util": "^2.0.2",
2655 - "bluebird": "^3.7.2",
2656 - "buffer": "^5.6.0",
2657 - "cachedir": "^2.3.0",
2658 - "chalk": "^4.1.0",
2659 - "check-more-types": "^2.24.0",
2660 - "cli-cursor": "^3.1.0",
2661 - "cli-table3": "~0.6.1",
2662 - "commander": "^6.2.1",
2663 - "common-tags": "^1.8.0",
2664 - "dayjs": "^1.10.4",
2665 - "debug": "^4.3.4",
2666 - "enquirer": "^2.3.6",
2667 - "eventemitter2": "6.4.7",
2668 - "execa": "4.1.0",
2669 - "executable": "^4.1.1",
2670 - "extract-zip": "2.0.1",
2671 - "figures": "^3.2.0",
2672 - "fs-extra": "^9.1.0",
2673 - "getos": "^3.2.1",
2674 - "is-ci": "^3.0.0",
2675 - "is-installed-globally": "~0.4.0",
2676 - "lazy-ass": "^1.6.0",
2677 - "listr2": "^3.8.3",
2678 - "lodash": "^4.17.21",
2679 - "log-symbols": "^4.0.0",
2680 - "minimist": "^1.2.8",
2681 - "ospath": "^1.2.2",
2682 - "pretty-bytes": "^5.6.0",
2683 - "process": "^0.11.10",
2684 - "proxy-from-env": "1.0.0",
2685 - "request-progress": "^3.0.0",
2686 - "semver": "^7.5.3",
2687 - "supports-color": "^8.1.1",
2688 - "tmp": "~0.2.1",
2689 - "untildify": "^4.0.0",
2690 - "yauzl": "^2.10.0"
2691 - },
2692 - "bin": {
2693 - "cypress": "bin/cypress"
2694 - },
2695 - "engines": {
2696 - "node": "^14.0.0 || ^16.0.0 || >=18.0.0"
2697 - }
2698 - },
2699 - "node_modules/cypress/node_modules/@types/node": {
2700 - "version": "16.18.39",
2701 - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.39.tgz",
2702 - "integrity": "sha512-8q9ZexmdYYyc5/cfujaXb4YOucpQxAV4RMG0himLyDUOEr8Mr79VrqsFI+cQ2M2h89YIuy95lbxuYjxT4Hk4kQ==",
2703 - "dev": true
2704 - },
2705 - "node_modules/dashdash": {
2706 - "version": "1.14.1",
2707 - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
2708 - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
2709 - "dev": true,
2710 - "dependencies": {
2711 - "assert-plus": "^1.0.0"
2712 - },
2713 - "engines": {
2714 - "node": ">=0.10"
2715 - }
2716 - },
2717 - "node_modules/data-urls": {
2718 - "version": "4.0.0",
2719 - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz",
2720 - "integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==",
2721 - "dev": true,
2722 - "dependencies": {
2723 - "abab": "^2.0.6",
2724 - "whatwg-mimetype": "^3.0.0",
2725 - "whatwg-url": "^12.0.0"
2726 - },
2727 - "engines": {
2728 - "node": ">=14"
2729 - }
2730 - },
2731 - "node_modules/date-fns": {
2732 - "version": "2.29.2",
2733 - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.2.tgz",
2734 - "integrity": "sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA==",
2735 - "optional": true,
2736 - "engines": {
2737 - "node": ">=0.11"
2738 - },
2739 - "funding": {
2740 - "type": "opencollective",
2741 - "url": "https://opencollective.com/date-fns"
2742 - }
2743 - },
2744 - "node_modules/dayjs": {
2745 - "version": "1.11.9",
2746 - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
2747 - "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA=="
2748 - },
2749 - "node_modules/de-indent": {
2750 - "version": "1.0.2",
2751 - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
2752 - "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
2753 - "dev": true
2754 - },
2755 - "node_modules/debug": {
2756 - "version": "4.3.4",
2757 - "dev": true,
2758 - "license": "MIT",
2759 - "dependencies": {
2760 - "ms": "2.1.2"
2761 - },
2762 - "engines": {
2763 - "node": ">=6.0"
2764 - },
2765 - "peerDependenciesMeta": {
2766 - "supports-color": {
2767 - "optional": true
2768 - }
2769 - }
2770 - },
2771 - "node_modules/decimal.js": {
2772 - "version": "10.4.3",
2773 - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
2774 - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==",
2775 - "dev": true
2776 - },
2777 - "node_modules/deep-eql": {
2778 - "version": "4.1.3",
2779 - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
2780 - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
2781 - "dev": true,
2782 - "dependencies": {
2783 - "type-detect": "^4.0.0"
2784 - },
2785 - "engines": {
2786 - "node": ">=6"
2787 - }
2788 - },
2789 - "node_modules/deep-equal": {
2790 - "version": "1.1.1",
2791 - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
2792 - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
2793 - "dependencies": {
2794 - "is-arguments": "^1.0.4",
2795 - "is-date-object": "^1.0.1",
2796 - "is-regex": "^1.0.4",
2797 - "object-is": "^1.0.1",
2798 - "object-keys": "^1.1.1",
2799 - "regexp.prototype.flags": "^1.2.0"
2800 - },
2801 - "funding": {
2802 - "url": "https://github.com/sponsors/ljharb"
2803 - }
2804 - },
2805 - "node_modules/deep-is": {
2806 - "version": "0.1.4",
2807 - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
2808 - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
2809 - "dev": true
2810 - },
2811 - "node_modules/default-browser": {
2812 - "version": "4.0.0",
2813 - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz",
2814 - "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==",
2815 - "dev": true,
2816 - "dependencies": {
2817 - "bundle-name": "^3.0.0",
2818 - "default-browser-id": "^3.0.0",
2819 - "execa": "^7.1.1",
2820 - "titleize": "^3.0.0"
2821 - },
2822 - "engines": {
2823 - "node": ">=14.16"
2824 - },
2825 - "funding": {
2826 - "url": "https://github.com/sponsors/sindresorhus"
2827 - }
2828 - },
2829 - "node_modules/default-browser-id": {
2830 - "version": "3.0.0",
2831 - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz",
2832 - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==",
2833 - "dev": true,
2834 - "dependencies": {
2835 - "bplist-parser": "^0.2.0",
2836 - "untildify": "^4.0.0"
2837 - },
2838 - "engines": {
2839 - "node": ">=12"
2840 - },
2841 - "funding": {
2842 - "url": "https://github.com/sponsors/sindresorhus"
2843 - }
2844 - },
2845 - "node_modules/default-browser/node_modules/execa": {
2846 - "version": "7.2.0",
2847 - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz",
2848 - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==",
2849 - "dev": true,
2850 - "dependencies": {
2851 - "cross-spawn": "^7.0.3",
2852 - "get-stream": "^6.0.1",
2853 - "human-signals": "^4.3.0",
2854 - "is-stream": "^3.0.0",
2855 - "merge-stream": "^2.0.0",
2856 - "npm-run-path": "^5.1.0",
2857 - "onetime": "^6.0.0",
2858 - "signal-exit": "^3.0.7",
2859 - "strip-final-newline": "^3.0.0"
2860 - },
2861 - "engines": {
2862 - "node": "^14.18.0 || ^16.14.0 || >=18.0.0"
2863 - },
2864 - "funding": {
2865 - "url": "https://github.com/sindresorhus/execa?sponsor=1"
2866 - }
2867 - },
2868 - "node_modules/default-browser/node_modules/get-stream": {
2869 - "version": "6.0.1",
2870 - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
2871 - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
2872 - "dev": true,
2873 - "engines": {
2874 - "node": ">=10"
2875 - },
2876 - "funding": {
2877 - "url": "https://github.com/sponsors/sindresorhus"
2878 - }
2879 - },
2880 - "node_modules/default-browser/node_modules/human-signals": {
2881 - "version": "4.3.1",
2882 - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
2883 - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
2884 - "dev": true,
2885 - "engines": {
2886 - "node": ">=14.18.0"
2887 - }
2888 - },
2889 - "node_modules/default-browser/node_modules/is-stream": {
2890 - "version": "3.0.0",
2891 - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
2892 - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
2893 - "dev": true,
2894 - "engines": {
2895 - "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
2896 - },
2897 - "funding": {
2898 - "url": "https://github.com/sponsors/sindresorhus"
2899 - }
2900 - },
2901 - "node_modules/default-browser/node_modules/mimic-fn": {
2902 - "version": "4.0.0",
2903 - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
2904 - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
2905 - "dev": true,
2906 - "engines": {
2907 - "node": ">=12"
2908 - },
2909 - "funding": {
2910 - "url": "https://github.com/sponsors/sindresorhus"
2911 - }
2912 - },
2913 - "node_modules/default-browser/node_modules/npm-run-path": {
2914 - "version": "5.1.0",
2915 - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
2916 - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
2917 - "dev": true,
2918 - "dependencies": {
2919 - "path-key": "^4.0.0"
2920 - },
2921 - "engines": {
2922 - "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
2923 - },
2924 - "funding": {
2925 - "url": "https://github.com/sponsors/sindresorhus"
2926 - }
2927 - },
2928 - "node_modules/default-browser/node_modules/onetime": {
2929 - "version": "6.0.0",
2930 - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
2931 - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
2932 - "dev": true,
2933 - "dependencies": {
2934 - "mimic-fn": "^4.0.0"
2935 - },
2936 - "engines": {
2937 - "node": ">=12"
2938 - },
2939 - "funding": {
2940 - "url": "https://github.com/sponsors/sindresorhus"
2941 - }
2942 - },
2943 - "node_modules/default-browser/node_modules/path-key": {
2944 - "version": "4.0.0",
2945 - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
2946 - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
2947 - "dev": true,
2948 - "engines": {
2949 - "node": ">=12"
2950 - },
2951 - "funding": {
2952 - "url": "https://github.com/sponsors/sindresorhus"
2953 - }
2954 - },
2955 - "node_modules/default-browser/node_modules/strip-final-newline": {
2956 - "version": "3.0.0",
2957 - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
2958 - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
2959 - "dev": true,
2960 - "engines": {
2961 - "node": ">=12"
2962 - },
2963 - "funding": {
2964 - "url": "https://github.com/sponsors/sindresorhus"
2965 - }
2966 - },
2967 - "node_modules/define-lazy-prop": {
2968 - "version": "3.0.0",
2969 - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
2970 - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
2971 - "dev": true,
2972 - "engines": {
2973 - "node": ">=12"
2974 - },
2975 - "funding": {
2976 - "url": "https://github.com/sponsors/sindresorhus"
2977 - }
2978 - },
2979 - "node_modules/define-properties": {
2980 - "version": "1.1.4",
2981 - "license": "MIT",
2982 - "dependencies": {
2983 - "has-property-descriptors": "^1.0.0",
2984 - "object-keys": "^1.1.1"
2985 - },
2986 - "engines": {
2987 - "node": ">= 0.4"
2988 - },
2989 - "funding": {
2990 - "url": "https://github.com/sponsors/ljharb"
2991 - }
2992 - },
2993 - "node_modules/delayed-stream": {
2994 - "version": "1.0.0",
2995 - "dev": true,
2996 - "license": "MIT",
2997 - "engines": {
2998 - "node": ">=0.4.0"
2999 - }
3000 - },
3001 - "node_modules/detect-browser": {
3002 - "version": "5.3.0",
3003 - "license": "MIT"
3004 - },
3005 - "node_modules/diff-sequences": {
3006 - "version": "29.4.3",
3007 - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
3008 - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==",
3009 - "dev": true,
3010 - "engines": {
3011 - "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
3012 - }
3013 - },
3014 - "node_modules/dir-glob": {
3015 - "version": "3.0.1",
3016 - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
3017 - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
3018 - "dev": true,
3019 - "dependencies": {
3020 - "path-type": "^4.0.0"
3021 - },
3022 - "engines": {
3023 - "node": ">=8"
3024 - }
3025 - },
3026 - "node_modules/doctrine": {
3027 - "version": "3.0.0",
3028 - "dev": true,
3029 - "license": "Apache-2.0",
3030 - "dependencies": {
3031 - "esutils": "^2.0.2"
3032 - },
3033 - "engines": {
3034 - "node": ">=6.0.0"
3035 - }
3036 - },
3037 - "node_modules/domexception": {
3038 - "version": "4.0.0",
3039 - "dev": true,
3040 - "license": "MIT",
3041 - "dependencies": {
3042 - "webidl-conversions": "^7.0.0"
3043 - },
3044 - "engines": {
3045 - "node": ">=12"
3046 - }
3047 - },
3048 - "node_modules/dompurify": {
3049 - "version": "2.4.0",
3050 - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.0.tgz",
3051 - "integrity": "sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA=="
3052 - },
3053 - "node_modules/drift-zoom": {
3054 - "version": "1.5.1",
3055 - "resolved": "https://registry.npmjs.org/drift-zoom/-/drift-zoom-1.5.1.tgz",
3056 - "integrity": "sha512-GNLWl0ydTkgyFxfPouKvAZXvJhTt2dqUGkXCqENe+Y1OlQuQ+nUNKgvSpNvjp3nrbcij75GbJR/iMf/qdZbgPw=="
3057 - },
3058 - "node_modules/duplexer": {
3059 - "version": "0.1.2",
3060 - "dev": true,
3061 - "license": "MIT"
3062 - },
3063 - "node_modules/earcut": {
3064 - "version": "2.2.4",
3065 - "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz",
3066 - "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ=="
3067 - },
3068 - "node_modules/ecc-jsbn": {
3069 - "version": "0.1.2",
3070 - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
3071 - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
3072 - "dev": true,
3073 - "dependencies": {
3074 - "jsbn": "~0.1.0",
3075 - "safer-buffer": "^2.1.0"
3076 - }
3077 - },
3078 - "node_modules/echarts": {
3079 - "version": "5.4.3",
3080 - "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.4.3.tgz",
3081 - "integrity": "sha512-mYKxLxhzy6zyTi/FaEbJMOZU1ULGEQHaeIeuMR5L+JnJTpz+YR03mnnpBhbR4+UYJAgiXgpyTVLffPAjOTLkZA==",
3082 - "dependencies": {
3083 - "tslib": "2.3.0",
3084 - "zrender": "5.4.4"
3085 - }
3086 - },
3087 - "node_modules/echarts/node_modules/tslib": {
3088 - "version": "2.3.0",
3089 - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
3090 - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
3091 - },
3092 - "node_modules/editorconfig": {
3093 - "version": "1.0.4",
3094 - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz",
3095 - "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==",
3096 - "dev": true,
3097 - "dependencies": {
3098 - "@one-ini/wasm": "0.1.1",
3099 - "commander": "^10.0.0",
3100 - "minimatch": "9.0.1",
3101 - "semver": "^7.5.3"
3102 - },
3103 - "bin": {
3104 - "editorconfig": "bin/editorconfig"
3105 - },
3106 - "engines": {
3107 - "node": ">=14"
3108 - }
3109 - },
3110 - "node_modules/editorconfig/node_modules/brace-expansion": {
3111 - "version": "2.0.1",
3112 - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
3113 - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
3114 - "dev": true,
3115 - "dependencies": {
3116 - "balanced-match": "^1.0.0"
3117 - }
3118 - },
3119 - "node_modules/editorconfig/node_modules/commander": {
3120 - "version": "10.0.1",
3121 - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
3122 - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
3123 - "dev": true,
3124 - "engines": {
3125 - "node": ">=14"
3126 - }
3127 - },
3128 - "node_modules/editorconfig/node_modules/minimatch": {
3129 - "version": "9.0.1",
3130 - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
3131 - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
3132 - "dev": true,
3133 - "dependencies": {
3134 - "brace-expansion": "^2.0.1"
3135 - },
3136 - "engines": {
3137 - "node": ">=16 || 14 >=14.17"
3138 - },
3139 - "funding": {
3140 - "url": "https://github.com/sponsors/isaacs"
3141 - }
3142 - },
3143 - "node_modules/element-plus": {
3144 - "version": "2.3.9",
3145 - "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.3.9.tgz",
3146 - "integrity": "sha512-TIOLnPl4cnoCPXqK3QYh+jpkthUBQnAM21O7o3Lhbse8v9pfrRXRTaBJtoEKnYNa8GZ4lZptUfH0PeZgDCNLUg==",
3147 - "dependencies": {
3148 - "@ctrl/tinycolor": "^3.4.1",
3149 - "@element-plus/icons-vue": "^2.0.6",
3150 - "@floating-ui/dom": "^1.0.1",
3151 - "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
3152 - "@types/lodash": "^4.14.182",
3153 - "@types/lodash-es": "^4.17.6",
3154 - "@vueuse/core": "^9.1.0",
3155 - "async-validator": "^4.2.5",
3156 - "dayjs": "^1.11.3",
3157 - "escape-html": "^1.0.3",
3158 - "lodash": "^4.17.21",
3159 - "lodash-es": "^4.17.21",
3160 - "lodash-unified": "^1.0.2",
3161 - "memoize-one": "^6.0.0",
3162 - "normalize-wheel-es": "^1.2.0"
3163 - },
3164 - "peerDependencies": {
3165 - "vue": "^3.2.0"
3166 - }
3167 - },
3168 - "node_modules/emoji-regex": {
3169 - "version": "8.0.0",
3170 - "dev": true,
3171 - "license": "MIT"
3172 - },
3173 - "node_modules/end-of-stream": {
3174 - "version": "1.4.4",
3175 - "dev": true,
3176 - "license": "MIT",
3177 - "dependencies": {
3178 - "once": "^1.4.0"
3179 - }
3180 - },
3181 - "node_modules/enquirer": {
3182 - "version": "2.3.6",
3183 - "dev": true,
3184 - "license": "MIT",
3185 - "dependencies": {
3186 - "ansi-colors": "^4.1.1"
3187 - },
3188 - "engines": {
3189 - "node": ">=8.6"
3190 - }
3191 - },
3192 - "node_modules/entities": {
3193 - "version": "4.4.0",
3194 - "dev": true,
3195 - "license": "BSD-2-Clause",
3196 - "engines": {
3197 - "node": ">=0.12"
3198 - },
3199 - "funding": {
3200 - "url": "https://github.com/fb55/entities?sponsor=1"
3201 - }
3202 - },
3203 - "node_modules/error-ex": {
3204 - "version": "1.3.2",
3205 - "dev": true,
3206 - "license": "MIT",
3207 - "dependencies": {
3208 - "is-arrayish": "^0.2.1"
3209 - }
3210 - },
3211 - "node_modules/es-abstract": {
3212 - "version": "1.20.2",
3213 - "dev": true,
3214 - "license": "MIT",
3215 - "dependencies": {
3216 - "call-bind": "^1.0.2",
3217 - "es-to-primitive": "^1.2.1",
3218 - "function-bind": "^1.1.1",
3219 - "function.prototype.name": "^1.1.5",
3220 - "get-intrinsic": "^1.1.2",
3221 - "get-symbol-description": "^1.0.0",
3222 - "has": "^1.0.3",
3223 - "has-property-descriptors": "^1.0.0",
3224 - "has-symbols": "^1.0.3",
3225 - "internal-slot": "^1.0.3",
3226 - "is-callable": "^1.2.4",
3227 - "is-negative-zero": "^2.0.2",
3228 - "is-regex": "^1.1.4",
3229 - "is-shared-array-buffer": "^1.0.2",
3230 - "is-string": "^1.0.7",
3231 - "is-weakref": "^1.0.2",
3232 - "object-inspect": "^1.12.2",
3233 - "object-keys": "^1.1.1",
3234 - "object.assign": "^4.1.4",
3235 - "regexp.prototype.flags": "^1.4.3",
3236 - "string.prototype.trimend": "^1.0.5",
3237 - "string.prototype.trimstart": "^1.0.5",
3238 - "unbox-primitive": "^1.0.2"
3239 - },
3240 - "engines": {
3241 - "node": ">= 0.4"
3242 - },
3243 - "funding": {
3244 - "url": "https://github.com/sponsors/ljharb"
3245 - }
3246 - },
3247 - "node_modules/es-to-primitive": {
3248 - "version": "1.2.1",
3249 - "dev": true,
3250 - "license": "MIT",
3251 - "dependencies": {
3252 - "is-callable": "^1.1.4",
3253 - "is-date-object": "^1.0.1",
3254 - "is-symbol": "^1.0.2"
3255 - },
3256 - "engines": {
3257 - "node": ">= 0.4"
3258 - },
3259 - "funding": {
3260 - "url": "https://github.com/sponsors/ljharb"
3261 - }
3262 - },
3263 - "node_modules/esbuild": {
3264 - "version": "0.18.20",
3265 - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
3266 - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
3267 - "dev": true,
3268 - "hasInstallScript": true,
3269 - "bin": {
3270 - "esbuild": "bin/esbuild"
3271 - },
3272 - "engines": {
3273 - "node": ">=12"
3274 - },
3275 - "optionalDependencies": {
3276 - "@esbuild/android-arm": "0.18.20",
3277 - "@esbuild/android-arm64": "0.18.20",
3278 - "@esbuild/android-x64": "0.18.20",
3279 - "@esbuild/darwin-arm64": "0.18.20",
3280 - "@esbuild/darwin-x64": "0.18.20",
3281 - "@esbuild/freebsd-arm64": "0.18.20",
3282 - "@esbuild/freebsd-x64": "0.18.20",
3283 - "@esbuild/linux-arm": "0.18.20",
3284 - "@esbuild/linux-arm64": "0.18.20",
3285 - "@esbuild/linux-ia32": "0.18.20",
3286 - "@esbuild/linux-loong64": "0.18.20",
3287 - "@esbuild/linux-mips64el": "0.18.20",
3288 - "@esbuild/linux-ppc64": "0.18.20",
3289 - "@esbuild/linux-riscv64": "0.18.20",
3290 - "@esbuild/linux-s390x": "0.18.20",
3291 - "@esbuild/linux-x64": "0.18.20",
3292 - "@esbuild/netbsd-x64": "0.18.20",
3293 - "@esbuild/openbsd-x64": "0.18.20",
3294 - "@esbuild/sunos-x64": "0.18.20",
3295 - "@esbuild/win32-arm64": "0.18.20",
3296 - "@esbuild/win32-ia32": "0.18.20",
3297 - "@esbuild/win32-x64": "0.18.20"
3298 - }
3299 - },
3300 - "node_modules/escape-html": {
3301 - "version": "1.0.3",
3302 - "license": "MIT"
3303 - },
3304 - "node_modules/escape-string-regexp": {
3305 - "version": "4.0.0",
3306 - "dev": true,
3307 - "license": "MIT",
3308 - "engines": {
3309 - "node": ">=10"
3310 - },
3311 - "funding": {
3312 - "url": "https://github.com/sponsors/sindresorhus"
3313 - }
3314 - },
3315 - "node_modules/eslint": {
3316 - "version": "8.47.0",
3317 - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz",
3318 - "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==",
3319 - "dev": true,
3320 - "dependencies": {
3321 - "@eslint-community/eslint-utils": "^4.2.0",
3322 - "@eslint-community/regexpp": "^4.6.1",
3323 - "@eslint/eslintrc": "^2.1.2",
3324 - "@eslint/js": "^8.47.0",
3325 - "@humanwhocodes/config-array": "^0.11.10",
3326 - "@humanwhocodes/module-importer": "^1.0.1",
3327 - "@nodelib/fs.walk": "^1.2.8",
3328 - "ajv": "^6.12.4",
3329 - "chalk": "^4.0.0",
3330 - "cross-spawn": "^7.0.2",
3331 - "debug": "^4.3.2",
3332 - "doctrine": "^3.0.0",
3333 - "escape-string-regexp": "^4.0.0",
3334 - "eslint-scope": "^7.2.2",
3335 - "eslint-visitor-keys": "^3.4.3",
3336 - "espree": "^9.6.1",
3337 - "esquery": "^1.4.2",
3338 - "esutils": "^2.0.2",
3339 - "fast-deep-equal": "^3.1.3",
3340 - "file-entry-cache": "^6.0.1",
3341 - "find-up": "^5.0.0",
3342 - "glob-parent": "^6.0.2",
3343 - "globals": "^13.19.0",
3344 - "graphemer": "^1.4.0",
3345 - "ignore": "^5.2.0",
3346 - "imurmurhash": "^0.1.4",
3347 - "is-glob": "^4.0.0",
3348 - "is-path-inside": "^3.0.3",
3349 - "js-yaml": "^4.1.0",
3350 - "json-stable-stringify-without-jsonify": "^1.0.1",
3351 - "levn": "^0.4.1",
3352 - "lodash.merge": "^4.6.2",
3353 - "minimatch": "^3.1.2",
3354 - "natural-compare": "^1.4.0",
3355 - "optionator": "^0.9.3",
3356 - "strip-ansi": "^6.0.1",
3357 - "text-table": "^0.2.0"
3358 - },
3359 - "bin": {
3360 - "eslint": "bin/eslint.js"
3361 - },
3362 - "engines": {
3363 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
3364 - },
3365 - "funding": {
3366 - "url": "https://opencollective.com/eslint"
3367 - }
3368 - },
3369 - "node_modules/eslint-config-prettier": {
3370 - "version": "8.10.0",
3371 - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz",
3372 - "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==",
3373 - "dev": true,
3374 - "bin": {
3375 - "eslint-config-prettier": "bin/cli.js"
3376 - },
3377 - "peerDependencies": {
3378 - "eslint": ">=7.0.0"
3379 - }
3380 - },
3381 - "node_modules/eslint-plugin-cypress": {
3382 - "version": "2.14.0",
3383 - "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.14.0.tgz",
3384 - "integrity": "sha512-eW6tv7iIg7xujleAJX4Ujm649Bf5jweqa4ObPEIuueYRyLZt7qXGWhCY/n4bfeFW/j6nQZwbIBHKZt6EKcL/cg==",
3385 - "dev": true,
3386 - "dependencies": {
3387 - "globals": "^13.20.0"
3388 - },
3389 - "peerDependencies": {
3390 - "eslint": ">= 3.2.1"
3391 - }
3392 - },
3393 - "node_modules/eslint-plugin-prettier": {
3394 - "version": "5.0.0",
3395 - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz",
3396 - "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==",
3397 - "dev": true,
3398 - "dependencies": {
3399 - "prettier-linter-helpers": "^1.0.0",
3400 - "synckit": "^0.8.5"
3401 - },
3402 - "engines": {
3403 - "node": "^14.18.0 || >=16.0.0"
3404 - },
3405 - "funding": {
3406 - "url": "https://opencollective.com/prettier"
3407 - },
3408 - "peerDependencies": {
3409 - "@types/eslint": ">=8.0.0",
3410 - "eslint": ">=8.0.0",
3411 - "prettier": ">=3.0.0"
3412 - },
3413 - "peerDependenciesMeta": {
3414 - "@types/eslint": {
3415 - "optional": true
3416 - },
3417 - "eslint-config-prettier": {
3418 - "optional": true
3419 - }
3420 - }
3421 - },
3422 - "node_modules/eslint-plugin-vue": {
3423 - "version": "9.17.0",
3424 - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.17.0.tgz",
3425 - "integrity": "sha512-r7Bp79pxQk9I5XDP0k2dpUC7Ots3OSWgvGZNu3BxmKK6Zg7NgVtcOB6OCna5Kb9oQwJPl5hq183WD0SY5tZtIQ==",
3426 - "dev": true,
3427 - "dependencies": {
3428 - "@eslint-community/eslint-utils": "^4.4.0",
3429 - "natural-compare": "^1.4.0",
3430 - "nth-check": "^2.1.1",
3431 - "postcss-selector-parser": "^6.0.13",
3432 - "semver": "^7.5.4",
3433 - "vue-eslint-parser": "^9.3.1",
3434 - "xml-name-validator": "^4.0.0"
3435 - },
3436 - "engines": {
3437 - "node": "^14.17.0 || >=16.0.0"
3438 - },
3439 - "peerDependencies": {
3440 - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0"
3441 - }
3442 - },
3443 - "node_modules/eslint-scope": {
3444 - "version": "5.1.1",
3445 - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
3446 - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
3447 - "dev": true,
3448 - "dependencies": {
3449 - "esrecurse": "^4.3.0",
3450 - "estraverse": "^4.1.1"
3451 - },
3452 - "engines": {
3453 - "node": ">=8.0.0"
3454 - }
3455 - },
3456 - "node_modules/eslint-visitor-keys": {
3457 - "version": "3.4.3",
3458 - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
3459 - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
3460 - "dev": true,
3461 - "engines": {
3462 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
3463 - },
3464 - "funding": {
3465 - "url": "https://opencollective.com/eslint"
3466 - }
3467 - },
3468 - "node_modules/eslint/node_modules/eslint-scope": {
3469 - "version": "7.2.2",
3470 - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
3471 - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
3472 - "dev": true,
3473 - "dependencies": {
3474 - "esrecurse": "^4.3.0",
3475 - "estraverse": "^5.2.0"
3476 - },
3477 - "engines": {
3478 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
3479 - },
3480 - "funding": {
3481 - "url": "https://opencollective.com/eslint"
3482 - }
3483 - },
3484 - "node_modules/eslint/node_modules/estraverse": {
3485 - "version": "5.3.0",
3486 - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
3487 - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
3488 - "dev": true,
3489 - "engines": {
3490 - "node": ">=4.0"
3491 - }
3492 - },
3493 - "node_modules/espree": {
3494 - "version": "9.6.1",
3495 - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
3496 - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
3497 - "dev": true,
3498 - "dependencies": {
3499 - "acorn": "^8.9.0",
3500 - "acorn-jsx": "^5.3.2",
3501 - "eslint-visitor-keys": "^3.4.1"
3502 - },
3503 - "engines": {
3504 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
3505 - },
3506 - "funding": {
3507 - "url": "https://opencollective.com/eslint"
3508 - }
3509 - },
3510 - "node_modules/esquery": {
3511 - "version": "1.5.0",
3512 - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
3513 - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
3514 - "dev": true,
3515 - "dependencies": {
3516 - "estraverse": "^5.1.0"
3517 - },
3518 - "engines": {
3519 - "node": ">=0.10"
3520 - }
3521 - },
3522 - "node_modules/esquery/node_modules/estraverse": {
3523 - "version": "5.3.0",
3524 - "dev": true,
3525 - "license": "BSD-2-Clause",
3526 - "engines": {
3527 - "node": ">=4.0"
3528 - }
3529 - },
3530 - "node_modules/esrecurse": {
3531 - "version": "4.3.0",
3532 - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
3533 - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
3534 - "dev": true,
3535 - "dependencies": {
3536 - "estraverse": "^5.2.0"
3537 - },
3538 - "engines": {
3539 - "node": ">=4.0"
3540 - }
3541 - },
3542 - "node_modules/esrecurse/node_modules/estraverse": {
3543 - "version": "5.3.0",
3544 - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
3545 - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
3546 - "dev": true,
3547 - "engines": {
3548 - "node": ">=4.0"
3549 - }
3550 - },
3551 - "node_modules/estraverse": {
3552 - "version": "4.3.0",
3553 - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
3554 - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
3555 - "dev": true,
3556 - "engines": {
3557 - "node": ">=4.0"
3558 - }
3559 - },
3560 - "node_modules/estree-walker": {
3561 - "version": "2.0.2",
3562 - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
3563 - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
3564 - },
3565 - "node_modules/esutils": {
3566 - "version": "2.0.3",
3567 - "dev": true,
3568 - "license": "BSD-2-Clause",
3569 - "engines": {
3570 - "node": ">=0.10.0"
3571 - }
3572 - },
3573 - "node_modules/event-stream": {
3574 - "version": "3.3.4",
3575 - "dev": true,
3576 - "license": "MIT",
3577 - "dependencies": {
3578 - "duplexer": "~0.1.1",
3579 - "from": "~0",
3580 - "map-stream": "~0.1.0",
3581 - "pause-stream": "0.0.11",
3582 - "split": "0.3",
3583 - "stream-combiner": "~0.0.4",
3584 - "through": "~2.3.1"
3585 - }
3586 - },
3587 - "node_modules/eventemitter2": {
3588 - "version": "6.4.7",
3589 - "dev": true,
3590 - "license": "MIT"
3591 - },
3592 - "node_modules/eventemitter3": {
3593 - "version": "2.0.3",
3594 - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
3595 - "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg=="
3596 - },
3597 - "node_modules/execa": {
3598 - "version": "4.1.0",
3599 - "dev": true,
3600 - "license": "MIT",
3601 - "dependencies": {
3602 - "cross-spawn": "^7.0.0",
3603 - "get-stream": "^5.0.0",
3604 - "human-signals": "^1.1.1",
3605 - "is-stream": "^2.0.0",
3606 - "merge-stream": "^2.0.0",
3607 - "npm-run-path": "^4.0.0",
3608 - "onetime": "^5.1.0",
3609 - "signal-exit": "^3.0.2",
3610 - "strip-final-newline": "^2.0.0"
3611 - },
3612 - "engines": {
3613 - "node": ">=10"
3614 - },
3615 - "funding": {
3616 - "url": "https://github.com/sindresorhus/execa?sponsor=1"
3617 - }
3618 - },
3619 - "node_modules/executable": {
3620 - "version": "4.1.1",
3621 - "dev": true,
3622 - "license": "MIT",
3623 - "dependencies": {
3624 - "pify": "^2.2.0"
3625 - },
3626 - "engines": {
3627 - "node": ">=4"
3628 - }
3629 - },
3630 - "node_modules/exit-on-epipe": {
3631 - "version": "1.0.1",
3632 - "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
3633 - "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==",
3634 - "engines": {
3635 - "node": ">=0.8"
3636 - }
3637 - },
3638 - "node_modules/extend": {
3639 - "version": "3.0.2",
3640 - "license": "MIT"
3641 - },
3642 - "node_modules/extract-zip": {
3643 - "version": "2.0.1",
3644 - "dev": true,
3645 - "license": "BSD-2-Clause",
3646 - "dependencies": {
3647 - "debug": "^4.1.1",
3648 - "get-stream": "^5.1.0",
3649 - "yauzl": "^2.10.0"
3650 - },
3651 - "bin": {
3652 - "extract-zip": "cli.js"
3653 - },
3654 - "engines": {
3655 - "node": ">= 10.17.0"
3656 - },
3657 - "optionalDependencies": {
3658 - "@types/yauzl": "^2.9.1"
3659 - }
3660 - },
3661 - "node_modules/extsprintf": {
3662 - "version": "1.3.0",
3663 - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
3664 - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
3665 - "dev": true,
3666 - "engines": [
3667 - "node >=0.6.0"
3668 - ]
3669 - },
3670 - "node_modules/fast-deep-equal": {
3671 - "version": "3.1.3",
3672 - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
3673 - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
3674 - "dev": true
3675 - },
3676 - "node_modules/fast-diff": {
3677 - "version": "1.3.0",
3678 - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
3679 - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
3680 - "dev": true
3681 - },
3682 - "node_modules/fast-glob": {
3683 - "version": "3.3.1",
3684 - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
3685 - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
3686 - "dev": true,
3687 - "dependencies": {
3688 - "@nodelib/fs.stat": "^2.0.2",
3689 - "@nodelib/fs.walk": "^1.2.3",
3690 - "glob-parent": "^5.1.2",
3691 - "merge2": "^1.3.0",
3692 - "micromatch": "^4.0.4"
3693 - },
3694 - "engines": {
3695 - "node": ">=8.6.0"
3696 - }
3697 - },
3698 - "node_modules/fast-glob/node_modules/glob-parent": {
3699 - "version": "5.1.2",
3700 - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
3701 - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
3702 - "dev": true,
3703 - "dependencies": {
3704 - "is-glob": "^4.0.1"
3705 - },
3706 - "engines": {
3707 - "node": ">= 6"
3708 - }
3709 - },
3710 - "node_modules/fast-json-stable-stringify": {
3711 - "version": "2.1.0",
3712 - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
3713 - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
3714 - "dev": true
3715 - },
3716 - "node_modules/fast-levenshtein": {
3717 - "version": "2.0.6",
3718 - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
3719 - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
3720 - "dev": true
3721 - },
3722 - "node_modules/fastq": {
3723 - "version": "1.13.0",
3724 - "dev": true,
3725 - "license": "ISC",
3726 - "dependencies": {
3727 - "reusify": "^1.0.4"
3728 - }
3729 - },
3730 - "node_modules/fd-slicer": {
3731 - "version": "1.1.0",
3732 - "dev": true,
3733 - "license": "MIT",
3734 - "dependencies": {
3735 - "pend": "~1.2.0"
3736 - }
3737 - },
3738 - "node_modules/figures": {
3739 - "version": "3.2.0",
3740 - "dev": true,
3741 - "license": "MIT",
3742 - "dependencies": {
3743 - "escape-string-regexp": "^1.0.5"
3744 - },
3745 - "engines": {
3746 - "node": ">=8"
3747 - },
3748 - "funding": {
3749 - "url": "https://github.com/sponsors/sindresorhus"
3750 - }
3751 - },
3752 - "node_modules/figures/node_modules/escape-string-regexp": {
3753 - "version": "1.0.5",
3754 - "dev": true,
3755 - "license": "MIT",
3756 - "engines": {
3757 - "node": ">=0.8.0"
3758 - }
3759 - },
3760 - "node_modules/file-entry-cache": {
3761 - "version": "6.0.1",
3762 - "dev": true,
3763 - "license": "MIT",
3764 - "dependencies": {
3765 - "flat-cache": "^3.0.4"
3766 - },
3767 - "engines": {
3768 - "node": "^10.12.0 || >=12.0.0"
3769 - }
3770 - },
3771 - "node_modules/file-saver": {
3772 - "version": "2.0.5",
3773 - "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
3774 - "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
3775 - },
3776 - "node_modules/fill-range": {
3777 - "version": "7.0.1",
3778 - "dev": true,
3779 - "license": "MIT",
3780 - "dependencies": {
3781 - "to-regex-range": "^5.0.1"
3782 - },
3783 - "engines": {
3784 - "node": ">=8"
3785 - }
3786 - },
3787 - "node_modules/find-up": {
3788 - "version": "5.0.0",
3789 - "dev": true,
3790 - "license": "MIT",
3791 - "dependencies": {
3792 - "locate-path": "^6.0.0",
3793 - "path-exists": "^4.0.0"
3794 - },
3795 - "engines": {
3796 - "node": ">=10"
3797 - },
3798 - "funding": {
3799 - "url": "https://github.com/sponsors/sindresorhus"
3800 - }
3801 - },
3802 - "node_modules/flag-icon-css": {
3803 - "version": "4.1.7",
3804 - "resolved": "https://registry.npmjs.org/flag-icon-css/-/flag-icon-css-4.1.7.tgz",
3805 - "integrity": "sha512-AFjSU+fv98XbU0vnTQ32vcLj89UEr1MhwDFcooQv14qWJCjg9fGZzfh9BVyDhAhIOZW/pGmJmq38RqpgPaeybQ==",
3806 - "deprecated": "The project has been renamed to flag-icons"
3807 - },
3808 - "node_modules/flat-cache": {
3809 - "version": "3.0.4",
3810 - "dev": true,
3811 - "license": "MIT",
3812 - "dependencies": {
3813 - "flatted": "^3.1.0",
3814 - "rimraf": "^3.0.2"
3815 - },
3816 - "engines": {
3817 - "node": "^10.12.0 || >=12.0.0"
3818 - }
3819 - },
3820 - "node_modules/flatted": {
3821 - "version": "3.2.7",
3822 - "dev": true,
3823 - "license": "ISC"
3824 - },
3825 - "node_modules/flex.box": {
3826 - "version": "3.4.4",
3827 - "license": "MIT"
3828 - },
3829 - "node_modules/follow-redirects": {
3830 - "version": "1.15.2",
3831 - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
3832 - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
3833 - "dev": true,
3834 - "funding": [
3835 - {
3836 - "type": "individual",
3837 - "url": "https://github.com/sponsors/RubenVerborgh"
3838 - }
3839 - ],
3840 - "engines": {
3841 - "node": ">=4.0"
3842 - },
3843 - "peerDependenciesMeta": {
3844 - "debug": {
3845 - "optional": true
3846 - }
3847 - }
3848 - },
3849 - "node_modules/forever-agent": {
3850 - "version": "0.6.1",
3851 - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
3852 - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
3853 - "dev": true,
3854 - "engines": {
3855 - "node": "*"
3856 - }
3857 - },
3858 - "node_modules/form-data": {
3859 - "version": "2.3.3",
3860 - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
3861 - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
3862 - "dev": true,
3863 - "dependencies": {
3864 - "asynckit": "^0.4.0",
3865 - "combined-stream": "^1.0.6",
3866 - "mime-types": "^2.1.12"
3867 - },
3868 - "engines": {
3869 - "node": ">= 0.12"
3870 - }
3871 - },
3872 - "node_modules/frac": {
3873 - "version": "1.1.2",
3874 - "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
3875 - "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
3876 - "engines": {
3877 - "node": ">=0.8"
3878 - }
3879 - },
3880 - "node_modules/from": {
3881 - "version": "0.1.7",
3882 - "dev": true,
3883 - "license": "MIT"
3884 - },
3885 - "node_modules/fs-extra": {
3886 - "version": "9.1.0",
3887 - "dev": true,
3888 - "license": "MIT",
3889 - "dependencies": {
3890 - "at-least-node": "^1.0.0",
3891 - "graceful-fs": "^4.2.0",
3892 - "jsonfile": "^6.0.1",
3893 - "universalify": "^2.0.0"
3894 - },
3895 - "engines": {
3896 - "node": ">=10"
3897 - }
3898 - },
3899 - "node_modules/fs.realpath": {
3900 - "version": "1.0.0",
3901 - "dev": true,
3902 - "license": "ISC"
3903 - },
3904 - "node_modules/fsevents": {
3905 - "version": "2.3.2",
3906 - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
3907 - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
3908 - "dev": true,
3909 - "hasInstallScript": true,
3910 - "optional": true,
3911 - "os": [
3912 - "darwin"
3913 - ],
3914 - "engines": {
3915 - "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
3916 - }
3917 - },
3918 - "node_modules/function-bind": {
3919 - "version": "1.1.1",
3920 - "license": "MIT"
3921 - },
3922 - "node_modules/function.prototype.name": {
3923 - "version": "1.1.5",
3924 - "dev": true,
3925 - "license": "MIT",
3926 - "dependencies": {
3927 - "call-bind": "^1.0.2",
3928 - "define-properties": "^1.1.3",
3929 - "es-abstract": "^1.19.0",
3930 - "functions-have-names": "^1.2.2"
3931 - },
3932 - "engines": {
3933 - "node": ">= 0.4"
3934 - },
3935 - "funding": {
3936 - "url": "https://github.com/sponsors/ljharb"
3937 - }
3938 - },
3939 - "node_modules/functions-have-names": {
3940 - "version": "1.2.3",
3941 - "license": "MIT",
3942 - "funding": {
3943 - "url": "https://github.com/sponsors/ljharb"
3944 - }
3945 - },
3946 - "node_modules/geojson-vt": {
3947 - "version": "3.2.1",
3948 - "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz",
3949 - "integrity": "sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg=="
3950 - },
3951 - "node_modules/get-func-name": {
3952 - "version": "2.0.0",
3953 - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
3954 - "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==",
3955 - "dev": true,
3956 - "engines": {
3957 - "node": "*"
3958 - }
3959 - },
3960 - "node_modules/get-intrinsic": {
3961 - "version": "1.1.2",
3962 - "license": "MIT",
3963 - "dependencies": {
3964 - "function-bind": "^1.1.1",
3965 - "has": "^1.0.3",
3966 - "has-symbols": "^1.0.3"
3967 - },
3968 - "funding": {
3969 - "url": "https://github.com/sponsors/ljharb"
3970 - }
3971 - },
3972 - "node_modules/get-stream": {
3973 - "version": "5.2.0",
3974 - "dev": true,
3975 - "license": "MIT",
3976 - "dependencies": {
3977 - "pump": "^3.0.0"
3978 - },
3979 - "engines": {
3980 - "node": ">=8"
3981 - },
3982 - "funding": {
3983 - "url": "https://github.com/sponsors/sindresorhus"
3984 - }
3985 - },
3986 - "node_modules/get-symbol-description": {
3987 - "version": "1.0.0",
3988 - "dev": true,
3989 - "license": "MIT",
3990 - "dependencies": {
3991 - "call-bind": "^1.0.2",
3992 - "get-intrinsic": "^1.1.1"
3993 - },
3994 - "engines": {
3995 - "node": ">= 0.4"
3996 - },
3997 - "funding": {
3998 - "url": "https://github.com/sponsors/ljharb"
3999 - }
4000 - },
4001 - "node_modules/getos": {
4002 - "version": "3.2.1",
4003 - "dev": true,
4004 - "license": "MIT",
4005 - "dependencies": {
4006 - "async": "^3.2.0"
4007 - }
4008 - },
4009 - "node_modules/getpass": {
4010 - "version": "0.1.7",
4011 - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
4012 - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
4013 - "dev": true,
4014 - "dependencies": {
4015 - "assert-plus": "^1.0.0"
4016 - }
4017 - },
4018 - "node_modules/gl-matrix": {
4019 - "version": "3.4.3",
4020 - "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
4021 - "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
4022 - },
4023 - "node_modules/glob": {
4024 - "version": "7.2.3",
4025 - "dev": true,
4026 - "license": "ISC",
4027 - "dependencies": {
4028 - "fs.realpath": "^1.0.0",
4029 - "inflight": "^1.0.4",
4030 - "inherits": "2",
4031 - "minimatch": "^3.1.1",
4032 - "once": "^1.3.0",
4033 - "path-is-absolute": "^1.0.0"
4034 - },
4035 - "engines": {
4036 - "node": "*"
4037 - },
4038 - "funding": {
4039 - "url": "https://github.com/sponsors/isaacs"
4040 - }
4041 - },
4042 - "node_modules/glob-parent": {
4043 - "version": "6.0.2",
4044 - "dev": true,
4045 - "license": "ISC",
4046 - "dependencies": {
4047 - "is-glob": "^4.0.3"
4048 - },
4049 - "engines": {
4050 - "node": ">=10.13.0"
4051 - }
4052 - },
4053 - "node_modules/global-dirs": {
4054 - "version": "3.0.0",
4055 - "dev": true,
4056 - "license": "MIT",
4057 - "dependencies": {
4058 - "ini": "2.0.0"
4059 - },
4060 - "engines": {
4061 - "node": ">=10"
4062 - },
4063 - "funding": {
4064 - "url": "https://github.com/sponsors/sindresorhus"
4065 - }
4066 - },
4067 - "node_modules/globals": {
4068 - "version": "13.20.0",
4069 - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
4070 - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
4071 - "dev": true,
4072 - "dependencies": {
4073 - "type-fest": "^0.20.2"
4074 - },
4075 - "engines": {
4076 - "node": ">=8"
4077 - },
4078 - "funding": {
4079 - "url": "https://github.com/sponsors/sindresorhus"
4080 - }
4081 - },
4082 - "node_modules/globby": {
4083 - "version": "11.1.0",
4084 - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
4085 - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
4086 - "dev": true,
4087 - "dependencies": {
4088 - "array-union": "^2.1.0",
4089 - "dir-glob": "^3.0.1",
4090 - "fast-glob": "^3.2.9",
4091 - "ignore": "^5.2.0",
4092 - "merge2": "^1.4.1",
4093 - "slash": "^3.0.0"
4094 - },
4095 - "engines": {
4096 - "node": ">=10"
4097 - },
4098 - "funding": {
4099 - "url": "https://github.com/sponsors/sindresorhus"
4100 - }
4101 - },
4102 - "node_modules/graceful-fs": {
4103 - "version": "4.2.10",
4104 - "dev": true,
4105 - "license": "ISC"
4106 - },
4107 - "node_modules/graphemer": {
4108 - "version": "1.4.0",
4109 - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
4110 - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
4111 - "dev": true
4112 - },
4113 - "node_modules/grid-index": {
4114 - "version": "1.1.0",
4115 - "resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.1.0.tgz",
4116 - "integrity": "sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA=="
4117 - },
4118 - "node_modules/has": {
4119 - "version": "1.0.3",
4120 - "license": "MIT",
4121 - "dependencies": {
4122 - "function-bind": "^1.1.1"
4123 - },
4124 - "engines": {
4125 - "node": ">= 0.4.0"
4126 - }
4127 - },
4128 - "node_modules/has-bigints": {
4129 - "version": "1.0.2",
4130 - "dev": true,
4131 - "license": "MIT",
4132 - "funding": {
4133 - "url": "https://github.com/sponsors/ljharb"
4134 - }
4135 - },
4136 - "node_modules/has-flag": {
4137 - "version": "4.0.0",
4138 - "dev": true,
4139 - "license": "MIT",
4140 - "engines": {
4141 - "node": ">=8"
4142 - }
4143 - },
4144 - "node_modules/has-property-descriptors": {
4145 - "version": "1.0.0",
4146 - "license": "MIT",
4147 - "dependencies": {
4148 - "get-intrinsic": "^1.1.1"
4149 - },
4150 - "funding": {
4151 - "url": "https://github.com/sponsors/ljharb"
4152 - }
4153 - },
4154 - "node_modules/has-symbols": {
4155 - "version": "1.0.3",
4156 - "license": "MIT",
4157 - "engines": {
4158 - "node": ">= 0.4"
4159 - },
4160 - "funding": {
4161 - "url": "https://github.com/sponsors/ljharb"
4162 - }
4163 - },
4164 - "node_modules/has-tostringtag": {
4165 - "version": "1.0.0",
4166 - "license": "MIT",
4167 - "dependencies": {
4168 - "has-symbols": "^1.0.2"
4169 - },
4170 - "engines": {
4171 - "node": ">= 0.4"
4172 - },
4173 - "funding": {
4174 - "url": "https://github.com/sponsors/ljharb"
4175 - }
4176 - },
4177 - "node_modules/he": {
4178 - "version": "1.2.0",
4179 - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
4180 - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
4181 - "dev": true,
4182 - "bin": {
4183 - "he": "bin/he"
4184 - }
4185 - },
4186 - "node_modules/highlight.js": {
4187 - "version": "10.7.3",
4188 - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
4189 - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
4190 - "engines": {
4191 - "node": "*"
4192 - }
4193 - },
4194 - "node_modules/hosted-git-info": {
4195 - "version": "2.8.9",
4196 - "dev": true,
4197 - "license": "ISC"
4198 - },
4199 - "node_modules/html-encoding-sniffer": {
4200 - "version": "3.0.0",
4201 - "dev": true,
4202 - "license": "MIT",
4203 - "dependencies": {
4204 - "whatwg-encoding": "^2.0.0"
4205 - },
4206 - "engines": {
4207 - "node": ">=12"
4208 - }
4209 - },
4210 - "node_modules/http-proxy-agent": {
4211 - "version": "5.0.0",
4212 - "dev": true,
4213 - "license": "MIT",
4214 - "dependencies": {
4215 - "@tootallnate/once": "2",
4216 - "agent-base": "6",
4217 - "debug": "4"
4218 - },
4219 - "engines": {
4220 - "node": ">= 6"
4221 - }
4222 - },
4223 - "node_modules/http-signature": {
4224 - "version": "1.3.6",
4225 - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz",
4226 - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==",
4227 - "dev": true,
4228 - "dependencies": {
4229 - "assert-plus": "^1.0.0",
4230 - "jsprim": "^2.0.2",
4231 - "sshpk": "^1.14.1"
4232 - },
4233 - "engines": {
4234 - "node": ">=0.10"
4235 - }
4236 - },
4237 - "node_modules/https-proxy-agent": {
4238 - "version": "5.0.1",
4239 - "dev": true,
4240 - "license": "MIT",
4241 - "dependencies": {
4242 - "agent-base": "6",
4243 - "debug": "4"
4244 - },
4245 - "engines": {
4246 - "node": ">= 6"
4247 - }
4248 - },
4249 - "node_modules/human-signals": {
4250 - "version": "1.1.1",
4251 - "dev": true,
4252 - "license": "Apache-2.0",
4253 - "engines": {
4254 - "node": ">=8.12.0"
4255 - }
4256 - },
4257 - "node_modules/iconv-lite": {
4258 - "version": "0.6.3",
4259 - "dev": true,
4260 - "license": "MIT",
4261 - "dependencies": {
4262 - "safer-buffer": ">= 2.1.2 < 3.0.0"
4263 - },
4264 - "engines": {
4265 - "node": ">=0.10.0"
4266 - }
4267 - },
4268 - "node_modules/ieee754": {
4269 - "version": "1.2.1",
4270 - "funding": [
4271 - {
4272 - "type": "github",
4273 - "url": "https://github.com/sponsors/feross"
4274 - },
4275 - {
4276 - "type": "patreon",
4277 - "url": "https://www.patreon.com/feross"
4278 - },
4279 - {
4280 - "type": "consulting",
4281 - "url": "https://feross.org/support"
4282 - }
4283 - ],
4284 - "license": "BSD-3-Clause"
4285 - },
4286 - "node_modules/ignore": {
4287 - "version": "5.2.4",
4288 - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
4289 - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
4290 - "dev": true,
4291 - "engines": {
4292 - "node": ">= 4"
4293 - }
4294 - },
4295 - "node_modules/immutable": {
4296 - "version": "4.1.0",
4297 - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz",
4298 - "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==",
4299 - "dev": true
4300 - },
4301 - "node_modules/import-fresh": {
4302 - "version": "3.3.0",
4303 - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
4304 - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
4305 - "dev": true,
4306 - "dependencies": {
4307 - "parent-module": "^1.0.0",
4308 - "resolve-from": "^4.0.0"
4309 - },
4310 - "engines": {
4311 - "node": ">=6"
4312 - },
4313 - "funding": {
4314 - "url": "https://github.com/sponsors/sindresorhus"
4315 - }
4316 - },
4317 - "node_modules/imurmurhash": {
4318 - "version": "0.1.4",
4319 - "dev": true,
4320 - "license": "MIT",
4321 - "engines": {
4322 - "node": ">=0.8.19"
4323 - }
4324 - },
4325 - "node_modules/indent-string": {
4326 - "version": "4.0.0",
4327 - "dev": true,
4328 - "license": "MIT",
4329 - "engines": {
4330 - "node": ">=8"
4331 - }
4332 - },
4333 - "node_modules/inflight": {
4334 - "version": "1.0.6",
4335 - "dev": true,
4336 - "license": "ISC",
4337 - "dependencies": {
4338 - "once": "^1.3.0",
4339 - "wrappy": "1"
4340 - }
4341 - },
4342 - "node_modules/inherits": {
4343 - "version": "2.0.4",
4344 - "dev": true,
4345 - "license": "ISC"
4346 - },
4347 - "node_modules/ini": {
4348 - "version": "2.0.0",
4349 - "dev": true,
4350 - "license": "ISC",
4351 - "engines": {
4352 - "node": ">=10"
4353 - }
4354 - },
4355 - "node_modules/internal-slot": {
4356 - "version": "1.0.3",
4357 - "dev": true,
4358 - "license": "MIT",
4359 - "dependencies": {
4360 - "get-intrinsic": "^1.1.0",
4361 - "has": "^1.0.3",
4362 - "side-channel": "^1.0.4"
4363 - },
4364 - "engines": {
4365 - "node": ">= 0.4"
4366 - }
4367 - },
4368 - "node_modules/is-arguments": {
4369 - "version": "1.1.1",
4370 - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
4371 - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
4372 - "dependencies": {
4373 - "call-bind": "^1.0.2",
4374 - "has-tostringtag": "^1.0.0"
4375 - },
4376 - "engines": {
4377 - "node": ">= 0.4"
4378 - },
4379 - "funding": {
4380 - "url": "https://github.com/sponsors/ljharb"
4381 - }
4382 - },
4383 - "node_modules/is-arrayish": {
4384 - "version": "0.2.1",
4385 - "dev": true,
4386 - "license": "MIT"
4387 - },
4388 - "node_modules/is-bigint": {
4389 - "version": "1.0.4",
4390 - "dev": true,
4391 - "license": "MIT",
4392 - "dependencies": {
4393 - "has-bigints": "^1.0.1"
4394 - },
4395 - "funding": {
4396 - "url": "https://github.com/sponsors/ljharb"
4397 - }
4398 - },
4399 - "node_modules/is-binary-path": {
4400 - "version": "2.1.0",
4401 - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
4402 - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
4403 - "dev": true,
4404 - "dependencies": {
4405 - "binary-extensions": "^2.0.0"
4406 - },
4407 - "engines": {
4408 - "node": ">=8"
4409 - }
4410 - },
4411 - "node_modules/is-boolean-object": {
4412 - "version": "1.1.2",
4413 - "dev": true,
4414 - "license": "MIT",
4415 - "dependencies": {
4416 - "call-bind": "^1.0.2",
4417 - "has-tostringtag": "^1.0.0"
4418 - },
4419 - "engines": {
4420 - "node": ">= 0.4"
4421 - },
4422 - "funding": {
4423 - "url": "https://github.com/sponsors/ljharb"
4424 - }
4425 - },
4426 - "node_modules/is-callable": {
4427 - "version": "1.2.4",
4428 - "dev": true,
4429 - "license": "MIT",
4430 - "engines": {
4431 - "node": ">= 0.4"
4432 - },
4433 - "funding": {
4434 - "url": "https://github.com/sponsors/ljharb"
4435 - }
4436 - },
4437 - "node_modules/is-ci": {
4438 - "version": "3.0.1",
4439 - "dev": true,
4440 - "license": "MIT",
4441 - "dependencies": {
4442 - "ci-info": "^3.2.0"
4443 - },
4444 - "bin": {
4445 - "is-ci": "bin.js"
4446 - }
4447 - },
4448 - "node_modules/is-core-module": {
4449 - "version": "2.10.0",
4450 - "dev": true,
4451 - "license": "MIT",
4452 - "dependencies": {
4453 - "has": "^1.0.3"
4454 - },
4455 - "funding": {
4456 - "url": "https://github.com/sponsors/ljharb"
4457 - }
4458 - },
4459 - "node_modules/is-date-object": {
4460 - "version": "1.0.5",
4461 - "license": "MIT",
4462 - "dependencies": {
4463 - "has-tostringtag": "^1.0.0"
4464 - },
4465 - "engines": {
4466 - "node": ">= 0.4"
4467 - },
4468 - "funding": {
4469 - "url": "https://github.com/sponsors/ljharb"
4470 - }
4471 - },
4472 - "node_modules/is-docker": {
4473 - "version": "3.0.0",
4474 - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
4475 - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
4476 - "dev": true,
4477 - "bin": {
4478 - "is-docker": "cli.js"
4479 - },
4480 - "engines": {
4481 - "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
4482 - },
4483 - "funding": {
4484 - "url": "https://github.com/sponsors/sindresorhus"
4485 - }
4486 - },
4487 - "node_modules/is-extglob": {
4488 - "version": "2.1.1",
4489 - "dev": true,
4490 - "license": "MIT",
4491 - "engines": {
4492 - "node": ">=0.10.0"
4493 - }
4494 - },
4495 - "node_modules/is-fullwidth-code-point": {
4496 - "version": "3.0.0",
4497 - "dev": true,
4498 - "license": "MIT",
4499 - "engines": {
4500 - "node": ">=8"
4501 - }
4502 - },
4503 - "node_modules/is-glob": {
4504 - "version": "4.0.3",
4505 - "dev": true,
4506 - "license": "MIT",
4507 - "dependencies": {
4508 - "is-extglob": "^2.1.1"
4509 - },
4510 - "engines": {
4511 - "node": ">=0.10.0"
4512 - }
4513 - },
4514 - "node_modules/is-inside-container": {
4515 - "version": "1.0.0",
4516 - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
4517 - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
4518 - "dev": true,
4519 - "dependencies": {
4520 - "is-docker": "^3.0.0"
4521 - },
4522 - "bin": {
4523 - "is-inside-container": "cli.js"
4524 - },
4525 - "engines": {
4526 - "node": ">=14.16"
4527 - },
4528 - "funding": {
4529 - "url": "https://github.com/sponsors/sindresorhus"
4530 - }
4531 - },
4532 - "node_modules/is-installed-globally": {
4533 - "version": "0.4.0",
4534 - "dev": true,
4535 - "license": "MIT",
4536 - "dependencies": {
4537 - "global-dirs": "^3.0.0",
4538 - "is-path-inside": "^3.0.2"
4539 - },
4540 - "engines": {
4541 - "node": ">=10"
4542 - },
4543 - "funding": {
4544 - "url": "https://github.com/sponsors/sindresorhus"
4545 - }
4546 - },
4547 - "node_modules/is-negative-zero": {
4548 - "version": "2.0.2",
4549 - "dev": true,
4550 - "license": "MIT",
4551 - "engines": {
4552 - "node": ">= 0.4"
4553 - },
4554 - "funding": {
4555 - "url": "https://github.com/sponsors/ljharb"
4556 - }
4557 - },
4558 - "node_modules/is-number": {
4559 - "version": "7.0.0",
4560 - "dev": true,
4561 - "license": "MIT",
4562 - "engines": {
4563 - "node": ">=0.12.0"
4564 - }
4565 - },
4566 - "node_modules/is-number-object": {
4567 - "version": "1.0.7",
4568 - "dev": true,
4569 - "license": "MIT",
4570 - "dependencies": {
4571 - "has-tostringtag": "^1.0.0"
4572 - },
4573 - "engines": {
4574 - "node": ">= 0.4"
4575 - },
4576 - "funding": {
4577 - "url": "https://github.com/sponsors/ljharb"
4578 - }
4579 - },
4580 - "node_modules/is-path-inside": {
4581 - "version": "3.0.3",
4582 - "dev": true,
4583 - "license": "MIT",
4584 - "engines": {
4585 - "node": ">=8"
4586 - }
4587 - },
4588 - "node_modules/is-potential-custom-element-name": {
4589 - "version": "1.0.1",
4590 - "dev": true,
4591 - "license": "MIT"
4592 - },
4593 - "node_modules/is-regex": {
4594 - "version": "1.1.4",
4595 - "license": "MIT",
4596 - "dependencies": {
4597 - "call-bind": "^1.0.2",
4598 - "has-tostringtag": "^1.0.0"
4599 - },
4600 - "engines": {
4601 - "node": ">= 0.4"
4602 - },
4603 - "funding": {
4604 - "url": "https://github.com/sponsors/ljharb"
4605 - }
4606 - },
4607 - "node_modules/is-shared-array-buffer": {
4608 - "version": "1.0.2",
4609 - "dev": true,
4610 - "license": "MIT",
4611 - "dependencies": {
4612 - "call-bind": "^1.0.2"
4613 - },
4614 - "funding": {
4615 - "url": "https://github.com/sponsors/ljharb"
4616 - }
4617 - },
4618 - "node_modules/is-stream": {
4619 - "version": "2.0.1",
4620 - "dev": true,
4621 - "license": "MIT",
4622 - "engines": {
4623 - "node": ">=8"
4624 - },
4625 - "funding": {
4626 - "url": "https://github.com/sponsors/sindresorhus"
4627 - }
4628 - },
4629 - "node_modules/is-string": {
4630 - "version": "1.0.7",
4631 - "dev": true,
4632 - "license": "MIT",
4633 - "dependencies": {
4634 - "has-tostringtag": "^1.0.0"
4635 - },
4636 - "engines": {
4637 - "node": ">= 0.4"
4638 - },
4639 - "funding": {
4640 - "url": "https://github.com/sponsors/ljharb"
4641 - }
4642 - },
4643 - "node_modules/is-symbol": {
4644 - "version": "1.0.4",
4645 - "dev": true,
4646 - "license": "MIT",
4647 - "dependencies": {
4648 - "has-symbols": "^1.0.2"
4649 - },
4650 - "engines": {
4651 - "node": ">= 0.4"
4652 - },
4653 - "funding": {
4654 - "url": "https://github.com/sponsors/ljharb"
4655 - }
4656 - },
4657 - "node_modules/is-typedarray": {
4658 - "version": "1.0.0",
4659 - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
4660 - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
4661 - "dev": true
4662 - },
4663 - "node_modules/is-unicode-supported": {
4664 - "version": "0.1.0",
4665 - "dev": true,
4666 - "license": "MIT",
4667 - "engines": {
4668 - "node": ">=10"
4669 - },
4670 - "funding": {
4671 - "url": "https://github.com/sponsors/sindresorhus"
4672 - }
4673 - },
4674 - "node_modules/is-weakref": {
4675 - "version": "1.0.2",
4676 - "dev": true,
4677 - "license": "MIT",
4678 - "dependencies": {
4679 - "call-bind": "^1.0.2"
4680 - },
4681 - "funding": {
4682 - "url": "https://github.com/sponsors/ljharb"
4683 - }
4684 - },
4685 - "node_modules/is-wsl": {
4686 - "version": "2.2.0",
4687 - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
4688 - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
4689 - "dev": true,
4690 - "dependencies": {
4691 - "is-docker": "^2.0.0"
4692 - },
4693 - "engines": {
4694 - "node": ">=8"
4695 - }
4696 - },
4697 - "node_modules/is-wsl/node_modules/is-docker": {
4698 - "version": "2.2.1",
4699 - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
4700 - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
4701 - "dev": true,
4702 - "bin": {
4703 - "is-docker": "cli.js"
4704 - },
4705 - "engines": {
4706 - "node": ">=8"
4707 - },
4708 - "funding": {
4709 - "url": "https://github.com/sponsors/sindresorhus"
4710 - }
4711 - },
4712 - "node_modules/isexe": {
4713 - "version": "2.0.0",
4714 - "dev": true,
4715 - "license": "ISC"
4716 - },
4717 - "node_modules/isstream": {
4718 - "version": "0.1.2",
4719 - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
4720 - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
4721 - "dev": true
4722 - },
4723 - "node_modules/joi": {
4724 - "version": "17.9.1",
4725 - "resolved": "https://registry.npmjs.org/joi/-/joi-17.9.1.tgz",
4726 - "integrity": "sha512-FariIi9j6QODKATGBrEX7HZcja8Bsh3rfdGYy/Sb65sGlZWK/QWesU1ghk7aJWDj95knjXlQfSmzFSPPkLVsfw==",
4727 - "dev": true,
4728 - "dependencies": {
4729 - "@hapi/hoek": "^9.0.0",
4730 - "@hapi/topo": "^5.0.0",
4731 - "@sideway/address": "^4.1.3",
4732 - "@sideway/formula": "^3.0.1",
4733 - "@sideway/pinpoint": "^2.0.0"
4734 - }
4735 - },
4736 - "node_modules/js-beautify": {
4737 - "version": "1.14.9",
4738 - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.9.tgz",
4739 - "integrity": "sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==",
4740 - "dev": true,
4741 - "dependencies": {
4742 - "config-chain": "^1.1.13",
4743 - "editorconfig": "^1.0.3",
4744 - "glob": "^8.1.0",
4745 - "nopt": "^6.0.0"
4746 - },
4747 - "bin": {
4748 - "css-beautify": "js/bin/css-beautify.js",
4749 - "html-beautify": "js/bin/html-beautify.js",
4750 - "js-beautify": "js/bin/js-beautify.js"
4751 - },
4752 - "engines": {
4753 - "node": ">=12"
4754 - }
4755 - },
4756 - "node_modules/js-beautify/node_modules/brace-expansion": {
4757 - "version": "2.0.1",
4758 - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
4759 - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
4760 - "dev": true,
4761 - "dependencies": {
4762 - "balanced-match": "^1.0.0"
4763 - }
4764 - },
4765 - "node_modules/js-beautify/node_modules/glob": {
4766 - "version": "8.1.0",
4767 - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
4768 - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
4769 - "dev": true,
4770 - "dependencies": {
4771 - "fs.realpath": "^1.0.0",
4772 - "inflight": "^1.0.4",
4773 - "inherits": "2",
4774 - "minimatch": "^5.0.1",
4775 - "once": "^1.3.0"
4776 - },
4777 - "engines": {
4778 - "node": ">=12"
4779 - },
4780 - "funding": {
4781 - "url": "https://github.com/sponsors/isaacs"
4782 - }
4783 - },
4784 - "node_modules/js-beautify/node_modules/minimatch": {
4785 - "version": "5.1.6",
4786 - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
4787 - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
4788 - "dev": true,
4789 - "dependencies": {
4790 - "brace-expansion": "^2.0.1"
4791 - },
4792 - "engines": {
4793 - "node": ">=10"
4794 - }
4795 - },
4796 - "node_modules/js-yaml": {
4797 - "version": "4.1.0",
4798 - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
4799 - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
4800 - "dev": true,
4801 - "dependencies": {
4802 - "argparse": "^2.0.1"
4803 - },
4804 - "bin": {
4805 - "js-yaml": "bin/js-yaml.js"
4806 - }
4807 - },
4808 - "node_modules/jsbn": {
4809 - "version": "0.1.1",
4810 - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
4811 - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
4812 - "dev": true
4813 - },
4814 - "node_modules/jsdom": {
4815 - "version": "22.1.0",
4816 - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz",
4817 - "integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==",
4818 - "dev": true,
4819 - "dependencies": {
4820 - "abab": "^2.0.6",
4821 - "cssstyle": "^3.0.0",
4822 - "data-urls": "^4.0.0",
4823 - "decimal.js": "^10.4.3",
4824 - "domexception": "^4.0.0",
4825 - "form-data": "^4.0.0",
4826 - "html-encoding-sniffer": "^3.0.0",
4827 - "http-proxy-agent": "^5.0.0",
4828 - "https-proxy-agent": "^5.0.1",
4829 - "is-potential-custom-element-name": "^1.0.1",
4830 - "nwsapi": "^2.2.4",
4831 - "parse5": "^7.1.2",
4832 - "rrweb-cssom": "^0.6.0",
4833 - "saxes": "^6.0.0",
4834 - "symbol-tree": "^3.2.4",
4835 - "tough-cookie": "^4.1.2",
4836 - "w3c-xmlserializer": "^4.0.0",
4837 - "webidl-conversions": "^7.0.0",
4838 - "whatwg-encoding": "^2.0.0",
4839 - "whatwg-mimetype": "^3.0.0",
4840 - "whatwg-url": "^12.0.1",
4841 - "ws": "^8.13.0",
4842 - "xml-name-validator": "^4.0.0"
4843 - },
4844 - "engines": {
4845 - "node": ">=16"
4846 - },
4847 - "peerDependencies": {
4848 - "canvas": "^2.5.0"
4849 - },
4850 - "peerDependenciesMeta": {
4851 - "canvas": {
4852 - "optional": true
4853 - }
4854 - }
4855 - },
4856 - "node_modules/jsdom/node_modules/form-data": {
4857 - "version": "4.0.0",
4858 - "dev": true,
4859 - "license": "MIT",
4860 - "dependencies": {
4861 - "asynckit": "^0.4.0",
4862 - "combined-stream": "^1.0.8",
4863 - "mime-types": "^2.1.12"
4864 - },
4865 - "engines": {
4866 - "node": ">= 6"
4867 - }
4868 - },
4869 - "node_modules/json-parse-better-errors": {
4870 - "version": "1.0.2",
4871 - "dev": true,
4872 - "license": "MIT"
4873 - },
4874 - "node_modules/json-schema": {
4875 - "version": "0.4.0",
4876 - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
4877 - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
4878 - "dev": true
4879 - },
4880 - "node_modules/json-schema-traverse": {
4881 - "version": "0.4.1",
4882 - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
4883 - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
4884 - "dev": true
4885 - },
4886 - "node_modules/json-stable-stringify-without-jsonify": {
4887 - "version": "1.0.1",
4888 - "dev": true,
4889 - "license": "MIT"
4890 - },
4891 - "node_modules/json-stringify-safe": {
4892 - "version": "5.0.1",
4893 - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
4894 - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
4895 - "dev": true
4896 - },
4897 - "node_modules/jsonc-parser": {
4898 - "version": "3.2.0",
4899 - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
4900 - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
4901 - "dev": true
4902 - },
4903 - "node_modules/jsonfile": {
4904 - "version": "6.1.0",
4905 - "dev": true,
4906 - "license": "MIT",
4907 - "dependencies": {
4908 - "universalify": "^2.0.0"
4909 - },
4910 - "optionalDependencies": {
4911 - "graceful-fs": "^4.1.6"
4912 - }
4913 - },
4914 - "node_modules/jsprim": {
4915 - "version": "2.0.2",
4916 - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz",
4917 - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==",
4918 - "dev": true,
4919 - "engines": [
4920 - "node >=0.6.0"
4921 - ],
4922 - "dependencies": {
4923 - "assert-plus": "1.0.0",
4924 - "extsprintf": "1.3.0",
4925 - "json-schema": "0.4.0",
4926 - "verror": "1.10.0"
4927 - }
4928 - },
4929 - "node_modules/kdbush": {
4930 - "version": "4.0.2",
4931 - "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz",
4932 - "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA=="
4933 - },
4934 - "node_modules/lazy-ass": {
4935 - "version": "1.6.0",
4936 - "dev": true,
4937 - "license": "MIT",
4938 - "engines": {
4939 - "node": "> 0.8"
4940 - }
4941 - },
4942 - "node_modules/leaflet": {
4943 - "version": "1.9.4",
4944 - "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
4945 - "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
4946 - },
4947 - "node_modules/levn": {
4948 - "version": "0.4.1",
4949 - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
4950 - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
4951 - "dev": true,
4952 - "dependencies": {
4953 - "prelude-ls": "^1.2.1",
4954 - "type-check": "~0.4.0"
4955 - },
4956 - "engines": {
4957 - "node": ">= 0.8.0"
4958 - }
4959 - },
4960 - "node_modules/listr2": {
4961 - "version": "3.14.0",
4962 - "dev": true,
4963 - "license": "MIT",
4964 - "dependencies": {
4965 - "cli-truncate": "^2.1.0",
4966 - "colorette": "^2.0.16",
4967 - "log-update": "^4.0.0",
4968 - "p-map": "^4.0.0",
4969 - "rfdc": "^1.3.0",
4970 - "rxjs": "^7.5.1",
4971 - "through": "^2.3.8",
4972 - "wrap-ansi": "^7.0.0"
4973 - },
4974 - "engines": {
4975 - "node": ">=10.0.0"
4976 - },
4977 - "peerDependencies": {
4978 - "enquirer": ">= 2.3.0 < 3"
4979 - },
4980 - "peerDependenciesMeta": {
4981 - "enquirer": {
4982 - "optional": true
4983 - }
4984 - }
4985 - },
4986 - "node_modules/load-json-file": {
4987 - "version": "4.0.0",
4988 - "dev": true,
4989 - "license": "MIT",
4990 - "dependencies": {
4991 - "graceful-fs": "^4.1.2",
4992 - "parse-json": "^4.0.0",
4993 - "pify": "^3.0.0",
4994 - "strip-bom": "^3.0.0"
4995 - },
4996 - "engines": {
4997 - "node": ">=4"
4998 - }
4999 - },

This file is too large to show in full.

package.json
+91 -89
@@ -1,90 +1,92 @@
1 {
2 - "name": "pragmatic",
3 - "version": "5.0.0",
4 - "private": true,
5 - "scripts": {
6 - "dev": "vite",
7 - "build": "run-p type-check build-only",
8 - "preview": "vite preview --port 4173",
9 - "serve": "vite preview",
10 - "test:unit": "vitest --environment jsdom",
11 - "test:e2e": "start-server-and-test preview http://localhost:4173/ 'cypress open --e2e'",
12 - "test:e2e:ci": "start-server-and-test preview http://localhost:4173/ 'cypress run --e2e'",
13 - "build-only": "vite build",
14 - "type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
15 - "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
16 - },
17 - "dependencies": {
18 - "@element-plus/icons-vue": "^2.1.0",
19 - "@fullcalendar/core": "^5.11.5",
20 - "@fullcalendar/daygrid": "^5.11.5",
21 - "@fullcalendar/interaction": "^5.11.5",
22 - "@fullcalendar/list": "^5.11.5",
23 - "@fullcalendar/timegrid": "^5.11.5",
24 - "@fullcalendar/vue3": "^5.11.5",
25 - "@mdi/font": "^7.2.96",
26 - "@vue-leaflet/vue-leaflet": "^0.10.1",
27 - "animate.css": "^4.1.1",
28 - "balloon-css": "^1.2.0",
29 - "chance": "^1.1.11",
30 - "cryptocoins-icons": "^2.9.0",
31 - "dayjs": "^1.11.9",
32 - "detect-browser": "^5.3.0",
33 - "drift-zoom": "^1.5.1",
34 - "echarts": "^5.4.3",
35 - "element-plus": "^2.3.9",
36 - "file-saver": "^2.0.5",
37 - "flag-icon-css": "^4.1.7",
38 - "flex.box": "^3.4.4",
39 - "leaflet": "^1.9.4",
40 - "lodash": "^4.17.21",
41 - "mapbox-gl": "^2.15.0",
42 - "marquee-infinite": "^0.0.4",
43 - "mavon-editor": "^3.0.1",
44 - "open-props": "^1.5.11",
45 - "papaparse": "^5.4.1",
46 - "pell": "^1.0.6",
47 - "perfect-scrollbar": "^1.5.5",
48 - "pinia": "2.0.22",
49 - "pinia-plugin-persistedstate": "^2.2.0",
50 - "quill": "^1.3.7",
51 - "tui-grid": "^4.21.15",
52 - "v-click-outside": "^3.2.0",
53 - "v-viewer": "3.0.11",
54 - "validator": "^13.11.0",
55 - "vue": "^3.3.4",
56 - "vue-chartkick": "^1.1.0",
57 - "vue-fullscreen": "^3.1.1",
58 - "vue-i18n": "^9.2.2",
59 - "vue-router": "^4.2.4",
60 - "vue-virtual-collection": "^1.5.0",
61 - "vue3-highlightjs": "^1.0.5",
62 - "vue3-marquee": "^4.0.0",
63 - "vue3-marquee-slider": "^1.0.5",
64 - "vue3-tui-grid": "^0.1.51"
65 - },
66 - "devDependencies": {
67 - "@rushstack/eslint-patch": "^1.3.3",
68 - "@types/jsdom": "^21.1.1",
69 - "@types/node": "^20.5.0",
70 - "@vitejs/plugin-vue": "^4.2.3",
71 - "@vue/eslint-config-prettier": "^8.0.0",
72 - "@vue/eslint-config-typescript": "^11.0.3",
73 - "@vue/test-utils": "^2.4.1",
74 - "@vue/tsconfig": "^0.4.0",
75 - "cypress": "^12.17.4",
76 - "eslint": "^8.47.0",
77 - "eslint-plugin-cypress": "^2.14.0",
78 - "eslint-plugin-vue": "^9.17.0",
79 - "jsdom": "^22.1.0",
80 - "npm-run-all": "^4.1.5",
81 - "prettier": "^3.0.2",
82 - "sass": "^1.65.1",
83 - "start-server-and-test": "^2.0.0",
84 - "typescript": "~5.1.6",
85 - "url": "^0.11.1",
86 - "vite": "^4.4.9",
87 - "vitest": "^0.34.1",
88 - "vue-tsc": "^1.8.8"
89 - }
90 -}
\ No newline at end of file
2 + "name": "pragmatic",
3 + "version": "5.0.0",
4 + "private": true,
5 + "scripts": {
6 + "dev": "vite",
7 + "build": "run-p type-check build-only",
8 + "preview": "vite preview --port 4173",
9 + "serve": "vite preview",
10 + "test:unit": "vitest --environment jsdom",
11 + "test:e2e": "start-server-and-test preview http://localhost:4173/ 'cypress open --e2e'",
12 + "test:e2e:ci": "start-server-and-test preview http://localhost:4173/ 'cypress run --e2e'",
13 + "build-only": "vite build",
14 + "type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
15 + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
16 + },
17 + "dependencies": {
18 + "@element-plus/icons-vue": "^2.1.0",
19 + "@fullcalendar/core": "^5.11.5",
20 + "@fullcalendar/daygrid": "^5.11.5",
21 + "@fullcalendar/interaction": "^5.11.5",
22 + "@fullcalendar/list": "^5.11.5",
23 + "@fullcalendar/timegrid": "^5.11.5",
24 + "@fullcalendar/vue3": "^5.11.5",
25 + "@mdi/font": "^7.2.96",
26 + "@vue-leaflet/vue-leaflet": "^0.10.1",
27 + "animate.css": "^4.1.1",
28 + "balloon-css": "^1.2.0",
29 + "bytes": "^3.1.2",
30 + "chance": "^1.1.11",
31 + "cryptocoins-icons": "^2.9.0",
32 + "dayjs": "^1.11.9",
33 + "detect-browser": "^5.3.0",
34 + "drift-zoom": "^1.5.1",
35 + "echarts": "^5.4.3",
36 + "element-plus": "^2.3.9",
37 + "file-saver": "^2.0.5",
38 + "flag-icon-css": "^4.1.7",
39 + "flex.box": "^3.4.4",
40 + "leaflet": "^1.9.4",
41 + "lodash": "^4.17.21",
42 + "mapbox-gl": "^2.15.0",
43 + "marquee-infinite": "^0.0.4",
44 + "mavon-editor": "^3.0.1",
45 + "nanoid": "^4.0.2",
46 + "open-props": "^1.5.13",
47 + "papaparse": "^5.4.1",
48 + "pell": "^1.0.6",
49 + "perfect-scrollbar": "^1.5.5",
50 + "pinia": "2.0.22",
51 + "pinia-plugin-persistedstate": "^2.2.0",
52 + "quill": "^1.3.7",
53 + "tui-grid": "^4.21.15",
54 + "v-click-outside": "^3.2.0",
55 + "v-viewer": "3.0.11",
56 + "validator": "^13.11.0",
57 + "vue": "^3.3.4",
58 + "vue-chartkick": "^1.1.0",
59 + "vue-fullscreen": "^3.1.1",
60 + "vue-i18n": "^9.2.2",
61 + "vue-router": "^4.2.4",
62 + "vue-virtual-collection": "^1.5.0",
63 + "vue3-highlightjs": "^1.0.5",
64 + "vue3-marquee": "^4.0.0",
65 + "vue3-marquee-slider": "^1.0.5",
66 + "vue3-tui-grid": "^0.1.51"
67 + },
68 + "devDependencies": {
69 + "@rushstack/eslint-patch": "^1.3.3",
70 + "@types/jsdom": "^21.1.1",
71 + "@types/node": "^20.5.2",
72 + "@vitejs/plugin-vue": "^4.3.3",
73 + "@vue/eslint-config-prettier": "^8.0.0",
74 + "@vue/eslint-config-typescript": "^11.0.3",
75 + "@vue/test-utils": "^2.4.1",
76 + "@vue/tsconfig": "^0.4.0",
77 + "cypress": "^12.17.4",
78 + "eslint": "^8.47.0",
79 + "eslint-plugin-cypress": "^2.14.0",
80 + "eslint-plugin-vue": "^9.17.0",
81 + "jsdom": "^22.1.0",
82 + "npm-run-all": "^4.1.5",
83 + "prettier": "^3.0.2",
84 + "sass": "^1.66.1",
85 + "start-server-and-test": "^2.0.0",
86 + "typescript": "~5.1.6",
87 + "url": "^0.11.1",
88 + "vite": "^4.4.9",
89 + "vitest": "^0.34.2",
90 + "vue-tsc": "^1.8.8"
91 + }
92 +}
src/components/indices/ClusterHealth.vue new
+163
@@ -0,0 +1,163 @@
1 +<template>
2 + <div class="cluster-health">
3 + <div class="title">Overall Health</div>
4 + <div v-loading="loading">
5 + <div class="info">
6 + <div class="cluster-card" :class="[`health-${cluster.status}`]" v-if="cluster">
7 + <el-scrollbar max-height="500px">
8 + <div class="card-wrap">
9 + <div class="box" v-for="prop of propsOrder" :key="prop">
10 + <template v-if="prop === 'status'">
11 + <div class="value text-uppercase">
12 + <IndexIcon :health="cluster.status" color />
13 + {{ cluster.status }}
14 + </div>
15 + </template>
16 + <template v-else>
17 + <div class="value">{{ cluster[prop] }}</div>
18 + </template>
19 + <div class="label">{{ sanitizeLabel(prop) }}</div>
20 + </div>
21 + </div>
22 + </el-scrollbar>
23 + </div>
24 + </div>
25 + </div>
26 + </div>
27 +</template>
28 +
29 +<script setup lang="ts">
30 +import { onBeforeMount, ref } from "vue"
31 +import IndexIcon from "@/components/indices/IndexIcon.vue"
32 +import { ClusterHealth } from "@/types/indices.d"
33 +import Api from "@/api"
34 +import { ElMessage } from "element-plus"
35 +
36 +const cluster = ref<ClusterHealth | null>(null)
37 +const loading = ref(true)
38 +
39 +const propsOrder = ref([
40 + "cluster_name",
41 + "status",
42 + "active_primary_shards",
43 + "active_shards",
44 + "active_shards_percent_as_number",
45 + "delayed_unassigned_shards",
46 + "discovered_cluster_manager",
47 + "discovered_master",
48 + "initializing_shards",
49 + "number_of_data_nodes",
50 + "number_of_in_flight_fetch",
51 + "number_of_nodes",
52 + "number_of_pending_tasks",
53 + "relocating_shards",
54 + "task_max_waiting_in_queue_millis",
55 + "timed_out",
56 + "unassigned_shards"
57 +])
58 +
59 +function sanitizeLabel(label: string) {
60 + return label.replaceAll("_", " ")
61 +}
62 +
63 +function getClusterHealth() {
64 + loading.value = true
65 + Api.indices
66 + .getClusterHealth()
67 + .then(res => {
68 + if (res.data.success) {
69 + cluster.value = res.data.cluster_health
70 + } else {
71 + ElMessage({
72 + message: res.data?.message || "An error occurred. Please try again later.",
73 + type: "error"
74 + })
75 + }
76 + })
77 + .catch(err => {
78 + if (err.response.status === 401) {
79 + ElMessage({
80 + message: err.response?.data?.message || "Wazuh-Indexer returned Unauthorized. Please check your connector credentials.",
81 + type: "error"
82 + })
83 + } else if (err.response.status === 404) {
84 + ElMessage({
85 + message: err.response?.data?.message || "No alerts were found.",
86 + type: "error"
87 + })
88 + } else {
89 + ElMessage({
90 + message: err.response?.data?.message || "An error occurred. Please try again later.",
91 + type: "error"
92 + })
93 + }
94 + })
95 + .finally(() => {
96 + loading.value = false
97 + })
98 +}
99 +
100 +onBeforeMount(() => {
101 + getClusterHealth()
102 +})
103 +</script>
104 +
105 +<style lang="scss" scoped>
106 +@import "@/assets/scss/_variables";
107 +@import "@/assets/scss/card-shadow";
108 +
109 +.cluster-health {
110 + padding: var(--size-5) var(--size-6);
111 + @extend .card-base;
112 +
113 + .title {
114 + font-size: var(--font-size-4);
115 + font-weight: var(--font-weight-6);
116 + margin-bottom: var(--size-5);
117 + }
118 + .info {
119 + min-height: 50px;
120 +
121 + .cluster-card {
122 + @extend .card-base;
123 + @extend .card-shadow--small;
124 + border: 2px solid transparent;
125 +
126 + .card-wrap {
127 + padding: var(--size-3) var(--size-4);
128 + column-width: 12rem;
129 + column-count: auto;
130 + column-gap: var(--size-6);
131 + gap: var(--size-6);
132 +
133 + .box {
134 + overflow: hidden;
135 + margin-bottom: var(--size-6);
136 + .value {
137 + font-weight: bold;
138 + margin-bottom: 2px;
139 + white-space: nowrap;
140 + }
141 + .label {
142 + font-size: var(--font-size-0);
143 + font-family: var(--font-mono);
144 + opacity: 0.8;
145 + }
146 + }
147 + }
148 +
149 + &.health-green {
150 + border-color: $text-color-success;
151 + }
152 +
153 + &.health-yellow {
154 + border-color: $text-color-warning;
155 + }
156 +
157 + &.health-red {
158 + border-color: $text-color-danger;
159 + }
160 + }
161 + }
162 +}
163 +</style>
src/components/indices/Details.vue new
+200
@@ -0,0 +1,200 @@
1 +<template>
2 + <div class="index-details-box" v-loading="loading" :class="{ active: currentIndex }">
3 + <div class="box-header">
4 + <div class="title">
5 + <span v-if="currentIndex"> Below the details for index </span>
6 + <span v-else> Select an index to see the details </span>
7 + </div>
8 + <div class="select-box" v-if="indices && indices.length">
9 + <el-select v-model="currentIndex" placeholder="Indices list" clearable value-key="index" filterable>
10 + <el-option v-for="index in indices" :key="index.index" :label="index.index" :value="index"></el-option>
11 + </el-select>
12 + </div>
13 + </div>
14 + <div class="details-box" v-if="currentIndex">
15 + <div class="info">
16 + <IndexCard :index="currentIndex" showActions @delete="clearCurrentIndex()" />
17 + </div>
18 + <div class="shards">
19 + <el-scrollbar>
20 + <table class="styled">
21 + <thead>
22 + <tr>
23 + <th>Node</th>
24 + <th>Shard</th>
25 + <th>Size</th>
26 + <th>State</th>
27 + </tr>
28 + </thead>
29 + <tbody>
30 + <tr v-for="shard of filteredShards" :key="shard.id">
31 + <td>{{ shard.node || "-" }}</td>
32 + <td>{{ shard.shard || "-" }}</td>
33 + <td>{{ shard.size || "-" }}</td>
34 + <td>
35 + <span class="shard-state" :class="shard.state">
36 + {{ shard.state || "-" }}
37 + </span>
38 + </td>
39 + </tr>
40 + </tbody>
41 + </table>
42 + </el-scrollbar>
43 + </div>
44 + </div>
45 + </div>
46 +</template>
47 +
48 +<script setup lang="ts">
49 +import { computed, onBeforeMount, ref, toRefs } from "vue"
50 +import { Index, IndexShard } from "@/types/indices.d"
51 +import { ElMessage } from "element-plus"
52 +import IndexCard from "@/components/indices/IndexCard.vue"
53 +import Api from "@/api"
54 +import { nanoid } from "nanoid"
55 +
56 +type IndexModel = Index | null | ""
57 +
58 +const emit = defineEmits<{
59 + (e: "update:modelValue", value: IndexModel): void
60 +}>()
61 +
62 +const props = defineProps<{
63 + indices: Index[] | null
64 + modelValue: IndexModel
65 +}>()
66 +const { indices, modelValue } = toRefs(props)
67 +
68 +const shards = ref<IndexShard[]>([])
69 +const loadingShards = ref(false)
70 +const loading = computed(() => !indices?.value || indices.value === null || loadingShards.value)
71 +
72 +const filteredShards = computed(() =>
73 + shards.value.filter((shard: IndexShard) => {
74 + if (!currentIndex.value || typeof currentIndex.value === "string") return false
75 + return shard.index === currentIndex.value?.index
76 + })
77 +)
78 +
79 +const currentIndex = computed<IndexModel>({
80 + get() {
81 + return modelValue.value
82 + },
83 + set(value) {
84 + emit("update:modelValue", value)
85 + }
86 +})
87 +
88 +function clearCurrentIndex() {
89 + currentIndex.value = null
90 +}
91 +
92 +function getShards() {
93 + loadingShards.value = true
94 + Api.indices
95 + .getShards()
96 + .then(res => {
97 + if (res.data.success) {
98 + shards.value = (res.data?.shards || []).map(obj => {
99 + obj.id = nanoid()
100 + return obj
101 + })
102 + } else {
103 + ElMessage({
104 + message: res.data?.message || "An error occurred. Please try again later.",
105 + type: "error"
106 + })
107 + }
108 + })
109 + .catch(err => {
110 + if (err.response.status === 401) {
111 + ElMessage({
112 + message: err.response?.data?.message || "Wazuh-Indexer returned Unauthorized. Please check your connector credentials.",
113 + type: "error"
114 + })
115 + } else if (err.response.status === 404) {
116 + ElMessage({
117 + message: err.response?.data?.message || "No alerts were found.",
118 + type: "error"
119 + })
120 + } else {
121 + ElMessage({
122 + message: err.response?.data?.message || "An error occurred. Please try again later.",
123 + type: "error"
124 + })
125 + }
126 + })
127 + .finally(() => {
128 + loadingShards.value = false
129 + })
130 +}
131 +
132 +onBeforeMount(() => {
133 + getShards()
134 +})
135 +</script>
136 +
137 +<style lang="scss" scoped>
138 +@import "@/assets/scss/_variables";
139 +@import "@/assets/scss/card-shadow";
140 +
141 +.index-details-box {
142 + padding: var(--size-5) var(--size-6);
143 + border: 2px solid transparent;
144 + @extend .card-base;
145 + &.active {
146 + border-color: $text-color-accent;
147 + @extend .card-shadow--small;
148 + }
149 +
150 + .box-header {
151 + display: flex;
152 + align-items: center;
153 +
154 + .title {
155 + margin-right: var(--size-4);
156 + }
157 +
158 + .select-box {
159 + .el-select {
160 + min-width: var(--size-fluid-9);
161 + max-width: 100%;
162 + }
163 + }
164 + }
165 +
166 + .details-box {
167 + margin-top: var(--size-6);
168 +
169 + .shards {
170 + margin-top: var(--size-4);
171 + @extend .card-base;
172 + @extend .card-shadow--small;
173 +
174 + .shard-state {
175 + font-weight: bold;
176 + &.STARTED {
177 + color: $text-color-success;
178 + }
179 + &.UNASSIGNED {
180 + color: $text-color-warning;
181 + }
182 + }
183 + }
184 + }
185 +
186 + @media (max-width: 1000px) {
187 + .box-header {
188 + flex-direction: column;
189 + align-items: flex-start;
190 + gap: var(--size-2);
191 + .select-box {
192 + width: 100%;
193 + .el-select {
194 + min-width: 100%;
195 + }
196 + }
197 + }
198 + }
199 +}
200 +</style>
src/components/indices/IndexCard.vue new
+193
@@ -0,0 +1,193 @@
1 +<template>
2 + <div class="index-card" :class="[`health-${index.health}`]" v-loading="loading">
3 + <div class="group">
4 + <div class="box">
5 + <div class="value">{{ index.index }}</div>
6 + <div class="label">name</div>
7 + </div>
8 + <div class="box">
9 + <div class="value text-uppercase">
10 + <IndexIcon :health="index.health" color />
11 + {{ index.health }}
12 + </div>
13 + <div class="label">health</div>
14 + </div>
15 + </div>
16 + <div class="group">
17 + <div class="box">
18 + <div class="value">{{ index.store_size }}</div>
19 + <div class="label">store_size</div>
20 + </div>
21 + <div class="box">
22 + <div class="value">{{ index.docs_count }}</div>
23 + <div class="label">docs_count</div>
24 + </div>
25 + <div class="box">
26 + <div class="value">{{ index.replica_count }}</div>
27 + <div class="label">replica_count</div>
28 + </div>
29 + </div>
30 + <div class="group actions" v-if="showActions">
31 + <div class="box">
32 + <!--
33 + <el-tooltip content="Rotate" placement="top" :show-arrow="false">
34 + <el-button type="primary" :icon="RefreshIcon" circle />
35 + </el-tooltip>
36 + -->
37 + <el-tooltip content="Delete" placement="top" :show-arrow="false">
38 + <el-button type="danger" :icon="DeleteIcon" circle @click="handleDelete" />
39 + </el-tooltip>
40 + </div>
41 + </div>
42 + </div>
43 +</template>
44 +
45 +<script setup lang="ts">
46 +import { ref, toRefs } from "vue"
47 +import IndexIcon from "@/components/indices/IndexIcon.vue"
48 +import { Index } from "@/types/indices.d"
49 +import Api from "@/api"
50 +import { ElMessage, ElMessageBox } from "element-plus"
51 +import { Refresh as RefreshIcon, Delete as DeleteIcon } from "@element-plus/icons-vue"
52 +
53 +const emit = defineEmits<{
54 + (e: "delete"): void
55 +}>()
56 +
57 +const props = defineProps<{
58 + index: Index
59 + showActions?: boolean
60 +}>()
61 +const { index, showActions } = toRefs(props)
62 +
63 +const loading = ref(false)
64 +
65 +const handleDelete = () => {
66 + ElMessageBox.confirm(`Are you sure you want to delete the index:<br/><strong>${index.value.index}</strong> ?`, "Warning", {
67 + confirmButtonText: "Yes I'm sure",
68 + confirmButtonClass: "el-button--warning",
69 + cancelButtonText: "Cancel",
70 + type: "warning",
71 + dangerouslyUseHTMLString: true,
72 + customStyle: {
73 + width: "90%",
74 + maxWidth: "400px"
75 + }
76 + })
77 + .then(() => {
78 + deleteIndex()
79 + })
80 + .catch(() => {
81 + ElMessage({
82 + type: "info",
83 + message: "Delete canceled"
84 + })
85 + })
86 +}
87 +
88 +function deleteIndex() {
89 + loading.value = true
90 +
91 + Api.indices
92 + .deleteIndex(index.value.index)
93 + .then(res => {
94 + if (res.data.success) {
95 + ElMessage({
96 + message: "Index was successfully deleted.",
97 + type: "success"
98 + })
99 +
100 + emit("delete")
101 + } else {
102 + ElMessage({
103 + message: res.data?.message || "An error occurred. Please try again later.",
104 + type: "error"
105 + })
106 + }
107 + })
108 + .catch(err => {
109 + if (err.response.status === 401) {
110 + ElMessage({
111 + message: err.response?.data?.message || "Wazuh-Indexer returned Unauthorized. Please check your connector credentials.",
112 + type: "error"
113 + })
114 + } else if (err.response.status === 404) {
115 + ElMessage({
116 + message: err.response?.data?.message || "An error occurred. Please try again later.",
117 + type: "error"
118 + })
119 + } else {
120 + ElMessage({
121 + message: err.response?.data?.message || "An error occurred. Please try again later.",
122 + type: "error"
123 + })
124 + }
125 + })
126 + .finally(() => {
127 + loading.value = false
128 + })
129 +}
130 +</script>
131 +
132 +<style lang="scss" scoped>
133 +@import "@/assets/scss/_variables";
134 +@import "@/assets/scss/card-shadow";
135 +
136 +.index-card {
137 + padding: var(--size-3) var(--size-4);
138 + @extend .card-base;
139 + @extend .card-shadow--small;
140 + border: 2px solid transparent;
141 +
142 + display: flex;
143 + justify-content: space-between;
144 + gap: var(--size-6);
145 + flex-wrap: wrap;
146 +
147 + .group {
148 + display: flex;
149 + justify-content: space-between;
150 + gap: var(--size-6);
151 + flex-grow: 1;
152 + flex-wrap: wrap;
153 +
154 + .box {
155 + flex-grow: 1;
156 +
157 + .value {
158 + font-weight: bold;
159 + margin-bottom: 2px;
160 + white-space: nowrap;
161 + }
162 + .label {
163 + white-space: nowrap;
164 + font-size: var(--font-size-0);
165 + font-family: var(--font-mono);
166 + opacity: 0.8;
167 + }
168 + }
169 + &.actions {
170 + flex-grow: 0;
171 + .box {
172 + padding: var(--size-2) var(--size-2);
173 + background-color: rgba(0, 0, 0, 0.07);
174 + display: flex;
175 + align-items: center;
176 + border-radius: var(--radius-6);
177 + }
178 + }
179 + }
180 +
181 + &.health-green {
182 + border-color: $text-color-success;
183 + }
184 +
185 + &.health-yellow {
186 + border-color: $text-color-warning;
187 + }
188 +
189 + &.health-red {
190 + border-color: $text-color-danger;
191 + }
192 +}
193 +</style>
src/components/indices/IndexIcon.vue new
+39
@@ -0,0 +1,39 @@
1 +<template>
2 + <span class="index-icon" :class="[`health-${health}`, { color }]">
3 + <i v-if="health === IndexHealth.GREEN" class="mdi mdi-shield-check"></i>
4 + <i v-else-if="health === IndexHealth.YELLOW" class="mdi mdi-alert"></i>
5 + <i v-else-if="health === IndexHealth.RED" class="mdi mdi-alert-decagram"></i>
6 + </span>
7 +</template>
8 +
9 +<script setup lang="ts">
10 +import { toRefs } from "vue"
11 +import { Index, IndexHealth } from "@/types/indices.d"
12 +
13 +const props = defineProps<{
14 + health: Index["health"]
15 + color?: boolean
16 +}>()
17 +const { health, color } = toRefs(props)
18 +</script>
19 +
20 +<style lang="scss" scoped>
21 +@import "@/assets/scss/_variables";
22 +@import "@/assets/scss/card-shadow";
23 +
24 +.index-icon {
25 + &.color {
26 + &.health-green {
27 + color: $text-color-success;
28 + }
29 +
30 + &.health-yellow {
31 + color: $text-color-warning;
32 + }
33 +
34 + &.health-red {
35 + color: $text-color-danger;
36 + }
37 + }
38 +}
39 +</style>
src/components/indices/Marquee.vue
+27 -14
@@ -9,40 +9,54 @@
9 :gradient-color="[255, 255, 255]"
10 gradient-length="10%"
11 >
12 - <span v-for="item in indices" :key="item.index" class="item" :class="item.health" @click="emit('click', item)">
13 - <i v-if="item.health === IndexHealth.GREEN" class="mdi mdi-shield-check"></i>
14 - <i v-else-if="item.health === IndexHealth.YELLOW" class="mdi mdi-alert"></i>
15 - <i v-else-if="item.health === IndexHealth.RED" class="mdi mdi-alert-decagram"></i>
12 + <span
13 + v-for="item in indices"
14 + :key="item.index"
15 + class="item"
16 + :class="item.health"
17 + @click="emit('click', item)"
18 + title="Click to select"
19 + >
20 + <IndexIcon :health="item.health" color />
21 {{ item.index }}
22 </span>
23 </Vue3Marquee>
24 + <div class="info"><i class="mdi mdi-information-outline"></i> Click on an index to select</div>
25 </div>
26 </template>
27
28 <script setup lang="ts">
29 import { computed, toRefs } from "vue"
24 -import { Index, IndexHealth } from "@/types/indices.d"
30 +import { Index } from "@/types/indices.d"
31 import { Vue3Marquee } from "vue3-marquee"
32 +import IndexIcon from "@/components/indices/IndexIcon.vue"
33
34 const emit = defineEmits<{
35 (e: "click", value: Index): void
36 }>()
37
38 const props = defineProps<{
32 - indices: Index[]
39 + indices: Index[] | null
40 }>()
41 const { indices } = toRefs(props)
42
36 -const loading = computed(() => !indices?.value || indices.value.length === 0)
43 +const loading = computed(() => !indices?.value || indices.value === null)
44 </script>
45
46 <style lang="scss" scoped>
47 @import "@/assets/scss/_variables";
48 +@import "@/assets/scss/card-shadow";
49
50 .indices-marquee {
43 - height: 45px;
51 + .info {
52 + opacity: 0.5;
53 + font-size: 12px;
54 + margin-top: 5px;
55 + }
56 .marquee-wrap {
57 + height: 45px;
58 transform: translate3d(0, 0, 0);
59 + @extend .card-base;
60
61 :deep() {
62 .marquee {
@@ -57,6 +71,7 @@ const loading = computed(() => !indices?.value || indices.value.length === 0)
71
72 .item {
73 padding: 10px 20px;
74 + cursor: pointer;
75
76 &.green {
77 i {
@@ -64,14 +79,12 @@ const loading = computed(() => !indices?.value || indices.value.length === 0)
79 }
80 }
81 &.yellow {
67 - i {
68 - color: $text-color-warning;
69 - }
82 + color: $text-color-warning;
83 + font-weight: bold;
84 }
85 &.red {
72 - i {
73 - color: $text-color-danger;
74 - }
86 + color: $text-color-danger;
87 + font-weight: bold;
88 }
89 }
90 }
src/components/indices/NodeAllocation.vue new
+200
@@ -0,0 +1,200 @@
1 +<template>
2 + <div class="cluster-health">
3 + <div class="title">
4 + Nodes Allocation <small class="o-050">({{ indicesAllocation.length }})</small>
5 + </div>
6 + <div v-loading="loading">
7 + <div class="info">
8 + <template v-if="indicesAllocation.length">
9 + <el-scrollbar max-height="500px">
10 + <div
11 + v-for="node of indicesAllocation"
12 + :key="node.id"
13 + class="item"
14 + :class="[`percent-${getStatusPercent(node.disk_percent)}`, `node-${node.node}`]"
15 + >
16 + <div class="group">
17 + <div class="box">
18 + <div class="value">{{ node.node }}</div>
19 + <div class="label">node</div>
20 + </div>
21 + </div>
22 + <div class="group">
23 + <div class="box">
24 + <div class="value">{{ node.disk_total || "-" }}</div>
25 + <div class="label">disk_total</div>
26 + </div>
27 + <div class="box">
28 + <div class="value">{{ node.disk_used || "-" }}</div>
29 + <div class="label">disk_used</div>
30 + </div>
31 + <div class="box">
32 + <div class="value">{{ node.disk_available || "-" }}</div>
33 + <div class="label">disk_available</div>
34 + </div>
35 + </div>
36 + <div class="group" v-if="node.disk_percent">
37 + <div class="box w-full">
38 + <el-progress
39 + :text-inside="true"
40 + :stroke-width="26"
41 + :percentage="node.disk_percent_value"
42 + :status="getStatusPercent(node.disk_percent_value)"
43 + />
44 + </div>
45 + </div>
46 + </div>
47 + </el-scrollbar>
48 + </template>
49 + </div>
50 + </div>
51 + </div>
52 +</template>
53 +
54 +<script setup lang="ts">
55 +import { onBeforeMount, ref } from "vue"
56 +import { IndexAllocation } from "@/types/indices.d"
57 +import Api from "@/api"
58 +import { ElMessage } from "element-plus"
59 +import { nanoid } from "nanoid"
60 +
61 +const indicesAllocation = ref<IndexAllocation[]>([])
62 +const loading = ref(true)
63 +
64 +// TODO: decide with Taylor
65 +function getStatusPercent(percent) {
66 + if (parseFloat(percent) < 20) return "exception"
67 + if (parseFloat(percent) < 40) return "warning"
68 + return "success"
69 +}
70 +
71 +function getIndicesAllocation() {
72 + loading.value = true
73 + Api.indices
74 + .getAllocation()
75 + .then(res => {
76 + if (res.data.success) {
77 + indicesAllocation.value = (res.data?.node_allocation || []).map(obj => {
78 + obj.id = nanoid()
79 + obj.disk_percent_value = parseFloat(obj.disk_percent)
80 + return obj
81 + })
82 + } else {
83 + ElMessage({
84 + message: res.data?.message || "An error occurred. Please try again later.",
85 + type: "error"
86 + })
87 + }
88 + })
89 + .catch(err => {
90 + if (err.response.status === 401) {
91 + ElMessage({
92 + message: err.response?.data?.message || "Wazuh-Indexer returned Unauthorized. Please check your connector credentials.",
93 + type: "error"
94 + })
95 + } else if (err.response.status === 404) {
96 + ElMessage({
97 + message: err.response?.data?.message || "No alerts were found.",
98 + type: "error"
99 + })
100 + } else {
101 + ElMessage({
102 + message: err.response?.data?.message || "An error occurred. Please try again later.",
103 + type: "error"
104 + })
105 + }
106 + })
107 + .finally(() => {
108 + loading.value = false
109 + })
110 +}
111 +
112 +onBeforeMount(() => {
113 + getIndicesAllocation()
114 +})
115 +</script>
116 +
117 +<style lang="scss" scoped>
118 +@import "@/assets/scss/_variables";
119 +@import "@/assets/scss/card-shadow";
120 +
121 +.cluster-health {
122 + padding: var(--size-5) var(--size-6);
123 + @extend .card-base;
124 +
125 + .title {
126 + font-size: var(--font-size-4);
127 + font-weight: var(--font-weight-6);
128 + margin-bottom: var(--size-5);
129 + }
130 + .info {
131 + min-height: 50px;
132 +
133 + .item {
134 + padding: var(--size-3) var(--size-4);
135 + @extend .card-base;
136 + @extend .card-shadow--small;
137 + border: 2px solid transparent;
138 +
139 + display: flex;
140 + flex-direction: column;
141 + gap: var(--size-6);
142 +
143 + .group {
144 + display: flex;
145 + justify-content: space-between;
146 + gap: var(--size-6);
147 + flex-grow: 1;
148 + flex-wrap: wrap;
149 +
150 + .box {
151 + .value {
152 + font-weight: bold;
153 + margin-bottom: 2px;
154 + white-space: nowrap;
155 + }
156 + .label {
157 + font-size: var(--font-size-0);
158 + font-family: var(--font-mono);
159 + opacity: 0.8;
160 + }
161 +
162 + :deep() {
163 + .el-progress-bar__outer {
164 + border-radius: 4px;
165 +
166 + .el-progress-bar__inner {
167 + border-radius: 0;
168 + }
169 + }
170 + }
171 +
172 + &.w-full {
173 + width: 100%;
174 + }
175 + }
176 + }
177 +
178 + &.percent-success {
179 + border-color: $text-color-success;
180 + }
181 +
182 + &.percent-warning {
183 + border-color: $text-color-warning;
184 + }
185 +
186 + &.percent-exception {
187 + border-color: $text-color-danger;
188 + }
189 +
190 + &.node-UNASSIGNED {
191 + border-color: $text-color-info;
192 + }
193 +
194 + &:not(:last-child) {
195 + margin-bottom: var(--size-3);
196 + }
197 + }
198 + }
199 +}
200 +</style>
src/components/indices/TopIndices.vue new
+184
@@ -0,0 +1,184 @@
1 +<template>
2 + <div class="top-indices-chart-container">
3 + <div class="title">Top 8 indices size & health</div>
4 + <div style="height: 400px" v-loading="loading">
5 + <div id="top-indices-chart" style="max-width: 100%; height: 400px"></div>
6 + </div>
7 + </div>
8 +</template>
9 +
10 +<script setup lang="ts">
11 +import { computed, onMounted, ref, toRefs, watch } from "vue"
12 +import * as echarts from "echarts"
13 +import { Index, IndexHealth } from "@/types/indices.d"
14 +import bytes from "bytes"
15 +import _ from "lodash"
16 +
17 +const props = defineProps<{
18 + indices: Index[] | null
19 +}>()
20 +const { indices } = toRefs(props)
21 +
22 +const loading = computed(() => !indices?.value || indices.value === null)
23 +const chartCtx = ref<echarts.ECharts>(null)
24 +
25 +function getOptions() {
26 + const data = _.chain(indices.value || [])
27 + .map(i => {
28 + if (typeof i.store_size === "string") {
29 + i.store_size_value = bytes(i.store_size)
30 + } else {
31 + i.store_size_value = i.store_size
32 + }
33 + return i
34 + })
35 + .orderBy(["store_size"], ["desc"])
36 + .slice(0, 8)
37 + .value()
38 +
39 + // TODO: slice here or after index health ??
40 +
41 + const green = data.filter(i => i.health === IndexHealth.GREEN).length
42 + const yellow = data.filter(i => i.health === IndexHealth.YELLOW).length
43 + const red = data.filter(i => i.health === IndexHealth.RED).length
44 +
45 + const sizeData: { value: number; name: string }[] = data.map(i => ({
46 + value: i.store_size_value,
47 + name: i.index
48 + }))
49 +
50 + return {
51 + tooltip: {
52 + trigger: "item",
53 + formatter: "{a}<hr/>{b}: <strong>{c}</strong> ({d}%)"
54 + },
55 + legend: {
56 + data: sizeData.map(i => i.name),
57 + left: "left",
58 + type: "scroll"
59 + },
60 + grid: {
61 + top: "0%",
62 + bottom: "0%",
63 + height: "80%"
64 + },
65 + series: [
66 + {
67 + name: "Indices Health",
68 + top: "-35%",
69 + bottom: "-50%",
70 + zlevel: 1,
71 + type: "pie",
72 + radius: [0, "20%"],
73 + label: {
74 + show: false
75 + },
76 + itemStyle: {
77 + borderColor: "#fff",
78 + borderWidth: 2
79 + },
80 + data: [
81 + { value: green, name: "Green", itemStyle: { color: "#13ce66" } },
82 + { value: yellow, name: "Yellow", itemStyle: { color: "#f7ba2a" } },
83 + { value: red, name: "Red", itemStyle: { color: "#ec205f" } }
84 + ]
85 + },
86 + {
87 + name: "Indices Size",
88 + type: "pie",
89 + top: "-35%",
90 + bottom: "-50%",
91 + color: ["#082f49", "#0c4a6e", "#075985", "#0369a1", "#0284c7", "#0ea5e9", "#38bdf8", "#7dd3fc", "#bae6fd"],
92 + tooltip: {
93 + formatter: params => {
94 + return `${params.seriesName}<hr/>${params.name}:<br/><strong>${bytes(params.value)}</strong> (${params.percent}%)`
95 + }
96 + },
97 + avoidLabelOverlap: true,
98 + radius: ["24%", "35%"],
99 + minAngle: 5,
100 + zlevel: 2,
101 + labelLine: {
102 + length: 25,
103 + length2: 5,
104 + showAbove: true,
105 + lineStyle: {
106 + width: 1.5,
107 + type: "dashed"
108 + }
109 + },
110 + label: {
111 + formatter: "{name|{b}}\n{per|{d}%}",
112 + minMargin: 10,
113 + edgeDistance: 10,
114 + lineHeight: 15,
115 + //alignTo: "edge",
116 + rich: {
117 + name: {
118 + color: "#4C5058",
119 + fontSize: window.innerWidth > 1000 ? 13 : 11
120 + },
121 + per: {
122 + fontSize: window.innerWidth > 1000 ? 13 : 11,
123 + fontWeight: "bold"
124 + }
125 + }
126 + },
127 + labelLayout: function (params) {
128 + const isLeft = params.labelRect.x < chartCtx.value.getWidth() / 2
129 + const points = params.labelLinePoints
130 + // Update the end point.
131 + points[2][0] = isLeft ? params.labelRect.x : params.labelRect.x + params.labelRect.width
132 + return {
133 + labelLinePoints: points,
134 + hideOverlap: false,
135 + moverOverlap: "shiftX",
136 + draggable: true
137 + }
138 + },
139 + itemStyle: {
140 + borderColor: "#fff",
141 + borderWidth: 1
142 + },
143 + data: sizeData
144 + }
145 + ]
146 + }
147 +}
148 +
149 +watch(indices, () => {
150 + if (chartCtx.value) {
151 + chartCtx.value.setOption(getOptions())
152 + }
153 +})
154 +
155 +onMounted(() => {
156 + const chartDom = document.getElementById("top-indices-chart")
157 + chartCtx.value = echarts.init(chartDom)
158 +
159 + chartCtx.value.setOption(getOptions())
160 +
161 + new ResizeObserver(() => {
162 + chartCtx.value.resize()
163 + }).observe(chartDom)
164 +})
165 +</script>
166 +
167 +<style lang="scss" scoped>
168 +@import "@/assets/scss/_variables";
169 +@import "@/assets/scss/card-shadow";
170 +
171 +.top-indices-chart-container {
172 + width: 100%;
173 + overflow: hidden;
174 + @extend .card-base;
175 + padding: var(--size-6);
176 + box-sizing: border-box;
177 +
178 + .title {
179 + font-size: var(--font-size-4);
180 + font-weight: var(--font-weight-6);
181 + margin-bottom: var(--size-5);
182 + }
183 +}
184 +</style>
src/components/indices/UnhealthyIndices.vue new
+70
@@ -0,0 +1,70 @@
1 +<template>
2 + <div class="unhealthy-indices">
3 + <div class="title">
4 + Unhealthy Indices <small class="o-050">({{ unhealthyIndices.length }})</small>
5 + </div>
6 + <div v-loading="loading">
7 + <div class="info">
8 + <template v-if="unhealthyIndices && unhealthyIndices.length">
9 + <div
10 + v-for="item of unhealthyIndices"
11 + :key="item.index"
12 + class="item"
13 + :class="item.health"
14 + @click="emit('click', item)"
15 + title="Click for details"
16 + >
17 + <IndexCard :index="item" />
18 + </div>
19 + </template>
20 + </div>
21 + </div>
22 + </div>
23 +</template>
24 +
25 +<script setup lang="ts">
26 +import { computed, toRefs } from "vue"
27 +import { Index, IndexHealth } from "@/types/indices.d"
28 +import IndexCard from "@/components/indices/IndexCard.vue"
29 +
30 +const emit = defineEmits<{
31 + (e: "click", value: Index): void
32 +}>()
33 +
34 +const props = defineProps<{
35 + indices: Index[] | null
36 +}>()
37 +const { indices } = toRefs(props)
38 +
39 +const loading = computed(() => !indices?.value || indices.value === null)
40 +
41 +const unhealthyIndices = computed(() =>
42 + (indices.value || []).filter((index: Index) => index.health === IndexHealth.YELLOW || index.health === IndexHealth.RED)
43 +)
44 +</script>
45 +
46 +<style lang="scss" scoped>
47 +@import "@/assets/scss/_variables";
48 +@import "@/assets/scss/card-shadow";
49 +
50 +.unhealthy-indices {
51 + padding: var(--size-5) var(--size-6);
52 + @extend .card-base;
53 +
54 + .title {
55 + font-size: var(--font-size-4);
56 + font-weight: var(--font-weight-6);
57 + margin-bottom: var(--size-5);
58 + }
59 + .info {
60 + min-height: 50px;
61 + .item {
62 + cursor: pointer;
63 +
64 + &:not(:last-child) {
65 + margin-bottom: var(--size-3);
66 + }
67 + }
68 + }
69 +}
70 +</style>
src/core/nav.vue
+3
@@ -15,6 +15,9 @@
15 <el-menu-item index="/indices">
16 <span slot="title">Indicies</span>
17 </el-menu-item>
18 + <el-menu-item index="/indices-bkp">
19 + <span slot="title">Indicies-bkp</span>
20 + </el-menu-item>
21 <el-menu-item index="/ecommerce-dashboard">
22 <span slot="title">eCommerce</span>
23 </el-menu-item>
src/router/index.ts
+12
@@ -12,6 +12,7 @@ import Mail from "../views/apps/Mail.vue"
12 import Ecommerce from "./ecommerce"
13 import Connectors from "../views/apps/Connectors.vue"
14 import Indices from "../views/apps/Dashboards/Indices.vue"
15 +import IndicesBKP from "../views/apps/Dashboards/_bkp_Indices.vue"
16 /*
17
18 //pages
@@ -104,6 +105,17 @@ const router = createRouter({
105 tags: ["app"]
106 }
107 },
108 + {
109 + path: "/indices-bkp",
110 + name: "indices-bkp",
111 + component: IndicesBKP,
112 + meta: {
113 + auth: true,
114 + layout: layouts.navLeft,
115 + searchable: true,
116 + tags: ["app"]
117 + }
118 + },
119 {
120 path: "/contacts",
121 name: "contacts",
src/types/indices.d.ts
+6 -1
@@ -4,6 +4,8 @@ export interface Index {
4 index: string
5 replica_count: string
6 store_size: string
7 + store_size_value?: number
8 + store_size_value?: number
9 }
10
11 // TODO: Better to use a status instead of a color
@@ -14,14 +16,17 @@ export enum IndexHealth {
16 }
17
18 export interface IndexAllocation {
19 + id?: string
20 disk_available: null | string
21 disk_percent: null | string
22 disk_total: null | string
23 disk_used: null | string
24 node: string | "UNASSIGNED"
25 + disk_percent_value?: number
26 }
27
28 export interface IndexShard {
29 + id?: string
30 index: string
31 node: null | string
32 shard: string
@@ -48,7 +53,7 @@ export interface ClusterHealth {
53 number_of_nodes: number
54 number_of_pending_tasks: number
55 relocating_shards: number
51 - status: string
56 + status: IndexHealth
57 task_max_waiting_in_queue_millis: number
58 timed_out: boolean
59 unassigned_shards: number
src/views/apps/Dashboards/Indices.vue
+124 -750
@@ -1,778 +1,152 @@
1 <template>
2 <el-scrollbar class="page page-indices">
3 - <div class="card-base mb-30">
3 + <div class="section">
4 <IndicesMarquee :indices="indices" @click="setIndex" />
5 </div>
6
7 - <!--BEGIN TEST-->
8 - <div class="box center left">
9 - <div class="page-header header-primary card-base card-shadow--small">
10 - <h1 class="title">Index Stats</h1>
7 + <div class="section">
8 + <Details :indices="indices" v-model="currentIndex" />
9 + </div>
10
12 - <div class="flex justify-center align-center bg-orange">
13 - <div class="widget-icon-box mr-20 animate__animated animate__fadeInRight">
14 - <span class="badge">
15 - <i v-if="selectedHealth === 'green'" class="mdi mdi-check-bold bg-green"></i>
16 - <i v-else-if="selectedHealth === 'yellow'" class="mdi mdi-alert-box bg-orange"></i>
17 - <i v-else-if="selectedHealth === 'red'" class="mdi mdi-alert-box bg-red"></i>
18 - <strong class="accent-text font-size-20">Index:</strong>
19 - </span>
20 - <span class="highlight font-size-20">{{ selectedValue }}</span>
21 - </div>
22 - <div class="widget-icon-box mr-20 animate__animated animate__fadeInRight">
23 - <span class="accent-text font-size-20">Health:</span>
24 - <span class="highlight font-size-20">{{ selectedHealth }}</span>
25 - </div>
11 + <div class="section">
12 + <div class="columns">
13 + <div class="col basis-50">
14 + <ClusterHealth class="stretchy" />
15 + </div>
16 + <div class="col basis-50">
17 + <UnhealthyIndices :indices="indices" @click="setIndex" class="stretchy" />
18 </div>
19 </div>
20 + </div>
21
29 - <div class="flex center demo-box bg-orange">
30 - <el-select v-model="selectedValue" placeholder="Select Your Index">
31 - <el-option v-for="index in indices" :key="index.index" :label="index.index" :value="index.index"></el-option>
32 - </el-select>
33 - </div>
34 -
35 - <div class="spacer"></div>
36 -
37 - <div class="card-base card-shadow--medium scrollable only-x bg-black">
38 - <el-row class="mt-0" :gutter="30">
39 - <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
40 - <div class="page-table scrollable only-y" id="affix-container">
41 - <div class="page-header">
42 - <h1 class="warning-text">Index Data</h1>
43 - </div>
44 -
45 - <div class="table-box card-base card-shadow--medium scrollable only-x">
46 - <table class="styled striped">
47 - <thead>
48 - <tr>
49 - <th scope="col">Index Name</th>
50 - <th scope="col">Index Health</th>
51 - <th scope="col">Index Document Size</th>
52 - <th scope="col">Storage Size</th>
53 - <th scope="col">Replica Count</th>
54 - </tr>
55 - </thead>
56 - <tr v-for="index in filteredIndices" :key="index.id" :class="getIndexRowClass(index)">
57 - <!-- Display the connector details in the table -->
58 - <td>{{ index.index }}</td>
59 - <td>{{ index.health }}</td>
60 - <td>{{ index.docs_count }}</td>
61 - <td>{{ index.store_size }}</td>
62 - <td>{{ index.replica_count }}</td>
63 -
64 - <!-- Add a buttton to Rotate an Index -->
65 - <td>
66 - <div class="btn-group" role="group" aria-label="Basic example">
67 - <button type="button" class="btn btn-info btn-sm" @click="rotateIndex(index.index)">
68 - Rotate Index
69 - </button>
70 - </div>
71 - </td>
72 - <!-- Add a buttton to Delete an Index -->
73 - <td>
74 - <div class="btn-group" role="group" aria-label="Basic example">
75 - <button type="button" class="btn btn-info btn-sm" @click="deleteIndex(index.index)">
76 - Delete Index
77 - </button>
78 - </div>
79 - </td>
80 - </tr>
81 - </table>
82 - </div>
83 - </div>
84 - </el-col>
85 - </el-row>
86 -
87 - <!-- New table to display shards -->
88 - <el-row class="mt-0" :gutter="30">
89 - <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
90 - <div class="page-table scrollable only-y" id="affix-container">
91 - <div class="page-header">
92 - <h1 class="warning-text">Index Shards</h1>
93 - </div>
94 -
95 - <div class="table-box card-base card-shadow--medium scrollable only-x">
96 - <table class="styled striped">
97 - <thead>
98 - <tr>
99 - <th scope="col">Shard Index</th>
100 - <th scope="col">Shard ID</th>
101 - <th scope="col">Shard State</th>
102 - <th scope="col">Shard Size</th>
103 - <th scope="col">Shard Node</th>
104 - </tr>
105 - </thead>
106 - <tr v-for="shard in filteredShards" :key="shard.id" class="bg-accent">
107 - <!-- Display the shard details in the table -->
108 - <td>{{ shard.index }}</td>
109 - <td>{{ shard.shard }}</td>
110 - <td>{{ shard.state }}</td>
111 - <td>{{ shard.size }}</td>
112 - <td>{{ shard.node }}</td>
113 - </tr>
114 - </table>
115 - </div>
116 - </div>
117 - </el-col>
118 - </el-row>
119 - </div>
120 -
121 - <div class="el-col el-col-24 el-col-xs-24 el-col-sm-12 el-col-md-12 el-col-lg-16 el-col-xl-16">
122 - <el-row class="chart-row">
123 - <el-col :xs="24" :sm="12" :md="12" :lg="16" :xl="16" class="chart-col">
124 - <div class="chart-container">
125 - <div id="chart" class="chart" :style="{ height: '500px', width: '120%' }"></div>
126 - </div>
127 - </el-col>
128 - <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8" class="chart-col">
129 - <div class="chart-container">
130 - <div id="pie" class="chart pie-chart" :style="{ height: '500px', width: '200%' }"></div>
131 - </div>
132 - </el-col>
133 - </el-row>
134 - </div>
135 -
136 - <div class="el-col el-col-24 el-col-xs-24 el-col-sm-12 el-col-md-12 el-col-lg-8 el-col-xl-8 flex box grow">
137 - <!-- New table to display shards -->
138 - <el-row class="mt-0" :gutter="30">
139 - <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
140 - <div class="page-table scrollable only-y" id="affix-container">
141 - <div class="page-header">
142 - <h1 class="warning-text">Overall Health</h1>
143 - </div>
144 -
145 - <div class="table-box card-base card-shadow--medium scrollable only-x">
146 - <table class="styled striped hover">
147 - <thead>
148 - <tr>
149 - <th scope="col">Cluster Name</th>
150 - <th scope="col">Status</th>
151 - <th scope="col">Number of Nodes</th>
152 - <th scope="col">Active Shards</th>
153 - <th scope="col">Unassigned Shards</th>
154 - </tr>
155 - </thead>
156 - <tbody>
157 - <tr
158 - v-for="health in clusterHealth"
159 - :key="health.id"
160 - :class="{
161 - 'bg-green': health.status === 'green',
162 - 'bg-orange': health.status === 'yellow',
163 - 'bg-red': health.status === 'red'
164 - }"
165 - >
166 - <!-- Display the shard details in the table -->
167 - <td>{{ health.cluster_name }}</td>
168 - <div class="item-box item-status status-Complete">
169 - <td>{{ health.status }}</td>
170 - </div>
171 - <td>{{ health.number_of_nodes }}</td>
172 - <td>{{ health.active_shards }}</td>
173 - <td>{{ health.unassigned_shards }}</td>
174 - </tr>
175 - </tbody>
176 - </table>
177 - </div>
178 - </div>
179 - </el-col>
180 -
181 - <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
182 - <div class="page-table scrollable only-y" id="affix-container">
183 - <div class="page-header">
184 - <h1 class="warning-text">Unhealthy Indices</h1>
185 - </div>
186 -
187 - <div class="table-box card-base card-shadow--medium scrollable only-x">
188 - <table class="styled striped hover">
189 - <thead>
190 - <tr>
191 - <th scope="col">Index Name</th>
192 - <th scope="col">Index Health</th>
193 - </tr>
194 - </thead>
195 - <tbody>
196 - <tr
197 - v-for="index in unhealthyIndices"
198 - :key="index.id"
199 - :class="{
200 - 'bg-orange': index.health === 'yellow',
201 - 'bg-red': index.health === 'red'
202 - }"
203 - >
204 - <!-- Display the shard details in the table -->
205 - <td>{{ index.index }}</td>
206 -
207 - <td>{{ index.health }}</td>
208 - </tr>
209 - </tbody>
210 - </table>
211 - </div>
212 - </div>
213 - </el-col>
214 - </el-row>
22 + <div class="section">
23 + <div class="columns column-1200">
24 + <div class="col basis-40">
25 + <NodeAllocation class="stretchy" />
26 + </div>
27 + <div class="col basis-60">
28 + <TopIndices :indices="indices" />
29 + </div>
30 </div>
31 </div>
217 - <!--END TEST-->
32 </el-scrollbar>
33 </template>
34
221 -<script>
222 -import MarqueeInfinite from "marquee-infinite"
223 -import * as echarts from "echarts"
224 -import _throttle from "lodash/throttle"
35 +<script lang="ts" setup>
36 +import { Index } from "@/types/indices.d"
37 import Api from "@/api"
226 -import { defineComponent } from "vue"
38 +import { ElMessage } from "element-plus"
39 +import { onBeforeMount, ref } from "vue"
40 import IndicesMarquee from "@/components/indices/Marquee.vue"
228 -
229 -export default defineComponent({
230 - data() {
231 - return {
232 - indices: [],
233 - shards: [],
234 - indicesAllocation: [],
235 - clusterHealth: [],
236 - loading: false,
237 - errorMessage: "",
238 - successMessage: "",
239 - asyncComponent: "peity",
240 - resized: false,
241 - marquee: null,
242 - chartWallet: null,
243 - chartPrice: null,
244 - chartCandle: null,
245 - selectedValue: "",
246 - selectedHealth: "",
247 - pie: null
248 - }
249 - },
250 - created() {
251 - this.getIndices()
252 - this.getShards()
253 - this.getIndicesAllocation()
254 - this.getClusterHealth()
255 - },
256 - computed: {
257 - filteredIndices() {
258 - return this.indices.filter(index => index.index === this.selectedValue)
259 - },
260 - filteredShards() {
261 - return this.shards.filter(shard => shard.index === this.selectedValue)
262 - },
263 - unhealthyIndices() {
264 - return this.indices.filter(index => index.health === "yellow" || index.health === "red")
265 - }
266 - },
267 - methods: {
268 - setIndex(index) {
269 - console.log("setIndex", index)
270 - },
271 - updateSelectedHealth() {
272 - const selectedIdx = this.indices.find(index => index.index === this.selectedValue)
273 - this.selectedHealth = selectedIdx ? selectedIdx.health : ""
274 - },
275 - initChart() {
276 - // Store the indicesAllocation
277 - const indicesAllocation = this.indicesAllocation
278 - // For the indicesAllocation, get the disk_used, disk_total, and timestamp for all items in the array
279 - let data = indicesAllocation.map(item => {
280 - const date = new Date(item.timestamp)
281 - const hours = date.getHours()
282 - const minutes = date.getMinutes()
283 - return {
284 - diskUsed: item.disk_used,
285 - diskTotal: item.disk_total,
286 - timestamp: `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`
287 - }
288 - })
289 -
290 - // Sort data array by timestamp
291 - data.sort((a, b) => {
292 - const aParts = a.timestamp.split(":").map(Number)
293 - const bParts = b.timestamp.split(":").map(Number)
294 - const aDate = new Date(1970, 0, 1, aParts[0], aParts[1])
295 - const bDate = new Date(1970, 0, 1, bParts[0], bParts[1])
296 - return aDate - bDate
297 - })
298 -
299 - // Get the last 12 data points
300 - data = data.slice(Math.max(data.length - 12, 0))
301 -
302 - // Separate the data array into individual arrays for diskUsed, diskTotal, and timestamp
303 - const diskUsed = data.map(item => item.diskUsed)
304 - const diskTotal = data.map(item => item.diskTotal)
305 - const timestamp = data.map(item => item.timestamp)
306 -
307 - console.log("diskUsed: ", diskUsed)
308 - console.log("diskTotal: ", diskTotal)
309 - console.log("timestamp: ", timestamp)
310 -
311 - // Initialize the chart
312 - this.chart = echarts.init(document.getElementById("chart"))
313 - this.chart.setOption({
314 - //backgroundColor: '#394056',
315 - title: {
316 - top: 20,
317 - text: "Wazuh-Indexer Disk Usage",
318 - textStyle: { fontWeight: "normal", fontSize: 16, fontFamily: "Nunito Sans" /*color: '#F1F1F3'*/ },
319 - left: "1%"
320 - },
321 - tooltip: {
322 - trigger: "axis",
323 - axisPointer: {
324 - lineStyle: {
325 - /*color: '#57617B'*/
326 - }
327 - }
328 - },
329 - legend: {
330 - top: 40,
331 - icon: "rect",
332 - itemWidth: 14,
333 - itemHeight: 5,
334 - itemGap: 13,
335 - data: ["Product-A", "Product-B"],
336 - right: "4%",
337 - textStyle: { fontSize: 12, fontFamily: "Nunito Sans" /*color: '#F1F1F3'*/ }
338 - },
339 - grid: {
340 - top: 100,
341 - left: "-5px",
342 - right: "30px",
343 - bottom: "2%",
344 - containLabel: true
345 - },
346 - xAxis: [
347 - {
348 - type: "category",
349 - boundaryGap: false,
350 - axisLine: {
351 - lineStyle: {
352 - /*color: '#57617B'*/
353 - }
354 - },
355 - data: timestamp //timestamp is the x-axis
356 - }
357 - ],
358 - yAxis: [
359 - {
360 - show: false,
361 - type: "value",
362 - name: "(%)",
363 - axisTick: { show: false },
364 - axisLine: {
365 - lineStyle: {
366 - /*color: '#57617B'*/
367 - }
368 - },
369 - axisLabel: {
370 - margin: 10,
371 - fontSize: 14
372 - },
373 - splitLine: { lineStyle: { color: "#eee" /*color: '#57617B'*/ } }
374 - }
375 - ],
376 - series: [
377 - {
378 - name: "Disk Used",
379 - type: "line",
380 - smooth: true,
381 - symbol: "circle",
382 - symbolSize: 5,
383 - showSymbol: false,
384 - lineStyle: { width: 1 },
385 - areaStyle: {
386 - color: new echarts.graphic.LinearGradient(
387 - 0,
388 - 0,
389 - 0,
390 - 1,
391 - [
392 - {
393 - offset: 0,
394 - color: "rgba(19, 206, 102, 0.3)"
395 - },
396 - {
397 - offset: 0.8,
398 - color: "rgba(19, 206, 102, 0)"
399 - }
400 - ],
401 - false
402 - ),
403 - shadowColor: "rgba(0, 0, 0, 0.1)",
404 - shadowBlur: 10
405 - },
406 - itemStyle: {
407 - color: "rgb(19, 206, 102)",
408 - borderColor: "rgba(19, 206, 102, 0.27)",
409 - borderWidth: 12
410 - },
411 - data: diskUsed
412 - },
413 - {
414 - name: "Disk Total",
415 - type: "line",
416 - smooth: true,
417 - symbol: "circle",
418 - symbolSize: 5,
419 - showSymbol: false,
420 - lineStyle: { width: 1 },
421 - areaStyle: {
422 - color: new echarts.graphic.LinearGradient(
423 - 0,
424 - 0,
425 - 0,
426 - 1,
427 - [
428 - {
429 - offset: 0,
430 - color: "rgba(95, 143, 223, 0.3)"
431 - },
432 - {
433 - offset: 0.8,
434 - color: "rgba(95, 143, 223, 0)"
435 - }
436 - ],
437 - false
438 - ),
439 - shadowColor: "rgba(0, 0, 0, 0.1)",
440 - shadowBlur: 10
441 - },
442 - itemStyle: {
443 - color: "rgb(95, 143, 223)",
444 - borderColor: "rgba(95, 143, 223, 0.2)",
445 - borderWidth: 12
446 - },
447 - data: diskTotal
448 - } /*{
449 - name: 'Product-C',
450 - type: 'line',
451 - smooth: true,
452 - symbol: 'circle',
453 - symbolSize: 5,
454 - showSymbol: false,
455 - lineStyle: { width: 1 },
456 - areaStyle: {
457 -
458 - color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
459 - offset: 0,
460 - color: 'rgba(236, 32, 95, 0.3)'
461 - }, {
462 - offset: 0.8,
463 - color: 'rgba(236, 32, 95, 0)'
464 - }], false),
465 - shadowColor: 'rgba(0, 0, 0, 0.1)',
466 - shadowBlur: 10
467 -
468 - },
469 - itemStyle: {
470 -
471 - color: 'rgb(236, 32, 95)',
472 - borderColor: 'rgba(236, 32, 95, 0.2)',
473 - borderWidth: 12
474 -
475 - },
476 - data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122]
477 - }*/
478 - ]
479 - })
480 - },
481 - initPie() {
482 - // const topIndexes = this.indices.sort((a, b) => b.store_size - a.store_size).slice(0, 5)
483 - const topIndexes = this.indices.sort((a, b) => b.store_size - a.store_size).slice(0, 8)
484 -
485 - const size = topIndexes.map(index => {
486 - const value = parseFloat(index.store_size) / 1024 // Convert MB to GB
487 - return {
488 - value: value,
489 - name: index.index,
490 - health: index.health,
491 - itemStyle: {
492 - color: "#3f84f6" // Custom color for each index
493 - }
494 - }
495 - })
496 - console.log("Size", size)
497 -
498 - const data = topIndexes.map(index => {
499 - // const value = parseFloat(index.store_size) // Parse the value as a float and remvoe the decimal
500 - const value = parseFloat(index.store_size) / 1000000000 // Parse the value as a float and convert to GB
501 - return {
502 - value: value,
503 - name: index.index,
504 - health: index.health,
505 - itemStyle: {
506 - color: "#3f84f6" // Custom color for each index
507 - }
508 - }
509 - })
510 - console.log(data)
511 -
512 - const redIndices = data.filter(index => index.health === "red")
513 - const yellowIndices = data.filter(index => index.health === "yellow")
514 - const greenIndices = data.filter(index => index.health === "green")
515 -
516 - // Get the percentage of green indices
517 - const greenPercentage = (greenIndices.length / data.length) * 100
518 - const yellowPercentage = (yellowIndices.length / data.length) * 100
519 - const redPercentage = (redIndices.length / data.length) * 100
520 - console.log("Red Indices:", redIndices)
521 - console.log("Yellow Indices:", yellowIndices)
522 - console.log("Green Indices:", greenIndices)
523 - console.log("Green Indices Percentage:", greenPercentage)
524 -
525 - // const ordersValue = data.length > 0 ? data[0].value.toFixed(2) : 0 // Get the rounded value of the first item in the data array
526 -
527 - this.pie = echarts.init(document.getElementById("pie"))
528 - this.pie.setOption({
529 - title: {
530 - top: 20,
531 - text: "Index Status and Top 8 Index Sizes By GB",
532 - textStyle: { fontWeight: "normal", fontSize: 16, fontFamily: "Nunito Sans" /*color: '#F1F1F3'*/ },
533 - left: "1%"
534 - },
535 - tooltip: {
536 - trigger: "item",
537 - formatter: "{a} <br/>{b}: {c} ({d}%)"
538 - },
539 - series: [
540 - {
541 - name: "Index",
542 - type: "pie",
543 - selectedMode: "single",
544 - radius: [0, "35%"],
545 -
546 - label: {
547 - position: "inner"
548 - },
549 - labelLine: {
550 - show: false
551 - },
552 - data: [
553 - {
554 - // set the value as the index size
555 - value: greenPercentage.toFixed(2),
556 - name: "Green Indices",
557 - selected: true,
558 - itemStyle: { color: "rgb(19, 206, 102)" }
559 - },
560 - {
561 - value: yellowPercentage.toFixed(2),
562 - name: "Yellow Indices",
563 - itemStyle: { color: "rgb(255, 255, 0)" }
564 - },
565 - {
566 - value: redPercentage.toFixed(2),
567 - name: "Red Indices",
568 - itemStyle: { color: "rgb(255, 0, 0)" }
569 - }
570 - ]
571 - },
572 - {
573 - name: "Index",
574 - type: "pie",
575 - radius: ["45%", "60%"],
576 - data: size.map((item, index) => ({
577 - value: item.value.toFixed(2),
578 - name: item.name,
579 - itemStyle: {
580 - color: item.itemStyle.color
581 - }
582 - })),
583 -
584 - itemStyle: {
585 - color: "rgb(19, 206, 102)"
586 - }
587 - }
588 - ]
589 - })
590 - },
591 - deleteIndex(index) {
592 - this.loading = true
593 - Api.indices
594 - .deleteIndex(index)
595 - .then(res => {
596 - this.successMessage = "Index was successfully deleted."
597 - this.$message({
598 - message: "Index was successfully deleted.",
599 - type: "success"
600 - })
601 - this.getIndices()
602 - })
603 - .catch(err => {
604 - if (err.response.status === 401) {
605 - this.errorMessage = "Wazuh-Indexer returned Unauthorized. Please check your connector credentials."
606 - } else if (err.response.status === 404) {
607 - // Extract the `message` from the response object
608 - this.errorMessage = err.response.data.message
609 - this.$message({
610 - message: err.response.data.message,
611 - type: "error"
612 - })
613 - } else {
614 - this.errorMessage = "An error occurred. Please try again later."
615 - }
616 - })
617 - .finally(() => {
618 - this.loading = false
619 - })
620 - },
621 - getIndicesAllocation() {
622 - this.loading = true
623 - Api.indices
624 - .getAllocation()
625 - .then(res => {
626 - this.indicesAllocation = res.data.node_allocation
627 - this.successMessage = "Indices allocation was successfully retrieved."
628 - this.initChart()
629 - console.log("Indices Allocation", this.indicesAllocation)
630 - })
631 - .catch(err => {
632 - if (err.response.status === 401) {
633 - this.errorMessage = "Wazuh-Indexer returned Unauthorized. Please check your connector credentials."
634 - } else if (err.response.status === 404) {
635 - this.errorMessage = "No alerts were found."
636 - } else {
637 - this.errorMessage = "An error occurred. Please try again later."
638 - }
639 - })
640 - .finally(() => {
641 - this.loading = false
642 - })
643 - },
644 - getIndices() {
645 - this.loading = true
646 - Api.indices
647 - .getIndices()
648 - .then(res => {
649 - this.indices = res.data.indices
650 - this.successMessage = "Indices were successfully retrieved."
651 - this.initPie()
41 +import NodeAllocation from "@/components/indices/NodeAllocation.vue"
42 +import ClusterHealth from "@/components/indices/ClusterHealth.vue"
43 +import Details from "@/components/indices/Details.vue"
44 +import UnhealthyIndices from "@/components/indices/UnhealthyIndices.vue"
45 +import TopIndices from "@/components/indices/TopIndices.vue"
46 +
47 +const indices = ref<Index[] | null>(null)
48 +const loadingIndex = ref(false)
49 +const currentIndex = ref<Index | null>(null)
50 +
51 +function setIndex(index: Index) {
52 + currentIndex.value = index
53 +}
54 +
55 +function getIndices() {
56 + loadingIndex.value = true
57 +
58 + Api.indices
59 + .getIndices()
60 + .then(res => {
61 + if (res.data.success) {
62 + indices.value = res.data.indices
63 + } else {
64 + ElMessage({
65 + message: res.data?.message || "An error occurred. Please try again later.",
66 + type: "error"
67 })
653 - .catch(err => {
654 - if (err.response.status === 401) {
655 - this.errorMessage = "Wazuh-Indexer returned Unauthorized. Please check your connector credentials."
656 - } else if (err.response.status === 404) {
657 - this.errorMessage = "No alerts were found."
658 - } else {
659 - this.errorMessage = "An error occurred. Please try again later."
660 - }
661 - })
662 - .finally(() => {
663 - this.loading = false
664 - })
665 - },
666 - getShards() {
667 - this.loading = true
668 - Api.indices
669 - .getShards()
670 - .then(res => {
671 - this.shards = res.data.shards
672 - this.successMessage = "Shards were successfully retrieved."
673 - })
674 - .catch(err => {
675 - if (err.response.status === 401) {
676 - this.errorMessage = "Wazuh-Indexer returned Unauthorized. Please check your connector credentials."
677 - } else if (err.response.status === 404) {
678 - this.errorMessage = "No alerts were found."
679 - } else {
680 - this.errorMessage = "An error occurred. Please try again later."
681 - }
682 - })
683 - .finally(() => {
684 - this.loading = false
685 - })
686 - },
687 - getIndexRowClass(index) {
688 - if (index.health === "green") {
689 - return "bg-green"
690 - } else if (index.health === "yellow") {
691 - return "bg-orange"
692 - } else if (index.health === "red") {
693 - return "bg-red"
68 }
695 - return ""
696 - },
697 - getClusterHealth() {
698 - this.loading = true
699 - Api.indices
700 - .getClusterHealth()
701 - .then(res => {
702 - this.clusterHealth = res.data
703 - this.successMessage = "Cluster health was successfully retrieved."
704 - console.log("Cluster Health", this.clusterHealth)
69 + })
70 + .catch(err => {
71 + if (err.response.status === 401) {
72 + ElMessage({
73 + message: err.response?.data?.message || "Wazuh-Indexer returned Unauthorized. Please check your connector credentials.",
74 + type: "error"
75 })
706 - .catch(err => {
707 - if (err.response.status === 401) {
708 - this.errorMessage = "Wazuh-Indexer returned Unauthorized. Please check your connector credentials."
709 - } else if (err.response.status === 404) {
710 - this.errorMessage = "No alerts were found."
711 - } else {
712 - this.errorMessage = "An error occurred. Please try again later."
713 - }
76 + } else if (err.response.status === 404) {
77 + ElMessage({
78 + message: err.response?.data?.message || "No alerts were found.",
79 + type: "error"
80 })
715 - .finally(() => {
716 - this.loading = false
81 + } else {
82 + ElMessage({
83 + message: err.response?.data?.message || "An error occurred. Please try again later.",
84 + type: "error"
85 })
718 - },
719 - getPieChartData() {
720 - const topIndexes = this.indices.sort((a, b) => b.store_size - a.store_size).slice(0, 8)
86 + }
87 + })
88 + .finally(() => {
89 + loadingIndex.value = false
90 + })
91 +}
92 +
93 +onBeforeMount(() => {
94 + getIndices()
95 +})
96 +</script>
97
722 - return topIndexes.map((index, i) => ({
723 - value: index.store_size,
724 - name: `p${i + 1}`,
725 - itemStyle: {
726 - color: "#3f84f6" // Custom color for each index
98 +<style lang="scss" scoped>
99 +@import "@/assets/scss/_variables";
100 +@import "@/assets/scss/card-shadow";
101 +
102 +.page-indices {
103 + .section {
104 + margin-bottom: var(--size-6);
105 +
106 + .columns {
107 + display: flex;
108 + gap: var(--size-6);
109 +
110 + .col {
111 + flex-grow: 1;
112 + overflow: hidden;
113 + &.basis-20 {
114 + flex-basis: 20%;
115 }
728 - }))
729 - }
730 - },
731 - watch: {
732 - selectedValue() {
733 - this.updateSelectedHealth()
734 - }
735 - },
736 - async mounted() {
737 - setTimeout(() => {
738 - this.initMarquee()
739 - }, 100)
740 -
741 - setTimeout(() => {
742 - //this.initChartPrice()
743 - }, 500)
116 + &.basis-40 {
117 + flex-basis: 40%;
118 + }
119 + &.basis-50 {
120 + flex-basis: 50%;
121 + }
122 + &.basis-60 {
123 + flex-basis: 60%;
124 + }
125 + &.basis-80 {
126 + flex-basis: 80%;
127 + }
128 + }
129
745 - setTimeout(() => {
746 - //this.initChartCandle()
747 - }, 500)
748 - },
749 - beforeUnmount() {
750 - if (this.chartWallet) {
751 - this.chartWallet.dispose()
752 - this.chartWallet = null
753 - }
754 - if (this.chartPrice) {
755 - this.chartPrice.dispose()
756 - this.chartPrice = null
757 - }
758 - if (this.chartCandle) {
759 - this.chartCandle.dispose()
760 - this.chartCandle = null
130 + .stretchy {
131 + height: 100%;
132 + box-sizing: border-box;
133 + }
134 }
762 - if (!this.pie) {
763 - return
135 + }
136 +
137 + @media (max-width: 1000px) {
138 + .section {
139 + .columns {
140 + flex-direction: column;
141 + }
142 }
765 - if (!this.chart) {
766 - return
143 + }
144 + @media (max-width: 1200px) {
145 + .section {
146 + .columns.column-1200 {
147 + flex-direction: column;
148 + }
149 }
768 -
769 - this.pie.dispose()
770 - this.chart.dispose()
771 - },
772 - components: { IndicesMarquee }
773 -})
774 -</script>
775 -
776 -<style lang="scss" scoped>
777 -@import "../../../assets/scss/_variables";
150 + }
151 +}
152 </style>
src/views/apps/Dashboards/_bkp_Indices.vue new
+694
@@ -0,0 +1,694 @@
1 +<template>
2 + <el-scrollbar class="page page-indices">
3 + bkp
4 + <div class="card-base mb-30">
5 + <IndicesMarquee :indices="indices" @click="setIndex" />
6 + </div>
7 +
8 + <div class="index-details-box">
9 + <div class="flex center demo-box bg-orange">
10 + <el-select v-model="currentIndex" placeholder="Select Your Index" clearable :value-key="'index'">
11 + <el-option v-for="index in indices" :key="index.index" :label="index.index" :value="index"></el-option>
12 + </el-select>
13 + </div>
14 + </div>
15 +
16 + <!--BEGIN TEST-->
17 + <div class="box center left">
18 + <div class="page-header header-primary card-base card-shadow--small">
19 + <h1 class="title">Index Stats</h1>
20 +
21 + <div class="flex justify-center align-center bg-orange" v-if="currentIndex">
22 + <div class="widget-icon-box mr-20 animate__animated animate__fadeInRight">
23 + <span class="badge">
24 + <i v-if="currentIndex.health === 'green'" class="mdi mdi-shield-check"></i>
25 + <i v-else-if="currentIndex.health === 'yellow'" class="mdi mdi-alert"></i>
26 + <i v-else-if="currentIndex.health === 'red'" class="mdi mdi-alert-decagram"></i>
27 + <strong class="accent-text font-size-20">Index:</strong>
28 + </span>
29 + <span class="highlight font-size-20">{{ currentIndex.index }}</span>
30 + </div>
31 + <div class="widget-icon-box mr-20 animate__animated animate__fadeInRight">
32 + <span class="accent-text font-size-20">Health:</span>
33 + <span class="highlight font-size-20">{{ currentIndex.health }}</span>
34 + </div>
35 + </div>
36 + </div>
37 +
38 + <div class="spacer"></div>
39 +
40 + <div class="card-base card-shadow--medium scrollable only-x bg-black">
41 + <el-row class="mt-0" :gutter="30">
42 + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
43 + <div class="page-table scrollable only-y" id="affix-container">
44 + <div class="page-header">
45 + <h1 class="warning-text">Index Data</h1>
46 + </div>
47 +
48 + <div class="table-box card-base card-shadow--medium scrollable only-x">
49 + <table class="styled striped">
50 + <thead>
51 + <tr>
52 + <th scope="col">Index Name</th>
53 + <th scope="col">Index Health</th>
54 + <th scope="col">Index Document Size</th>
55 + <th scope="col">Storage Size</th>
56 + <th scope="col">Replica Count</th>
57 + </tr>
58 + </thead>
59 + <tr v-for="index in filteredIndices" :key="index.id" :class="{ health: index.health }">
60 + <!-- Display the connector details in the table -->
61 + <td>{{ index.index }}</td>
62 + <td>{{ index.health }}</td>
63 + <td>{{ index.docs_count }}</td>
64 + <td>{{ index.store_size }}</td>
65 + <td>{{ index.replica_count }}</td>
66 +
67 + <!-- Add a buttton to Rotate an Index -->
68 + <td>
69 + <div class="btn-group" role="group" aria-label="Basic example">
70 + <button type="button" class="btn btn-info btn-sm">Rotate Index</button>
71 + </div>
72 + </td>
73 + <!-- Add a buttton to Delete an Index -->
74 + <td>
75 + <div class="btn-group" role="group" aria-label="Basic example">
76 + <button type="button" class="btn btn-info btn-sm" @click="deleteIndex(index.index)">
77 + Delete Index
78 + </button>
79 + </div>
80 + </td>
81 + </tr>
82 + </table>
83 + </div>
84 + </div>
85 + </el-col>
86 + </el-row>
87 +
88 + <!-- New table to display shards -->
89 + <el-row class="mt-0" :gutter="30">
90 + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
91 + <div class="page-table scrollable only-y" id="affix-container">
92 + <div class="page-header">
93 + <h1 class="warning-text">Index Shards</h1>
94 + </div>
95 +
96 + <div class="table-box card-base card-shadow--medium scrollable only-x">
97 + <table class="styled striped">
98 + <thead>
99 + <tr>
100 + <th scope="col">Shard Index</th>
101 + <th scope="col">Shard ID</th>
102 + <th scope="col">Shard State</th>
103 + <th scope="col">Shard Size</th>
104 + <th scope="col">Shard Node</th>
105 + </tr>
106 + </thead>
107 + <tr v-for="shard in filteredShards" :key="shard.id" class="bg-accent">
108 + <!-- Display the shard details in the table -->
109 + <td>{{ shard.index }}</td>
110 + <td>{{ shard.shard }}</td>
111 + <td>{{ shard.state }}</td>
112 + <td>{{ shard.size }}</td>
113 + <td>{{ shard.node }}</td>
114 + </tr>
115 + </table>
116 + </div>
117 + </div>
118 + </el-col>
119 + </el-row>
120 + </div>
121 +
122 + <div class="el-col el-col-24 el-col-xs-24 el-col-sm-12 el-col-md-12 el-col-lg-16 el-col-xl-16">
123 + <el-row class="chart-row">
124 + <el-col :xs="24" :sm="12" :md="12" :lg="16" :xl="16" class="chart-col">
125 + <div class="chart-container">
126 + <div id="chart" class="chart" :style="{ height: '500px', width: '120%' }"></div>
127 + </div>
128 + </el-col>
129 + <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8" class="chart-col">
130 + <div class="chart-container">
131 + <div id="pie" class="chart pie-chart" :style="{ height: '500px', width: '200%' }"></div>
132 + </div>
133 + </el-col>
134 + </el-row>
135 + </div>
136 +
137 + <div class="el-col el-col-24 el-col-xs-24 el-col-sm-12 el-col-md-12 el-col-lg-8 el-col-xl-8 flex box grow">
138 + <!-- New table to display shards -->
139 + <el-row class="mt-0" :gutter="30">
140 + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
141 + <ClusterHealth />
142 + </el-col>
143 +
144 + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
145 + <div class="page-table scrollable only-y" id="affix-container">
146 + <div class="page-header">
147 + <h1 class="warning-text">Unhealthy Indices</h1>
148 + </div>
149 +
150 + <div class="table-box card-base card-shadow--medium scrollable only-x">
151 + <table class="styled striped hover">
152 + <thead>
153 + <tr>
154 + <th scope="col">Index Name</th>
155 + <th scope="col">Index Health</th>
156 + </tr>
157 + </thead>
158 + <tbody>
159 + <tr
160 + v-for="index in unhealthyIndices"
161 + :key="index.id"
162 + :class="{
163 + 'bg-orange': index.health === 'yellow',
164 + 'bg-red': index.health === 'red'
165 + }"
166 + >
167 + <!-- Display the shard details in the table -->
168 + <td>{{ index.index }}</td>
169 +
170 + <td>{{ index.health }}</td>
171 + </tr>
172 + </tbody>
173 + </table>
174 + </div>
175 + </div>
176 + </el-col>
177 + </el-row>
178 + </div>
179 + </div>
180 + <!--END TEST-->
181 + </el-scrollbar>
182 +</template>
183 +
184 +<script lang="ts">
185 +import * as echarts from "echarts"
186 +import { Index, IndexAllocation, IndexHealth, IndexShard } from "@/types/indices.d"
187 +import Api from "@/api"
188 +import { ElMessage } from "element-plus"
189 +import { defineComponent } from "vue"
190 +import IndicesMarquee from "@/components/indices/Marquee.vue"
191 +import ClusterHealth from "@/components/indices/ClusterHealth.vue"
192 +
193 +export default defineComponent({
194 + data() {
195 + return {
196 + indices: [] as Index[],
197 + shards: [] as IndexShard[],
198 + indicesAllocation: [] as IndexAllocation[],
199 + loadingIndex: false,
200 + loadingShards: false,
201 + loadingAllocation: false,
202 + loadingDeleteIndex: false,
203 + currentIndex: null as Index | null,
204 + selectedValue: "",
205 + selectedHealth: ""
206 + }
207 + },
208 + computed: {
209 + filteredIndices() {
210 + return this.indices.filter((index: Index) => index.index === this.currentIndex?.index)
211 + },
212 + filteredShards() {
213 + return this.shards.filter((shard: IndexShard) => shard.index === this.currentIndex?.index)
214 + },
215 + unhealthyIndices() {
216 + return this.indices.filter((index: Index) => index.health === IndexHealth.YELLOW || index.health === IndexHealth.RED)
217 + },
218 + loading() {
219 + return this.loadingIndex || this.loadingShards || this.loadingAllocation
220 + }
221 + },
222 + methods: {
223 + setIndex(index: Index) {
224 + this.currentIndex = index
225 + },
226 + initChart() {
227 + // Store the indicesAllocation
228 + const indicesAllocation = this.indicesAllocation
229 + // For the indicesAllocation, get the disk_used, disk_total, and timestamp for all items in the array
230 + let data = indicesAllocation.map(item => {
231 + const date = new Date(item.timestamp)
232 + const hours = date.getHours()
233 + const minutes = date.getMinutes()
234 + return {
235 + diskUsed: item.disk_used,
236 + diskTotal: item.disk_total,
237 + timestamp: `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`
238 + }
239 + })
240 +
241 + // Sort data array by timestamp
242 + data.sort((a, b) => {
243 + const aParts = a.timestamp.split(":").map(Number)
244 + const bParts = b.timestamp.split(":").map(Number)
245 + const aDate = new Date(1970, 0, 1, aParts[0], aParts[1])
246 + const bDate = new Date(1970, 0, 1, bParts[0], bParts[1])
247 + return aDate - bDate
248 + })
249 +
250 + // Get the last 12 data points
251 + data = data.slice(Math.max(data.length - 12, 0))
252 +
253 + // Separate the data array into individual arrays for diskUsed, diskTotal, and timestamp
254 + const diskUsed = data.map(item => item.diskUsed)
255 + const diskTotal = data.map(item => item.diskTotal)
256 + const timestamp = data.map(item => item.timestamp)
257 +
258 + console.log("diskUsed: ", diskUsed)
259 + console.log("diskTotal: ", diskTotal)
260 + console.log("timestamp: ", timestamp)
261 +
262 + // Initialize the chart
263 + this.chart = echarts.init(document.getElementById("chart"))
264 + this.chart.setOption({
265 + //backgroundColor: '#394056',
266 + title: {
267 + top: 20,
268 + text: "Wazuh-Indexer Disk Usage",
269 + textStyle: { fontWeight: "normal", fontSize: 16, fontFamily: "Nunito Sans" /*color: '#F1F1F3'*/ },
270 + left: "1%"
271 + },
272 + tooltip: {
273 + trigger: "axis",
274 + axisPointer: {
275 + lineStyle: {
276 + /*color: '#57617B'*/
277 + }
278 + }
279 + },
280 + legend: {
281 + top: 40,
282 + icon: "rect",
283 + itemWidth: 14,
284 + itemHeight: 5,
285 + itemGap: 13,
286 + data: ["Product-A", "Product-B"],
287 + right: "4%",
288 + textStyle: { fontSize: 12, fontFamily: "Nunito Sans" /*color: '#F1F1F3'*/ }
289 + },
290 + grid: {
291 + top: 100,
292 + left: "-5px",
293 + right: "30px",
294 + bottom: "2%",
295 + containLabel: true
296 + },
297 + xAxis: [
298 + {
299 + type: "category",
300 + boundaryGap: false,
301 + axisLine: {
302 + lineStyle: {
303 + /*color: '#57617B'*/
304 + }
305 + },
306 + data: timestamp //timestamp is the x-axis
307 + }
308 + ],
309 + yAxis: [
310 + {
311 + show: false,
312 + type: "value",
313 + name: "(%)",
314 + axisTick: { show: false },
315 + axisLine: {
316 + lineStyle: {
317 + /*color: '#57617B'*/
318 + }
319 + },
320 + axisLabel: {
321 + margin: 10,
322 + fontSize: 14
323 + },
324 + splitLine: { lineStyle: { color: "#eee" /*color: '#57617B'*/ } }
325 + }
326 + ],
327 + series: [
328 + {
329 + name: "Disk Used",
330 + type: "line",
331 + smooth: true,
332 + symbol: "circle",
333 + symbolSize: 5,
334 + showSymbol: false,
335 + lineStyle: { width: 1 },
336 + areaStyle: {
337 + color: new echarts.graphic.LinearGradient(
338 + 0,
339 + 0,
340 + 0,
341 + 1,
342 + [
343 + {
344 + offset: 0,
345 + color: "rgba(19, 206, 102, 0.3)"
346 + },
347 + {
348 + offset: 0.8,
349 + color: "rgba(19, 206, 102, 0)"
350 + }
351 + ],
352 + false
353 + ),
354 + shadowColor: "rgba(0, 0, 0, 0.1)",
355 + shadowBlur: 10
356 + },
357 + itemStyle: {
358 + color: "rgb(19, 206, 102)",
359 + borderColor: "rgba(19, 206, 102, 0.27)",
360 + borderWidth: 12
361 + },
362 + data: diskUsed
363 + },
364 + {
365 + name: "Disk Total",
366 + type: "line",
367 + smooth: true,
368 + symbol: "circle",
369 + symbolSize: 5,
370 + showSymbol: false,
371 + lineStyle: { width: 1 },
372 + areaStyle: {
373 + color: new echarts.graphic.LinearGradient(
374 + 0,
375 + 0,
376 + 0,
377 + 1,
378 + [
379 + {
380 + offset: 0,
381 + color: "rgba(95, 143, 223, 0.3)"
382 + },
383 + {
384 + offset: 0.8,
385 + color: "rgba(95, 143, 223, 0)"
386 + }
387 + ],
388 + false
389 + ),
390 + shadowColor: "rgba(0, 0, 0, 0.1)",
391 + shadowBlur: 10
392 + },
393 + itemStyle: {
394 + color: "rgb(95, 143, 223)",
395 + borderColor: "rgba(95, 143, 223, 0.2)",
396 + borderWidth: 12
397 + },
398 + data: diskTotal
399 + } /*{
400 + name: 'Product-C',
401 + type: 'line',
402 + smooth: true,
403 + symbol: 'circle',
404 + symbolSize: 5,
405 + showSymbol: false,
406 + lineStyle: { width: 1 },
407 + areaStyle: {
408 +
409 + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
410 + offset: 0,
411 + color: 'rgba(236, 32, 95, 0.3)'
412 + }, {
413 + offset: 0.8,
414 + color: 'rgba(236, 32, 95, 0)'
415 + }], false),
416 + shadowColor: 'rgba(0, 0, 0, 0.1)',
417 + shadowBlur: 10
418 +
419 + },
420 + itemStyle: {
421 +
422 + color: 'rgb(236, 32, 95)',
423 + borderColor: 'rgba(236, 32, 95, 0.2)',
424 + borderWidth: 12
425 +
426 + },
427 + data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122]
428 + }*/
429 + ]
430 + })
431 + },
432 + initPie() {
433 + // const topIndexes = this.indices.sort((a, b) => b.store_size - a.store_size).slice(0, 5)
434 + const topIndexes = this.indices.sort((a, b) => b.store_size - a.store_size).slice(0, 8)
435 +
436 + const size = topIndexes.map(index => {
437 + const value = parseFloat(index.store_size) / 1024 // Convert MB to GB
438 + return {
439 + value: value,
440 + name: index.index,
441 + health: index.health,
442 + itemStyle: {
443 + color: "#3f84f6" // Custom color for each index
444 + }
445 + }
446 + })
447 + console.log("Size", size)
448 +
449 + const data = topIndexes.map(index => {
450 + // const value = parseFloat(index.store_size) // Parse the value as a float and remvoe the decimal
451 + const value = parseFloat(index.store_size) / 1000000000 // Parse the value as a float and convert to GB
452 + return {
453 + value: value,
454 + name: index.index,
455 + health: index.health,
456 + itemStyle: {
457 + color: "#3f84f6" // Custom color for each index
458 + }
459 + }
460 + })
461 + console.log(data)
462 +
463 + const redIndices = data.filter(index => index.health === "red")
464 + const yellowIndices = data.filter(index => index.health === "yellow")
465 + const greenIndices = data.filter(index => index.health === "green")
466 +
467 + // Get the percentage of green indices
468 + const greenPercentage = (greenIndices.length / data.length) * 100
469 + const yellowPercentage = (yellowIndices.length / data.length) * 100
470 + const redPercentage = (redIndices.length / data.length) * 100
471 + console.log("Red Indices:", redIndices)
472 + console.log("Yellow Indices:", yellowIndices)
473 + console.log("Green Indices:", greenIndices)
474 + console.log("Green Indices Percentage:", greenPercentage)
475 +
476 + // const ordersValue = data.length > 0 ? data[0].value.toFixed(2) : 0 // Get the rounded value of the first item in the data array
477 +
478 + this.pie = echarts.init(document.getElementById("pie"))
479 + this.pie.setOption({
480 + title: {
481 + top: 20,
482 + text: "Index Status and Top 8 Index Sizes By GB",
483 + textStyle: { fontWeight: "normal", fontSize: 16, fontFamily: "Nunito Sans" /*color: '#F1F1F3'*/ },
484 + left: "1%"
485 + },
486 + tooltip: {
487 + trigger: "item",
488 + formatter: "{a} <br/>{b}: {c} ({d}%)"
489 + },
490 + series: [
491 + {
492 + name: "Index",
493 + type: "pie",
494 + selectedMode: "single",
495 + radius: [0, "35%"],
496 +
497 + label: {
498 + position: "inner"
499 + },
500 + labelLine: {
501 + show: false
502 + },
503 + data: [
504 + {
505 + // set the value as the index size
506 + value: greenPercentage.toFixed(2),
507 + name: "Green Indices",
508 + selected: true,
509 + itemStyle: { color: "rgb(19, 206, 102)" }
510 + },
511 + {
512 + value: yellowPercentage.toFixed(2),
513 + name: "Yellow Indices",
514 + itemStyle: { color: "rgb(255, 255, 0)" }
515 + },
516 + {
517 + value: redPercentage.toFixed(2),
518 + name: "Red Indices",
519 + itemStyle: { color: "rgb(255, 0, 0)" }
520 + }
521 + ]
522 + },
523 + {
524 + name: "Index",
525 + type: "pie",
526 + radius: ["45%", "60%"],
527 + data: size.map((item, index) => ({
528 + value: item.value.toFixed(2),
529 + name: item.name,
530 + itemStyle: {
531 + color: item.itemStyle.color
532 + }
533 + })),
534 +
535 + itemStyle: {
536 + color: "rgb(19, 206, 102)"
537 + }
538 + }
539 + ]
540 + })
541 + },
542 + deleteIndex(index) {
543 + this.loadingDeleteIndex = true
544 +
545 + Api.indices
546 + .deleteIndex(index)
547 + .then(res => {
548 + ElMessage({
549 + message: "Index was successfully deleted.",
550 + type: "success"
551 + })
552 +
553 + this.getIndices()
554 + })
555 + .catch(err => {
556 + if (err.response.status === 401) {
557 + ElMessage({
558 + message: "Wazuh-Indexer returned Unauthorized. Please check your connector credentials.",
559 + type: "error"
560 + })
561 + } else if (err.response.status === 404) {
562 + ElMessage({
563 + message: err.response?.data?.message || "An error occurred. Please try again later.",
564 + type: "error"
565 + })
566 + } else {
567 + ElMessage({
568 + message: "An error occurred. Please try again later.",
569 + type: "error"
570 + })
571 + }
572 + })
573 + .finally(() => {
574 + this.loadingDeleteIndex = false
575 + })
576 + },
577 + getIndicesAllocation() {
578 + this.loadingAllocation = true
579 + Api.indices
580 + .getAllocation()
581 + .then(res => {
582 + this.indicesAllocation = res.data.node_allocation
583 + this.initChart()
584 + })
585 + .catch(err => {
586 + if (err.response.status === 401) {
587 + ElMessage({
588 + message: "Wazuh-Indexer returned Unauthorized. Please check your connector credentials.",
589 + type: "error"
590 + })
591 + } else if (err.response.status === 404) {
592 + ElMessage({
593 + message: "No alerts were found.",
594 + type: "error"
595 + })
596 + } else {
597 + ElMessage({
598 + message: "An error occurred. Please try again later.",
599 + type: "error"
600 + })
601 + }
602 + })
603 + .finally(() => {
604 + this.loadingAllocation = false
605 + })
606 + },
607 + getIndices() {
608 + this.loadingIndex = true
609 + Api.indices
610 + .getIndices()
611 + .then(res => {
612 + this.indices = res.data.indices
613 + this.initPie()
614 + })
615 + .catch(err => {
616 + if (err.response.status === 401) {
617 + ElMessage({
618 + message: "Wazuh-Indexer returned Unauthorized. Please check your connector credentials.",
619 + type: "error"
620 + })
621 + } else if (err.response.status === 404) {
622 + ElMessage({
623 + message: "No alerts were found.",
624 + type: "error"
625 + })
626 + } else {
627 + ElMessage({
628 + message: "An error occurred. Please try again later.",
629 + type: "error"
630 + })
631 + }
632 + })
633 + .finally(() => {
634 + this.loadingIndex = false
635 + })
636 + },
637 + getShards() {
638 + this.loadingShards = true
639 + Api.indices
640 + .getShards()
641 + .then(res => {
642 + this.shards = res.data.shards
643 + })
644 + .catch(err => {
645 + if (err.response.status === 401) {
646 + ElMessage({
647 + message: "Wazuh-Indexer returned Unauthorized. Please check your connector credentials.",
648 + type: "error"
649 + })
650 + } else if (err.response.status === 404) {
651 + ElMessage({
652 + message: "No alerts were found.",
653 + type: "error"
654 + })
655 + } else {
656 + ElMessage({
657 + message: "An error occurred. Please try again later.",
658 + type: "error"
659 + })
660 + }
661 + })
662 + .finally(() => {
663 + this.loadingShards = false
664 + })
665 + },
666 +
667 + getPieChartData() {
668 + const topIndexes = this.indices.sort((a, b) => b.store_size - a.store_size).slice(0, 8)
669 +
670 + return topIndexes.map((index, i) => ({
671 + value: index.store_size,
672 + name: `p${i + 1}`,
673 + itemStyle: {
674 + color: "#3f84f6" // Custom color for each index
675 + }
676 + }))
677 + }
678 + },
679 + beforeUnmount() {
680 + this.pie?.dispose()
681 + this.chart?.dispose()
682 + },
683 + created() {
684 + this.getIndices()
685 + this.getShards()
686 + this.getIndicesAllocation()
687 + },
688 + components: { IndicesMarquee, ClusterHealth }
689 +})
690 +</script>
691 +
692 +<style lang="scss" scoped>
693 +@import "../../../assets/scss/_variables";
694 +</style>
src/views/apps/_bkp_Connectors.vue deleted
-725
@@ -1,725 +0,0 @@
1 -<template>
2 - <div class="page-table scrollable only-y">
3 - <div class="page-header">
4 - <h1>Connectors</h1>
5 - <h4>Configure connections to your toolset.</h4>
6 - <el-breadcrumb separator="/">
7 - <el-breadcrumb-item :to="{ path: '/' }"><i class="mdi mdi-home-outline"></i></el-breadcrumb-item>
8 - <el-breadcrumb-item>Connectors</el-breadcrumb-item>
9 - </el-breadcrumb>
10 - </div>
11 -
12 - <div class="table-box card-base card-shadow--medium scrollable only-x" v-loading="loading">
13 - <table class="styled striped">
14 - <thead>
15 - <tr>
16 - <th scope="col">Connector Name</th>
17 - <th scope="col">Connector Description</th>
18 - <th scope="col">Connector Supports</th>
19 - <th scope="col">Connector Configured</th>
20 - <th scope="col">Connector Verified</th>
21 - <th scope="col">Connector Options</th>
22 - </tr>
23 - </thead>
24 - <tbody>
25 - <tr v-for="connector in connectors" :key="connector.id">
26 - <!-- Display the connector details in the table -->
27 - <td>{{ connector.connector_name }}</td>
28 - <td>{{ connector.connector_description }}</td>
29 - <td>{{ connector.connector_supports }}</td>
30 - <td>
31 - <el-button type="primary" v-if="connector.connector_configured == true">True</el-button>
32 - <el-button type="info" v-else>False</el-button>
33 - </td>
34 - <!-- Show the connector verified which is in the `connector` table -->
35 - <td>
36 - <el-button type="success" v-if="connector.connector_verified == true">True</el-button>
37 - <el-button type="danger" v-else>False</el-button>
38 - </td>
39 - <td>
40 - <div class="btn-group" role="group">
41 - <!--If the connector is not already configured then display the configure button -->
42 - <el-button
43 - type="primary"
44 - round
45 - v-if="
46 - (connector.connector_configured == false || connector.connector_configured == null) &&
47 - connector.connector_name.toLowerCase() !== 'velociraptor'
48 - "
49 - @click="openConfigureModal(connector)"
50 - >
51 - Configure
52 - </el-button>
53 -
54 - <!--If the connector is not already configured and the connector_name IS `velociraptor`, then display the configure button -->
55 - <el-button
56 - type="primary"
57 - round
58 - v-if="
59 - (connector.connector_configured == false || connector.connector_configured == null) &&
60 - connector.connector_name.toLowerCase() === 'velociraptor'
61 - "
62 - @click="openConfigureModalFile(connector)"
63 - >
64 - Configure
65 - </el-button>
66 - <!-- If the connector is already configured and the connector_name is not `shuffle` or `dfir-iris` to lower, then display the update button -->
67 - <el-button
68 - type="warning"
69 - round
70 - v-if="
71 - connector.connector_configured == true &&
72 - // connector.connector_name.toLowerCase() !==
73 - // 'shuffle' &&
74 - // connector.connector_name.toLowerCase() !==
75 - // 'dfir-iris' &&
76 - connector.connector_name.toLowerCase() !== 'velociraptor'
77 - "
78 - @click="openUpdateModal(connector)"
79 - >
80 - Update
81 - </el-button>
82 - <!-- Update Velociraptor -->
83 - <el-button
84 - type="warning"
85 - round
86 - v-if="
87 - connector.connector_configured == true &&
88 - // connector.connector_name.toLowerCase() !==
89 - // 'shuffle' &&
90 - // connector.connector_name.toLowerCase() !==
91 - // 'dfir-iris' &&
92 - connector.connector_name.toLowerCase() === 'velociraptor'
93 - "
94 - @click="openConfigureModalFile(connector)"
95 - >
96 - Update
97 - </el-button>
98 - <!-- If the connector is already configured and the connector_name IS `shuffle` or `dfir-iris` to lower, then display the update button -->
99 - <!-- <el-button type="warning" round
100 - v-if="
101 - connector.connector_configured == true &&
102 - (connector.connector_name.toLowerCase() ===
103 - 'shuffle' ||
104 - connector.connector_name.toLowerCase() ===
105 - 'dfir-iris')
106 - "
107 - @click="openUpdateModal(connector)"
108 - >
109 - Update
110 - </el-button> -->
111 -
112 - <!--<button type="button" class="btn btn-info btn-sm" @click="updateConnector(connector)">Update</button>-->
113 - <!--<button type="button" class="btn btn-info btn-sm" @click="deleteConnector(connector)">Delete</button>-->
114 - </div>
115 - </td>
116 - </tr>
117 - </tbody>
118 - </table>
119 - </div>
120 -
121 - <el-dialog
122 - title="Connector configuration"
123 - v-model:visible="showConfigDialog"
124 - :close-on-click-modal="false"
125 - :close-on-press-escape="false"
126 - width="600px"
127 - >
128 - <ConfigForm />
129 - </el-dialog>
130 -
131 - <!-- Configure Modal Username and Password API Key -->
132 - <div v-bind:class="{ 'modal-window': true, 'is-active': isConfigureModalActive }">
133 - <div class="modal-background" @click="openConfigureModal = false"></div>
134 - <div>
135 - <el-form :model="connectorForm" status-icon :rules="rules2" ref="connectorForm" label-width="120px" class="demo-ruleForm">
136 - <div class="modal-card">
137 - <header class="modal-card-head">
138 - <h2 class="modal-card-title">Configure {{ currentConnector ? currentConnector.connector_name : "" }}</h2>
139 - <img
140 - :src="`/src/assets/images/${
141 - currentConnector ? currentConnector.connector_name.toLowerCase() + '.svg' : 'default-logo.svg'
142 - }`"
143 - alt="Logo"
144 - class="modal-logo"
145 - />
146 - </header>
147 - <section class="modal-card-body">
148 - <div class="field">
149 - <label class="label">Connector URL</label>
150 - <div class="control">
151 - <input class="input" type="text" v-model="connectorForm.connector_url" required />
152 - </div>
153 - </div>
154 -
155 - <!-- API Key input for dfir-iris and shuffle -->
156 - <div
157 - class="field"
158 - v-if="
159 - ['dfir-iris', 'shuffle'].includes(currentConnector ? currentConnector.connector_name.toLowerCase() : '')
160 - "
161 - >
162 - <label class="label">API Key</label>
163 - <div class="control">
164 - <input class="input" type="text" v-model="connectorForm.connector_api_key" required />
165 - </div>
166 - </div>
167 -
168 - <!-- Username and Password inputs for other connectors -->
169 - <template v-else>
170 - <div class="field">
171 - <label class="label">Username</label>
172 - <div class="control">
173 - <input class="input" type="text" v-model="connectorForm.username" required />
174 - </div>
175 - </div>
176 - <div class="field">
177 - <label class="label">Password</label>
178 - <div class="control">
179 - <input class="input" type="password" v-model="connectorForm.password" required />
180 - </div>
181 - </div>
182 - </template>
183 -
184 - <div class="field">
185 - <div class="control">
186 - <button class="button is-primary" type="submit" @click.prevent="configureConnector">Save</button>
187 - <button class="button" type="button" @click="closeDialogUserandPass">Cancel</button>
188 - </div>
189 - </div>
190 - </section>
191 - </div>
192 - </el-form>
193 - </div>
194 - </div>
195 -
196 - <!-- Configure Modal File -->
197 - <div v-bind:class="{ 'modal-window': true, 'is-active': isConfigureModalFileActive }">
198 - <div class="modal-background" @click="openConfigureModalFile = false"></div>
199 - <div>
200 - <el-form :model="connectorForm" status-icon :rules="rules2" ref="connectorForm" label-width="120px" class="demo-ruleForm">
201 - <div class="modal-card">
202 - <header class="modal-card-head">
203 - <h2 class="modal-card-title">Configure File {{ currentConnector ? currentConnector.connector_name : "" }}</h2>
204 - <img
205 - :src="`/src/assets/images/${
206 - currentConnector ? currentConnector.connector_name.toLowerCase() + '.svg' : 'default-logo.svg'
207 - }`"
208 - alt="Logo"
209 - class="modal-logo"
210 - />
211 - </header>
212 - <section class="modal-card-body">
213 - <!-- Add the el-upload component here -->
214 - <el-upload
215 - class="upload-demo"
216 - action="http://localhost:5000/connectors/upload"
217 - :on-preview="handlePreview"
218 - :on-remove="handleRemove"
219 - :before-remove="beforeRemove"
220 - :on-success="handleSuccess"
221 - multiple
222 - drag
223 - :limit="3"
224 - :on-exceed="handleExceed"
225 - :file-list="fileList"
226 - >
227 - <i class="el-icon-upload"></i>
228 - <div class="el-upload__text">Drop file here or <em>click to upload</em></div>
229 - <div class="el-upload__tip" slot="tip">jpg/png files with a size less than 500kb</div>
230 - </el-upload>
231 - <!-- Add the cancel and submit buttons -->
232 - <div class="field">
233 - <div class="control">
234 - <button class="button" type="button" @click="closeConfigureModuleFile">Cancel</button>
235 - </div>
236 - </div>
237 - <!-- Rest of your existing code... -->
238 - </section>
239 - </div>
240 - </el-form>
241 - </div>
242 - </div>
243 -
244 - <!-- Update Modal Username and Password-->
245 - <div v-bind:class="{ 'modal-window': true, 'is-active': isUpdateModalActive }">
246 - <div class="modal-background" @click="openUpdateModal = false"></div>
247 - <div>
248 - <el-form :model="connectorForm" status-icon :rules="rules2" ref="connectorForm" label-width="120px" class="demo-ruleForm">
249 - <div class="modal-card">
250 - <header class="modal-card-head">
251 - <h2 class="modal-card-title">Update {{ currentConnector ? currentConnector.connector_name : "" }}</h2>
252 - <img
253 - :src="`/src/assets/images/${
254 - currentConnector ? currentConnector.connector_name.toLowerCase() + '.svg' : 'default-logo.svg'
255 - }`"
256 - alt="Logo"
257 - class="modal-logo"
258 - />
259 - </header>
260 - <section class="modal-card-body">
261 - <div class="field">
262 - <label class="label">Connector URL</label>
263 - <div class="control">
264 - <input class="input" type="text" v-model="connectorForm.connector_url" required />
265 - </div>
266 - </div>
267 -
268 - <!-- API Key input for dfir-iris and shuffle -->
269 - <div
270 - class="field"
271 - v-if="
272 - ['dfir-iris', 'shuffle'].includes(currentConnector ? currentConnector.connector_name.toLowerCase() : '')
273 - "
274 - >
275 - <label class="label">API Key</label>
276 - <div class="control">
277 - <input class="input" type="text" v-model="connectorForm.connector_api_key" required />
278 - </div>
279 - </div>
280 -
281 - <!-- Username and Password inputs for other connectors -->
282 - <template v-else>
283 - <div class="field">
284 - <label class="label">Username</label>
285 - <div class="control">
286 - <input class="input" type="text" v-model="connectorForm.username" required />
287 - </div>
288 - </div>
289 - <div class="field">
290 - <label class="label">Password</label>
291 - <div class="control">
292 - <input class="input" type="password" v-model="connectorForm.password" required />
293 - </div>
294 - </div>
295 - </template>
296 -
297 - <div class="field">
298 - <div class="control">
299 - <button class="button is-primary" type="submit" @click.prevent="updateConnector">Save</button>
300 - <button class="button" type="button" @click="closeUpdateModal">Cancel</button>
301 - </div>
302 - </div>
303 - </section>
304 - </div>
305 - </el-form>
306 - </div>
307 - </div>
308 - </div>
309 -</template>
310 -
311 -<script lang="ts">
312 -import axios from "axios"
313 -import Api from "@/api"
314 -import { defineComponent } from "vue"
315 -import ConfigForm from "@/components/connectors/ConfigForm.vue"
316 -import { Connector } from "@/types/connectors"
317 -
318 -export default defineComponent({
319 - data() {
320 - return {
321 - connectors: [] as Connector[],
322 - currentConnector: null,
323 -
324 - // Configure Modal
325 - isConfigureModalActive: false,
326 - isConfigureModalFileActive: false,
327 -
328 - // Update Modal
329 - isUpdateModalActive: false,
330 -
331 - loading: false,
332 - showConfigDialog: false,
333 -
334 - successMessage: "",
335 - errorMessage: "",
336 - connectorForm: {
337 - connector_url: "",
338 - username: "",
339 - password: "",
340 - connector_api_key: ""
341 - }
342 - }
343 - },
344 - methods: {
345 - showDialogUserandPass(connector) {
346 - this.currentConnector = connector
347 - this.showConfigDialog = true
348 - // this.$refs.userAndPassDialog.showModal();
349 - },
350 -
351 - openConfigureModal(connector) {
352 - // Open the configure modal and set the initial form values
353 - this.isConfigureModalActive = true
354 - this.currentConnector = connector // Store the current connector
355 - this.connectorForm.connector_url = connector.connector_url
356 - this.connectorForm.username = connector.connector_username
357 - this.connectorForm.password = connector.connector_password
358 - this.connectorForm.connector_api_key = connector.connector_api_key
359 - },
360 -
361 - openConfigureModalFile(connector) {
362 - // Open the configure modal and set the initial form values
363 - this.isConfigureModalFileActive = true
364 - this.currentConnector = connector // Store the current connector
365 - this.connectorForm.connector_url = connector.connector_url
366 - this.connectorForm.username = connector.connector_username
367 - this.connectorForm.password = connector.connector_password
368 - this.connectorForm.connector_api_key = connector.connector_api_key
369 - },
370 -
371 - closeDialogUserandPass() {
372 - // this.$refs.userAndPassDialog.close();
373 - this.showConfigDialog = false
374 - this.isConfigureModalActive = false
375 - },
376 -
377 - closeConfigureModuleFile() {
378 - // this.$refs.userAndPassDialog.close();
379 - this.showConfigDialog = false
380 - this.isConfigureModalFileActive = false
381 - },
382 -
383 - openUpdateModal(connector) {
384 - // Open the update modal and set the initial form values
385 - this.isUpdateModalActive = true
386 - this.currentConnector = connector // Store the current connector
387 - this.connectorForm.connector_url = connector.connector_url
388 - this.connectorForm.username = connector.connector_username
389 - this.connectorForm.password = connector.connector_password
390 - this.connectorForm.connector_api_key = connector.connector_api_key
391 - },
392 -
393 - closeUpdateModal() {
394 - // this.$refs.userAndPassDialog.close();
395 - this.showConfigDialog = false
396 - this.isUpdateModalActive = false
397 - },
398 -
399 - configureConnector(event) {
400 - event.preventDefault()
401 - const { connector_url, username, password, connector_api_key } = this.connectorForm
402 - const path = `http://127.0.0.1:5000/connectors/${this.currentConnector.id}`
403 - this.loading = true
404 - this.closeDialogUserandPass()
405 -
406 - if (connector_api_key) {
407 - console.log("POST request to: ", path)
408 - console.log("Data: ", {
409 - connector_url: connector_url,
410 - connector_api_key: connector_api_key
411 - })
412 - axios
413 - .post(path, {
414 - connector_url: connector_url,
415 - connector_api_key: connector_api_key
416 - })
417 - .then(() => {
418 - this.successMessage = "Connector has been successfully configured." // Set success message
419 - setTimeout(() => {
420 - this.successMessage = "" // Clear success message after 5 seconds
421 - }, 5000)
422 - this.getConnectors() // Refresh the connectors
423 - })
424 - .catch(err => {
425 - if (err.response.status === 400) {
426 - this.errorMessage =
427 - "This connector is already configured. If you would like to reconfigure this connector select `Edit`." // Set the error message
428 - } else if (err.response.status === 401) {
429 - this.errorMessage = "Unauthorized. Please check your endpoint URL, username and password." // Set the error message
430 - } else {
431 - this.errorMessage =
432 - "Error updating the connector. Your settings were not inserted into the keystore. Please try again." // Set the error message
433 - }
434 - setTimeout(() => {
435 - this.errorMessage = "" // Clear error message after 5 seconds
436 - }, 5000)
437 - this.getConnectors() // Refresh the connectors
438 - console.error(err) // Also log the error for debugging
439 - })
440 - .finally(() => {
441 - this.loading = false // Set loading to false
442 - })
443 - } else {
444 - axios
445 - .post(path, {
446 - connector_url: connector_url,
447 - connector_username: username,
448 - connector_password: password
449 - })
450 - .then(() => {
451 - this.successMessage = "Connector has been successfully configured." // Set success message
452 - setTimeout(() => {
453 - this.successMessage = "" // Clear success message after 5 seconds
454 - }, 5000)
455 - this.getConnectors() // Refresh the connectors
456 - })
457 - .catch(err => {
458 - if (err.response.status === 400) {
459 - this.errorMessage =
460 - "This connector is already configured. If you would like to reconfigure this connector select `Edit`." // Set the error message
461 - } else if (err.response.status === 401) {
462 - this.errorMessage = "Unauthorized. Please check your endpoint URL, username and password." // Set the error message
463 - } else {
464 - this.errorMessage =
465 - "Error updating the connector. Your settings were not inserted into the keystore. Please try again." // Set the error message
466 - }
467 - setTimeout(() => {
468 - this.errorMessage = "" // Clear error message after 5 seconds
469 - }, 5000)
470 - this.getConnectors() // Refresh the connectors
471 - console.error(err) // Also log the error for debugging
472 - })
473 - .finally(() => {
474 - this.loading = false // Set loading to false
475 - })
476 - }
477 - },
478 -
479 - updateConnector(event) {
480 - event.preventDefault()
481 - const { connector_url, username, password, connector_api_key } = this.connectorForm
482 - const path = `http://127.0.0.1:5000/connectors/${this.currentConnector.id}`
483 - this.loading = true
484 - this.closeUpdateModal()
485 -
486 - if (connector_api_key) {
487 - console.log("POST request to: ", path)
488 - console.log("Data: ", {
489 - connector_url: connector_url,
490 - connector_api_key: connector_api_key
491 - })
492 -
493 - axios
494 - .put(path, {
495 - connector_url: connector_url,
496 - connector_username: username,
497 - connector_password: password,
498 - connector_api_key: connector_api_key
499 - })
500 - .then(() => {
501 - this.successMessage = "Connector has been successfully updated." // Set success message
502 - setTimeout(() => {
503 - this.successMessage = "" // Clear success message after 5 seconds
504 - }, 5000)
505 - this.getConnectors() // Refresh the connectors
506 - })
507 - .catch(err => {
508 - if (err.response.status === 400) {
509 - this.errorMessage =
510 - "This connector is not configured. If you would like to configure this connector select `Configure`." // Set the error message
511 - } else if (err.response.status === 401) {
512 - this.errorMessage = "Unauthorized. Please check your endpoint URL, username and password." // Set the error message
513 - } else {
514 - this.errorMessage = "Error updating the connector. Please try again." // Set the error message
515 - }
516 - setTimeout(() => {
517 - this.errorMessage = "" // Clear error message after 5 seconds
518 - }, 5000)
519 - this.getConnectors() // Refresh the connectors
520 - console.error(err) // Also log the error for debugging
521 - })
522 - .finally(() => {
523 - this.loading = false // Set loading to false
524 - })
525 - } else {
526 - axios
527 - .put(path, {
528 - connector_url: connector_url,
529 - connector_username: username,
530 - connector_password: password
531 - })
532 - .then(() => {
533 - this.successMessage = "Connector has been successfully updated." // Set success message
534 - setTimeout(() => {
535 - this.successMessage = "" // Clear success message after 5 seconds
536 - }, 5000)
537 - this.getConnectors() // Refresh the connectors
538 - })
539 - .catch(err => {
540 - if (err.response.status === 400) {
541 - this.errorMessage =
542 - "This connector is not configured. If you would like to configure this connector select `Configure`." // Set the error message
543 - } else if (err.response.status === 401) {
544 - this.errorMessage = "Unauthorized. Please check your endpoint URL, username and password." // Set the error message
545 - } else {
546 - this.errorMessage = "Error updating the connector. Please try again." // Set the error message
547 - }
548 - setTimeout(() => {
549 - this.errorMessage = "" // Clear error message after 5 seconds
550 - }, 5000)
551 - this.getConnectors() // Refresh the connectors
552 - console.error(err) // Also log the error for debugging
553 - })
554 - .finally(() => {
555 - this.loading = false // Set loading to false
556 - })
557 - }
558 - },
559 -
560 - getConnectors() {
561 - this.loading = true
562 - Api.connectors
563 - .getAll()
564 - .then(res => {
565 - this.connectors = res.data.connectors
566 - })
567 - .catch(err => {
568 - console.error(err)
569 - })
570 - .finally(() => {
571 - this.loading = false
572 - })
573 - },
574 -
575 - resetForm(formName) {
576 - this.$refs[formName].resetFields()
577 - }
578 - },
579 - created() {
580 - this.getConnectors()
581 - },
582 - components: {
583 - ConfigForm
584 - }
585 -})
586 -</script>
587 -
588 -<style lang="scss" scoped>
589 -@import "../../assets/scss/_variables";
590 -
591 -.page-table {
592 - padding-left: 20px;
593 - padding-right: 15px;
594 - padding-bottom: 20px;
595 -}
596 -.table-box {
597 - overflow: auto;
598 -}
599 -
600 -.modal-window {
601 - position: fixed;
602 - background-color: rgba(255, 255, 255, 0.25);
603 - top: 0;
604 - right: 0;
605 - bottom: 0;
606 - left: 0;
607 - z-index: 999;
608 - visibility: hidden;
609 - opacity: 0;
610 - pointer-events: none;
611 - transition: all 0.3s;
612 - &.is-active {
613 - visibility: visible;
614 - opacity: 1;
615 - pointer-events: auto;
616 - }
617 - &:target {
618 - visibility: visible;
619 - opacity: 1;
620 - pointer-events: auto;
621 - }
622 - & > div {
623 - width: 400px;
624 - position: absolute;
625 - top: 50%;
626 - left: 50%;
627 - transform: translate(-50%, -50%);
628 - padding: 2em;
629 - background: white;
630 - }
631 - header {
632 - font-weight: bold;
633 - }
634 - h1 {
635 - font-size: 150%;
636 - margin: 0 0 15px;
637 - }
638 -}
639 -
640 -.modal-close {
641 - color: #aaa;
642 - line-height: 50px;
643 - font-size: 80%;
644 - position: absolute;
645 - right: 0;
646 - text-align: center;
647 - top: 0;
648 - width: 70px;
649 - text-decoration: none;
650 - &:hover {
651 - color: black;
652 - }
653 -}
654 -
655 -/* Demo Styles */
656 -
657 -html,
658 -body {
659 - height: 100%;
660 -}
661 -
662 -html {
663 - font-size: 18px;
664 - line-height: 1.4;
665 -}
666 -
667 -body {
668 - font-family: apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
669 - font-weight: 600;
670 - background-image: linear-gradient(to right, #7f53ac 0, #657ced 100%);
671 - color: black;
672 -}
673 -
674 -a {
675 - color: inherit;
676 - text-decoration: none;
677 -}
678 -
679 -.container {
680 - display: grid;
681 - justify-content: center;
682 - align-items: center;
683 - height: 100vh;
684 -}
685 -
686 -.modal-window {
687 - & > div {
688 - border-radius: 1rem;
689 - }
690 -}
691 -
692 -.modal-window div:not(:last-of-type) {
693 - margin-bottom: 15px;
694 -}
695 -
696 -.logo {
697 - max-width: 150px;
698 - display: block;
699 -}
700 -
701 -small {
702 - color: lightgray;
703 -}
704 -
705 -.btn {
706 - background-color: white;
707 - padding: 1em 1.5em;
708 - border-radius: 0.5rem;
709 - text-decoration: none;
710 - i {
711 - padding-right: 0.3em;
712 - }
713 -}
714 -
715 -.modal-card-head {
716 - display: flex;
717 - justify-content: space-between;
718 - align-items: center;
719 -}
720 -
721 -.modal-logo {
722 - height: auto; /* adjust as needed */
723 - width: auto; /* adjust as needed */
724 -}
725 -</style>