@cryptotaxi247 / CoPilot / commits / 73ac9452

Add iocs to alerts (#328)

* `refactor: Add IoC and AlertToIoC models` * `refactor: Add IoC and AlertToIoC models` * `refactor: delete ioc from alert` * `refactor: Add IoC collection to list alerts` * `refactor: Add IoC collection to list alerts` * `feat: Add IoC filtering to list alerts` * chore: update dependencies in frontend * feat: add alert iocs list and creation form * feat: add CollapseKeepAlive component * refactor: incident list * feat: improved ioc form validation * feat: add ioc filter on alerts list * `refactor: Update connector IDs for Huntress integration` * precommit fixes --------- Co-authored-by: Davide Di Modica <webmaster.ddm@gmail.com>

taylor_socfortress committed Nov 4, 2024 at 14:59 UTC 73ac94525827a80a194d07d1f8287543d52ec898
23 files changed +1489 -748
.vscode/settings.json
+1
@@ -31,6 +31,7 @@
31 "hoverable",
32 "iconoir",
33 "Indicies",
34 + "iocs",
35 "lastupdate",
36 "linebreak",
37 "Logsource",
backend/alembic/env.py
+2
@@ -26,6 +26,7 @@ from app.incidents.models import Alert
26 from app.incidents.models import AlertContext
27 from app.incidents.models import AlertTag
28 from app.incidents.models import AlertTitleFieldName
29 +from app.incidents.models import AlertToIoC
30 from app.incidents.models import AlertToTag
31 from app.incidents.models import Asset
32 from app.incidents.models import AssetFieldName
@@ -36,6 +37,7 @@ from app.incidents.models import CaseReportTemplateDataStore
37 from app.incidents.models import Comment
38 from app.incidents.models import CustomerCodeFieldName
39 from app.incidents.models import FieldName
40 +from app.incidents.models import IoC
41 from app.incidents.models import Notification
42 from app.integrations.alert_creation_settings.models.alert_creation_settings import (
43 AlertCreationSettings,
backend/alembic/versions/33e4754d845b_add_ioc_table_for_alerts.py new
+53
@@ -0,0 +1,53 @@
1 +"""Add ioc table for alerts
2 +
3 +Revision ID: 33e4754d845b
4 +Revises: a1e4beb87498
5 +Create Date: 2024-10-30 15:16:50.509086
6 +
7 +"""
8 +from typing import Sequence
9 +from typing import Union
10 +
11 +import sqlalchemy as sa
12 +
13 +from alembic import op
14 +
15 +# revision identifiers, used by Alembic.
16 +revision: str = "33e4754d845b"
17 +down_revision: Union[str, None] = "a1e4beb87498"
18 +branch_labels: Union[str, Sequence[str], None] = None
19 +depends_on: Union[str, Sequence[str], None] = None
20 +
21 +
22 +def upgrade() -> None:
23 + # ### commands auto generated by Alembic - please adjust! ###
24 + op.create_table(
25 + "incident_management_ioc",
26 + sa.Column("id", sa.Integer(), nullable=False),
27 + sa.Column("value", sa.String(length=250), nullable=False),
28 + sa.Column("type", sa.String(length=50), nullable=False),
29 + sa.Column("description", sa.String(length=10000), nullable=True),
30 + sa.PrimaryKeyConstraint("id"),
31 + )
32 + op.create_table(
33 + "incident_management_alert_to_ioc",
34 + sa.Column("alert_id", sa.Integer(), nullable=False),
35 + sa.Column("ioc_id", sa.Integer(), nullable=False),
36 + sa.ForeignKeyConstraint(
37 + ["alert_id"],
38 + ["incident_management_alert.id"],
39 + ),
40 + sa.ForeignKeyConstraint(
41 + ["ioc_id"],
42 + ["incident_management_ioc.id"],
43 + ),
44 + sa.PrimaryKeyConstraint("alert_id", "ioc_id"),
45 + )
46 + # ### end Alembic commands ###
47 +
48 +
49 +def downgrade() -> None:
50 + # ### commands auto generated by Alembic - please adjust! ###
51 + op.drop_table("incident_management_alert_to_ioc")
52 + op.drop_table("incident_management_ioc")
53 + # ### end Alembic commands ###
backend/app/incidents/models.py
+20
@@ -12,6 +12,25 @@ from sqlmodel import SQLModel
12 from sqlmodel import Text
13
14
15 +class IoC(SQLModel, table=True):
16 + __tablename__ = "incident_management_ioc"
17 + id: Optional[int] = Field(default=None, primary_key=True)
18 + value: str = Field(nullable=False)
19 + type: str = Field(max_length=50, nullable=False) # e.g., IP address, domain, URL, etc.
20 + description: Optional[str] = Field(sa_column=Text, nullable=True)
21 +
22 + alerts: List["AlertToIoC"] = Relationship(back_populates="ioc")
23 +
24 +
25 +class AlertToIoC(SQLModel, table=True):
26 + __tablename__ = "incident_management_alert_to_ioc"
27 + alert_id: int = Field(foreign_key="incident_management_alert.id", primary_key=True)
28 + ioc_id: int = Field(foreign_key="incident_management_ioc.id", primary_key=True)
29 +
30 + alert: "Alert" = Relationship(back_populates="iocs")
31 + ioc: "IoC" = Relationship(back_populates="alerts")
32 +
33 +
34 class Alert(SQLModel, table=True):
35 __tablename__ = "incident_management_alert"
36 id: Optional[int] = Field(default=None, primary_key=True)
@@ -28,6 +47,7 @@ class Alert(SQLModel, table=True):
47 assets: List["Asset"] = Relationship(back_populates="alert")
48 cases: List["CaseAlertLink"] = Relationship(back_populates="alert")
49 tags: List["AlertToTag"] = Relationship(back_populates="alert")
50 + iocs: List["AlertToIoC"] = Relationship(back_populates="alert")
51
52
53 class AlertTag(SQLModel, table=True):
backend/app/incidents/routes/db_operations.py
+49
@@ -31,6 +31,9 @@ from app.incidents.models import FieldName
31 from app.incidents.schema.db_operations import AlertContextCreate
32 from app.incidents.schema.db_operations import AlertContextResponse
33 from app.incidents.schema.db_operations import AlertCreate
34 +from app.incidents.schema.db_operations import AlertIoCCreate
35 +from app.incidents.schema.db_operations import AlertIoCDelete
36 +from app.incidents.schema.db_operations import AlertIoCResponse
37 from app.incidents.schema.db_operations import AlertOutResponse
38 from app.incidents.schema.db_operations import AlertResponse
39 from app.incidents.schema.db_operations import AlertStatus
@@ -82,6 +85,7 @@ from app.incidents.services.db_operations import alerts_closed_by_alert_title
85 from app.incidents.services.db_operations import alerts_closed_by_asset_name
86 from app.incidents.services.db_operations import alerts_closed_by_assigned_to
87 from app.incidents.services.db_operations import alerts_closed_by_customer_code
88 +from app.incidents.services.db_operations import alerts_closed_by_ioc
89 from app.incidents.services.db_operations import alerts_closed_by_source
90 from app.incidents.services.db_operations import alerts_closed_by_tag
91 from app.incidents.services.db_operations import alerts_closed_multiple_filters
@@ -90,6 +94,7 @@ from app.incidents.services.db_operations import alerts_in_progress_by_alert_tit
94 from app.incidents.services.db_operations import alerts_in_progress_by_assest_name
95 from app.incidents.services.db_operations import alerts_in_progress_by_assigned_to
96 from app.incidents.services.db_operations import alerts_in_progress_by_customer_code
97 +from app.incidents.services.db_operations import alerts_in_progress_by_ioc
98 from app.incidents.services.db_operations import alerts_in_progress_by_source
99 from app.incidents.services.db_operations import alerts_in_progress_by_tag
100 from app.incidents.services.db_operations import alerts_in_progress_multiple_filters
@@ -98,16 +103,19 @@ from app.incidents.services.db_operations import alerts_open_by_alert_title
103 from app.incidents.services.db_operations import alerts_open_by_assest_name
104 from app.incidents.services.db_operations import alerts_open_by_assigned_to
105 from app.incidents.services.db_operations import alerts_open_by_customer_code
106 +from app.incidents.services.db_operations import alerts_open_by_ioc
107 from app.incidents.services.db_operations import alerts_open_by_source
108 from app.incidents.services.db_operations import alerts_open_by_tag
109 from app.incidents.services.db_operations import alerts_open_multiple_filters
110 from app.incidents.services.db_operations import alerts_total_by_assigned_to
111 from app.incidents.services.db_operations import alerts_total_by_customer_code
112 +from app.incidents.services.db_operations import alerts_total_by_ioc
113 from app.incidents.services.db_operations import alerts_total_by_source
114 from app.incidents.services.db_operations import alerts_total_by_tag
115 from app.incidents.services.db_operations import alerts_total_multiple_filters
116 from app.incidents.services.db_operations import create_alert
117 from app.incidents.services.db_operations import create_alert_context
118 +from app.incidents.services.db_operations import create_alert_ioc
119 from app.incidents.services.db_operations import create_alert_tag
120 from app.incidents.services.db_operations import create_asset
121 from app.incidents.services.db_operations import create_case
@@ -115,6 +123,7 @@ from app.incidents.services.db_operations import create_case_alert_link
123 from app.incidents.services.db_operations import create_case_from_alert
124 from app.incidents.services.db_operations import create_comment
125 from app.incidents.services.db_operations import delete_alert
126 +from app.incidents.services.db_operations import delete_alert_ioc
127 from app.incidents.services.db_operations import delete_alert_tag
128 from app.incidents.services.db_operations import delete_alert_title_name
129 from app.incidents.services.db_operations import delete_asset_name
@@ -140,6 +149,7 @@ from app.incidents.services.db_operations import list_alert_by_status
149 from app.incidents.services.db_operations import list_alerts
150 from app.incidents.services.db_operations import list_alerts_by_asset_name
151 from app.incidents.services.db_operations import list_alerts_by_customer_code
152 +from app.incidents.services.db_operations import list_alerts_by_ioc
153 from app.incidents.services.db_operations import list_alerts_by_source
154 from app.incidents.services.db_operations import list_alerts_by_tag
155 from app.incidents.services.db_operations import list_alerts_by_title
@@ -407,6 +417,38 @@ async def create_asset_endpoint(asset: AssetCreate, db: AsyncSession = Depends(g
417 return AssetResponse(asset=await create_asset(asset, db), success=True, message="Asset created successfully")
418
419
420 +@incidents_db_operations_router.post("/alert/ioc", response_model=AlertIoCResponse)
421 +async def create_alert_ioc_endpoint(ioc: AlertIoCCreate, db: AsyncSession = Depends(get_db)):
422 + return AlertIoCResponse(alert_ioc=await create_alert_ioc(ioc, db), success=True, message="Alert IoC created successfully")
423 +
424 +
425 +@incidents_db_operations_router.get("/alert/ioc/{ioc_value}", response_model=AlertOutResponse)
426 +async def list_alerts_by_ioc_value_endpoint(
427 + ioc_value: str,
428 + db: AsyncSession = Depends(get_db),
429 + page: int = Query(1, ge=1),
430 + page_size: int = Query(25, ge=1),
431 +):
432 + return AlertOutResponse(
433 + alerts=await list_alerts_by_ioc(ioc_value, db, page, page_size),
434 + total=await alerts_total_by_ioc(db, ioc_value),
435 + open=await alerts_open_by_ioc(db, ioc_value),
436 + in_progress=await alerts_in_progress_by_ioc(db, ioc_value),
437 + closed=await alerts_closed_by_ioc(db, ioc_value),
438 + success=True,
439 + message="Alerts retrieved successfully",
440 + )
441 +
442 +
443 +@incidents_db_operations_router.delete("/alert/ioc", response_model=AlertIoCResponse)
444 +async def delete_alert_ioc_endpoint(ioc: AlertIoCDelete, db: AsyncSession = Depends(get_db)):
445 + return AlertIoCResponse(
446 + alert_ioc=await delete_alert_ioc(ioc=ioc, db=db),
447 + success=True,
448 + message="Alert IoC deleted successfully",
449 + )
450 +
451 +
452 @incidents_db_operations_router.post("/alert/tag", response_model=AlertTagResponse)
453 async def create_alert_tag_endpoint(alert_tag: AlertTagCreate, db: AsyncSession = Depends(get_db)):
454 return AlertTagResponse(alert_tag=await create_alert_tag(alert_tag, db), success=True, message="Alert tag created successfully")
@@ -620,6 +662,7 @@ async def list_alerts_multiple_filters_endpoint(
662 asset_name: Optional[str] = Query(None),
663 status: Optional[str] = Query(None),
664 tags: Optional[List[str]] = Query(None),
665 + ioc_value: Optional[str] = Query(None),
666 page: int = Query(1, ge=1),
667 page_size: int = Query(25, ge=1),
668 order: str = Query("desc", regex="^(asc|desc)$"),
@@ -636,6 +679,7 @@ async def list_alerts_multiple_filters_endpoint(
679 - asset_name (str, optional): Filter by asset name.
680 - status (str, optional): Filter by status.
681 - tags (List[str], optional): Filter by tags.
682 + - ioc_value (str, optional): Filter by IoC value.
683 - page (int, default=1): Page number.
684 - page_size (int, default=25): Number of alerts per page.
685 - order (str, default='desc'): Sorting order ('asc' or 'desc').
@@ -659,6 +703,7 @@ async def list_alerts_multiple_filters_endpoint(
703 asset_name=asset_name,
704 status=status,
705 tags=tags,
706 + ioc_value=ioc_value,
707 db=db,
708 page=page,
709 page_size=page_size,
@@ -672,6 +717,7 @@ async def list_alerts_multiple_filters_endpoint(
717 asset_name=asset_name,
718 status=status,
719 tags=tags,
720 + ioc_value=ioc_value,
721 db=db,
722 ),
723 open=await alerts_open_multiple_filters(
@@ -682,6 +728,7 @@ async def list_alerts_multiple_filters_endpoint(
728 asset_name=asset_name,
729 status=status,
730 tags=tags,
731 + ioc_value=ioc_value,
732 db=db,
733 ),
734 in_progress=await alerts_in_progress_multiple_filters(
@@ -692,6 +739,7 @@ async def list_alerts_multiple_filters_endpoint(
739 asset_name=asset_name,
740 status=status,
741 tags=tags,
742 + ioc_value=ioc_value,
743 db=db,
744 ),
745 closed=await alerts_closed_multiple_filters(
@@ -702,6 +750,7 @@ async def list_alerts_multiple_filters_endpoint(
750 asset_name=asset_name,
751 status=status,
752 tags=tags,
753 + ioc_value=ioc_value,
754 db=db,
755 ),
756 success=True,
backend/app/incidents/schema/db_operations.py
+44
@@ -4,12 +4,14 @@ from typing import Dict
4 from typing import List
5 from typing import Optional
6
7 +from fastapi import HTTPException
8 from pydantic import BaseModel
9 from pydantic import validator
10
11 from app.incidents.models import Alert
12 from app.incidents.models import AlertContext
13 from app.incidents.models import AlertTag
14 +from app.incidents.models import AlertToIoC
15 from app.incidents.models import Asset
16 from app.incidents.models import Case
17 from app.incidents.models import CaseAlertLink
@@ -136,6 +138,35 @@ class AlertTagResponse(BaseModel):
138 message: str
139
140
141 +class AlertIocValue(str, Enum):
142 + IP = "IP"
143 + DOMAIN = "DOMAIN"
144 + HASH = "HASH"
145 + URL = "URL"
146 +
147 +
148 +class AlertIoCCreate(BaseModel):
149 + alert_id: int
150 + ioc_value: str
151 + ioc_type: AlertIocValue
152 + ioc_description: Optional[str] = None
153 +
154 + @validator("ioc_type")
155 + def validate_ioc_type(cls, v):
156 + if v not in AlertIocValue:
157 + raise HTTPException(
158 + status_code=400,
159 + detail=f"Invalid IoC type. Must be one of {', '.join([ioc.value for ioc in AlertIocValue])}",
160 + )
161 + return v
162 +
163 +
164 +class AlertIoCResponse(BaseModel):
165 + alert_ioc: AlertToIoC
166 + success: bool
167 + message: str
168 +
169 +
170 class CaseResponse(BaseModel):
171 case: Case
172 success: bool
@@ -258,6 +289,11 @@ class AlertTagDelete(BaseModel):
289 tag_id: int
290
291
292 +class AlertIoCDelete(BaseModel):
293 + alert_id: int
294 + ioc_id: int
295 +
296 +
297 class CommentBase(BaseModel):
298 user_name: str
299 alert_id: int
@@ -278,6 +314,13 @@ class AssetBase(BaseModel):
314 index_name: str
315
316
317 +class IoCBase(BaseModel):
318 + value: str
319 + type: AlertIocValue
320 + description: Optional[str] = None
321 + id: int
322 +
323 +
324 class AlertOut(BaseModel):
325 id: int
326 alert_creation_time: datetime
@@ -292,6 +335,7 @@ class AlertOut(BaseModel):
335 assets: List[AssetBase] = []
336 tags: List[AlertTagBase] = []
337 linked_cases: List[LinkedCaseCreate] = []
338 + iocs: List[IoCBase] = []
339
340
341 class AlertOutResponse(BaseModel):
backend/app/incidents/services/db_operations.py
+188 -15
@@ -30,6 +30,7 @@ from app.incidents.models import Alert
30 from app.incidents.models import AlertContext
31 from app.incidents.models import AlertTag
32 from app.incidents.models import AlertTitleFieldName
33 +from app.incidents.models import AlertToIoC
34 from app.incidents.models import AlertToTag
35 from app.incidents.models import Asset
36 from app.incidents.models import AssetFieldName
@@ -40,10 +41,13 @@ from app.incidents.models import CaseReportTemplateDataStore
41 from app.incidents.models import Comment
42 from app.incidents.models import CustomerCodeFieldName
43 from app.incidents.models import FieldName
44 +from app.incidents.models import IoC
45 from app.incidents.models import Notification
46 from app.incidents.models import TimestampFieldName
47 from app.incidents.schema.db_operations import AlertContextCreate
48 from app.incidents.schema.db_operations import AlertCreate
49 +from app.incidents.schema.db_operations import AlertIoCCreate
50 +from app.incidents.schema.db_operations import AlertIoCDelete
51 from app.incidents.schema.db_operations import AlertOut
52 from app.incidents.schema.db_operations import AlertTagBase
53 from app.incidents.schema.db_operations import AlertTagCreate
@@ -55,6 +59,7 @@ from app.incidents.schema.db_operations import CaseOut
59 from app.incidents.schema.db_operations import CaseReportTemplateDataStoreListResponse
60 from app.incidents.schema.db_operations import CommentBase
61 from app.incidents.schema.db_operations import CommentCreate
62 +from app.incidents.schema.db_operations import IoCBase
63 from app.incidents.schema.db_operations import LinkedCaseCreate
64 from app.incidents.schema.db_operations import PutNotification
65 from app.incidents.schema.db_operations import UpdateAlertStatus
@@ -206,6 +211,7 @@ async def alerts_total_multiple_filters(
211 asset_name: Optional[str] = None,
212 status: Optional[str] = None,
213 tags: Optional[List[str]] = None,
214 + ioc_value: Optional[str] = None,
215 ) -> int:
216 # Build dynamic filters
217 filters = []
@@ -223,14 +229,18 @@ async def alerts_total_multiple_filters(
229 filters.append(Alert.status == status)
230 if tags:
231 filters.append(AlertTag.tag.in_(tags))
232 + if ioc_value:
233 + filters.append(IoC.value == ioc_value)
234
227 - # Build the query
235 + # Build the query with dynamic filters
236 query = (
237 select(func.count(distinct(Alert.id)))
238 .select_from(Alert)
231 - .join(Asset, isouter=True)
232 - .join(AlertToTag, isouter=True)
233 - .join(AlertTag, AlertToTag.tag_id == AlertTag.id, isouter=True)
239 + .join(Asset, Asset.alert_linked == Alert.id, isouter=True) # Join with Asset table
240 + .join(AlertToTag, AlertToTag.alert_id == Alert.id, isouter=True) # Join with AlertToTag table
241 + .join(AlertTag, AlertToTag.tag_id == AlertTag.id, isouter=True) # Join with AlertTag table
242 + .join(AlertToIoC, AlertToIoC.alert_id == Alert.id, isouter=True) # Join with AlertToIoC table
243 + .join(IoC, AlertToIoC.ioc_id == IoC.id, isouter=True) # Join with IoC table
244 .where(*filters)
245 )
246
@@ -248,6 +258,7 @@ async def alerts_closed_multiple_filters(
258 asset_name: Optional[str] = None,
259 status: Optional[str] = None,
260 tags: Optional[List[str]] = None,
261 + ioc_value: Optional[str] = None,
262 ) -> int:
263 # Include the status filter
264 filters = [Alert.status == "CLOSED"]
@@ -265,13 +276,18 @@ async def alerts_closed_multiple_filters(
276 filters.append(Alert.status == status)
277 if tags:
278 filters.append(AlertTag.tag.in_(tags))
279 + if ioc_value:
280 + filters.append(IoC.value == ioc_value)
281
282 + # Build the query with dynamic filters
283 query = (
284 select(func.count(distinct(Alert.id)))
285 .select_from(Alert)
272 - .join(Asset, isouter=True)
273 - .join(AlertToTag, isouter=True)
274 - .join(AlertTag, AlertToTag.tag_id == AlertTag.id, isouter=True)
286 + .join(Asset, Asset.alert_linked == Alert.id, isouter=True) # Join with Asset table
287 + .join(AlertToTag, AlertToTag.alert_id == Alert.id, isouter=True) # Join with AlertToTag table
288 + .join(AlertTag, AlertToTag.tag_id == AlertTag.id, isouter=True) # Join with AlertTag table
289 + .join(AlertToIoC, AlertToIoC.alert_id == Alert.id, isouter=True) # Join with AlertToIoC table
290 + .join(IoC, AlertToIoC.ioc_id == IoC.id, isouter=True) # Join with IoC table
291 .where(*filters)
292 )
293
@@ -289,6 +305,7 @@ async def alerts_in_progress_multiple_filters(
305 asset_name: Optional[str] = None,
306 status: Optional[str] = None,
307 tags: Optional[List[str]] = None,
308 + ioc_value: Optional[str] = None,
309 ) -> int:
310 filters = [Alert.status == "IN_PROGRESS"]
311 if assigned_to:
@@ -305,13 +322,17 @@ async def alerts_in_progress_multiple_filters(
322 filters.append(Alert.status == status)
323 if tags:
324 filters.append(AlertTag.tag.in_(tags))
325 + if ioc_value:
326 + filters.append(IoC.value == ioc_value)
327
328 query = (
329 select(func.count(distinct(Alert.id)))
330 .select_from(Alert)
312 - .join(Asset, isouter=True)
313 - .join(AlertToTag, isouter=True)
314 - .join(AlertTag, AlertToTag.tag_id == AlertTag.id, isouter=True)
331 + .join(Asset, Asset.alert_linked == Alert.id, isouter=True) # Join with Asset table
332 + .join(AlertToTag, AlertToTag.alert_id == Alert.id, isouter=True) # Join with AlertToTag table
333 + .join(AlertTag, AlertToTag.tag_id == AlertTag.id, isouter=True) # Join with AlertTag table
334 + .join(AlertToIoC, AlertToIoC.alert_id == Alert.id, isouter=True) # Join with AlertToIoC table
335 + .join(IoC, AlertToIoC.ioc_id == IoC.id, isouter=True) # Join with IoC table
336 .where(*filters)
337 )
338
@@ -329,6 +350,7 @@ async def alerts_open_multiple_filters(
350 asset_name: Optional[str] = None,
351 status: Optional[str] = None,
352 tags: Optional[List[str]] = None,
353 + ioc_value: Optional[str] = None,
354 ) -> int:
355 filters = [Alert.status == "OPEN"]
356 if assigned_to:
@@ -345,13 +367,17 @@ async def alerts_open_multiple_filters(
367 filters.append(Alert.status == status)
368 if tags:
369 filters.append(AlertTag.tag.in_(tags))
370 + if ioc_value:
371 + filters.append(IoC.value == ioc_value)
372
373 query = (
374 select(func.count(distinct(Alert.id)))
375 .select_from(Alert)
352 - .join(Asset, isouter=True)
353 - .join(AlertToTag, isouter=True)
354 - .join(AlertTag, AlertToTag.tag_id == AlertTag.id, isouter=True)
376 + .join(Asset, Asset.alert_linked == Alert.id, isouter=True) # Join with Asset table
377 + .join(AlertToTag, AlertToTag.alert_id == Alert.id, isouter=True) # Join with AlertToTag table
378 + .join(AlertTag, AlertToTag.tag_id == AlertTag.id, isouter=True) # Join with AlertTag table
379 + .join(AlertToIoC, AlertToIoC.alert_id == Alert.id, isouter=True) # Join with AlertToIoC table
380 + .join(IoC, AlertToIoC.ioc_id == IoC.id, isouter=True) # Join with IoC table
381 .where(*filters)
382 )
383
@@ -360,6 +386,46 @@ async def alerts_open_multiple_filters(
386 return open_count
387
388
389 +async def alerts_total_by_ioc(db: AsyncSession, ioc_value: str) -> int:
390 + result = await db.execute(
391 + select(Alert)
392 + .join(AlertToIoC, Alert.id == AlertToIoC.alert_id)
393 + .join(IoC, AlertToIoC.ioc_id == IoC.id)
394 + .where(IoC.value == ioc_value),
395 + )
396 + return len(result.scalars().all())
397 +
398 +
399 +async def alerts_closed_by_ioc(db: AsyncSession, ioc_value: str) -> int:
400 + result = await db.execute(
401 + select(Alert)
402 + .join(AlertToIoC, Alert.id == AlertToIoC.alert_id)
403 + .join(IoC, AlertToIoC.ioc_id == IoC.id)
404 + .where((Alert.status == "CLOSED") & (IoC.value == ioc_value)),
405 + )
406 + return len(result.scalars().all())
407 +
408 +
409 +async def alerts_in_progress_by_ioc(db: AsyncSession, ioc_value: str) -> int:
410 + result = await db.execute(
411 + select(Alert)
412 + .join(AlertToIoC, Alert.id == AlertToIoC.alert_id)
413 + .join(IoC, AlertToIoC.ioc_id == IoC.id)
414 + .where((Alert.status == "IN_PROGRESS") & (IoC.value == ioc_value)),
415 + )
416 + return len(result.scalars().all())
417 +
418 +
419 +async def alerts_open_by_ioc(db: AsyncSession, ioc_value: str) -> int:
420 + result = await db.execute(
421 + select(Alert)
422 + .join(AlertToIoC, Alert.id == AlertToIoC.alert_id)
423 + .join(IoC, AlertToIoC.ioc_id == IoC.id)
424 + .where((Alert.status == "OPEN") & (IoC.value == ioc_value)),
425 + )
426 + return len(result.scalars().all())
427 +
428 +
429 async def alerts_total_by_tag(db: AsyncSession, tag: str) -> int:
430 result = await db.execute(
431 select(Alert)
@@ -731,6 +797,48 @@ async def create_asset(asset: AssetCreate, db: AsyncSession) -> Asset:
797 return db_asset
798
799
800 +async def create_alert_ioc(alert_ioc: AlertIoCCreate, db: AsyncSession) -> AlertToIoC:
801 + # Create the IoC instance
802 + db_alert_ioc = IoC(
803 + value=alert_ioc.ioc_value,
804 + type=alert_ioc.ioc_type,
805 + description=alert_ioc.ioc_description,
806 + )
807 + db.add(db_alert_ioc)
808 + await db.flush()
809 +
810 + # Create the AlertToIoC instance
811 + db_alert_to_ioc = AlertToIoC(alert_id=alert_ioc.alert_id, ioc_id=db_alert_ioc.id)
812 + db.add(db_alert_to_ioc)
813 +
814 + try:
815 + await db.commit()
816 + except IntegrityError:
817 + await db.rollback()
818 + raise HTTPException(status_code=400, detail="Alert IoC already exists")
819 + return AlertToIoC(alert_id=db_alert_to_ioc.alert_id, ioc_id=db_alert_to_ioc.ioc_id)
820 +
821 +
822 +async def delete_alert_ioc(ioc: AlertIoCDelete, db: AsyncSession) -> AlertToIoC:
823 + result = await db.execute(select(AlertToIoC).where((AlertToIoC.alert_id == ioc.alert_id) & (AlertToIoC.ioc_id == ioc.ioc_id)))
824 + alert_ioc = result.scalars().first()
825 + if not alert_ioc:
826 + raise HTTPException(status_code=404, detail="Alert IoC not found")
827 +
828 + await db.execute(delete(AlertToIoC).where((AlertToIoC.alert_id == ioc.alert_id) & (AlertToIoC.ioc_id == ioc.ioc_id)))
829 +
830 + # Delete the IoC from the IoC table
831 + await db.execute(delete(IoC).where(IoC.id == ioc.ioc_id))
832 +
833 + try:
834 + await db.commit()
835 + except IntegrityError:
836 + await db.rollback()
837 + raise HTTPException(status_code=400, detail="Error deleting alert IoC")
838 +
839 + return alert_ioc
840 +
841 +
842 async def create_alert_tag(alert_tag: AlertTagCreate, db: AsyncSession) -> AlertTag:
843 # Create the AlertTag instance
844 db_alert_tag = AlertTag(**alert_tag.dict())
@@ -837,6 +945,7 @@ async def list_alerts(db: AsyncSession, page: int = 1, page_size: int = 25, orde
945 selectinload(Alert.assets),
946 selectinload(Alert.cases).selectinload(CaseAlertLink.case),
947 selectinload(Alert.tags).selectinload(AlertToTag.tag),
948 + selectinload(Alert.iocs).selectinload(AlertToIoC.ioc),
949 )
950 .order_by(order_by)
951 .offset(offset)
@@ -849,6 +958,7 @@ async def list_alerts(db: AsyncSession, page: int = 1, page_size: int = 25, orde
958 comments = [CommentBase(**comment.__dict__) for comment in alert.comments]
959 assets = [AssetBase(**asset.__dict__) for asset in alert.assets]
960 tags = [AlertTagBase(**alert_to_tag.tag.__dict__) for alert_to_tag in alert.tags]
961 + iocs = [IoCBase(**alert_to_ioc.ioc.__dict__) for alert_to_ioc in alert.iocs]
962 linked_cases = [LinkedCaseCreate(**case_alert_link.case.__dict__) for case_alert_link in alert.cases]
963 alert_out = AlertOut(
964 id=alert.id,
@@ -863,6 +973,7 @@ async def list_alerts(db: AsyncSession, page: int = 1, page_size: int = 25, orde
973 comments=comments,
974 assets=assets,
975 tags=tags,
976 + iocs=iocs,
977 linked_cases=linked_cases,
978 )
979 alerts_out.append(alert_out)
@@ -1221,6 +1332,54 @@ async def get_alert_context_by_id(alert_context_id: int, db: AsyncSession) -> Al
1332 return alert_context
1333
1334
1335 +async def list_alerts_by_ioc(ioc_value: str, db: AsyncSession, page: int = 1, page_size: int = 25, order: str = "desc") -> List[AlertOut]:
1336 + offset = (page - 1) * page_size
1337 + order_by = asc(Alert.id) if order == "asc" else desc(Alert.id)
1338 + logger.info(f"Listing alerts by IoC {ioc_value}")
1339 +
1340 + result = await db.execute(
1341 + select(Alert)
1342 + .join(AlertToIoC)
1343 + .join(IoC)
1344 + .where(IoC.value == ioc_value)
1345 + .options(
1346 + selectinload(Alert.comments),
1347 + selectinload(Alert.assets),
1348 + selectinload(Alert.cases),
1349 + selectinload(Alert.tags).selectinload(AlertToTag.tag),
1350 + selectinload(Alert.iocs).selectinload(AlertToIoC.ioc),
1351 + )
1352 + .order_by(order_by)
1353 + .offset(offset)
1354 + .limit(page_size),
1355 + )
1356 +
1357 + alerts = result.scalars().all()
1358 + alerts_out = []
1359 + for alert in alerts:
1360 + comments: List[CommentBase] = [CommentBase(**comment.__dict__) for comment in alert.comments]
1361 + assets: List[AssetBase] = [AssetBase(**asset.__dict__) for asset in alert.assets]
1362 + tags: List[AlertTagBase] = [AlertTagBase(**alert_to_tag.tag.__dict__) for alert_to_tag in alert.tags]
1363 + iocs: List[IoCBase] = [IoCBase(**alert_to_ioc.ioc.__dict__) for alert_to_ioc in alert.iocs]
1364 + alert_out = AlertOut(
1365 + id=alert.id,
1366 + alert_creation_time=alert.alert_creation_time,
1367 + time_closed=alert.time_closed,
1368 + alert_name=alert.alert_name,
1369 + alert_description=alert.alert_description,
1370 + status=alert.status,
1371 + customer_code=alert.customer_code,
1372 + source=alert.source,
1373 + assigned_to=alert.assigned_to,
1374 + comments=comments,
1375 + assets=assets,
1376 + tags=tags,
1377 + iocs=iocs,
1378 + )
1379 + alerts_out.append(alert_out)
1380 + return alerts_out
1381 +
1382 +
1383 async def list_alerts_by_tag(tag: str, db: AsyncSession, page: int = 1, page_size: int = 25, order: str = "desc") -> List[AlertOut]:
1384 offset = (page - 1) * page_size
1385 order_by = asc(Alert.id) if order == "asc" else desc(Alert.id)
@@ -1235,6 +1394,7 @@ async def list_alerts_by_tag(tag: str, db: AsyncSession, page: int = 1, page_siz
1394 selectinload(Alert.assets),
1395 selectinload(Alert.cases),
1396 selectinload(Alert.tags).selectinload(AlertToTag.tag),
1397 + selectinload(Alert.iocs).selectinload(AlertToIoC.ioc),
1398 )
1399 .order_by(order_by)
1400 .offset(offset)
@@ -1246,6 +1406,7 @@ async def list_alerts_by_tag(tag: str, db: AsyncSession, page: int = 1, page_siz
1406 comments = [CommentBase(**comment.__dict__) for comment in alert.comments]
1407 assets = [AssetBase(**asset.__dict__) for asset in alert.assets]
1408 tags = [AlertTagBase(**alert_to_tag.tag.__dict__) for alert_to_tag in alert.tags]
1409 + iocs = [IoCBase(**alert_to_ioc.ioc.__dict__) for alert_to_ioc in alert.iocs]
1410 alert_out = AlertOut(
1411 id=alert.id,
1412 alert_creation_time=alert.alert_creation_time,
@@ -1259,6 +1420,7 @@ async def list_alerts_by_tag(tag: str, db: AsyncSession, page: int = 1, page_siz
1420 comments=comments,
1421 assets=assets,
1422 tags=tags,
1423 + iocs=iocs,
1424 )
1425 alerts_out.append(alert_out)
1426 return alerts_out
@@ -1276,6 +1438,7 @@ async def list_alert_by_status(status: str, db: AsyncSession, page: int = 1, pag
1438 selectinload(Alert.assets),
1439 selectinload(Alert.cases),
1440 selectinload(Alert.tags).selectinload(AlertToTag.tag),
1441 + selectinload(Alert.iocs).selectinload(AlertToIoC.ioc),
1442 )
1443 .order_by(order_by)
1444 .offset(offset)
@@ -1288,6 +1451,7 @@ async def list_alert_by_status(status: str, db: AsyncSession, page: int = 1, pag
1451 comments = [CommentBase(**comment.__dict__) for comment in alert.comments]
1452 assets = [AssetBase(**asset.__dict__) for asset in alert.assets]
1453 tags = [AlertTagBase(**alert_to_tag.tag.__dict__) for alert_to_tag in alert.tags]
1454 + iocs = [IoCBase(**alert_to_ioc.ioc.__dict__) for alert_to_ioc in alert.iocs]
1455 alert_out = AlertOut(
1456 id=alert.id,
1457 alert_creation_time=alert.alert_creation_time,
@@ -1301,6 +1465,7 @@ async def list_alert_by_status(status: str, db: AsyncSession, page: int = 1, pag
1465 comments=comments,
1466 assets=assets,
1467 tags=tags,
1468 + iocs=iocs,
1469 )
1470 alerts_out.append(alert_out)
1471 return alerts_out
@@ -1551,6 +1716,7 @@ async def list_alerts_multiple_filters(
1716 asset_name: Optional[str] = None,
1717 status: Optional[str] = None,
1718 tags: Optional[List[str]] = None,
1719 + ioc_value: Optional[str] = None,
1720 page: int = 1,
1721 page_size: int = 25,
1722 order: str = "desc",
@@ -1574,20 +1740,25 @@ async def list_alerts_multiple_filters(
1740 filters.append(Alert.status == status)
1741 if tags:
1742 filters.append(AlertTag.tag.in_(tags))
1743 + if ioc_value:
1744 + filters.append(IoC.value == ioc_value)
1745
1746 # Build the query with dynamic filters
1747 query = (
1748 select(Alert)
1749 .distinct(Alert.id)
1582 - .join(Asset, isouter=True) # Join with Asset table
1583 - .join(AlertToTag, isouter=True) # Join with AlertToTag table
1750 + .join(Asset, Asset.alert_linked == Alert.id, isouter=True) # Join with Asset table
1751 + .join(AlertToTag, AlertToTag.alert_id == Alert.id, isouter=True) # Join with AlertToTag table
1752 .join(AlertTag, AlertToTag.tag_id == AlertTag.id, isouter=True) # Join with AlertTag table
1753 + .join(AlertToIoC, AlertToIoC.alert_id == Alert.id, isouter=True) # Join with AlertToIoC table
1754 + .join(IoC, AlertToIoC.ioc_id == IoC.id, isouter=True) # Join with IoC table
1755 .where(*filters)
1756 .options(
1757 selectinload(Alert.comments),
1758 selectinload(Alert.assets),
1759 selectinload(Alert.cases),
1760 selectinload(Alert.tags).selectinload(AlertToTag.tag),
1761 + selectinload(Alert.iocs).selectinload(AlertToIoC.ioc),
1762 )
1763 .order_by(order_by)
1764 .offset(offset)
@@ -1602,6 +1773,7 @@ async def list_alerts_multiple_filters(
1773 comments = [CommentBase(**comment.__dict__) for comment in alert.comments]
1774 assets = [AssetBase(**asset.__dict__) for asset in alert.assets]
1775 tags = [AlertTagBase(**alert_to_tag.tag.__dict__) for alert_to_tag in alert.tags]
1776 + iocs = [IoCBase(**alert_to_ioc.ioc.__dict__) for alert_to_ioc in alert.iocs]
1777 alert_out = AlertOut(
1778 id=alert.id,
1779 alert_creation_time=alert.alert_creation_time,
@@ -1615,6 +1787,7 @@ async def list_alerts_multiple_filters(
1787 comments=comments,
1788 assets=assets,
1789 tags=tags,
1790 + iocs=iocs,
1791 )
1792 alerts_out.append(alert_out)
1793
backend/app/integrations/modules/routes/huntress.py
+2 -2
@@ -42,12 +42,12 @@ async def get_collect_huntress_data(huntress_request, session, auth_keys):
42 integration="huntress",
43 customer_code=huntress_request.customer_code,
44 graylog_host=await get_connector_attribute(
45 - connector_id=14,
45 + connector_id=10,
46 column_name="connector_url",
47 session=session,
48 ),
49 graylog_port=await get_connector_attribute(
50 - connector_id=14,
50 + connector_id=10,
51 column_name="connector_extra_data",
52 session=session,
53 ),
frontend/package-lock.json
+519 -591
@@ -9,13 +9,13 @@
9 "version": "1.0.0",
10 "dependencies": {
11 "@ajoelp/json-to-formdata": "^1.5.0",
12 - "@f3ve/vue-markdown-it": "^0.2.2",
12 + "@f3ve/vue-markdown-it": "^0.2.3",
13 "@fontsource/jetbrains-mono": "^5.1.1",
14 "@fontsource/lexend": "^5.1.1",
15 "@fontsource/public-sans": "^5.1.1",
16 - "@shikijs/markdown-it": "^1.22.1",
16 + "@shikijs/markdown-it": "^1.22.2",
17 "@tailwindcss/container-queries": "^0.1.1",
18 - "@vueuse/core": "^11.1.0",
18 + "@vueuse/core": "^11.2.0",
19 "axios": "^1.7.7",
20 "bytes": "^3.1.2",
21 "colord": "^2.9.3",
@@ -29,12 +29,12 @@
29 "lodash": "^4.17.21",
30 "mitt": "^3.0.1",
31 "naive-ui": "^2.40.1",
32 - "nanoid": "^5.0.7",
32 + "nanoid": "^5.0.8",
33 "password-validator": "^5.3.0",
34 - "pinia": "^2.2.4",
34 + "pinia": "^2.2.6",
35 "pinia-plugin-persistedstate": "^4.1.2",
36 "secure-ls": "^2.0.0",
37 - "shiki": "^1.22.1",
37 + "shiki": "^1.22.2",
38 "validator": "^13.12.0",
39 "vue": "^3.5.12",
40 "vue-advanced-cropper": "^2.8.9",
@@ -55,8 +55,8 @@
55 "@types/file-saver": "^2.0.7",
56 "@types/fs-extra": "^11.0.4",
57 "@types/jsdom": "^21.1.7",
58 - "@types/lodash": "^4.17.12",
59 - "@types/node": "^22.8.0",
58 + "@types/lodash": "^4.17.13",
59 + "@types/node": "^22.8.7",
60 "@types/validator": "^13.12.2",
61 "@vitejs/plugin-vue": "^5.1.4",
62 "@vitejs/plugin-vue-jsx": "^4.0.1",
@@ -65,7 +65,7 @@
65 "autoprefixer": "^10.4.20",
66 "cypress": "^13.15.1",
67 "depcheck": "^1.4.7",
68 - "eslint": "^9.13.0",
68 + "eslint": "^9.14.0",
69 "flourite": "^1.3.0",
70 "fs-extra": "^11.2.0",
71 "jsdom": "^25.0.1",
@@ -73,26 +73,26 @@
73 "postcss": "^8.4.47",
74 "prettier": "^3.3.3",
75 "prettier-plugin-tailwindcss": "^0.6.8",
76 - "sass": "^1.80.4",
76 + "sass": "^1.80.6",
77 "start-server-and-test": "^2.0.8",
78 "tailwind-config-viewer": "^2.0.4",
79 "tailwindcss": "^3.4.14",
80 - "taze": "^0.17.2",
80 + "taze": "^0.18.0",
81 "type-fest": "^4.26.1",
82 "typescript": "~5.6.3",
83 "unplugin-vue-components": "^0.27.4",
84 "vite": "^5.4.10",
85 "vite-bundle-visualizer": "^1.2.1",
86 - "vite-plugin-vue-devtools": "^7.5.4",
86 + "vite-plugin-vue-devtools": "^7.6.2",
87 "vite-svg-loader": "^5.1.0",
88 - "vitest": "^2.1.3",
89 - "vue-tsc": "^2.1.6"
88 + "vitest": "^2.1.4",
89 + "vue-tsc": "^2.1.10"
90 },
91 "engines": {
92 "node": ">=18.0.0"
93 },
94 "optionalDependencies": {
95 - "@rollup/rollup-linux-x64-gnu": "^4.24.0"
95 + "@rollup/rollup-linux-x64-gnu": "^4.24.4"
96 }
97 },
98 "node_modules/@ajoelp/json-to-formdata": {
@@ -264,6 +264,7 @@
264 "version": "0.7.10",
265 "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz",
266 "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==",
267 + "dev": true,
268 "funding": {
269 "url": "https://github.com/sponsors/antfu"
270 }
@@ -1250,6 +1251,7 @@
1251 "version": "4.4.0",
1252 "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
1253 "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
1254 + "dev": true,
1255 "dependencies": {
1256 "eslint-visitor-keys": "^3.3.0"
1257 },
@@ -1264,6 +1266,7 @@
1266 "version": "3.4.3",
1267 "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
1268 "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
1269 + "dev": true,
1270 "engines": {
1271 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1272 },
@@ -1272,9 +1275,10 @@
1275 }
1276 },
1277 "node_modules/@eslint-community/regexpp": {
1275 - "version": "4.11.1",
1276 - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz",
1277 - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==",
1278 + "version": "4.12.1",
1279 + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
1280 + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
1281 + "dev": true,
1282 "engines": {
1283 "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
1284 }
@@ -1300,6 +1304,7 @@
1304 "version": "0.18.0",
1305 "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz",
1306 "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==",
1307 + "dev": true,
1308 "dependencies": {
1309 "@eslint/object-schema": "^2.1.4",
1310 "debug": "^4.3.1",
@@ -1313,6 +1318,7 @@
1318 "version": "1.1.11",
1319 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1320 "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1321 + "dev": true,
1322 "dependencies": {
1323 "balanced-match": "^1.0.0",
1324 "concat-map": "0.0.1"
@@ -1322,6 +1328,7 @@
1328 "version": "3.1.2",
1329 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1330 "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1331 + "dev": true,
1332 "dependencies": {
1333 "brace-expansion": "^1.1.7"
1334 },
@@ -1333,6 +1340,7 @@
1340 "version": "0.7.0",
1341 "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz",
1342 "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==",
1343 + "dev": true,
1344 "engines": {
1345 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1346 }
@@ -1341,6 +1349,7 @@
1349 "version": "3.1.0",
1350 "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz",
1351 "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==",
1352 + "dev": true,
1353 "dependencies": {
1354 "ajv": "^6.12.4",
1355 "debug": "^4.3.2",
@@ -1362,12 +1371,14 @@
1371 "node_modules/@eslint/eslintrc/node_modules/argparse": {
1372 "version": "2.0.1",
1373 "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
1365 - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
1374 + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
1375 + "dev": true
1376 },
1377 "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
1378 "version": "1.1.11",
1379 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1380 "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1381 + "dev": true,
1382 "dependencies": {
1383 "balanced-match": "^1.0.0",
1384 "concat-map": "0.0.1"
@@ -1377,6 +1388,7 @@
1388 "version": "14.0.0",
1389 "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
1390 "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
1391 + "dev": true,
1392 "engines": {
1393 "node": ">=18"
1394 },
@@ -1388,6 +1400,7 @@
1400 "version": "4.1.0",
1401 "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
1402 "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
1403 + "dev": true,
1404 "dependencies": {
1405 "argparse": "^2.0.1"
1406 },
@@ -1399,6 +1412,7 @@
1412 "version": "3.1.2",
1413 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1414 "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1415 + "dev": true,
1416 "dependencies": {
1417 "brace-expansion": "^1.1.7"
1418 },
@@ -1410,6 +1424,9 @@
1424 "version": "8.57.1",
1425 "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
1426 "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
1427 + "dev": true,
1428 + "optional": true,
1429 + "peer": true,
1430 "engines": {
1431 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1432 }
@@ -1433,6 +1450,7 @@
1450 "version": "2.1.4",
1451 "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz",
1452 "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==",
1453 + "dev": true,
1454 "engines": {
1455 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1456 }
@@ -1441,6 +1459,7 @@
1459 "version": "0.2.1",
1460 "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.1.tgz",
1461 "integrity": "sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==",
1462 + "dev": true,
1463 "dependencies": {
1464 "levn": "^0.4.1"
1465 },
@@ -1448,233 +1467,11 @@
1467 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1468 }
1469 },
1451 - "node_modules/@f3ve/eslint-config": {
1452 - "version": "1.0.6",
1453 - "resolved": "https://registry.npmjs.org/@f3ve/eslint-config/-/eslint-config-1.0.6.tgz",
1454 - "integrity": "sha512-DVLPAVZskaOUY6Gu/1VFaL0gGyY3VhjZBVExZVde2siwwgdwt+8XDSupLll0arKqVv4bqO2fRK21QomN3jy2yg==",
1455 - "funding": [
1456 - {
1457 - "type": "GitHub Sponsors",
1458 - "url": "https://github.com/sponsors/f3ve"
1459 - },
1460 - {
1461 - "type": "Buy me a Coffee",
1462 - "url": "https://www.buymeacoffee.com/f3ve"
1463 - }
1464 - ],
1465 - "dependencies": {
1466 - "@eslint/js": "^8.50.0",
1467 - "@typescript-eslint/eslint-plugin": "^6.7.3",
1468 - "@typescript-eslint/parser": "^6.7.3",
1469 - "@unocss/eslint-config": "^0.56.4",
1470 - "eslint-config-prettier": "^9.0.0",
1471 - "eslint-define-config": "^1.23.0",
1472 - "eslint-plugin-prettier": "^5.0.0",
1473 - "eslint-plugin-vue": "^9.17.0",
1474 - "globals": "^13.22.0",
1475 - "vue-eslint-parser": "^9.3.1"
1476 - },
1477 - "peerDependencies": {
1478 - "eslint": ">=8.0.0"
1479 - }
1480 - },
1481 - "node_modules/@f3ve/eslint-config/node_modules/@typescript-eslint/eslint-plugin": {
1482 - "version": "6.21.0",
1483 - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
1484 - "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==",
1485 - "dependencies": {
1486 - "@eslint-community/regexpp": "^4.5.1",
1487 - "@typescript-eslint/scope-manager": "6.21.0",
1488 - "@typescript-eslint/type-utils": "6.21.0",
1489 - "@typescript-eslint/utils": "6.21.0",
1490 - "@typescript-eslint/visitor-keys": "6.21.0",
1491 - "debug": "^4.3.4",
1492 - "graphemer": "^1.4.0",
1493 - "ignore": "^5.2.4",
1494 - "natural-compare": "^1.4.0",
1495 - "semver": "^7.5.4",
1496 - "ts-api-utils": "^1.0.1"
1497 - },
1498 - "engines": {
1499 - "node": "^16.0.0 || >=18.0.0"
1500 - },
1501 - "funding": {
1502 - "type": "opencollective",
1503 - "url": "https://opencollective.com/typescript-eslint"
1504 - },
1505 - "peerDependencies": {
1506 - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
1507 - "eslint": "^7.0.0 || ^8.0.0"
1508 - },
1509 - "peerDependenciesMeta": {
1510 - "typescript": {
1511 - "optional": true
1512 - }
1513 - }
1514 - },
1515 - "node_modules/@f3ve/eslint-config/node_modules/@typescript-eslint/parser": {
1516 - "version": "6.21.0",
1517 - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz",
1518 - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
1519 - "dependencies": {
1520 - "@typescript-eslint/scope-manager": "6.21.0",
1521 - "@typescript-eslint/types": "6.21.0",
1522 - "@typescript-eslint/typescript-estree": "6.21.0",
1523 - "@typescript-eslint/visitor-keys": "6.21.0",
1524 - "debug": "^4.3.4"
1525 - },
1526 - "engines": {
1527 - "node": "^16.0.0 || >=18.0.0"
1528 - },
1529 - "funding": {
1530 - "type": "opencollective",
1531 - "url": "https://opencollective.com/typescript-eslint"
1532 - },
1533 - "peerDependencies": {
1534 - "eslint": "^7.0.0 || ^8.0.0"
1535 - },
1536 - "peerDependenciesMeta": {
1537 - "typescript": {
1538 - "optional": true
1539 - }
1540 - }
1541 - },
1542 - "node_modules/@f3ve/eslint-config/node_modules/@typescript-eslint/scope-manager": {
1543 - "version": "6.21.0",
1544 - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
1545 - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
1546 - "dependencies": {
1547 - "@typescript-eslint/types": "6.21.0",
1548 - "@typescript-eslint/visitor-keys": "6.21.0"
1549 - },
1550 - "engines": {
1551 - "node": "^16.0.0 || >=18.0.0"
1552 - },
1553 - "funding": {
1554 - "type": "opencollective",
1555 - "url": "https://opencollective.com/typescript-eslint"
1556 - }
1557 - },
1558 - "node_modules/@f3ve/eslint-config/node_modules/@typescript-eslint/type-utils": {
1559 - "version": "6.21.0",
1560 - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz",
1561 - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==",
1562 - "dependencies": {
1563 - "@typescript-eslint/typescript-estree": "6.21.0",
1564 - "@typescript-eslint/utils": "6.21.0",
1565 - "debug": "^4.3.4",
1566 - "ts-api-utils": "^1.0.1"
1567 - },
1568 - "engines": {
1569 - "node": "^16.0.0 || >=18.0.0"
1570 - },
1571 - "funding": {
1572 - "type": "opencollective",
1573 - "url": "https://opencollective.com/typescript-eslint"
1574 - },
1575 - "peerDependencies": {
1576 - "eslint": "^7.0.0 || ^8.0.0"
1577 - },
1578 - "peerDependenciesMeta": {
1579 - "typescript": {
1580 - "optional": true
1581 - }
1582 - }
1583 - },
1584 - "node_modules/@f3ve/eslint-config/node_modules/@typescript-eslint/types": {
1585 - "version": "6.21.0",
1586 - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
1587 - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
1588 - "engines": {
1589 - "node": "^16.0.0 || >=18.0.0"
1590 - },
1591 - "funding": {
1592 - "type": "opencollective",
1593 - "url": "https://opencollective.com/typescript-eslint"
1594 - }
1595 - },
1596 - "node_modules/@f3ve/eslint-config/node_modules/@typescript-eslint/utils": {
1597 - "version": "6.21.0",
1598 - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz",
1599 - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==",
1600 - "dependencies": {
1601 - "@eslint-community/eslint-utils": "^4.4.0",
1602 - "@types/json-schema": "^7.0.12",
1603 - "@types/semver": "^7.5.0",
1604 - "@typescript-eslint/scope-manager": "6.21.0",
1605 - "@typescript-eslint/types": "6.21.0",
1606 - "@typescript-eslint/typescript-estree": "6.21.0",
1607 - "semver": "^7.5.4"
1608 - },
1609 - "engines": {
1610 - "node": "^16.0.0 || >=18.0.0"
1611 - },
1612 - "funding": {
1613 - "type": "opencollective",
1614 - "url": "https://opencollective.com/typescript-eslint"
1615 - },
1616 - "peerDependencies": {
1617 - "eslint": "^7.0.0 || ^8.0.0"
1618 - }
1619 - },
1620 - "node_modules/@f3ve/eslint-config/node_modules/@typescript-eslint/visitor-keys": {
1621 - "version": "6.21.0",
1622 - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
1623 - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
1624 - "dependencies": {
1625 - "@typescript-eslint/types": "6.21.0",
1626 - "eslint-visitor-keys": "^3.4.1"
1627 - },
1628 - "engines": {
1629 - "node": "^16.0.0 || >=18.0.0"
1630 - },
1631 - "funding": {
1632 - "type": "opencollective",
1633 - "url": "https://opencollective.com/typescript-eslint"
1634 - }
1635 - },
1636 - "node_modules/@f3ve/eslint-config/node_modules/eslint-visitor-keys": {
1637 - "version": "3.4.3",
1638 - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
1639 - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
1640 - "engines": {
1641 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1642 - },
1643 - "funding": {
1644 - "url": "https://opencollective.com/eslint"
1645 - }
1646 - },
1647 - "node_modules/@f3ve/eslint-config/node_modules/globals": {
1648 - "version": "13.24.0",
1649 - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
1650 - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
1651 - "dependencies": {
1652 - "type-fest": "^0.20.2"
1653 - },
1654 - "engines": {
1655 - "node": ">=8"
1656 - },
1657 - "funding": {
1658 - "url": "https://github.com/sponsors/sindresorhus"
1659 - }
1660 - },
1661 - "node_modules/@f3ve/eslint-config/node_modules/type-fest": {
1662 - "version": "0.20.2",
1663 - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
1664 - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
1665 - "engines": {
1666 - "node": ">=10"
1667 - },
1668 - "funding": {
1669 - "url": "https://github.com/sponsors/sindresorhus"
1670 - }
1671 - },
1470 "node_modules/@f3ve/vue-markdown-it": {
1673 - "version": "0.2.2",
1674 - "resolved": "https://registry.npmjs.org/@f3ve/vue-markdown-it/-/vue-markdown-it-0.2.2.tgz",
1675 - "integrity": "sha512-0LVoa7bCI+pKuMRp8iap7DNNSVgXH51xkAxFmBWjdY6gd9yXBwD64P0p7o1NSYFUXaQCGR+cfOpsudJY7zjeBg==",
1471 + "version": "0.2.3",
1472 + "resolved": "https://registry.npmjs.org/@f3ve/vue-markdown-it/-/vue-markdown-it-0.2.3.tgz",
1473 + "integrity": "sha512-v0VNd7wb55kwsUUy3n6DLI9+0FYSG0PrCTD3bWuSRo6WS3OHD5wghh/aHzebVdsVkSBXfVpiEUlMA3DrxLs7Lw==",
1474 "dependencies": {
1677 - "@f3ve/eslint-config": "^1.0.6",
1475 "markdown-it": "^14.1.0"
1476 },
1477 "peerDependencies": {
@@ -1712,30 +1509,47 @@
1509 }
1510 },
1511 "node_modules/@humanfs/core": {
1715 - "version": "0.19.0",
1716 - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz",
1717 - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==",
1512 + "version": "0.19.1",
1513 + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
1514 + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
1515 + "dev": true,
1516 "engines": {
1517 "node": ">=18.18.0"
1518 }
1519 },
1520 "node_modules/@humanfs/node": {
1723 - "version": "0.16.5",
1724 - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz",
1725 - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==",
1521 + "version": "0.16.6",
1522 + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
1523 + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
1524 + "dev": true,
1525 "dependencies": {
1727 - "@humanfs/core": "^0.19.0",
1526 + "@humanfs/core": "^0.19.1",
1527 "@humanwhocodes/retry": "^0.3.0"
1528 },
1529 "engines": {
1530 "node": ">=18.18.0"
1531 }
1532 },
1533 + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
1534 + "version": "0.3.1",
1535 + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
1536 + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
1537 + "dev": true,
1538 + "engines": {
1539 + "node": ">=18.18"
1540 + },
1541 + "funding": {
1542 + "type": "github",
1543 + "url": "https://github.com/sponsors/nzakas"
1544 + }
1545 + },
1546 "node_modules/@humanwhocodes/config-array": {
1547 "version": "0.13.0",
1548 "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
1549 "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
1550 "deprecated": "Use @eslint/config-array instead",
1551 + "dev": true,
1552 + "optional": true,
1553 "peer": true,
1554 "dependencies": {
1555 "@humanwhocodes/object-schema": "^2.0.3",
@@ -1750,6 +1564,8 @@
1564 "version": "1.1.11",
1565 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1566 "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1567 + "dev": true,
1568 + "optional": true,
1569 "peer": true,
1570 "dependencies": {
1571 "balanced-match": "^1.0.0",
@@ -1760,6 +1576,8 @@
1576 "version": "3.1.2",
1577 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1578 "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1579 + "dev": true,
1580 + "optional": true,
1581 "peer": true,
1582 "dependencies": {
1583 "brace-expansion": "^1.1.7"
@@ -1772,6 +1590,7 @@
1590 "version": "1.0.1",
1591 "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
1592 "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
1593 + "dev": true,
1594 "engines": {
1595 "node": ">=12.22"
1596 },
@@ -1785,12 +1604,15 @@
1604 "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
1605 "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
1606 "deprecated": "Use @eslint/object-schema instead",
1607 + "dev": true,
1608 + "optional": true,
1609 "peer": true
1610 },
1611 "node_modules/@humanwhocodes/retry": {
1791 - "version": "0.3.1",
1792 - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
1793 - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
1612 + "version": "0.4.0",
1613 + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.0.tgz",
1614 + "integrity": "sha512-xnRgu9DxZbkWak/te3fcytNyp8MTbuiZIaueg2rgEvBuN55n04nwLYLU9TX/VVlusc9L2ZNXi99nUFNkHXtr5g==",
1615 + "dev": true,
1616 "engines": {
1617 "node": ">=18.18"
1618 },
@@ -2082,6 +1904,7 @@
1904 "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz",
1905 "integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==",
1906 "dev": true,
1907 + "optional": true,
1908 "dependencies": {
1909 "detect-libc": "^1.0.3",
1910 "is-glob": "^4.0.3",
@@ -2363,6 +2186,7 @@
2186 "version": "0.1.1",
2187 "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
2188 "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
2189 + "dev": true,
2190 "engines": {
2191 "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
2192 },
@@ -2541,9 +2365,9 @@
2365 ]
2366 },
2367 "node_modules/@rollup/rollup-linux-x64-gnu": {
2544 - "version": "4.24.0",
2545 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz",
2546 - "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==",
2368 + "version": "4.24.4",
2369 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.4.tgz",
2370 + "integrity": "sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA==",
2371 "cpu": [
2372 "x64"
2373 ],
@@ -2605,50 +2429,50 @@
2429 ]
2430 },
2431 "node_modules/@shikijs/core": {
2608 - "version": "1.22.1",
2609 - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.1.tgz",
2610 - "integrity": "sha512-bqAhT/Ri5ixV4oYsvJNH8UJjpjbINWlWyXY6tBTsP4OmD6XnFv43nRJ+lTdxd2rmG5pgam/x+zGR6kLRXrpEKA==",
2432 + "version": "1.22.2",
2433 + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.2.tgz",
2434 + "integrity": "sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==",
2435 "dependencies": {
2612 - "@shikijs/engine-javascript": "1.22.1",
2613 - "@shikijs/engine-oniguruma": "1.22.1",
2614 - "@shikijs/types": "1.22.1",
2436 + "@shikijs/engine-javascript": "1.22.2",
2437 + "@shikijs/engine-oniguruma": "1.22.2",
2438 + "@shikijs/types": "1.22.2",
2439 "@shikijs/vscode-textmate": "^9.3.0",
2440 "@types/hast": "^3.0.4",
2441 "hast-util-to-html": "^9.0.3"
2442 }
2443 },
2444 "node_modules/@shikijs/engine-javascript": {
2621 - "version": "1.22.1",
2622 - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.1.tgz",
2623 - "integrity": "sha512-540pyoy0LWe4jj2BVbgELwOFu1uFvRI7lg4hdsExrSXA9x7gqfzZ/Nnh4RfX86aDAgJ647gx4TCmRwACbnQSvw==",
2445 + "version": "1.22.2",
2446 + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.2.tgz",
2447 + "integrity": "sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==",
2448 "dependencies": {
2625 - "@shikijs/types": "1.22.1",
2449 + "@shikijs/types": "1.22.2",
2450 "@shikijs/vscode-textmate": "^9.3.0",
2451 "oniguruma-to-js": "0.4.3"
2452 }
2453 },
2454 "node_modules/@shikijs/engine-oniguruma": {
2631 - "version": "1.22.1",
2632 - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.1.tgz",
2633 - "integrity": "sha512-L+1Vmd+a2kk8HtogUFymQS6BjUfJnzcWoUp1BUgxoDiklbKSMvrsMuLZGevTOP1m0rEjgnC5MsDmsr8lX1lC+Q==",
2455 + "version": "1.22.2",
2456 + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.2.tgz",
2457 + "integrity": "sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==",
2458 "dependencies": {
2635 - "@shikijs/types": "1.22.1",
2459 + "@shikijs/types": "1.22.2",
2460 "@shikijs/vscode-textmate": "^9.3.0"
2461 }
2462 },
2463 "node_modules/@shikijs/markdown-it": {
2640 - "version": "1.22.1",
2641 - "resolved": "https://registry.npmjs.org/@shikijs/markdown-it/-/markdown-it-1.22.1.tgz",
2642 - "integrity": "sha512-OlzsxMrICd/wrwXXEnA+gpcvBh9zbRCxtC6OssjVzBcMIIhc6Uz64KnWFW02T6G7Ac6FRsl8CNIIWIDVIlhU0w==",
2464 + "version": "1.22.2",
2465 + "resolved": "https://registry.npmjs.org/@shikijs/markdown-it/-/markdown-it-1.22.2.tgz",
2466 + "integrity": "sha512-PgNY3s350UijOWLaoeAXHcYUeDqJKM2De9t8DMkBnQHi6tibo4eoV6sfnsULiJu47TwD1d4VG2YsH0Lxp/VM7A==",
2467 "dependencies": {
2468 "markdown-it": "^14.1.0",
2645 - "shiki": "1.22.1"
2469 + "shiki": "1.22.2"
2470 }
2471 },
2472 "node_modules/@shikijs/types": {
2649 - "version": "1.22.1",
2650 - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.1.tgz",
2651 - "integrity": "sha512-+45f8mu/Hxqs6Kyhfm98Nld5n7Q7lwhjU8UtdQwrOPs7BnM4VAb929O3IQ2ce+4D7SlNFlZGd8CnKRSnwbQreQ==",
2473 + "version": "1.22.2",
2474 + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.2.tgz",
2475 + "integrity": "sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==",
2476 "dependencies": {
2477 "@shikijs/vscode-textmate": "^9.3.0",
2478 "@types/hast": "^3.0.4"
@@ -2791,7 +2615,8 @@
2615 "node_modules/@types/json-schema": {
2616 "version": "7.0.15",
2617 "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
2794 - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
2618 + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
2619 + "dev": true
2620 },
2621 "node_modules/@types/jsonfile": {
2622 "version": "6.1.4",
@@ -2808,9 +2633,9 @@
2633 "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ=="
2634 },
2635 "node_modules/@types/lodash": {
2811 - "version": "4.17.12",
2812 - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.12.tgz",
2813 - "integrity": "sha512-sviUmCE8AYdaF/KIHLDJBQgeYzPBI0vf/17NaYehBJfYD1j6/L95Slh07NlyK2iNyBNaEkb3En2jRt+a8y3xZQ=="
2636 + "version": "4.17.13",
2637 + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz",
2638 + "integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg=="
2639 },
2640 "node_modules/@types/lodash-es": {
2641 "version": "4.17.12",
@@ -2841,9 +2666,9 @@
2666 "dev": true
2667 },
2668 "node_modules/@types/node": {
2844 - "version": "22.8.0",
2845 - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.0.tgz",
2846 - "integrity": "sha512-84rafSBHC/z1i1E3p0cJwKA+CfYDNSXX9WSZBRopjIzLET8oNt6ht2tei4C7izwDeEiLLfdeSVBv1egOH916hg==",
2669 + "version": "22.8.7",
2670 + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.7.tgz",
2671 + "integrity": "sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==",
2672 "dev": true,
2673 "dependencies": {
2674 "undici-types": "~6.19.8"
@@ -2864,7 +2689,10 @@
2689 "node_modules/@types/semver": {
2690 "version": "7.5.8",
2691 "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
2867 - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ=="
2692 + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
2693 + "dev": true,
2694 + "optional": true,
2695 + "peer": true
2696 },
2697 "node_modules/@types/sinonjs__fake-timers": {
2698 "version": "8.1.1",
@@ -3016,6 +2844,7 @@
2844 "version": "8.11.0",
2845 "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz",
2846 "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==",
2847 + "dev": true,
2848 "engines": {
2849 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2850 },
@@ -3025,12 +2854,13 @@
2854 }
2855 },
2856 "node_modules/@typescript-eslint/typescript-estree": {
3028 - "version": "8.11.0",
3029 - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz",
3030 - "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==",
2857 + "version": "8.12.2",
2858 + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz",
2859 + "integrity": "sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==",
2860 + "dev": true,
2861 "dependencies": {
3032 - "@typescript-eslint/types": "8.11.0",
3033 - "@typescript-eslint/visitor-keys": "8.11.0",
2862 + "@typescript-eslint/types": "8.12.2",
2863 + "@typescript-eslint/visitor-keys": "8.12.2",
2864 "debug": "^4.3.4",
2865 "fast-glob": "^3.3.2",
2866 "is-glob": "^4.0.3",
@@ -3051,6 +2881,48 @@
2881 }
2882 }
2883 },
2884 + "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/types": {
2885 + "version": "8.12.2",
2886 + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.2.tgz",
2887 + "integrity": "sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==",
2888 + "dev": true,
2889 + "engines": {
2890 + "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2891 + },
2892 + "funding": {
2893 + "type": "opencollective",
2894 + "url": "https://opencollective.com/typescript-eslint"
2895 + }
2896 + },
2897 + "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/visitor-keys": {
2898 + "version": "8.12.2",
2899 + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz",
2900 + "integrity": "sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==",
2901 + "dev": true,
2902 + "dependencies": {
2903 + "@typescript-eslint/types": "8.12.2",
2904 + "eslint-visitor-keys": "^3.4.3"
2905 + },
2906 + "engines": {
2907 + "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2908 + },
2909 + "funding": {
2910 + "type": "opencollective",
2911 + "url": "https://opencollective.com/typescript-eslint"
2912 + }
2913 + },
2914 + "node_modules/@typescript-eslint/typescript-estree/node_modules/eslint-visitor-keys": {
2915 + "version": "3.4.3",
2916 + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
2917 + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
2918 + "dev": true,
2919 + "engines": {
2920 + "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
2921 + },
2922 + "funding": {
2923 + "url": "https://opencollective.com/eslint"
2924 + }
2925 + },
2926 "node_modules/@typescript-eslint/utils": {
2927 "version": "8.11.0",
2928 "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz",
@@ -3077,6 +2949,7 @@
2949 "version": "8.11.0",
2950 "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz",
2951 "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==",
2952 + "dev": true,
2953 "dependencies": {
2954 "@typescript-eslint/types": "8.11.0",
2955 "eslint-visitor-keys": "^3.4.3"
@@ -3093,6 +2966,7 @@
2966 "version": "3.4.3",
2967 "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
2968 "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
2969 + "dev": true,
2970 "engines": {
2971 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
2972 },
@@ -3109,6 +2983,9 @@
2983 "version": "0.56.5",
2984 "resolved": "https://registry.npmjs.org/@unocss/config/-/config-0.56.5.tgz",
2985 "integrity": "sha512-rscnFIYgUlN/0hXHdhANyjFcDjDutt3JO0ZRITdNLzoglh7GVNiDTURBJwUZejF/vGJ7IkMd3qOdNhPFuRY1Bg==",
2986 + "dev": true,
2987 + "optional": true,
2988 + "peer": true,
2989 "dependencies": {
2990 "@unocss/core": "0.56.5",
2991 "unconfig": "^0.3.10"
@@ -3124,20 +3001,9 @@
3001 "version": "0.56.5",
3002 "resolved": "https://registry.npmjs.org/@unocss/core/-/core-0.56.5.tgz",
3003 "integrity": "sha512-fx5VhOjSHn0HdV2D34pEwFMAHJcJQRTCp1xEE4GzxY1irXzaa+m2aYf5PZjmDxehiOC16IH7TO9FOWANXk1E0w==",
3127 - "funding": {
3128 - "url": "https://github.com/sponsors/antfu"
3129 - }
3130 - },
3131 - "node_modules/@unocss/eslint-config": {
3132 - "version": "0.56.5",
3133 - "resolved": "https://registry.npmjs.org/@unocss/eslint-config/-/eslint-config-0.56.5.tgz",
3134 - "integrity": "sha512-UP7EBTl4ORRO0yqptW7oUWxM0qNh1Nk+z4rufC0C2kI8vKc8yab+sWvlBSC8DeX3kzR7uJxvtUsHGcBcoqZujg==",
3135 - "dependencies": {
3136 - "@unocss/eslint-plugin": "0.56.5"
3137 - },
3138 - "engines": {
3139 - "node": ">=14"
3140 - },
3004 + "dev": true,
3005 + "optional": true,
3006 + "peer": true,
3007 "funding": {
3008 "url": "https://github.com/sponsors/antfu"
3009 }
@@ -3146,6 +3012,9 @@
3012 "version": "0.56.5",
3013 "resolved": "https://registry.npmjs.org/@unocss/eslint-plugin/-/eslint-plugin-0.56.5.tgz",
3014 "integrity": "sha512-nMVw/kc0sYU5i8UBU1rEahzKhZRPTUjCztpPzo2KUKFKLBPAbTv0gJAOmU/n2kV3YiGk5Tl6jmShxu1MHjk5rA==",
3015 + "dev": true,
3016 + "optional": true,
3017 + "peer": true,
3018 "dependencies": {
3019 "@typescript-eslint/utils": "^6.7.3",
3020 "@unocss/config": "0.56.5",
@@ -3164,6 +3033,8 @@
3033 "version": "2.1.4",
3034 "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
3035 "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
3036 + "dev": true,
3037 + "optional": true,
3038 "peer": true,
3039 "dependencies": {
3040 "ajv": "^6.12.4",
@@ -3187,6 +3058,9 @@
3058 "version": "6.21.0",
3059 "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
3060 "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
3061 + "dev": true,
3062 + "optional": true,
3063 + "peer": true,
3064 "dependencies": {
3065 "@typescript-eslint/types": "6.21.0",
3066 "@typescript-eslint/visitor-keys": "6.21.0"
@@ -3203,6 +3077,9 @@
3077 "version": "6.21.0",
3078 "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
3079 "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
3080 + "dev": true,
3081 + "optional": true,
3082 + "peer": true,
3083 "engines": {
3084 "node": "^16.0.0 || >=18.0.0"
3085 },
@@ -3215,6 +3092,9 @@
3092 "version": "6.21.0",
3093 "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz",
3094 "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==",
3095 + "dev": true,
3096 + "optional": true,
3097 + "peer": true,
3098 "dependencies": {
3099 "@eslint-community/eslint-utils": "^4.4.0",
3100 "@types/json-schema": "^7.0.12",
@@ -3239,6 +3119,9 @@
3119 "version": "6.21.0",
3120 "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
3121 "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
3122 + "dev": true,
3123 + "optional": true,
3124 + "peer": true,
3125 "dependencies": {
3126 "@typescript-eslint/types": "6.21.0",
3127 "eslint-visitor-keys": "^3.4.1"
@@ -3255,12 +3138,16 @@
3138 "version": "2.0.1",
3139 "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
3140 "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
3141 + "dev": true,
3142 + "optional": true,
3143 "peer": true
3144 },
3145 "node_modules/@unocss/eslint-plugin/node_modules/brace-expansion": {
3146 "version": "1.1.11",
3147 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
3148 "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
3149 + "dev": true,
3150 + "optional": true,
3151 "peer": true,
3152 "dependencies": {
3153 "balanced-match": "^1.0.0",
@@ -3272,6 +3159,8 @@
3159 "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
3160 "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
3161 "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
3162 + "dev": true,
3163 + "optional": true,
3164 "peer": true,
3165 "dependencies": {
3166 "@eslint-community/eslint-utils": "^4.2.0",
@@ -3327,6 +3216,8 @@
3216 "version": "7.2.2",
3217 "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
3218 "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
3219 + "dev": true,
3220 + "optional": true,
3221 "peer": true,
3222 "dependencies": {
3223 "esrecurse": "^4.3.0",
@@ -3343,6 +3234,9 @@
3234 "version": "3.4.3",
3235 "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
3236 "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
3237 + "dev": true,
3238 + "optional": true,
3239 + "peer": true,
3240 "engines": {
3241 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
3242 },
@@ -3354,6 +3248,8 @@
3248 "version": "9.6.1",
3249 "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
3250 "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
3251 + "dev": true,
3252 + "optional": true,
3253 "peer": true,
3254 "dependencies": {
3255 "acorn": "^8.9.0",
@@ -3371,6 +3267,8 @@
3267 "version": "6.0.1",
3268 "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
3269 "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
3270 + "dev": true,
3271 + "optional": true,
3272 "peer": true,
3273 "dependencies": {
3274 "flat-cache": "^3.0.4"
@@ -3383,6 +3281,8 @@
3281 "version": "3.2.0",
3282 "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
3283 "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
3284 + "dev": true,
3285 + "optional": true,
3286 "peer": true,
3287 "dependencies": {
3288 "flatted": "^3.2.9",
@@ -3397,6 +3297,8 @@
3297 "version": "13.24.0",
3298 "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
3299 "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
3300 + "dev": true,
3301 + "optional": true,
3302 "peer": true,
3303 "dependencies": {
3304 "type-fest": "^0.20.2"
@@ -3412,6 +3314,8 @@
3314 "version": "4.1.0",
3315 "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
3316 "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
3317 + "dev": true,
3318 + "optional": true,
3319 "peer": true,
3320 "dependencies": {
3321 "argparse": "^2.0.1"
@@ -3424,6 +3328,8 @@
3328 "version": "3.1.2",
3329 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
3330 "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
3331 + "dev": true,
3332 + "optional": true,
3333 "peer": true,
3334 "dependencies": {
3335 "brace-expansion": "^1.1.7"
@@ -3436,6 +3342,8 @@
3342 "version": "0.20.2",
3343 "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
3344 "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
3345 + "dev": true,
3346 + "optional": true,
3347 "peer": true,
3348 "engines": {
3349 "node": ">=10"
@@ -3496,14 +3404,14 @@
3404 }
3405 },
3406 "node_modules/@vitest/expect": {
3499 - "version": "2.1.3",
3500 - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz",
3501 - "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==",
3407 + "version": "2.1.4",
3408 + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.4.tgz",
3409 + "integrity": "sha512-DOETT0Oh1avie/D/o2sgMHGrzYUFFo3zqESB2Hn70z6QB1HrS2IQ9z5DfyTqU8sg4Bpu13zZe9V4+UTNQlUeQA==",
3410 "dev": true,
3411 "dependencies": {
3504 - "@vitest/spy": "2.1.3",
3505 - "@vitest/utils": "2.1.3",
3506 - "chai": "^5.1.1",
3412 + "@vitest/spy": "2.1.4",
3413 + "@vitest/utils": "2.1.4",
3414 + "chai": "^5.1.2",
3415 "tinyrainbow": "^1.2.0"
3416 },
3417 "funding": {
@@ -3511,21 +3419,20 @@
3419 }
3420 },
3421 "node_modules/@vitest/mocker": {
3514 - "version": "2.1.3",
3515 - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz",
3516 - "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==",
3422 + "version": "2.1.4",
3423 + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.4.tgz",
3424 + "integrity": "sha512-Ky/O1Lc0QBbutJdW0rqLeFNbuLEyS+mIPiNdlVlp2/yhJ0SbyYqObS5IHdhferJud8MbbwMnexg4jordE5cCoQ==",
3425 "dev": true,
3426 "dependencies": {
3519 - "@vitest/spy": "2.1.3",
3427 + "@vitest/spy": "2.1.4",
3428 "estree-walker": "^3.0.3",
3521 - "magic-string": "^0.30.11"
3429 + "magic-string": "^0.30.12"
3430 },
3431 "funding": {
3432 "url": "https://opencollective.com/vitest"
3433 },
3434 "peerDependencies": {
3527 - "@vitest/spy": "2.1.3",
3528 - "msw": "^2.3.5",
3435 + "msw": "^2.4.9",
3436 "vite": "^5.0.0"
3437 },
3438 "peerDependenciesMeta": {
@@ -3547,9 +3454,9 @@
3454 }
3455 },
3456 "node_modules/@vitest/pretty-format": {
3550 - "version": "2.1.3",
3551 - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz",
3552 - "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==",
3457 + "version": "2.1.4",
3458 + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.4.tgz",
3459 + "integrity": "sha512-L95zIAkEuTDbUX1IsjRl+vyBSLh3PwLLgKpghl37aCK9Jvw0iP+wKwIFhfjdUtA2myLgjrG6VU6JCFLv8q/3Ww==",
3460 "dev": true,
3461 "dependencies": {
3462 "tinyrainbow": "^1.2.0"
@@ -3559,12 +3466,12 @@
3466 }
3467 },
3468 "node_modules/@vitest/runner": {
3562 - "version": "2.1.3",
3563 - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz",
3564 - "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==",
3469 + "version": "2.1.4",
3470 + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.4.tgz",
3471 + "integrity": "sha512-sKRautINI9XICAMl2bjxQM8VfCMTB0EbsBc/EDFA57V6UQevEKY/TOPOF5nzcvCALltiLfXWbq4MaAwWx/YxIA==",
3472 "dev": true,
3473 "dependencies": {
3567 - "@vitest/utils": "2.1.3",
3474 + "@vitest/utils": "2.1.4",
3475 "pathe": "^1.1.2"
3476 },
3477 "funding": {
@@ -3572,13 +3479,13 @@
3479 }
3480 },
3481 "node_modules/@vitest/snapshot": {
3575 - "version": "2.1.3",
3576 - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz",
3577 - "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==",
3482 + "version": "2.1.4",
3483 + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.4.tgz",
3484 + "integrity": "sha512-3Kab14fn/5QZRog5BPj6Rs8dc4B+mim27XaKWFWHWA87R56AKjHTGcBFKpvZKDzC4u5Wd0w/qKsUIio3KzWW4Q==",
3485 "dev": true,
3486 "dependencies": {
3580 - "@vitest/pretty-format": "2.1.3",
3581 - "magic-string": "^0.30.11",
3487 + "@vitest/pretty-format": "2.1.4",
3488 + "magic-string": "^0.30.12",
3489 "pathe": "^1.1.2"
3490 },
3491 "funding": {
@@ -3586,25 +3493,25 @@
3493 }
3494 },
3495 "node_modules/@vitest/spy": {
3589 - "version": "2.1.3",
3590 - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz",
3591 - "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==",
3496 + "version": "2.1.4",
3497 + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.4.tgz",
3498 + "integrity": "sha512-4JOxa+UAizJgpZfaCPKK2smq9d8mmjZVPMt2kOsg/R8QkoRzydHH1qHxIYNvr1zlEaFj4SXiaaJWxq/LPLKaLg==",
3499 "dev": true,
3500 "dependencies": {
3594 - "tinyspy": "^3.0.0"
3501 + "tinyspy": "^3.0.2"
3502 },
3503 "funding": {
3504 "url": "https://opencollective.com/vitest"
3505 }
3506 },
3507 "node_modules/@vitest/utils": {
3601 - "version": "2.1.3",
3602 - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz",
3603 - "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==",
3508 + "version": "2.1.4",
3509 + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.4.tgz",
3510 + "integrity": "sha512-MXDnZn0Awl2S86PSNIim5PWXgIAx8CIkzu35mBdSApUip6RFOGXBCf3YFyeEu8n1IHk4bWD46DeYFu9mQlFIRg==",
3511 "dev": true,
3512 "dependencies": {
3606 - "@vitest/pretty-format": "2.1.3",
3607 - "loupe": "^3.1.1",
3513 + "@vitest/pretty-format": "2.1.4",
3514 + "loupe": "^3.1.2",
3515 "tinyrainbow": "^1.2.0"
3516 },
3517 "funding": {
@@ -3612,27 +3519,27 @@
3519 }
3520 },
3521 "node_modules/@volar/language-core": {
3615 - "version": "2.4.7",
3616 - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.7.tgz",
3617 - "integrity": "sha512-G/EB0vkArVB04F8DVBf30AlRK/QAOx63CzsuKKuda2ZIJamQlv4t6gEJrFVmYF560kbslFtaAJcmn8cyg7QmLA==",
3522 + "version": "2.4.8",
3523 + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.8.tgz",
3524 + "integrity": "sha512-K/GxMOXGq997bO00cdFhTNuR85xPxj0BEEAy+BaqqayTmy9Tmhfgmq2wpJcVspRhcwfgPoE2/mEJa26emUhG/g==",
3525 "dev": true,
3526 "dependencies": {
3620 - "@volar/source-map": "2.4.7"
3527 + "@volar/source-map": "2.4.8"
3528 }
3529 },
3530 "node_modules/@volar/source-map": {
3624 - "version": "2.4.7",
3625 - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.7.tgz",
3626 - "integrity": "sha512-c+7IJrD4mht1s8FLlCf6dAUC1aTUY9leKeLosfUiuMxavcG/sY3IPBiD1rdLL5qrhzYVmUWRGxhWvJeyYa/bsQ==",
3531 + "version": "2.4.8",
3532 + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.8.tgz",
3533 + "integrity": "sha512-jeWJBkC/WivdelMwxKkpFL811uH/jJ1kVxa+c7OvG48DXc3VrP7pplSWPP2W1dLMqBxD+awRlg55FQQfiup4cA==",
3534 "dev": true
3535 },
3536 "node_modules/@volar/typescript": {
3630 - "version": "2.4.7",
3631 - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.7.tgz",
3632 - "integrity": "sha512-sp3mFLmMtXY47S8GrMwFnwjGiW7aVtCLMAwnePRJA4P7CfSkrRj2DjoSxl//0pt+KR7oGG/48T2q413b8TvPbg==",
3537 + "version": "2.4.8",
3538 + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.8.tgz",
3539 + "integrity": "sha512-6xkIYJ5xxghVBhVywMoPMidDDAFT1OoQeXwa27HSgJ6AiIKRe61RXLoik+14Z7r0JvnblXVsjsRLmCr42SGzqg==",
3540 "dev": true,
3541 "dependencies": {
3635 - "@volar/language-core": "2.4.7",
3542 + "@volar/language-core": "2.4.8",
3543 "path-browserify": "^1.0.1",
3544 "vscode-uri": "^3.0.8"
3545 }
@@ -3747,13 +3654,13 @@
3654 "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
3655 },
3656 "node_modules/@vue/devtools-core": {
3750 - "version": "7.5.4",
3751 - "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-7.5.4.tgz",
3752 - "integrity": "sha512-igB2iUKsCUrXkp0wKLn3n5X8jz3AgXWk7if0QpLu3Do16QmlTO0e+/VvTpX0ZbLMh8OOAxDKyfPvJMMO/4QJ5w==",
3657 + "version": "7.6.2",
3658 + "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-7.6.2.tgz",
3659 + "integrity": "sha512-hJfjNR3ai94Mb6i0PB42kxUPkPreS6Dl07FUaHAcw+umtkUX55jTXe7+mhsHx9NI6NFT+1WMFREIy8O81KLYyA==",
3660 "dev": true,
3661 "dependencies": {
3755 - "@vue/devtools-kit": "^7.5.4",
3756 - "@vue/devtools-shared": "^7.5.4",
3662 + "@vue/devtools-kit": "^7.6.2",
3663 + "@vue/devtools-shared": "^7.6.2",
3664 "mitt": "^3.0.1",
3665 "nanoid": "^3.3.4",
3666 "pathe": "^1.1.2",
@@ -3782,12 +3689,12 @@
3689 }
3690 },
3691 "node_modules/@vue/devtools-kit": {
3785 - "version": "7.5.4",
3786 - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.5.4.tgz",
3787 - "integrity": "sha512-0i7WFgc1B2TL52tstn82zlb9opSA0aIiHfkUYFXtZb8CIpmlFMTkHtgwVl6PMWNBj3LNhYou1YJCLpCYvJYYoA==",
3692 + "version": "7.6.2",
3693 + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.6.2.tgz",
3694 + "integrity": "sha512-k61BxHRmcTtIQZFouF9QWt9nCCNtSdw12lhg8VNtHq5/XOBGD+ewiK27a40UJ8UPYoCJvi80hbvbYr5E/Zeu1g==",
3695 "dev": true,
3696 "dependencies": {
3790 - "@vue/devtools-shared": "^7.5.4",
3697 + "@vue/devtools-shared": "^7.6.2",
3698 "birpc": "^0.2.19",
3699 "hookable": "^5.5.3",
3700 "mitt": "^3.0.1",
@@ -3797,25 +3704,25 @@
3704 }
3705 },
3706 "node_modules/@vue/devtools-shared": {
3800 - "version": "7.5.4",
3801 - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.5.4.tgz",
3802 - "integrity": "sha512-dwuq4YmwTyLc7eBOqX63s3JB8il7qnKsNgENglSMkUPwiItHkVAYYfPESN1rxSdYkl1RCux1l5TBidYqfUDNAA==",
3707 + "version": "7.6.2",
3708 + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.6.2.tgz",
3709 + "integrity": "sha512-lcjyJ7hCC0W0kNwnCGMLVTMvDLoZgjcq9BvboPgS+6jQyDul7fpzRSKTGtGhCHoxrDox7qBAKGbAl2Rcf7GE1A==",
3710 "dev": true,
3711 "dependencies": {
3712 "rfdc": "^1.4.1"
3713 }
3714 },
3715 "node_modules/@vue/language-core": {
3809 - "version": "2.1.6",
3810 - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.1.6.tgz",
3811 - "integrity": "sha512-MW569cSky9R/ooKMh6xa2g1D0AtRKbL56k83dzus/bx//RDJk24RHWkMzbAlXjMdDNyxAaagKPRquBIxkxlCkg==",
3716 + "version": "2.1.10",
3717 + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.1.10.tgz",
3718 + "integrity": "sha512-DAI289d0K3AB5TUG3xDp9OuQ71CnrujQwJrQnfuZDwo6eGNf0UoRlPuaVNO+Zrn65PC3j0oB2i7mNmVPggeGeQ==",
3719 "dev": true,
3720 "dependencies": {
3814 - "@volar/language-core": "~2.4.1",
3815 - "@vue/compiler-dom": "^3.4.0",
3721 + "@volar/language-core": "~2.4.8",
3722 + "@vue/compiler-dom": "^3.5.0",
3723 "@vue/compiler-vue2": "^2.7.16",
3817 - "@vue/shared": "^3.4.0",
3818 - "computeds": "^0.0.1",
3724 + "@vue/shared": "^3.5.0",
3725 + "alien-signals": "^0.2.0",
3726 "minimatch": "^9.0.3",
3727 "muggle-string": "^0.4.1",
3728 "path-browserify": "^1.0.1"
@@ -3891,13 +3798,13 @@
3798 "dev": true
3799 },
3800 "node_modules/@vueuse/core": {
3894 - "version": "11.1.0",
3895 - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-11.1.0.tgz",
3896 - "integrity": "sha512-P6dk79QYA6sKQnghrUz/1tHi0n9mrb/iO1WTMk/ElLmTyNqgDeSZ3wcDf6fRBGzRJbeG1dxzEOvLENMjr+E3fg==",
3801 + "version": "11.2.0",
3802 + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-11.2.0.tgz",
3803 + "integrity": "sha512-JIUwRcOqOWzcdu1dGlfW04kaJhW3EXnnjJJfLTtddJanymTL7lF1C0+dVVZ/siLfc73mWn+cGP1PE1PKPruRSA==",
3804 "dependencies": {
3805 "@types/web-bluetooth": "^0.0.20",
3899 - "@vueuse/metadata": "11.1.0",
3900 - "@vueuse/shared": "11.1.0",
3806 + "@vueuse/metadata": "11.2.0",
3807 + "@vueuse/shared": "11.2.0",
3808 "vue-demi": ">=0.14.10"
3809 },
3810 "funding": {
@@ -3930,17 +3837,17 @@
3837 }
3838 },
3839 "node_modules/@vueuse/metadata": {
3933 - "version": "11.1.0",
3934 - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-11.1.0.tgz",
3935 - "integrity": "sha512-l9Q502TBTaPYGanl1G+hPgd3QX5s4CGnpXriVBR5fEZ/goI6fvDaVmIl3Td8oKFurOxTmbXvBPSsgrd6eu6HYg==",
3840 + "version": "11.2.0",
3841 + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-11.2.0.tgz",
3842 + "integrity": "sha512-L0ZmtRmNx+ZW95DmrgD6vn484gSpVeRbgpWevFKXwqqQxW9hnSi2Ppuh2BzMjnbv4aJRiIw8tQatXT9uOB23dQ==",
3843 "funding": {
3844 "url": "https://github.com/sponsors/antfu"
3845 }
3846 },
3847 "node_modules/@vueuse/shared": {
3941 - "version": "11.1.0",
3942 - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-11.1.0.tgz",
3943 - "integrity": "sha512-YUtIpY122q7osj+zsNMFAfMTubGz0sn5QzE5gPzAIiCmtt2ha3uQUY1+JPyL4gRCTsLPX82Y9brNbo/aqlA91w==",
3848 + "version": "11.2.0",
3849 + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-11.2.0.tgz",
3850 + "integrity": "sha512-VxFjie0EanOudYSgMErxXfq6fo8vhr5ICI+BuE3I9FnX7ePllEsVrRQ7O6Q1TLgApeLuPKcHQxAXpP+KnlrJsg==",
3851 "dependencies": {
3852 "vue-demi": ">=0.14.10"
3853 },
@@ -4002,9 +3909,9 @@
3909 }
3910 },
3911 "node_modules/acorn": {
4005 - "version": "8.13.0",
4006 - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz",
4007 - "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==",
3912 + "version": "8.14.0",
3913 + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
3914 + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
3915 "bin": {
3916 "acorn": "bin/acorn"
3917 },
@@ -4016,6 +3923,7 @@
3923 "version": "5.3.2",
3924 "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
3925 "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
3926 + "dev": true,
3927 "peerDependencies": {
3928 "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
3929 }
@@ -4049,6 +3957,7 @@
3957 "version": "6.12.6",
3958 "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
3959 "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
3960 + "dev": true,
3961 "dependencies": {
3962 "fast-deep-equal": "^3.1.1",
3963 "fast-json-stable-stringify": "^2.0.0",
@@ -4060,6 +3969,12 @@
3969 "url": "https://github.com/sponsors/epoberezkin"
3970 }
3971 },
3972 + "node_modules/alien-signals": {
3973 + "version": "0.2.0",
3974 + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-0.2.0.tgz",
3975 + "integrity": "sha512-StlonZhBBrsPPwrDjiPAiVTf/rolxffLxVPT60Qv/t88BZ81BvUVzHgGqEFvJ1ii8HXtm1+zU2Icr59tfWEcag==",
3976 + "dev": true
3977 + },
3978 "node_modules/ansi-colors": {
3979 "version": "4.1.3",
3980 "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
@@ -4423,7 +4338,8 @@
4338 "node_modules/boolbase": {
4339 "version": "1.0.0",
4340 "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
4426 - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
4341 + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
4342 + "dev": true
4343 },
4344 "node_modules/brace-expansion": {
4345 "version": "2.0.1",
@@ -4648,6 +4564,7 @@
4564 "version": "3.1.0",
4565 "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
4566 "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
4567 + "dev": true,
4568 "engines": {
4569 "node": ">=6"
4570 }
@@ -4726,6 +4643,7 @@
4643 "version": "4.1.2",
4644 "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
4645 "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
4646 + "dev": true,
4647 "dependencies": {
4648 "ansi-styles": "^4.1.0",
4649 "supports-color": "^7.1.0"
@@ -4741,6 +4659,7 @@
4659 "version": "7.2.0",
4660 "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
4661 "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
4662 + "dev": true,
4663 "dependencies": {
4664 "has-flag": "^4.0.0"
4665 },
@@ -5057,16 +4976,11 @@
4976 "resolved": "https://registry.npmjs.org/compatx/-/compatx-0.1.8.tgz",
4977 "integrity": "sha512-jcbsEAR81Bt5s1qOFymBufmCbXCXbk0Ql+K5ouj6gCyx2yHlu6AgmGIi9HxfKixpUDO5bCFJUHQ5uM6ecbTebw=="
4978 },
5060 - "node_modules/computeds": {
5061 - "version": "0.0.1",
5062 - "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz",
5063 - "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==",
5064 - "dev": true
5065 - },
4979 "node_modules/concat-map": {
4980 "version": "0.0.1",
4981 "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
5069 - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
4982 + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
4983 + "dev": true
4984 },
4985 "node_modules/confbox": {
4986 "version": "0.1.8",
@@ -5510,7 +5424,8 @@
5424 "node_modules/deep-is": {
5425 "version": "0.1.4",
5426 "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
5513 - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
5427 + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
5428 + "dev": true
5429 },
5430 "node_modules/deep-pick-omit": {
5431 "version": "1.2.1",
@@ -5749,6 +5664,7 @@
5664 "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
5665 "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
5666 "dev": true,
5667 + "optional": true,
5668 "bin": {
5669 "detect-libc": "bin/detect-libc.js"
5670 },
@@ -5787,6 +5703,7 @@
5703 "version": "3.0.0",
5704 "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
5705 "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
5706 + "dev": true,
5707 "dependencies": {
5708 "esutils": "^2.0.2"
5709 },
@@ -6109,6 +6026,7 @@
6026 "version": "4.0.0",
6027 "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
6028 "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
6029 + "dev": true,
6030 "engines": {
6031 "node": ">=10"
6032 },
@@ -6117,20 +6035,21 @@
6035 }
6036 },
6037 "node_modules/eslint": {
6120 - "version": "9.13.0",
6121 - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz",
6122 - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==",
6038 + "version": "9.14.0",
6039 + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz",
6040 + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==",
6041 + "dev": true,
6042 "dependencies": {
6043 "@eslint-community/eslint-utils": "^4.2.0",
6125 - "@eslint-community/regexpp": "^4.11.0",
6044 + "@eslint-community/regexpp": "^4.12.1",
6045 "@eslint/config-array": "^0.18.0",
6046 "@eslint/core": "^0.7.0",
6047 "@eslint/eslintrc": "^3.1.0",
6129 - "@eslint/js": "9.13.0",
6048 + "@eslint/js": "9.14.0",
6049 "@eslint/plugin-kit": "^0.2.0",
6131 - "@humanfs/node": "^0.16.5",
6050 + "@humanfs/node": "^0.16.6",
6051 "@humanwhocodes/module-importer": "^1.0.1",
6133 - "@humanwhocodes/retry": "^0.3.1",
6052 + "@humanwhocodes/retry": "^0.4.0",
6053 "@types/estree": "^1.0.6",
6054 "@types/json-schema": "^7.0.15",
6055 "ajv": "^6.12.4",
@@ -6138,9 +6057,9 @@
6057 "cross-spawn": "^7.0.2",
6058 "debug": "^4.3.2",
6059 "escape-string-regexp": "^4.0.0",
6141 - "eslint-scope": "^8.1.0",
6142 - "eslint-visitor-keys": "^4.1.0",
6143 - "espree": "^10.2.0",
6060 + "eslint-scope": "^8.2.0",
6061 + "eslint-visitor-keys": "^4.2.0",
6062 + "espree": "^10.3.0",
6063 "esquery": "^1.5.0",
6064 "esutils": "^2.0.2",
6065 "fast-deep-equal": "^3.1.3",
@@ -6206,37 +6125,6 @@
6125 "eslint": "^9.5.0"
6126 }
6127 },
6209 - "node_modules/eslint-config-prettier": {
6210 - "version": "9.1.0",
6211 - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
6212 - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
6213 - "bin": {
6214 - "eslint-config-prettier": "bin/cli.js"
6215 - },
6216 - "peerDependencies": {
6217 - "eslint": ">=7.0.0"
6218 - }
6219 - },
6220 - "node_modules/eslint-define-config": {
6221 - "version": "1.24.1",
6222 - "resolved": "https://registry.npmjs.org/eslint-define-config/-/eslint-define-config-1.24.1.tgz",
6223 - "integrity": "sha512-o36vBhPSWyIQlHoMqGhhcGmOOm2A2ccBVIdLTG/AWdm9YmjpsLpf+5ntf9LlHR6dduLREgxtGwvwPwSt7vnXJg==",
6224 - "funding": [
6225 - {
6226 - "type": "github",
6227 - "url": "https://github.com/Shinigami92"
6228 - },
6229 - {
6230 - "type": "paypal",
6231 - "url": "https://www.paypal.com/donate/?hosted_button_id=L7GY729FBKTZY"
6232 - }
6233 - ],
6234 - "engines": {
6235 - "node": ">=18.0.0",
6236 - "npm": ">=9.0.0",
6237 - "pnpm": ">= 8.6.0"
6238 - }
6239 - },
6128 "node_modules/eslint-flat-config-utils": {
6129 "version": "0.4.0",
6130 "resolved": "https://registry.npmjs.org/eslint-flat-config-utils/-/eslint-flat-config-utils-0.4.0.tgz",
@@ -6564,55 +6452,6 @@
6452 }
6453 }
6454 },
6567 - "node_modules/eslint-plugin-prettier": {
6568 - "version": "5.2.1",
6569 - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz",
6570 - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==",
6571 - "dependencies": {
6572 - "prettier-linter-helpers": "^1.0.0",
6573 - "synckit": "^0.9.1"
6574 - },
6575 - "engines": {
6576 - "node": "^14.18.0 || >=16.0.0"
6577 - },
6578 - "funding": {
6579 - "url": "https://opencollective.com/eslint-plugin-prettier"
6580 - },
6581 - "peerDependencies": {
6582 - "@types/eslint": ">=8.0.0",
6583 - "eslint": ">=8.0.0",
6584 - "eslint-config-prettier": "*",
6585 - "prettier": ">=3.0.0"
6586 - },
6587 - "peerDependenciesMeta": {
6588 - "@types/eslint": {
6589 - "optional": true
6590 - },
6591 - "eslint-config-prettier": {
6592 - "optional": true
6593 - }
6594 - }
6595 - },
6596 - "node_modules/eslint-plugin-prettier/node_modules/synckit": {
6597 - "version": "0.9.2",
6598 - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz",
6599 - "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==",
6600 - "dependencies": {
6601 - "@pkgr/core": "^0.1.0",
6602 - "tslib": "^2.6.2"
6603 - },
6604 - "engines": {
6605 - "node": "^14.18.0 || >=16.0.0"
6606 - },
6607 - "funding": {
6608 - "url": "https://opencollective.com/unts"
6609 - }
6610 - },
6611 - "node_modules/eslint-plugin-prettier/node_modules/tslib": {
6612 - "version": "2.8.0",
6613 - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz",
6614 - "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA=="
6615 - },
6455 "node_modules/eslint-plugin-regexp": {
6456 "version": "2.6.0",
6457 "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.6.0.tgz",
@@ -6707,6 +6546,7 @@
6546 "version": "9.29.1",
6547 "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.29.1.tgz",
6548 "integrity": "sha512-MH/MbVae4HV/tM8gKAVWMPJbYgW04CK7SuzYRrlNERpxbO0P3+Zdsa2oAcFBW6xNu7W6lIkGOsFAMCRTYmrlWQ==",
6549 + "dev": true,
6550 "dependencies": {
6551 "@eslint-community/eslint-utils": "^4.4.0",
6552 "globals": "^13.24.0",
@@ -6728,6 +6568,7 @@
6568 "version": "13.24.0",
6569 "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
6570 "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
6571 + "dev": true,
6572 "dependencies": {
6573 "type-fest": "^0.20.2"
6574 },
@@ -6742,6 +6583,7 @@
6583 "version": "0.20.2",
6584 "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
6585 "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
6586 + "dev": true,
6587 "engines": {
6588 "node": ">=10"
6589 },
@@ -6785,9 +6627,10 @@
6627 }
6628 },
6629 "node_modules/eslint-scope": {
6788 - "version": "8.1.0",
6789 - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz",
6790 - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==",
6630 + "version": "8.2.0",
6631 + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz",
6632 + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==",
6633 + "dev": true,
6634 "dependencies": {
6635 "esrecurse": "^4.3.0",
6636 "estraverse": "^5.2.0"
@@ -6800,9 +6643,10 @@
6643 }
6644 },
6645 "node_modules/eslint-visitor-keys": {
6803 - "version": "4.1.0",
6804 - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz",
6805 - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==",
6646 + "version": "4.2.0",
6647 + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
6648 + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
6649 + "dev": true,
6650 "engines": {
6651 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
6652 },
@@ -6811,9 +6655,10 @@
6655 }
6656 },
6657 "node_modules/eslint/node_modules/@eslint/js": {
6814 - "version": "9.13.0",
6815 - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz",
6816 - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==",
6658 + "version": "9.14.0",
6659 + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz",
6660 + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==",
6661 + "dev": true,
6662 "engines": {
6663 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
6664 }
@@ -6822,6 +6667,7 @@
6667 "version": "1.1.11",
6668 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
6669 "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
6670 + "dev": true,
6671 "dependencies": {
6672 "balanced-match": "^1.0.0",
6673 "concat-map": "0.0.1"
@@ -6831,6 +6677,7 @@
6677 "version": "3.1.2",
6678 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
6679 "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
6680 + "dev": true,
6681 "dependencies": {
6682 "brace-expansion": "^1.1.7"
6683 },
@@ -6839,13 +6686,14 @@
6686 }
6687 },
6688 "node_modules/espree": {
6842 - "version": "10.2.0",
6843 - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz",
6844 - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==",
6689 + "version": "10.3.0",
6690 + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
6691 + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
6692 + "dev": true,
6693 "dependencies": {
6846 - "acorn": "^8.12.0",
6694 + "acorn": "^8.14.0",
6695 "acorn-jsx": "^5.3.2",
6848 - "eslint-visitor-keys": "^4.1.0"
6696 + "eslint-visitor-keys": "^4.2.0"
6697 },
6698 "engines": {
6699 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -6871,6 +6719,7 @@
6719 "version": "1.6.0",
6720 "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
6721 "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
6722 + "dev": true,
6723 "dependencies": {
6724 "estraverse": "^5.1.0"
6725 },
@@ -6882,6 +6731,7 @@
6731 "version": "4.3.0",
6732 "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
6733 "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
6734 + "dev": true,
6735 "dependencies": {
6736 "estraverse": "^5.2.0"
6737 },
@@ -6893,6 +6743,7 @@
6743 "version": "5.3.0",
6744 "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
6745 "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
6746 + "dev": true,
6747 "engines": {
6748 "node": ">=4.0"
6749 }
@@ -6906,6 +6757,7 @@
6757 "version": "2.0.3",
6758 "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
6759 "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
6760 + "dev": true,
6761 "engines": {
6762 "node": ">=0.10.0"
6763 }
@@ -6983,6 +6835,15 @@
6835 "node": ">=0.10.0"
6836 }
6837 },
6838 + "node_modules/expect-type": {
6839 + "version": "1.1.0",
6840 + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz",
6841 + "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==",
6842 + "dev": true,
6843 + "engines": {
6844 + "node": ">=12.0.0"
6845 + }
6846 + },
6847 "node_modules/extend": {
6848 "version": "3.0.2",
6849 "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -7021,12 +6882,8 @@
6882 "node_modules/fast-deep-equal": {
6883 "version": "3.1.3",
6884 "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
7024 - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
7025 - },
7026 - "node_modules/fast-diff": {
7027 - "version": "1.3.0",
7028 - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
7029 - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="
6885 + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
6886 + "dev": true
6887 },
6888 "node_modules/fast-glob": {
6889 "version": "3.3.2",
@@ -7057,12 +6914,14 @@
6914 "node_modules/fast-json-stable-stringify": {
6915 "version": "2.1.0",
6916 "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
7060 - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
6917 + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
6918 + "dev": true
6919 },
6920 "node_modules/fast-levenshtein": {
6921 "version": "2.0.6",
6922 "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
7065 - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
6923 + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
6924 + "dev": true
6925 },
6926 "node_modules/fastq": {
6927 "version": "1.17.1",
@@ -7109,6 +6968,7 @@
6968 "version": "8.0.0",
6969 "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
6970 "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
6971 + "dev": true,
6972 "dependencies": {
6973 "flat-cache": "^4.0.0"
6974 },
@@ -7136,6 +6996,7 @@
6996 "version": "5.0.0",
6997 "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
6998 "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
6999 + "dev": true,
7000 "dependencies": {
7001 "locate-path": "^6.0.0",
7002 "path-exists": "^4.0.0"
@@ -7178,6 +7039,7 @@
7039 "version": "4.0.1",
7040 "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
7041 "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
7042 + "dev": true,
7043 "dependencies": {
7044 "flatted": "^3.2.9",
7045 "keyv": "^4.5.4"
@@ -7189,7 +7051,8 @@
7051 "node_modules/flatted": {
7052 "version": "3.3.1",
7053 "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
7192 - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="
7054 + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
7055 + "dev": true
7056 },
7057 "node_modules/flourite": {
7058 "version": "1.3.0",
@@ -7349,7 +7212,8 @@
7212 "node_modules/fs.realpath": {
7213 "version": "1.0.0",
7214 "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
7352 - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
7215 + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
7216 + "dev": true
7217 },
7218 "node_modules/fsevents": {
7219 "version": "2.3.3",
@@ -7627,12 +7491,14 @@
7491 "node_modules/graphemer": {
7492 "version": "1.4.0",
7493 "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
7630 - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="
7494 + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
7495 + "dev": true
7496 },
7497 "node_modules/has-flag": {
7498 "version": "4.0.0",
7499 "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
7500 "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
7501 + "dev": true,
7502 "engines": {
7503 "node": ">=8"
7504 }
@@ -7993,6 +7859,7 @@
7859 "version": "3.3.0",
7860 "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
7861 "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
7862 + "dev": true,
7863 "dependencies": {
7864 "parent-module": "^1.0.0",
7865 "resolve-from": "^4.0.0"
@@ -8008,6 +7875,7 @@
7875 "version": "4.0.0",
7876 "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
7877 "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
7878 + "dev": true,
7879 "engines": {
7880 "node": ">=4"
7881 }
@@ -8065,6 +7933,7 @@
7933 "version": "0.1.4",
7934 "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
7935 "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
7936 + "dev": true,
7937 "engines": {
7938 "node": ">=0.8.19"
7939 }
@@ -8083,6 +7952,7 @@
7952 "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
7953 "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
7954 "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
7955 + "dev": true,
7956 "dependencies": {
7957 "once": "^1.3.0",
7958 "wrappy": "1"
@@ -8091,7 +7961,8 @@
7961 "node_modules/inherits": {
7962 "version": "2.0.4",
7963 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
8094 - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
7964 + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
7965 + "dev": true
7966 },
7967 "node_modules/ini": {
7968 "version": "2.0.0",
@@ -8293,6 +8164,7 @@
8164 "version": "3.0.3",
8165 "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
8166 "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
8167 + "dev": true,
8168 "engines": {
8169 "node": ">=8"
8170 }
@@ -8563,7 +8435,8 @@
8435 "node_modules/json-buffer": {
8436 "version": "3.0.1",
8437 "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
8566 - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
8438 + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
8439 + "dev": true
8440 },
8441 "node_modules/json-parse-even-better-errors": {
8442 "version": "2.3.1",
@@ -8580,12 +8453,14 @@
8453 "node_modules/json-schema-traverse": {
8454 "version": "0.4.1",
8455 "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
8583 - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
8456 + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
8457 + "dev": true
8458 },
8459 "node_modules/json-stable-stringify-without-jsonify": {
8460 "version": "1.0.1",
8461 "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
8588 - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
8462 + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
8463 + "dev": true
8464 },
8465 "node_modules/json-stringify-safe": {
8466 "version": "5.0.1",
@@ -8694,6 +8569,7 @@
8569 "version": "4.5.4",
8570 "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
8571 "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
8572 + "dev": true,
8573 "dependencies": {
8574 "json-buffer": "3.0.1"
8575 }
@@ -8887,6 +8763,7 @@
8763 "version": "0.4.1",
8764 "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
8765 "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
8766 + "dev": true,
8767 "dependencies": {
8768 "prelude-ls": "^1.2.1",
8769 "type-check": "~0.4.0"
@@ -8988,6 +8865,7 @@
8865 "version": "6.0.0",
8866 "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
8867 "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
8868 + "dev": true,
8869 "dependencies": {
8870 "p-locate": "^5.0.0"
8871 },
@@ -9011,7 +8889,8 @@
8889 "node_modules/lodash.merge": {
8890 "version": "4.6.2",
8891 "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
9014 - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
8892 + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
8893 + "dev": true
8894 },
8895 "node_modules/lodash.once": {
8896 "version": "4.1.1",
@@ -10246,9 +10125,9 @@
10125 }
10126 },
10127 "node_modules/nanoid": {
10249 - "version": "5.0.7",
10250 - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz",
10251 - "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==",
10128 + "version": "5.0.8",
10129 + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.8.tgz",
10130 + "integrity": "sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==",
10131 "funding": [
10132 {
10133 "type": "github",
@@ -10265,7 +10144,8 @@
10144 "node_modules/natural-compare": {
10145 "version": "1.4.0",
10146 "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
10268 - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
10147 + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
10148 + "dev": true
10149 },
10150 "node_modules/natural-compare-lite": {
10151 "version": "1.4.0",
@@ -10286,7 +10166,8 @@
10166 "version": "7.1.1",
10167 "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
10168 "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
10289 - "dev": true
10169 + "dev": true,
10170 + "optional": true
10171 },
10172 "node_modules/node-fetch-native": {
10173 "version": "1.6.4",
@@ -10438,6 +10319,7 @@
10319 "version": "2.1.1",
10320 "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
10321 "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
10322 + "dev": true,
10323 "dependencies": {
10324 "boolbase": "^1.0.0"
10325 },
@@ -10654,6 +10536,7 @@
10536 "version": "1.4.0",
10537 "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
10538 "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
10539 + "dev": true,
10540 "dependencies": {
10541 "wrappy": "1"
10542 }
@@ -10710,6 +10593,7 @@
10593 "version": "0.9.4",
10594 "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
10595 "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
10596 + "dev": true,
10597 "dependencies": {
10598 "deep-is": "^0.1.3",
10599 "fast-levenshtein": "^2.0.6",
@@ -10732,6 +10616,7 @@
10616 "version": "3.1.0",
10617 "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
10618 "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
10619 + "dev": true,
10620 "dependencies": {
10621 "yocto-queue": "^0.1.0"
10622 },
@@ -10746,6 +10631,7 @@
10631 "version": "5.0.0",
10632 "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
10633 "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
10634 + "dev": true,
10635 "dependencies": {
10636 "p-limit": "^3.0.2"
10637 },
@@ -10795,6 +10681,7 @@
10681 "version": "1.0.1",
10682 "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
10683 "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
10684 + "dev": true,
10685 "dependencies": {
10686 "callsites": "^3.0.0"
10687 },
@@ -10890,6 +10777,7 @@
10777 "version": "4.0.0",
10778 "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
10779 "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
10780 + "dev": true,
10781 "engines": {
10782 "node": ">=8"
10783 }
@@ -10898,6 +10786,7 @@
10786 "version": "1.0.1",
10787 "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
10788 "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
10789 + "dev": true,
10790 "engines": {
10791 "node": ">=0.10.0"
10792 }
@@ -11027,9 +10916,9 @@
10916 }
10917 },
10918 "node_modules/pinia": {
11030 - "version": "2.2.4",
11031 - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.2.4.tgz",
11032 - "integrity": "sha512-K7ZhpMY9iJ9ShTC0cR2+PnxdQRuwVIsXDO/WIEV/RnMC/vmSoKDTKW/exNQYPI+4ij10UjXqdNiEHwn47McANQ==",
10919 + "version": "2.2.6",
10920 + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.2.6.tgz",
10921 + "integrity": "sha512-vIsR8JkDN5Ga2vAxqOE2cJj4VtsHnzpR1Fz30kClxlh0yCHfec6uoMeM3e/ddqmwFUejK3NlrcQa/shnpyT4hA==",
10922 "dependencies": {
10923 "@vue/devtools-api": "^6.6.3",
10924 "vue-demi": "^0.14.10"
@@ -11040,7 +10929,7 @@
10929 "peerDependencies": {
10930 "@vue/composition-api": "^1.4.0",
10931 "typescript": ">=4.4.4",
11043 - "vue": "^2.6.14 || ^3.3.0"
10932 + "vue": "^2.6.14 || ^3.5.11"
10933 },
10934 "peerDependenciesMeta": {
10935 "@vue/composition-api": {
@@ -11346,6 +11235,7 @@
11235 "version": "1.2.1",
11236 "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
11237 "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
11238 + "dev": true,
11239 "engines": {
11240 "node": ">= 0.8.0"
11241 }
@@ -11354,6 +11244,7 @@
11244 "version": "3.3.3",
11245 "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
11246 "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
11247 + "dev": true,
11248 "bin": {
11249 "prettier": "bin/prettier.cjs"
11250 },
@@ -11364,17 +11255,6 @@
11255 "url": "https://github.com/prettier/prettier?sponsor=1"
11256 }
11257 },
11367 - "node_modules/prettier-linter-helpers": {
11368 - "version": "1.0.0",
11369 - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
11370 - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
11371 - "dependencies": {
11372 - "fast-diff": "^1.1.2"
11373 - },
11374 - "engines": {
11375 - "node": ">=6.0.0"
11376 - }
11377 - },
11258 "node_modules/prettier-plugin-tailwindcss": {
11259 "version": "0.6.8",
11260 "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.8.tgz",
@@ -11529,6 +11409,7 @@
11409 "version": "2.3.1",
11410 "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
11411 "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
11412 + "dev": true,
11413 "engines": {
11414 "node": ">=6"
11415 }
@@ -11757,9 +11638,9 @@
11638 }
11639 },
11640 "node_modules/regex": {
11760 - "version": "4.3.3",
11761 - "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz",
11762 - "integrity": "sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg=="
11641 + "version": "4.4.0",
11642 + "resolved": "https://registry.npmjs.org/regex/-/regex-4.4.0.tgz",
11643 + "integrity": "sha512-uCUSuobNVeqUupowbdZub6ggI5/JZkYyJdDogddJr60L764oxC2pMZov1fQ3wM9bdyzUILDG+Sqx6NAKAz9rKQ=="
11644 },
11645 "node_modules/regexp-ast-analysis": {
11646 "version": "0.7.1",
@@ -12032,6 +11913,8 @@
11913 "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
11914 "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
11915 "deprecated": "Rimraf versions prior to v4 are no longer supported",
11916 + "dev": true,
11917 + "optional": true,
11918 "peer": true,
11919 "dependencies": {
11920 "glob": "^7.1.3"
@@ -12047,6 +11930,8 @@
11930 "version": "1.1.11",
11931 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
11932 "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
11933 + "dev": true,
11934 + "optional": true,
11935 "peer": true,
11936 "dependencies": {
11937 "balanced-match": "^1.0.0",
@@ -12058,6 +11943,8 @@
11943 "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
11944 "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
11945 "deprecated": "Glob versions prior to v9 are no longer supported",
11946 + "dev": true,
11947 + "optional": true,
11948 "peer": true,
11949 "dependencies": {
11950 "fs.realpath": "^1.0.0",
@@ -12078,6 +11965,8 @@
11965 "version": "3.1.2",
11966 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
11967 "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
11968 + "dev": true,
11969 + "optional": true,
11970 "peer": true,
11971 "dependencies": {
11972 "brace-expansion": "^1.1.7"
@@ -12176,6 +12065,19 @@
12065 "url": "https://github.com/sponsors/jonschlinkert"
12066 }
12067 },
12068 + "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": {
12069 + "version": "4.24.0",
12070 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz",
12071 + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==",
12072 + "cpu": [
12073 + "x64"
12074 + ],
12075 + "dev": true,
12076 + "optional": true,
12077 + "os": [
12078 + "linux"
12079 + ]
12080 + },
12081 "node_modules/rrweb-cssom": {
12082 "version": "0.7.1",
12083 "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz",
@@ -12252,12 +12154,11 @@
12154 "dev": true
12155 },
12156 "node_modules/sass": {
12255 - "version": "1.80.4",
12256 - "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.4.tgz",
12257 - "integrity": "sha512-rhMQ2tSF5CsuuspvC94nPM9rToiAFw2h3JTrLlgmNw1MH79v8Cr3DH6KF6o6r+8oofY3iYVPUf66KzC8yuVN1w==",
12157 + "version": "1.80.6",
12158 + "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.6.tgz",
12159 + "integrity": "sha512-ccZgdHNiBF1NHBsWvacvT5rju3y1d/Eu+8Ex6c21nHp2lZGLBEtuwc415QfiI1PJa1TpCo3iXwwSRjRpn2Ckjg==",
12160 "dev": true,
12161 "dependencies": {
12260 - "@parcel/watcher": "^2.4.1",
12162 "chokidar": "^4.0.0",
12163 "immutable": "^4.0.0",
12164 "source-map-js": ">=0.6.2 <2.0.0"
@@ -12267,6 +12168,9 @@
12168 },
12169 "engines": {
12170 "node": ">=14.0.0"
12171 + },
12172 + "optionalDependencies": {
12173 + "@parcel/watcher": "^2.4.1"
12174 }
12175 },
12176 "node_modules/sass/node_modules/chokidar": {
@@ -12414,14 +12318,14 @@
12318 }
12319 },
12320 "node_modules/shiki": {
12417 - "version": "1.22.1",
12418 - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.1.tgz",
12419 - "integrity": "sha512-PbJ6XxrWLMwB2rm3qdjIHNm3zq4SfFnOx0B3rEoi4AN8AUngsdyZ1tRe5slMPtn6jQkbUURLNZPpLR7Do3k78g==",
12420 - "dependencies": {
12421 - "@shikijs/core": "1.22.1",
12422 - "@shikijs/engine-javascript": "1.22.1",
12423 - "@shikijs/engine-oniguruma": "1.22.1",
12424 - "@shikijs/types": "1.22.1",
12321 + "version": "1.22.2",
12322 + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.2.tgz",
12323 + "integrity": "sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==",
12324 + "dependencies": {
12325 + "@shikijs/core": "1.22.2",
12326 + "@shikijs/engine-javascript": "1.22.2",
12327 + "@shikijs/engine-oniguruma": "1.22.2",
12328 + "@shikijs/types": "1.22.2",
12329 "@shikijs/vscode-textmate": "^9.3.0",
12330 "@types/hast": "^3.0.4"
12331 }
@@ -12823,6 +12727,7 @@
12727 "version": "3.1.1",
12728 "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
12729 "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
12730 + "dev": true,
12731 "engines": {
12732 "node": ">=8"
12733 },
@@ -13054,6 +12959,9 @@
12959 "version": "0.8.8",
12960 "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz",
12961 "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==",
12962 + "dev": true,
12963 + "optional": true,
12964 + "peer": true,
12965 "dependencies": {
12966 "@pkgr/core": "^0.1.0",
12967 "tslib": "^2.6.2"
@@ -13068,7 +12976,10 @@
12976 "node_modules/synckit/node_modules/tslib": {
12977 "version": "2.8.0",
12978 "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz",
13071 - "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA=="
12979 + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==",
12980 + "dev": true,
12981 + "optional": true,
12982 + "peer": true
12983 },
12984 "node_modules/tailwind-config-viewer": {
12985 "version": "2.0.4",
@@ -13197,16 +13108,16 @@
13108 "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
13109 },
13110 "node_modules/taze": {
13200 - "version": "0.17.2",
13201 - "resolved": "https://registry.npmjs.org/taze/-/taze-0.17.2.tgz",
13202 - "integrity": "sha512-VZvB2PfuIXVQdgEnjqg1NLAnxzEv28ypxTLpbtSs8rO0gdZbFRwRj3ES9QXneo112rdIwx1SM2QcIL83EfNBdg==",
13111 + "version": "0.18.0",
13112 + "resolved": "https://registry.npmjs.org/taze/-/taze-0.18.0.tgz",
13113 + "integrity": "sha512-aL8g+4tZvfhsn147u9dRP2eUE2MV+HfJe1sAtSJp46b0Gd8AjyqlJ2uDwnJfM1XNv301Mvh98RkXQw27sco5tQ==",
13114 "dev": true,
13115 "dependencies": {
13116 "@antfu/ni": "^0.23.0",
13117 "js-yaml": "^4.1.0",
13207 - "ofetch": "^1.4.0",
13208 - "package-manager-detector": "^0.2.0",
13209 - "tinyexec": "^0.3.0",
13118 + "ofetch": "^1.4.1",
13119 + "package-manager-detector": "^0.2.2",
13120 + "tinyexec": "^0.3.1",
13121 "unconfig": "^0.6.0",
13122 "yargs": "^17.7.2"
13123 },
@@ -13252,7 +13163,8 @@
13163 "node_modules/text-table": {
13164 "version": "0.2.0",
13165 "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
13255 - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="
13166 + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
13167 + "dev": true
13168 },
13169 "node_modules/thenify": {
13170 "version": "3.3.1",
@@ -13473,6 +13385,7 @@
13385 "version": "1.3.0",
13386 "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
13387 "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
13388 + "dev": true,
13389 "engines": {
13390 "node": ">=16"
13391 },
@@ -13947,6 +13860,7 @@
13860 "version": "0.4.0",
13861 "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
13862 "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
13863 + "dev": true,
13864 "dependencies": {
13865 "prelude-ls": "^1.2.1"
13866 },
@@ -13983,6 +13897,7 @@
13897 "version": "5.6.3",
13898 "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
13899 "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
13900 + "devOptional": true,
13901 "bin": {
13902 "tsc": "bin/tsc",
13903 "tsserver": "bin/tsserver"
@@ -14005,6 +13920,9 @@
13920 "version": "0.3.13",
13921 "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-0.3.13.tgz",
13922 "integrity": "sha512-N9Ph5NC4+sqtcOjPfHrRcHekBCadCXWTBzp2VYYbySOHW0PfD9XLCeXshTXjkPYwLrBr9AtSeU0CZmkYECJhng==",
13923 + "dev": true,
13924 + "optional": true,
13925 + "peer": true,
13926 "dependencies": {
13927 "@antfu/utils": "^0.7.7",
13928 "defu": "^6.1.4",
@@ -14290,6 +14208,7 @@
14208 "version": "4.4.1",
14209 "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
14210 "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
14211 + "dev": true,
14212 "dependencies": {
14213 "punycode": "^2.1.0"
14214 }
@@ -14496,13 +14415,13 @@
14415 }
14416 },
14417 "node_modules/vite-node": {
14499 - "version": "2.1.3",
14500 - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz",
14501 - "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==",
14418 + "version": "2.1.4",
14419 + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.4.tgz",
14420 + "integrity": "sha512-kqa9v+oi4HwkG6g8ufRnb5AeplcRw8jUF6/7/Qz1qRQOXHImG8YnLbB+LLszENwFnoBl9xIf9nVdCFzNd7GQEg==",
14421 "dev": true,
14422 "dependencies": {
14423 "cac": "^6.7.14",
14505 - "debug": "^4.3.6",
14424 + "debug": "^4.3.7",
14425 "pathe": "^1.1.2",
14426 "vite": "^5.0.0"
14427 },
@@ -14607,14 +14526,14 @@
14526 }
14527 },
14528 "node_modules/vite-plugin-vue-devtools": {
14610 - "version": "7.5.4",
14611 - "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-7.5.4.tgz",
14612 - "integrity": "sha512-6yTcGrF+YdplDhNiNCkwj23BQDHA/jp06FR4Bo3rui1GW+8VdFcc26au2gtynPwRDNJXNueTxiVtVb6dq+lNZA==",
14529 + "version": "7.6.2",
14530 + "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-7.6.2.tgz",
14531 + "integrity": "sha512-YPE/8AIBsomvHadZ02Kkp8yZo2FR0SFNjbC2lcMgW+hNA1ZoXu9b5oi18gTMzJcLLFRNNSMNjShA4RLqXlIR/A==",
14532 "dev": true,
14533 "dependencies": {
14615 - "@vue/devtools-core": "^7.5.4",
14616 - "@vue/devtools-kit": "^7.5.4",
14617 - "@vue/devtools-shared": "^7.5.4",
14534 + "@vue/devtools-core": "^7.6.2",
14535 + "@vue/devtools-kit": "^7.6.2",
14536 + "@vue/devtools-shared": "^7.6.2",
14537 "execa": "^8.0.1",
14538 "sirv": "^3.0.0",
14539 "vite-plugin-inspect": "^0.8.7",
@@ -14794,29 +14713,30 @@
14713 }
14714 },
14715 "node_modules/vitest": {
14797 - "version": "2.1.3",
14798 - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz",
14799 - "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==",
14800 - "dev": true,
14801 - "dependencies": {
14802 - "@vitest/expect": "2.1.3",
14803 - "@vitest/mocker": "2.1.3",
14804 - "@vitest/pretty-format": "^2.1.3",
14805 - "@vitest/runner": "2.1.3",
14806 - "@vitest/snapshot": "2.1.3",
14807 - "@vitest/spy": "2.1.3",
14808 - "@vitest/utils": "2.1.3",
14809 - "chai": "^5.1.1",
14810 - "debug": "^4.3.6",
14811 - "magic-string": "^0.30.11",
14716 + "version": "2.1.4",
14717 + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.4.tgz",
14718 + "integrity": "sha512-eDjxbVAJw1UJJCHr5xr/xM86Zx+YxIEXGAR+bmnEID7z9qWfoxpHw0zdobz+TQAFOLT+nEXz3+gx6nUJ7RgmlQ==",
14719 + "dev": true,
14720 + "dependencies": {
14721 + "@vitest/expect": "2.1.4",
14722 + "@vitest/mocker": "2.1.4",
14723 + "@vitest/pretty-format": "^2.1.4",
14724 + "@vitest/runner": "2.1.4",
14725 + "@vitest/snapshot": "2.1.4",
14726 + "@vitest/spy": "2.1.4",
14727 + "@vitest/utils": "2.1.4",
14728 + "chai": "^5.1.2",
14729 + "debug": "^4.3.7",
14730 + "expect-type": "^1.1.0",
14731 + "magic-string": "^0.30.12",
14732 "pathe": "^1.1.2",
14733 "std-env": "^3.7.0",
14734 "tinybench": "^2.9.0",
14815 - "tinyexec": "^0.3.0",
14816 - "tinypool": "^1.0.0",
14735 + "tinyexec": "^0.3.1",
14736 + "tinypool": "^1.0.1",
14737 "tinyrainbow": "^1.2.0",
14738 "vite": "^5.0.0",
14819 - "vite-node": "2.1.3",
14739 + "vite-node": "2.1.4",
14740 "why-is-node-running": "^2.3.0"
14741 },
14742 "bin": {
@@ -14831,8 +14751,8 @@
14751 "peerDependencies": {
14752 "@edge-runtime/vm": "*",
14753 "@types/node": "^18.0.0 || >=20.0.0",
14834 - "@vitest/browser": "2.1.3",
14835 - "@vitest/ui": "2.1.3",
14754 + "@vitest/browser": "2.1.4",
14755 + "@vitest/ui": "2.1.4",
14756 "happy-dom": "*",
14757 "jsdom": "*"
14758 },
@@ -14921,6 +14841,7 @@
14841 "version": "9.4.3",
14842 "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
14843 "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==",
14844 + "dev": true,
14845 "dependencies": {
14846 "debug": "^4.3.4",
14847 "eslint-scope": "^7.1.1",
@@ -14944,6 +14865,7 @@
14865 "version": "7.2.2",
14866 "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
14867 "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
14868 + "dev": true,
14869 "dependencies": {
14870 "esrecurse": "^4.3.0",
14871 "estraverse": "^5.2.0"
@@ -14959,6 +14881,7 @@
14881 "version": "3.4.3",
14882 "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
14883 "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
14884 + "dev": true,
14885 "engines": {
14886 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
14887 },
@@ -14970,6 +14893,7 @@
14893 "version": "9.6.1",
14894 "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
14895 "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
14896 + "dev": true,
14897 "dependencies": {
14898 "acorn": "^8.9.0",
14899 "acorn-jsx": "^5.3.2",
@@ -15035,13 +14959,13 @@
14959 }
14960 },
14961 "node_modules/vue-tsc": {
15038 - "version": "2.1.6",
15039 - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.1.6.tgz",
15040 - "integrity": "sha512-f98dyZp5FOukcYmbFpuSCJ4Z0vHSOSmxGttZJCsFeX0M4w/Rsq0s4uKXjcSRsZqsRgQa6z7SfuO+y0HVICE57Q==",
14962 + "version": "2.1.10",
14963 + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.1.10.tgz",
14964 + "integrity": "sha512-RBNSfaaRHcN5uqVqJSZh++Gy/YUzryuv9u1aFWhsammDJXNtUiJMNoJ747lZcQ68wUQFx6E73y4FY3D8E7FGMA==",
14965 "dev": true,
14966 "dependencies": {
15043 - "@volar/typescript": "~2.4.1",
15044 - "@vue/language-core": "2.1.6",
14967 + "@volar/typescript": "~2.4.8",
14968 + "@vue/language-core": "2.1.10",
14969 "semver": "^7.5.4"
14970 },
14971 "bin": {
@@ -15221,6 +15145,7 @@
15145 "version": "1.2.5",
15146 "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
15147 "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
15148 + "dev": true,
15149 "engines": {
15150 "node": ">=0.10.0"
15151 }
@@ -15318,7 +15243,8 @@
15243 "node_modules/wrappy": {
15244 "version": "1.0.2",
15245 "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
15321 - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
15246 + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
15247 + "dev": true
15248 },
15249 "node_modules/ws": {
15250 "version": "8.18.0",
@@ -15345,6 +15271,7 @@
15271 "version": "4.0.0",
15272 "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
15273 "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
15274 + "dev": true,
15275 "engines": {
15276 "node": ">=12"
15277 }
@@ -15469,6 +15396,7 @@
15396 "version": "0.1.0",
15397 "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
15398 "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
15399 + "dev": true,
15400 "engines": {
15401 "node": ">=10"
15402 },
frontend/package.json
+20 -20
@@ -36,13 +36,13 @@
36 },
37 "dependencies": {
38 "@ajoelp/json-to-formdata": "^1.5.0",
39 - "@f3ve/vue-markdown-it": "^0.2.2",
39 + "@f3ve/vue-markdown-it": "^0.2.3",
40 "@fontsource/jetbrains-mono": "^5.1.1",
41 "@fontsource/lexend": "^5.1.1",
42 "@fontsource/public-sans": "^5.1.1",
43 - "@shikijs/markdown-it": "^1.22.1",
43 + "@shikijs/markdown-it": "^1.22.2",
44 "@tailwindcss/container-queries": "^0.1.1",
45 - "@vueuse/core": "^11.1.0",
45 + "@vueuse/core": "^11.2.0",
46 "axios": "^1.7.7",
47 "bytes": "^3.1.2",
48 "colord": "^2.9.3",
@@ -56,12 +56,12 @@
56 "lodash": "^4.17.21",
57 "mitt": "^3.0.1",
58 "naive-ui": "^2.40.1",
59 - "nanoid": "^5.0.7",
59 + "nanoid": "^5.0.8",
60 "password-validator": "^5.3.0",
61 - "pinia": "^2.2.4",
61 + "pinia": "^2.2.6",
62 "pinia-plugin-persistedstate": "^4.1.2",
63 "secure-ls": "^2.0.0",
64 - "shiki": "^1.22.1",
64 + "shiki": "^1.22.2",
65 "validator": "^13.12.0",
66 "vue": "^3.5.12",
67 "vue-advanced-cropper": "^2.8.9",
@@ -74,7 +74,7 @@
74 "vuedraggable": "^4.1.0"
75 },
76 "optionalDependencies": {
77 - "@rollup/rollup-linux-x64-gnu": "^4.24.0"
77 + "@rollup/rollup-linux-x64-gnu": "^4.24.4"
78 },
79 "devDependencies": {
80 "@antfu/eslint-config": "^3.8.0",
@@ -85,8 +85,8 @@
85 "@types/file-saver": "^2.0.7",
86 "@types/fs-extra": "^11.0.4",
87 "@types/jsdom": "^21.1.7",
88 - "@types/lodash": "^4.17.12",
89 - "@types/node": "^22.8.0",
88 + "@types/lodash": "^4.17.13",
89 + "@types/node": "^22.8.7",
90 "@types/validator": "^13.12.2",
91 "@vitejs/plugin-vue": "^5.1.4",
92 "@vitejs/plugin-vue-jsx": "^4.0.1",
@@ -95,7 +95,7 @@
95 "autoprefixer": "^10.4.20",
96 "cypress": "^13.15.1",
97 "depcheck": "^1.4.7",
98 - "eslint": "^9.13.0",
98 + "eslint": "^9.14.0",
99 "flourite": "^1.3.0",
100 "fs-extra": "^11.2.0",
101 "jsdom": "^25.0.1",
@@ -103,37 +103,37 @@
103 "postcss": "^8.4.47",
104 "prettier": "^3.3.3",
105 "prettier-plugin-tailwindcss": "^0.6.8",
106 - "sass": "^1.80.4",
106 + "sass": "^1.80.6",
107 "start-server-and-test": "^2.0.8",
108 "tailwind-config-viewer": "^2.0.4",
109 "tailwindcss": "^3.4.14",
110 - "taze": "^0.17.2",
110 + "taze": "^0.18.0",
111 "type-fest": "^4.26.1",
112 "typescript": "~5.6.3",
113 "unplugin-vue-components": "^0.27.4",
114 "vite": "^5.4.10",
115 "vite-bundle-visualizer": "^1.2.1",
116 - "vite-plugin-vue-devtools": "^7.5.4",
116 + "vite-plugin-vue-devtools": "^7.6.2",
117 "vite-svg-loader": "^5.1.0",
118 - "vitest": "^2.1.3",
119 - "vue-tsc": "^2.1.6"
118 + "vitest": "^2.1.4",
119 + "vue-tsc": "^2.1.10"
120 },
121 "pnpm": {
122 "overrides": {
123 - "@typescript-eslint/eslint-plugin": "^8.11.0",
123 + "@typescript-eslint/eslint-plugin": "^8.12.2",
124 "@typescript-eslint/eslint-plugin>eslint": "$eslint",
125 - "@typescript-eslint/parser": "^8.11.0",
125 + "@typescript-eslint/parser": "^8.12.2",
126 "@typescript-eslint/parser>eslint": "$eslint",
127 "eslint": "$eslint"
128 }
129 },
130 "overrides": {
131 "@typescript-eslint/eslint-plugin": {
132 - "eslint": "^9.13.0"
132 + "eslint": "^9.14.0"
133 },
134 "@typescript-eslint/parser": {
135 - "eslint": "^9.13.0"
135 + "eslint": "^9.14.0"
136 },
137 - "@typescript-eslint/typescript-estree": "^8.11.0"
137 + "@typescript-eslint/typescript-estree": "^8.12.2"
138 }
139 }
frontend/src/api/endpoints/incidentManagement.ts
+21
@@ -46,6 +46,13 @@ export type CasesFilterTypes = KeysOfUnion<CasesFilter>
46
47 export type AlertCommentPayload = Omit<AlertComment, "id">
48
49 +export interface AlertIocPayload {
50 + alert_id: number
51 + ioc_value: string
52 + ioc_type: string
53 + ioc_description: string
54 +}
55 +
56 export interface CaseReportPayload {
57 case_id: number
58 file_name: string
@@ -152,6 +159,9 @@ export default {
159 case "assetName":
160 params.asset_name = filter.value
161 break
162 + case "iocValue":
163 + params.ioc_value = filter.value
164 + break
165 case "status":
166 params.status = filter.value
167 break
@@ -238,6 +248,17 @@ export default {
248 tag
249 })
250 },
251 + createAlertIoc(payload: AlertIocPayload) {
252 + return HttpClient.post<FlaskBaseResponse & { alert_ioc: { alert_id: number; ioc_id: number } }>(
253 + `/incidents/db_operations/alert/ioc`,
254 + payload
255 + )
256 + },
257 + deleteAlertIoc(alertId: number, iocId: number) {
258 + return HttpClient.delete<FlaskBaseResponse>(`/incidents/db_operations/alert/ioc`, {
259 + data: { alert_id: alertId, ioc_id: iocId }
260 + })
261 + },
262 // #endregion
263
264 // #region Cases
frontend/src/assets/scss/overrides/naive-override.scss
+4 -1
@@ -102,12 +102,15 @@
102 .n-spin-container .n-spin-body {
103 inset: 0 !important;
104 transform: none !important;
105 + display: block;
106
107 .n-base-loading {
108 position: sticky;
109 top: 0;
110 bottom: 0;
110 - height: min(450px, 100%);
111 + left: 50%;
112 + height: min(calc(100vh / 1.5), 100%);
113 + transform: translateX(-50%);
114
115 .n-base-loading__transition-wrapper {
116 transform: translateY(-50%);
frontend/src/components/common/CollapseKeepAlive.vue new
+97
@@ -0,0 +1,97 @@
1 +<template>
2 + <div
3 + class="collapse-box"
4 + :style="arrowOffset ? `--arrow-offset: ${arrowOffset}` : undefined"
5 + :class="[arrow ? `arrow arrow-${arrow}` : undefined, { show, embedded }]"
6 + >
7 + <div>
8 + <slot />
9 + </div>
10 + </div>
11 +</template>
12 +
13 +<script setup lang="ts">
14 +const { show, embedded, arrow, arrowOffset } = defineProps<{
15 + show: boolean
16 + embedded?: boolean
17 + arrow?: "top-left" | "top-right" | "top"
18 + arrowOffset?: string
19 +}>()
20 +</script>
21 +
22 +<style lang="scss" scoped>
23 +.collapse-box {
24 + --transition-time: 0.3s;
25 + --arrow-size: 10px;
26 + --arrow-offset: 8px;
27 + overflow: hidden;
28 + display: grid;
29 + grid-template-rows: 0fr;
30 + padding-top: 0px;
31 + opacity: 0;
32 + position: relative;
33 + transition:
34 + opacity var(--transition-time) var(--bezier-ease),
35 + grid-template-rows var(--transition-time) var(--bezier-ease),
36 + padding-top var(--transition-time) var(--bezier-ease);
37 +
38 + &.arrow-top,
39 + &.arrow-top-left,
40 + &.arrow-top-right {
41 + &::after {
42 + content: "";
43 + width: 0;
44 + height: 0;
45 + border-left: var(--arrow-size) solid transparent;
46 + border-right: var(--arrow-size) solid transparent;
47 + border-bottom: var(--arrow-size) solid var(--bg-secondary-color);
48 + position: absolute;
49 + transition: transform var(--transition-time) var(--bezier-ease);
50 +
51 + top: 2px;
52 + transform: rotateX(90deg);
53 + transform-origin: top center;
54 + }
55 + }
56 + &.arrow-top {
57 + &::after {
58 + margin-left: calc(var(--arrow-size) / -2);
59 + left: 50%;
60 + }
61 + }
62 + &.arrow-top-left {
63 + &::after {
64 + left: var(--arrow-offset);
65 + right: initial;
66 + }
67 + }
68 + &.arrow-top-right {
69 + &::after {
70 + right: var(--arrow-offset);
71 + left: initial;
72 + }
73 + }
74 +
75 + & > * {
76 + overflow: hidden;
77 + }
78 +
79 + &.embedded > * {
80 + background-color: var(--bg-secondary-color);
81 + border-radius: var(--border-radius);
82 + }
83 +
84 + &.show {
85 + grid-template-rows: 1fr;
86 + opacity: 1;
87 +
88 + &.arrow {
89 + @apply pt-3;
90 +
91 + &::after {
92 + transform: rotateX(0deg);
93 + }
94 + }
95 + }
96 +}
97 +</style>
frontend/src/components/incidentManagement/alerts/AlertComment.vue
+1 -1
@@ -42,7 +42,7 @@ onBeforeMount(() => {
42 width: 100%;
43
44 .user-pic {
45 - padding-top: 4px;
45 + padding-top: 2px;
46 }
47
48 .comment {
frontend/src/components/incidentManagement/alerts/AlertDetails.vue
+13 -1
@@ -32,12 +32,17 @@
32 />
33 </div>
34 </n-tab-pane>
35 + <n-tab-pane name="IoCs" tab="IoCs" display-directive="show:lazy">
36 + <div class="p-7 pt-4">
37 + <AlertIoCsList :iocs="alert.iocs" :alert-id="alert.id" @updated="updateIos($event)" />
38 + </div>
39 + </n-tab-pane>
40 </n-tabs>
41 </n-spin>
42 </template>
43
44 <script setup lang="ts">
40 -import type { Alert, AlertComment } from "@/types/incidentManagement/alerts.d"
45 +import type { Alert, AlertComment, AlertIOC } from "@/types/incidentManagement/alerts.d"
46 import Api from "@/api"
47 import _clone from "lodash/cloneDeep"
48 import { NSpin, NTabPane, NTabs, useMessage } from "naive-ui"
@@ -54,6 +59,7 @@ const emit = defineEmits<{
59 const AlertTimeline = defineAsyncComponent(() => import("./AlertTimeline.vue"))
60 const AlertAssetsList = defineAsyncComponent(() => import("./AlertAssetsList.vue"))
61 const AlertCommentsList = defineAsyncComponent(() => import("./AlertCommentsList.vue"))
62 +const AlertIoCsList = defineAsyncComponent(() => import("./AlertIoCsList.vue"))
63 const AlertOverview = defineAsyncComponent(() => import("./AlertOverview.vue"))
64
65 const { alertData, alertId } = toRefs(props)
@@ -73,6 +79,12 @@ function updateComments(comments: AlertComment[]) {
79 emit("updated", alert.value)
80 }
81 }
82 +function updateIos(iocs: AlertIOC[]) {
83 + if (alert.value) {
84 + alert.value.iocs = iocs
85 + emit("updated", alert.value)
86 + }
87 +}
88
89 function getAlert(alertId: number) {
90 loading.value = true
frontend/src/components/incidentManagement/alerts/AlertIoCItem.vue new
+70
@@ -0,0 +1,70 @@
1 +<template>
2 + <CardEntity :embedded hoverable>
3 + <template #default>
4 + <div class="flex flex-wrap gap-2">
5 + <strong>{{ ioc.type }}</strong>
6 + <span>{{ ioc.value }}</span>
7 + </div>
8 + <p class="mt-2">{{ ioc.description }}</p>
9 + </template>
10 + <template #footerExtra>
11 + <n-popconfirm
12 + v-model:show="showDeleteConfirm"
13 + trigger="manual"
14 + to="body"
15 + @positive-click="deleteIoc()"
16 + @clickoutside="showDeleteConfirm = false"
17 + >
18 + <template #trigger>
19 + <n-button quaternary size="tiny" :loading="canceling" @click.stop="showDeleteConfirm = true">
20 + Delete
21 + </n-button>
22 + </template>
23 + Are you sure you want to delete this IoC?
24 + </n-popconfirm>
25 + </template>
26 + </CardEntity>
27 +</template>
28 +
29 +<script setup lang="ts">
30 +import type { AlertIOC } from "@/types/incidentManagement/alerts"
31 +import Api from "@/api"
32 +import CardEntity from "@/components/common/cards/CardEntity.vue"
33 +import { NButton, NPopconfirm, useMessage } from "naive-ui"
34 +import { ref } from "vue"
35 +
36 +const { ioc, embedded, alertId } = defineProps<{
37 + ioc: AlertIOC
38 + alertId: number
39 + embedded?: boolean
40 +}>()
41 +
42 +const emit = defineEmits<{
43 + (e: "deleted"): void
44 +}>()
45 +
46 +const message = useMessage()
47 +const canceling = ref(false)
48 +const showDeleteConfirm = ref(false)
49 +
50 +function deleteIoc() {
51 + canceling.value = true
52 +
53 + Api.incidentManagement
54 + .deleteAlertIoc(alertId, ioc.id)
55 + .then(res => {
56 + if (res.data.success) {
57 + message.success(res.data?.message || "Case Data Store File deleted successfully")
58 + emit("deleted")
59 + } else {
60 + message.warning(res.data?.message || "An error occurred. Please try again later.")
61 + }
62 + })
63 + .catch(err => {
64 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
65 + })
66 + .finally(() => {
67 + canceling.value = false
68 + })
69 +}
70 +</script>
frontend/src/components/incidentManagement/alerts/AlertIoCsForm.vue new
+234
@@ -0,0 +1,234 @@
1 +<template>
2 + <n-spin :show="submitting" class="flex min-h-48 grow flex-col" content-class="flex flex-col grow gap-4">
3 + <n-form ref="formRef" :label-width="80" :model="form" :rules="rules">
4 + <div class="flex flex-col gap-3">
5 + <div>
6 + <n-form-item label="Description" path="ioc_description">
7 + <n-input
8 + v-model:value.trim="form.ioc_description"
9 + placeholder="Input the description..."
10 + clearable
11 + type="textarea"
12 + :autosize="{
13 + minRows: 5,
14 + maxRows: 15
15 + }"
16 + />
17 + </n-form-item>
18 + </div>
19 + <div class="flex flex-col gap-3 sm:flex-row">
20 + <n-form-item label="Type" path="ioc_type" class="basis-1/2">
21 + <n-select
22 + v-model:value="form.ioc_type"
23 + :options="iocTypeOptions"
24 + placeholder="Select the Type..."
25 + clearable
26 + to="body"
27 + @update:value="form.ioc_value && validate()"
28 + />
29 + </n-form-item>
30 + <n-form-item label="Value" path="ioc_value" class="basis-1/2">
31 + <n-input
32 + v-model:value.trim="form.ioc_value"
33 + :disabled="!form.ioc_type"
34 + placeholder="Input the value..."
35 + clearable
36 + />
37 + </n-form-item>
38 + </div>
39 +
40 + <div class="flex justify-between gap-4">
41 + <div class="flex gap-4">
42 + <slot name="additionalActions"></slot>
43 + </div>
44 + <div class="flex gap-4">
45 + <n-button :disabled="submitting" @click="reset()">Reset</n-button>
46 + <n-button :disabled="!isValid" :loading="submitting" type="primary" @click="validate(submit)">
47 + Submit
48 + </n-button>
49 + </div>
50 + </div>
51 + </div>
52 + </n-form>
53 + </n-spin>
54 +</template>
55 +
56 +<script setup lang="ts">
57 +import type { AlertIocPayload } from "@/api/endpoints/incidentManagement"
58 +import type { DeepNullable } from "@/types/common"
59 +import type { AlertIOC } from "@/types/incidentManagement/alerts.d"
60 +import Api from "@/api"
61 +import _get from "lodash/get"
62 +import _trim from "lodash/trim"
63 +import {
64 + type FormInst,
65 + type FormItemRule,
66 + type FormRules,
67 + type FormValidationError,
68 + NButton,
69 + NForm,
70 + NFormItem,
71 + NInput,
72 + NSelect,
73 + NSpin,
74 + useMessage
75 +} from "naive-ui"
76 +import isIP from "validator/es/lib/isIP"
77 +import isURL from "validator/es/lib/isURL"
78 +import { computed, onMounted, ref, toRefs, watch } from "vue"
79 +
80 +const props = defineProps<{ alertId: number }>()
81 +const emit = defineEmits<{
82 + (e: "update:loading", value: boolean): void
83 + (e: "submitted", value: AlertIOC): void
84 + (
85 + e: "mounted",
86 + value: {
87 + reset: () => void
88 + }
89 + ): void
90 +}>()
91 +
92 +const { alertId } = toRefs(props)
93 +const submitting = ref(false)
94 +const message = useMessage()
95 +const form = ref<DeepNullable<AlertIocPayload>>(getForm())
96 +const formRef = ref<FormInst | null>(null)
97 +
98 +const rules: FormRules = {
99 + ioc_value: {
100 + validator: validateValue,
101 + required: true,
102 + trigger: ["input", "blur"]
103 + },
104 + ioc_type: {
105 + message: "Please input the Type",
106 + required: true,
107 + trigger: ["input", "blur"]
108 + },
109 + ioc_description: {
110 + message: "Please input the Description",
111 + required: true,
112 + trigger: ["input", "blur"]
113 + }
114 +}
115 +
116 +const iocTypeOptions: { label: string; value: string }[] = [
117 + { label: "IP", value: "IP" },
118 + { label: "DOMAIN", value: "DOMAIN" },
119 + { label: "HASH", value: "HASH" },
120 + { label: "URL", value: "URL" }
121 +]
122 +
123 +const isValid = computed(() => {
124 + let valid = true
125 +
126 + for (const key in rules) {
127 + const rule = rules[key] as FormRules
128 +
129 + if (rule.required && !_trim(_get(form.value, key))) {
130 + valid = false
131 + }
132 + }
133 +
134 + return valid
135 +})
136 +
137 +function validateValue(rule: FormItemRule, value: string) {
138 + if (!value) {
139 + return new Error("Please input a valid Value")
140 + }
141 +
142 + switch (form.value.ioc_type) {
143 + case "URL":
144 + if (!isURL(value, { require_tld: false })) {
145 + return new Error("Please input a valid URL")
146 + }
147 + break
148 + case "DOMAIN":
149 + if (!isURL(value, { require_tld: false })) {
150 + return new Error("Please input a valid DOMAIN")
151 + }
152 + break
153 + case "IP":
154 + if (!isIP(value)) {
155 + return new Error("Please input a valid IP Address")
156 + }
157 + break
158 + }
159 +
160 + return true
161 +}
162 +
163 +function validate(cb?: () => void) {
164 + if (!formRef.value) return
165 +
166 + formRef.value.validate((errors?: Array<FormValidationError>) => {
167 + if (!errors) {
168 + if (cb && typeof cb === "function") {
169 + cb()
170 + }
171 + } else {
172 + message.warning("You must fill in the required fields correctly.")
173 + return false
174 + }
175 + })
176 +}
177 +
178 +function getForm() {
179 + const payload = {
180 + alert_id: alertId.value,
181 + ioc_value: null,
182 + ioc_type: null,
183 + ioc_description: null
184 + }
185 + return payload
186 +}
187 +
188 +function reset(force?: boolean) {
189 + if (!submitting.value || force) {
190 + resetForm()
191 + formRef.value?.restoreValidation()
192 + }
193 +}
194 +
195 +function resetForm() {
196 + form.value = getForm()
197 +}
198 +
199 +function submit() {
200 + submitting.value = true
201 +
202 + Api.incidentManagement
203 + .createAlertIoc(form.value as AlertIocPayload)
204 + .then(res => {
205 + if (res.data.success) {
206 + emit("submitted", {
207 + id: res.data.alert_ioc.ioc_id,
208 + description: form.value.ioc_description || "",
209 + type: form.value.ioc_type || "",
210 + value: form.value.ioc_value || ""
211 + })
212 + reset()
213 + } else {
214 + message.warning(res.data?.message || "An error occurred. Please try again later.")
215 + }
216 + })
217 + .catch(err => {
218 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
219 + })
220 + .finally(() => {
221 + submitting.value = false
222 + })
223 +}
224 +
225 +watch(submitting, val => {
226 + emit("update:loading", val)
227 +})
228 +
229 +onMounted(() => {
230 + emit("mounted", {
231 + reset
232 + })
233 +})
234 +</script>
frontend/src/components/incidentManagement/alerts/AlertIoCsList.vue new
+97
@@ -0,0 +1,97 @@
1 +<template>
2 + <div>
3 + <n-collapse-transition :show="!showForm">
4 + <n-button v-if="iocs.length" :loading="submitting" type="primary" @click="openForm()">
5 + <template #icon>
6 + <Icon :name="AddIcon" />
7 + </template>
8 + Create IoC
9 + </n-button>
10 + </n-collapse-transition>
11 +
12 + <CollapseKeepAlive :show="showForm">
13 + <div class="flex flex-col gap-2">
14 + <AlertIoCsForm
15 + v-model:loading="submitting"
16 + :alert-id
17 + @mounted="formCTX = $event"
18 + @submitted="addIoc($event)"
19 + >
20 + <template #additionalActions>
21 + <n-button secondary :disabled="submitting" @click="closeForm()">Close</n-button>
22 + </template>
23 + </AlertIoCsForm>
24 + </div>
25 + </CollapseKeepAlive>
26 +
27 + <div class="mt-3 flex flex-col gap-2">
28 + <template v-if="iocs.length">
29 + <AlertIoCItem v-for="ioc of iocs" :key="ioc.id" :ioc :alert-id embedded @deleted="delIoc(ioc)" />
30 + </template>
31 + <template v-else>
32 + <n-collapse-transition :show="!showForm">
33 + <n-empty v-if="!loading" class="min-h-48">
34 + <div class="flex flex-col items-center gap-4">
35 + <p>No IoCs found</p>
36 + <n-button type="primary" :loading="submitting" @click="openForm()">
37 + <template #icon>
38 + <Icon :name="AddIcon" />
39 + </template>
40 + Create an IoCs
41 + </n-button>
42 + </div>
43 + </n-empty>
44 + </n-collapse-transition>
45 + </template>
46 + </div>
47 + </div>
48 +</template>
49 +
50 +<script setup lang="ts">
51 +import type { AlertIOC } from "@/types/incidentManagement/alerts.d"
52 +import CollapseKeepAlive from "@/components/common/CollapseKeepAlive.vue"
53 +import Icon from "@/components/common/Icon.vue"
54 +import _get from "lodash/get"
55 +import _trim from "lodash/trim"
56 +import { NButton, NCollapseTransition, NEmpty } from "naive-ui"
57 +import { computed, ref, toRefs } from "vue"
58 +import AlertIoCItem from "./AlertIoCItem.vue"
59 +import AlertIoCsForm from "./AlertIoCsForm.vue"
60 +
61 +const props = defineProps<{ iocs: AlertIOC[]; alertId: number }>()
62 +const emit = defineEmits<{
63 + (e: "updated", value: AlertIOC[]): void
64 +}>()
65 +
66 +const { iocs, alertId } = toRefs(props)
67 +
68 +const AddIcon = "carbon:add-alt"
69 +const iocsList = ref<AlertIOC[]>(iocs.value)
70 +const showForm = ref(false)
71 +const submitting = ref(false)
72 +const deleting = ref(false)
73 +const loading = computed(() => submitting.value || deleting.value)
74 +const formCTX = ref<{ reset: (force?: boolean) => void } | null>(null)
75 +
76 +function openForm() {
77 + showForm.value = true
78 +}
79 +
80 +function closeForm(doReset?: boolean) {
81 + showForm.value = false
82 + if (doReset) {
83 + formCTX.value?.reset(true)
84 + }
85 +}
86 +
87 +function delIoc(ioc: AlertIOC) {
88 + iocsList.value = iocsList.value.filter(o => o.id !== ioc.id)
89 + emit("updated", iocsList.value)
90 +}
91 +
92 +function addIoc(ioc: AlertIOC) {
93 + iocsList.value.push(ioc)
94 + closeForm(true)
95 + emit("updated", iocsList.value)
96 +}
97 +</script>
frontend/src/components/incidentManagement/alerts/AlertItem.vue
+15
@@ -205,6 +205,20 @@
205 Comments
206 </n-tooltip>
207
208 + <n-tooltip trigger="hover">
209 + <template #trigger>
210 + <Badge type="splitted" class="xs:!flex !hidden">
211 + <template #iconLeft>
212 + <Icon :name="IoCsIcon" :size="16" />
213 + </template>
214 + <template #value>
215 + {{ alert.iocs?.length || 0 }}
216 + </template>
217 + </Badge>
218 + </template>
219 + IoC
220 + </n-tooltip>
221 +
222 <span
223 v-for="tag of alert.tags"
224 :key="tag.tag"
@@ -286,6 +300,7 @@ const TimeIcon = "carbon:time"
300 const EditIcon = "uil:edit-alt"
301 const CommentsIcon = "carbon:chat"
302 const AssetsIcon = "carbon:document-security"
303 +const IoCsIcon = "carbon:ibm-watson-discovery"
304
305 const { gotoCustomer } = useGoto()
306 const dialog = useDialog()
frontend/src/components/incidentManagement/alerts/AlertsFilters.vue
+14 -1
@@ -115,6 +115,18 @@
115 </template>
116 </n-button>
117 </n-input-group>
118 +
119 + <n-input-group
120 + v-if="filter.type === 'iocValue' && (typeof filter.value === 'string' || filter.value === null)"
121 + >
122 + <n-input-group-label size="small">{{ getFilterLabel(filter.type) }}</n-input-group-label>
123 + <n-input v-model:value="filter.value" autosize placeholder="Input..." size="small" class="!min-w-40" />
124 + <n-button size="small" secondary tabindex="-1" @click="delFilter(filter.type)">
125 + <template #icon>
126 + <Icon :name="DelIcon" />
127 + </template>
128 + </n-button>
129 + </n-input-group>
130 </div>
131
132 <n-dropdown
@@ -194,7 +206,8 @@ const typeOptions: { label: string; value: AlertsFilterTypes }[] = [
206 { label: "Tag", value: "tag" },
207 { label: "Title", value: "title" },
208 { label: "Customer Code", value: "customerCode" },
197 - { label: "Source", value: "source" }
209 + { label: "Source", value: "source" },
210 + { label: "IoC", value: "iocValue" }
211 ]
212
213 const filters = ref<AlertsListFilter[]>([])
frontend/src/components/incidentManagement/alerts/AlertsList.vue
+10 -60
@@ -92,16 +92,15 @@
92 </n-badge>
93 </div>
94
95 - <div v-if="showFilters" class="filters-box" :class="{ open: showFiltersView }">
96 - <n-card size="small" :bordered="false">
97 - <AlertsFilters
98 - :use-query-string="!preset?.length"
99 - :preset
100 - @submit="applyFilters"
101 - @mounted="filtersCTX = $event"
102 - />
103 - </n-card>
104 - </div>
95 + <CollapseKeepAlive v-if="showFilters" :show="showFiltersView" embedded arrow="top-right">
96 + <AlertsFilters
97 + :use-query-string="!preset?.length"
98 + :preset
99 + class="p-3"
100 + @submit="applyFilters"
101 + @mounted="filtersCTX = $event"
102 + />
103 + </CollapseKeepAlive>
104
105 <n-spin :show="loading">
106 <div class="my-3 flex min-h-52 flex-col gap-2">
@@ -141,6 +140,7 @@ import type { Alert } from "@/types/incidentManagement/alerts.d"
140 import type { Case } from "@/types/incidentManagement/cases.d"
141 import type { AlertsListFilter } from "./types.d"
142 import Api from "@/api"
143 +import CollapseKeepAlive from "@/components/common/CollapseKeepAlive.vue"
144 import Icon from "@/components/common/Icon.vue"
145 import { useResizeObserver, useStorage } from "@vueuse/core"
146 import axios from "axios"
@@ -336,53 +336,3 @@ onBeforeMount(() => {
336 getCases()
337 })
338 </script>
339 -
340 -<style lang="scss" scoped>
341 -.alerts-list {
342 - .filters-box {
343 - overflow: hidden;
344 - display: grid;
345 - grid-template-rows: 0fr;
346 - padding-top: 0px;
347 - opacity: 0;
348 - position: relative;
349 - transition:
350 - opacity var(--router-transition-duration) ease-out,
351 - grid-template-rows var(--router-transition-duration) ease-out,
352 - padding-top var(--router-transition-duration) ease-out;
353 -
354 - &::after {
355 - --size: 10px;
356 - content: "";
357 - width: 0;
358 - height: 0;
359 - border-left: var(--size) solid transparent;
360 - border-right: var(--size) solid transparent;
361 - border-bottom: var(--size) solid var(--bg-secondary-color);
362 - position: absolute;
363 - top: 2px;
364 - right: 8px;
365 - transform: rotateX(90deg);
366 - transform-origin: top center;
367 - transition:
368 - opacity var(--router-transition-duration) ease-out,
369 - transform var(--router-transition-duration) ease-out;
370 - }
371 -
372 - & > * {
373 - background-color: var(--bg-secondary-color);
374 - overflow: hidden;
375 - }
376 -
377 - &.open {
378 - grid-template-rows: 1fr;
379 - opacity: 1;
380 - @apply pt-3;
381 -
382 - &::after {
383 - transform: rotateX(0deg);
384 - }
385 - }
386 - }
387 -}
388 -</style>
frontend/src/components/sigma/QueriesList.vue
+5 -56
@@ -92,14 +92,12 @@
92 </n-popover>
93 </div>
94
95 - <div class="actions-box" :class="{ open: showActionsView }">
96 - <n-card size="small" content-class="bg-secondary" class="overflow-hidden" :bordered="false">
97 - <QueriesActions @updated="getData()" />
98 - </n-card>
99 - </div>
95 + <CollapseKeepAlive :show="showActionsView" embedded arrow="top-left" arrow-offset="54px">
96 + <QueriesActions class="p-3" @updated="getData()" />
97 + </CollapseKeepAlive>
98
99 <n-spin :show="loading">
102 - <div class="list my-3 flex flex-col gap-2">
100 + <div class="my-3 flex min-h-52 flex-col gap-2">
101 <template v-if="queriesList.length">
102 <QueryItem
103 v-for="query of itemsPaginated"
@@ -131,6 +129,7 @@
129 <script setup lang="ts">
130 import type { SigmaQuery } from "@/types/sigma.d"
131 import Api from "@/api"
132 +import CollapseKeepAlive from "@/components/common/CollapseKeepAlive.vue"
133 import Icon from "@/components/common/Icon.vue"
134 import { useResizeObserver, useStorage } from "@vueuse/core"
135 import _cloneDeep from "lodash/cloneDeep"
@@ -256,53 +255,3 @@ onBeforeMount(() => {
255 getData()
256 })
257 </script>
259 -
260 -<style lang="scss" scoped>
261 -.sigma-queries-list {
262 - .list {
263 - container-type: inline-size;
264 - min-height: 200px;
265 - }
266 -
267 - .actions-box {
268 - overflow: hidden;
269 - display: grid;
270 - grid-template-rows: 0fr;
271 - padding-top: 0px;
272 - opacity: 0;
273 - position: relative;
274 - transition:
275 - opacity var(--router-transition-duration) ease-out,
276 - grid-template-rows var(--router-transition-duration) ease-out,
277 - padding-top var(--router-transition-duration) ease-out;
278 -
279 - &::after {
280 - --size: 10px;
281 - content: "";
282 - width: 0;
283 - height: 0;
284 - border-left: var(--size) solid transparent;
285 - border-right: var(--size) solid transparent;
286 - border-bottom: var(--size) solid var(--bg-secondary-color);
287 - position: absolute;
288 - top: 2px;
289 - left: 54px;
290 - transform: rotateX(90deg);
291 - transform-origin: top center;
292 - transition:
293 - opacity var(--router-transition-duration) ease-out,
294 - transform var(--router-transition-duration) ease-out;
295 - }
296 -
297 - &.open {
298 - grid-template-rows: 1fr;
299 - opacity: 1;
300 - @apply pt-3;
301 -
302 - &::after {
303 - transform: rotateX(0deg);
304 - }
305 - }
306 - }
307 -}
308 -</style>
frontend/src/types/incidentManagement/alerts.d.ts
+10
@@ -8,6 +8,8 @@ export type AlertsFilter =
8 | { title: string }
9 | { customerCode: string }
10 | { source: string }
11 + | { source: string }
12 + | { iocValue: string }
13
14 export interface Alert {
15 id: number
@@ -23,6 +25,14 @@ export interface Alert {
25 assets: AlertAsset[]
26 tags: AlertTag[]
27 linked_cases: Omit<Case, "alerts">[]
28 + iocs: AlertIOC[]
29 +}
30 +
31 +export interface AlertIOC {
32 + id: number
33 + description: string
34 + type: string
35 + value: string
36 }
37
38 export type AlertStatus = "OPEN" | "CLOSED" | "IN_PROGRESS"