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"