From 5423cc34a9497d2e0f86e4431c05e6c51a3069c5 Mon Sep 17 00:00:00 2001 From: Kirill Zotkin Date: Thu, 13 Feb 2025 13:52:02 +0200 Subject: [PATCH] Init commit --- .gitignore | 5 + .vscode/launch.json | 15 + .vscode/tasks.json | 37 + README.md | 39 + ...sProject.CommunicationControl.Logic.csproj | 18 + .../Services/CommunicationControlService.cs | 155 + .../ICommunicationControlService.cs | 14 + .../Services/Interfaces/IPublishService.cs | 7 + .../Interfaces/IRedisKeyValueService.cs | 12 + .../Services/Interfaces/ISpatialService.cs | 9 + .../Services/RedisKeyValueService.cs | 75 + .../Services/RedisPublishService.cs | 28 + .../Services/SpatialService.cs | 35 + ...vOpsProject.Example.MessageListener.csproj | 14 + .../Program.cs | 28 + .../Clients/HiveHttpClient.cs | 36 + .../Configuration/RedisKeys.cs | 7 + .../Configuration/RedisOptions.cs | 8 + .../DevOpsProject.Shared.csproj | 9 + .../DevOpsProject.Shared/Enums/State.cs | 9 + .../Exceptions/HiveConnectionException.cs | 19 + .../Exceptions/HiveNotFoundException.cs | 19 + .../Messages/BaseMessage.cs | 7 + .../Messages/HiveConnectedMessage.cs | 11 + .../Messages/HiveDisconnectedMessage.cs | 9 + .../Messages/MoveHiveMessage.cs | 10 + .../Messages/TelemetrySentMessage.cs | 10 + .../DevOpsProject.Shared/Models/HiveModel.cs | 10 + .../Models/HiveOperationalArea.cs | 12 + .../Models/HiveTelemetryModel.cs | 14 + .../DevOpsProject.Shared/Models/Location.cs | 8 + .../Models/OperationalAreaConfig.cs | 13 + src/CommunicationControl/DevOpsProject.sln | 40 + .../DevOpsProject.sln.DotSettings.user | 2 + .../Controllers/ClientController.cs | 67 + .../Controllers/HiveController.cs | 63 + .../DevOpsProject/DI/LogicConfiguration.cs | 18 + .../DevOpsProject/DI/RedisConfiguration.cs | 31 + .../DTO/Client/Request/MoveHivesRequest.cs | 10 + .../DTO/Hive/Request/HiveConnectRequest.cs | 9 + .../DTO/Hive/Request/HiveTelemetryRequest.cs | 14 + .../DTO/Hive/Response/HiveConnectResponse.cs | 10 + .../Hive/Response/HiveTelemetryResponse.cs | 7 + ...OpsProject.CommunicationControl.API.csproj | 29 + ...oject.CommunicationControl.API.csproj.user | 8 + .../DevOpsProject/DevOpsProject.http | 6 + .../Middleware/ExceptionHandlingMiddleware.cs | 35 + .../DevOpsProject/Program.cs | 85 + .../Properties/launchSettings.json | 41 + .../appsettings.Development.json | 8 + .../DevOpsProject/appsettings.json | 50 + src/MapClient/.devcontainer/devcontainer.json | 22 + src/MapClient/README.md | 20 + src/MapClient/eslint.config.js | 38 + src/MapClient/index.html | 13 + src/MapClient/package-lock.json | 4955 +++++++++++++++++ src/MapClient/package.json | 31 + src/MapClient/public/256x256.ico | Bin 0 -> 104937 bytes src/MapClient/public/256x256.png | Bin 0 -> 17276 bytes src/MapClient/public/vite.svg | 1 + src/MapClient/src/App.css | 42 + src/MapClient/src/App.jsx | 8 + src/MapClient/src/api/mapService.js | 48 + src/MapClient/src/assets/react.svg | 1 + src/MapClient/src/components/MapView.jsx | 182 + src/MapClient/src/components/Popup.jsx | 52 + src/MapClient/src/index.css | 68 + src/MapClient/src/main.jsx | 10 + src/MapClient/src/pages/Home.jsx | 12 + src/MapClient/src/styles/global.css | 5 + src/MapClient/src/styles/map.css | 0 src/MapClient/vite.config.js | 10 + 72 files changed, 6753 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json create mode 100644 README.md create mode 100644 src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/DevOpsProject.CommunicationControl.Logic.csproj create mode 100644 src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/CommunicationControlService.cs create mode 100644 src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/ICommunicationControlService.cs create mode 100644 src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/IPublishService.cs create mode 100644 src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/IRedisKeyValueService.cs create mode 100644 src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/ISpatialService.cs create mode 100644 src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/RedisKeyValueService.cs create mode 100644 src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/RedisPublishService.cs create mode 100644 src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/SpatialService.cs create mode 100644 src/CommunicationControl/DevOpsProject.Example.MessageListener/DevOpsProject.Example.MessageListener.csproj create mode 100644 src/CommunicationControl/DevOpsProject.Example.MessageListener/Program.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Clients/HiveHttpClient.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Configuration/RedisKeys.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Configuration/RedisOptions.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/DevOpsProject.Shared.csproj create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Enums/State.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Exceptions/HiveConnectionException.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Exceptions/HiveNotFoundException.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Messages/BaseMessage.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Messages/HiveConnectedMessage.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Messages/HiveDisconnectedMessage.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Messages/MoveHiveMessage.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Messages/TelemetrySentMessage.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Models/HiveModel.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Models/HiveOperationalArea.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Models/HiveTelemetryModel.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Models/Location.cs create mode 100644 src/CommunicationControl/DevOpsProject.Shared/Models/OperationalAreaConfig.cs create mode 100644 src/CommunicationControl/DevOpsProject.sln create mode 100644 src/CommunicationControl/DevOpsProject.sln.DotSettings.user create mode 100644 src/CommunicationControl/DevOpsProject/Controllers/ClientController.cs create mode 100644 src/CommunicationControl/DevOpsProject/Controllers/HiveController.cs create mode 100644 src/CommunicationControl/DevOpsProject/DI/LogicConfiguration.cs create mode 100644 src/CommunicationControl/DevOpsProject/DI/RedisConfiguration.cs create mode 100644 src/CommunicationControl/DevOpsProject/DTO/Client/Request/MoveHivesRequest.cs create mode 100644 src/CommunicationControl/DevOpsProject/DTO/Hive/Request/HiveConnectRequest.cs create mode 100644 src/CommunicationControl/DevOpsProject/DTO/Hive/Request/HiveTelemetryRequest.cs create mode 100644 src/CommunicationControl/DevOpsProject/DTO/Hive/Response/HiveConnectResponse.cs create mode 100644 src/CommunicationControl/DevOpsProject/DTO/Hive/Response/HiveTelemetryResponse.cs create mode 100644 src/CommunicationControl/DevOpsProject/DevOpsProject.CommunicationControl.API.csproj create mode 100644 src/CommunicationControl/DevOpsProject/DevOpsProject.CommunicationControl.API.csproj.user create mode 100644 src/CommunicationControl/DevOpsProject/DevOpsProject.http create mode 100644 src/CommunicationControl/DevOpsProject/Middleware/ExceptionHandlingMiddleware.cs create mode 100644 src/CommunicationControl/DevOpsProject/Program.cs create mode 100644 src/CommunicationControl/DevOpsProject/Properties/launchSettings.json create mode 100644 src/CommunicationControl/DevOpsProject/appsettings.Development.json create mode 100644 src/CommunicationControl/DevOpsProject/appsettings.json create mode 100644 src/MapClient/.devcontainer/devcontainer.json create mode 100644 src/MapClient/README.md create mode 100644 src/MapClient/eslint.config.js create mode 100644 src/MapClient/index.html create mode 100644 src/MapClient/package-lock.json create mode 100644 src/MapClient/package.json create mode 100644 src/MapClient/public/256x256.ico create mode 100644 src/MapClient/public/256x256.png create mode 100644 src/MapClient/public/vite.svg create mode 100644 src/MapClient/src/App.css create mode 100644 src/MapClient/src/App.jsx create mode 100644 src/MapClient/src/api/mapService.js create mode 100644 src/MapClient/src/assets/react.svg create mode 100644 src/MapClient/src/components/MapView.jsx create mode 100644 src/MapClient/src/components/Popup.jsx create mode 100644 src/MapClient/src/index.css create mode 100644 src/MapClient/src/main.jsx create mode 100644 src/MapClient/src/pages/Home.jsx create mode 100644 src/MapClient/src/styles/global.css create mode 100644 src/MapClient/src/styles/map.css create mode 100644 src/MapClient/vite.config.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a56a28a --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +src/MapClient/node_modules +src/CommunicationControl/.idea +bin +obj +Logs \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..722aad0 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "C#: Communication Control Debug", + "type": "dotnet", + "request": "launch", + "projectPath": "${workspaceFolder}/src/CommunicationControl/DevOpsProject/DevOpsProject.CommunicationControl.API.csproj" + } + + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..321cbc4 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,37 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..43ba548 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# Hive Emulator + +## About +This is a demo project used in the Uni DevOps course + +## Installation + +### Run Redis +```bash +docker run --name redis -d -p 6379:6379 redis +``` + +### Map Component +```bash +cd src/MapClient + +npm install + +npm run dev +``` + +### Communiction Control +```bash +cd src/CommunicationControl + +dotnet build DevOpsProject/ +``` + +## Usage + +1. Map Control is available at http://localhost:3000 +2. Redis - Get available keys: + ```bash + docker exec -it redis redis-cli + keys * + get [hiveKey] + ``` + +3. Communication Control Swagger: http://localhost:8080 \ No newline at end of file diff --git a/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/DevOpsProject.CommunicationControl.Logic.csproj b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/DevOpsProject.CommunicationControl.Logic.csproj new file mode 100644 index 0000000..6417dac --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/DevOpsProject.CommunicationControl.Logic.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/CommunicationControlService.cs b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/CommunicationControlService.cs new file mode 100644 index 0000000..d218e32 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/CommunicationControlService.cs @@ -0,0 +1,155 @@ +using DevOpsProject.CommunicationControl.Logic.Services.Interfaces; +using DevOpsProject.Shared.Clients; +using DevOpsProject.Shared.Configuration; +using DevOpsProject.Shared.Exceptions; +using DevOpsProject.Shared.Messages; +using DevOpsProject.Shared.Models; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace DevOpsProject.CommunicationControl.Logic.Services +{ + public class CommunicationControlService : ICommunicationControlService + { + private readonly ISpatialService _spatialService; + private readonly IRedisKeyValueService _redisService; + private readonly RedisKeys _redisKeys; + private readonly IPublishService _messageBus; + private readonly HiveHttpClient _hiveHttpClient; + private readonly ILogger _logger; + + public CommunicationControlService(ISpatialService spatialService, IRedisKeyValueService redisService, IOptionsSnapshot redisKeysSnapshot, + IPublishService messageBus, HiveHttpClient hiveHttpClient, ILogger logger) + { + _spatialService = spatialService; + _redisService = redisService; + _redisKeys = redisKeysSnapshot.Value; + _messageBus = messageBus; + _hiveHttpClient = hiveHttpClient; + _logger = logger; + } + + public async Task DisconnectHive(string hiveId) + { + bool isSuccessfullyDisconnected = false; + try + { + var result = await _redisService.DeleteAsync(hiveId); + isSuccessfullyDisconnected = result; + return result; + } + finally + { + await _messageBus.Publish(new HiveDisconnectedMessage + { + HiveID = hiveId, + IsSuccessfullyDisconnected = isSuccessfullyDisconnected + }); + } + } + + public async Task GetHiveModel(string hiveId) + { + var result = await _redisService.GetAsync(GetHiveKey(hiveId)); + return result; + } + + public async Task> GetAllHives() + { + var result = await _redisService.GetAllAsync($"{_redisKeys.HiveKey}:"); + return result; + } + + public async Task ConnectHive(HiveModel model) + { + bool result = await _redisService.SetAsync(GetHiveKey(model.HiveID), model); + if (result) + { + var operationalArea = await _spatialService.GetHiveOperationalArea(model); + await _messageBus.Publish(new HiveConnectedMessage + { + HiveID = model.HiveID, + Hive = model, + InitialOperationalArea = operationalArea, + IsSuccessfullyConnected = result + }); + return operationalArea; + } + else + { + await _messageBus.Publish(new HiveConnectedMessage + { + HiveID = model.HiveID, + Hive = model, + IsSuccessfullyConnected = result + }); + throw new HiveConnectionException($"Failed to connect hive for HiveId: {model.HiveID}"); + } + } + + public async Task AddTelemetry(HiveTelemetryModel model) + { + string hiveKey = GetHiveKey(model.HiveID); + bool hiveExists = await _redisService.CheckIfKeyExists(hiveKey); + if (hiveExists) + { + bool result = await _redisService.UpdateAsync(hiveKey, (HiveModel hive) => + { + hive.Telemetry = model; + }); + + await _messageBus.Publish(new TelemetrySentMessage + { + HiveID = model.HiveID, + Telemetry = model, + IsSuccessfullySent = result + }); + return model.Timestamp; + } + else + { + await _messageBus.Publish(new TelemetrySentMessage + { + HiveID = model.HiveID, + Telemetry = model, + IsSuccessfullySent = false + }); + throw new HiveNotFoundException($"Hive not found for id: {model.HiveID}"); + } + + } + + public async Task SendHiveControlSignal(string hiveId, Location destination) + { + var hive = await GetHiveModel(hiveId); + if (hive == null) + { + throw new Exception($"Hive control signal error: cannot find hive with id: {hiveId}"); + } + + bool isSuccessfullySent = false; + + try + { + // TODO: Schema can be moved to appsettings + var result = await _hiveHttpClient.SendHiveControlCommandAsync("http", hive.HiveIP, hive.HivePort, destination); + isSuccessfullySent = true; + return result; + } + finally + { + await _messageBus.Publish(new MoveHiveMessage + { + IsSuccessfullySent = isSuccessfullySent, + Destination = destination, + HiveID = hiveId + }); + } + } + + private string GetHiveKey(string hiveId) + { + return $"{_redisKeys.HiveKey}:{hiveId}"; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/ICommunicationControlService.cs b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/ICommunicationControlService.cs new file mode 100644 index 0000000..8e3b363 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/ICommunicationControlService.cs @@ -0,0 +1,14 @@ +using DevOpsProject.Shared.Models; + +namespace DevOpsProject.CommunicationControl.Logic.Services.Interfaces +{ + public interface ICommunicationControlService + { + Task DisconnectHive(string hiveId); + Task GetHiveModel(string hiveId); + Task> GetAllHives(); + Task ConnectHive(HiveModel model); + Task AddTelemetry(HiveTelemetryModel model); + Task SendHiveControlSignal(string hiveId, Location destination); + } +} diff --git a/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/IPublishService.cs b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/IPublishService.cs new file mode 100644 index 0000000..40cf3d8 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/IPublishService.cs @@ -0,0 +1,7 @@ +namespace DevOpsProject.CommunicationControl.Logic.Services.Interfaces +{ + public interface IPublishService + { + Task Publish(T message); + } +} diff --git a/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/IRedisKeyValueService.cs b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/IRedisKeyValueService.cs new file mode 100644 index 0000000..6dd3aba --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/IRedisKeyValueService.cs @@ -0,0 +1,12 @@ +namespace DevOpsProject.CommunicationControl.Logic.Services.Interfaces +{ + public interface IRedisKeyValueService + { + Task GetAsync(string key); + Task> GetAllAsync(string keyPattern); + Task SetAsync(string key, T value); + Task UpdateAsync(string key, Action updateAction); + Task CheckIfKeyExists(string key); + Task DeleteAsync(string key); + } +} diff --git a/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/ISpatialService.cs b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/ISpatialService.cs new file mode 100644 index 0000000..7a8d8f8 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/Interfaces/ISpatialService.cs @@ -0,0 +1,9 @@ +using DevOpsProject.Shared.Models; + +namespace DevOpsProject.CommunicationControl.Logic.Services.Interfaces +{ + public interface ISpatialService + { + Task GetHiveOperationalArea(HiveModel hiveModel); + } +} diff --git a/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/RedisKeyValueService.cs b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/RedisKeyValueService.cs new file mode 100644 index 0000000..f5e0116 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/RedisKeyValueService.cs @@ -0,0 +1,75 @@ +using DevOpsProject.CommunicationControl.Logic.Services.Interfaces; +using StackExchange.Redis; +using System.Text.Json; + +namespace DevOpsProject.CommunicationControl.Logic.Services +{ + public class RedisKeyValueService : IRedisKeyValueService + { + private readonly IConnectionMultiplexer _connectionMultiplexer; + + public RedisKeyValueService(IConnectionMultiplexer connectionMultiplexer) + { + _connectionMultiplexer = connectionMultiplexer; + } + + public async Task GetAsync(string key) + { + var db = _connectionMultiplexer.GetDatabase(); + var json = await db.StringGetAsync(key); + + return json.HasValue ? JsonSerializer.Deserialize(json) : default; + } + + public async Task> GetAllAsync(string keyPattern) + { + var server = _connectionMultiplexer.GetServer(_connectionMultiplexer.GetEndPoints().First()); + var keys = server.Keys(pattern: $"{keyPattern}*"); + + var resultList = new List(); + foreach ( var key in keys) + { + var entry = await GetAsync(key); + if (entry != null) + { + resultList.Add(entry); + } + } + + return resultList; + } + + public async Task UpdateAsync(string key, Action updateAction) + { + var db = _connectionMultiplexer.GetDatabase(); + var jsonData = await db.StringGetAsync(key); + if (!jsonData.HasValue) return false; + + var obj = JsonSerializer.Deserialize(jsonData); + if (obj == null) return false; + + updateAction(obj); + return await SetAsync(key, obj); + } + + public async Task SetAsync(string key, T value) + { + var db = _connectionMultiplexer.GetDatabase(); + var json = JsonSerializer.Serialize(value); + + return await db.StringSetAsync(key, json); + } + + public async Task CheckIfKeyExists(string key) + { + var db = _connectionMultiplexer.GetDatabase(); + return await db.KeyExistsAsync(key); + } + + public async Task DeleteAsync(string key) + { + var db = _connectionMultiplexer.GetDatabase(); + return await db.KeyDeleteAsync(key); + } + } +} diff --git a/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/RedisPublishService.cs b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/RedisPublishService.cs new file mode 100644 index 0000000..4c62e93 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/RedisPublishService.cs @@ -0,0 +1,28 @@ +using DevOpsProject.CommunicationControl.Logic.Services.Interfaces; +using DevOpsProject.Shared.Configuration; +using Microsoft.Extensions.Options; +using StackExchange.Redis; +using System.Text.Json; + +namespace DevOpsProject.CommunicationControl.Logic.Services +{ + public class RedisPublishService : IPublishService + { + private readonly IConnectionMultiplexer _connectionMultiplexer; + private readonly RedisOptions _redisOptions; + + public RedisPublishService(IConnectionMultiplexer connectionMultiplexer, IOptions redisOptions) + { + _connectionMultiplexer = connectionMultiplexer; + _redisOptions = redisOptions.Value; + } + + public async Task Publish(T message) + { + var pubsub = _connectionMultiplexer.GetSubscriber(); + var messageJson = JsonSerializer.Serialize(message); + + await pubsub.PublishAsync(_redisOptions.PublishChannel, messageJson); + } + } +} diff --git a/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/SpatialService.cs b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/SpatialService.cs new file mode 100644 index 0000000..af7f3bd --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/SpatialService.cs @@ -0,0 +1,35 @@ +using DevOpsProject.CommunicationControl.Logic.Services.Interfaces; +using DevOpsProject.Shared.Models; +using Microsoft.Extensions.Options; + +namespace DevOpsProject.CommunicationControl.Logic.Services +{ + public class SpatialService : ISpatialService + { + private readonly IOptionsMonitor _operationalAreaConfig; + + public SpatialService(IOptionsMonitor operationalAreaConfig) + { + _operationalAreaConfig = operationalAreaConfig; + } + + public async Task GetHiveOperationalArea(HiveModel hiveModel) + { + var operationalArea = new HiveOperationalArea + { + RadiusKM = _operationalAreaConfig.CurrentValue.Radius_KM, + InitialLocation = new Location + { + Latitude = _operationalAreaConfig.CurrentValue.Latitude, + Longitude = _operationalAreaConfig.CurrentValue.Longitude + }, + InitialHeight = _operationalAreaConfig.CurrentValue.InitialHeight_KM, + Speed = _operationalAreaConfig.CurrentValue.InitialSpeed_KM, + TelemetryIntervalMs = _operationalAreaConfig.CurrentValue.TelemetryInterval_MS, + PingIntervalMs = _operationalAreaConfig.CurrentValue.PingInterval_MS + }; + + return operationalArea; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Example.MessageListener/DevOpsProject.Example.MessageListener.csproj b/src/CommunicationControl/DevOpsProject.Example.MessageListener/DevOpsProject.Example.MessageListener.csproj new file mode 100644 index 0000000..32cf93d --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Example.MessageListener/DevOpsProject.Example.MessageListener.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/src/CommunicationControl/DevOpsProject.Example.MessageListener/Program.cs b/src/CommunicationControl/DevOpsProject.Example.MessageListener/Program.cs new file mode 100644 index 0000000..867ca1a --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Example.MessageListener/Program.cs @@ -0,0 +1,28 @@ +using StackExchange.Redis; + +class Program +{ + /// + /// Sample app with only purpose to listen message bus and keep queue alive inside redis + /// + /// + static async Task Main() + { + Console.WriteLine("Connecting to Redis..."); + + var redis = await ConnectionMultiplexer.ConnectAsync("localhost:6379"); + var subscriber = redis.GetSubscriber(); + + string channelName = "HiveChannel"; + + await subscriber.SubscribeAsync(channelName, (channel, message) => + { + Console.WriteLine($"Received message: {message}"); + }); + + Console.WriteLine($"Listening for messages on channel: {channelName}"); + Console.WriteLine("Press any key to exit..."); + + Console.ReadKey(); + } +} \ No newline at end of file diff --git a/src/CommunicationControl/DevOpsProject.Shared/Clients/HiveHttpClient.cs b/src/CommunicationControl/DevOpsProject.Shared/Clients/HiveHttpClient.cs new file mode 100644 index 0000000..d3fd4c5 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Clients/HiveHttpClient.cs @@ -0,0 +1,36 @@ +using System.Text; +using System.Text.Json; + +namespace DevOpsProject.Shared.Clients +{ + public class HiveHttpClient + { + private readonly HttpClient _httpClient; + + public HiveHttpClient(HttpClient httpClient) + { + _httpClient = httpClient; + } + + public async Task SendHiveControlCommandAsync(string scheme, string ip, int port, object payload) + { + var uriBuilder = new UriBuilder + { + Scheme = scheme, + Host = ip, + Port = port, + Path = "api/control" + }; + + var jsonContent = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json"); + + var response = await _httpClient.PostAsync(uriBuilder.Uri, jsonContent); + + if (response.IsSuccessStatusCode) + { + return await response.Content.ReadAsStringAsync(); + } + return null; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/Configuration/RedisKeys.cs b/src/CommunicationControl/DevOpsProject.Shared/Configuration/RedisKeys.cs new file mode 100644 index 0000000..92a0069 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Configuration/RedisKeys.cs @@ -0,0 +1,7 @@ +namespace DevOpsProject.Shared.Configuration +{ + public class RedisKeys + { + public string HiveKey { get; set; } + } +} \ No newline at end of file diff --git a/src/CommunicationControl/DevOpsProject.Shared/Configuration/RedisOptions.cs b/src/CommunicationControl/DevOpsProject.Shared/Configuration/RedisOptions.cs new file mode 100644 index 0000000..a4a68a5 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Configuration/RedisOptions.cs @@ -0,0 +1,8 @@ +namespace DevOpsProject.Shared.Configuration +{ + public class RedisOptions + { + public string ConnectionString { get; set; } + public string PublishChannel { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/DevOpsProject.Shared.csproj b/src/CommunicationControl/DevOpsProject.Shared/DevOpsProject.Shared.csproj new file mode 100644 index 0000000..bb23fb7 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/DevOpsProject.Shared.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/src/CommunicationControl/DevOpsProject.Shared/Enums/State.cs b/src/CommunicationControl/DevOpsProject.Shared/Enums/State.cs new file mode 100644 index 0000000..6c3866e --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Enums/State.cs @@ -0,0 +1,9 @@ +namespace DevOpsProject.Shared.Enums +{ + public enum State + { + Stop, + Move, + Error + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/Exceptions/HiveConnectionException.cs b/src/CommunicationControl/DevOpsProject.Shared/Exceptions/HiveConnectionException.cs new file mode 100644 index 0000000..91d8fe4 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Exceptions/HiveConnectionException.cs @@ -0,0 +1,19 @@ +namespace DevOpsProject.Shared.Exceptions +{ + public class HiveConnectionException : Exception + { + public HiveConnectionException() + { + } + + public HiveConnectionException(string message) + : base(message) + { + } + + public HiveConnectionException(string message, Exception inner) + : base(message, inner) + { + } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/Exceptions/HiveNotFoundException.cs b/src/CommunicationControl/DevOpsProject.Shared/Exceptions/HiveNotFoundException.cs new file mode 100644 index 0000000..ada24fa --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Exceptions/HiveNotFoundException.cs @@ -0,0 +1,19 @@ +namespace DevOpsProject.Shared.Exceptions +{ + public class HiveNotFoundException : Exception + { + public HiveNotFoundException() + { + } + + public HiveNotFoundException(string message) + : base(message) + { + } + + public HiveNotFoundException(string message, Exception inner) + : base(message, inner) + { + } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/Messages/BaseMessage.cs b/src/CommunicationControl/DevOpsProject.Shared/Messages/BaseMessage.cs new file mode 100644 index 0000000..6a20b1a --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Messages/BaseMessage.cs @@ -0,0 +1,7 @@ +namespace DevOpsProject.Shared.Messages +{ + public abstract class BaseMessage + { + public string HiveID { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/Messages/HiveConnectedMessage.cs b/src/CommunicationControl/DevOpsProject.Shared/Messages/HiveConnectedMessage.cs new file mode 100644 index 0000000..03295c9 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Messages/HiveConnectedMessage.cs @@ -0,0 +1,11 @@ +using DevOpsProject.Shared.Models; + +namespace DevOpsProject.Shared.Messages +{ + public class HiveConnectedMessage : BaseMessage + { + public bool IsSuccessfullyConnected { get; set; } + public HiveModel Hive { get; set; } + public HiveOperationalArea InitialOperationalArea { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/Messages/HiveDisconnectedMessage.cs b/src/CommunicationControl/DevOpsProject.Shared/Messages/HiveDisconnectedMessage.cs new file mode 100644 index 0000000..a7331ef --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Messages/HiveDisconnectedMessage.cs @@ -0,0 +1,9 @@ +using DevOpsProject.Shared.Models; + +namespace DevOpsProject.Shared.Messages +{ + public class HiveDisconnectedMessage : BaseMessage + { + public bool IsSuccessfullyDisconnected { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/Messages/MoveHiveMessage.cs b/src/CommunicationControl/DevOpsProject.Shared/Messages/MoveHiveMessage.cs new file mode 100644 index 0000000..612f255 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Messages/MoveHiveMessage.cs @@ -0,0 +1,10 @@ +using DevOpsProject.Shared.Models; + +namespace DevOpsProject.Shared.Messages +{ + public class MoveHiveMessage : BaseMessage + { + public bool IsSuccessfullySent { get; set; } + public Location Destination { get;set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/Messages/TelemetrySentMessage.cs b/src/CommunicationControl/DevOpsProject.Shared/Messages/TelemetrySentMessage.cs new file mode 100644 index 0000000..f0bb684 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Messages/TelemetrySentMessage.cs @@ -0,0 +1,10 @@ +using DevOpsProject.Shared.Models; + +namespace DevOpsProject.Shared.Messages +{ + public class TelemetrySentMessage : BaseMessage + { + public bool IsSuccessfullySent { get; set; } + public HiveTelemetryModel Telemetry { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/Models/HiveModel.cs b/src/CommunicationControl/DevOpsProject.Shared/Models/HiveModel.cs new file mode 100644 index 0000000..9a77869 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Models/HiveModel.cs @@ -0,0 +1,10 @@ +namespace DevOpsProject.Shared.Models +{ + public class HiveModel + { + public string HiveID { get; set; } + public string HiveIP { get; set; } + public int HivePort { get; set; } + public HiveTelemetryModel Telemetry { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/Models/HiveOperationalArea.cs b/src/CommunicationControl/DevOpsProject.Shared/Models/HiveOperationalArea.cs new file mode 100644 index 0000000..f71fd4b --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Models/HiveOperationalArea.cs @@ -0,0 +1,12 @@ +namespace DevOpsProject.Shared.Models +{ + public class HiveOperationalArea + { + public double RadiusKM { get; set; } + public Location InitialLocation { get; set; } + public float InitialHeight { get; set; } + public float Speed { get; set; } + public int TelemetryIntervalMs { get; set; } + public int PingIntervalMs { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/Models/HiveTelemetryModel.cs b/src/CommunicationControl/DevOpsProject.Shared/Models/HiveTelemetryModel.cs new file mode 100644 index 0000000..372902c --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Models/HiveTelemetryModel.cs @@ -0,0 +1,14 @@ +using DevOpsProject.Shared.Enums; + +namespace DevOpsProject.Shared.Models +{ + public class HiveTelemetryModel + { + public string HiveID { get; set; } + public Location Location { get; set; } + public float Speed { get; set; } + public float Height { get; set; } + public State State { get; set; } + public DateTime Timestamp { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/Models/Location.cs b/src/CommunicationControl/DevOpsProject.Shared/Models/Location.cs new file mode 100644 index 0000000..513bec9 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Models/Location.cs @@ -0,0 +1,8 @@ +namespace DevOpsProject.Shared.Models +{ + public struct Location + { + public float Latitude { get; set; } + public float Longitude { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject.Shared/Models/OperationalAreaConfig.cs b/src/CommunicationControl/DevOpsProject.Shared/Models/OperationalAreaConfig.cs new file mode 100644 index 0000000..0b5505e --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.Shared/Models/OperationalAreaConfig.cs @@ -0,0 +1,13 @@ +namespace DevOpsProject.Shared.Models +{ + public class OperationalAreaConfig + { + public float Latitude { get; set; } + public float Longitude { get; set; } + public float Radius_KM { get; set; } + public float InitialHeight_KM { get; set; } + public float InitialSpeed_KM { get; set; } + public int TelemetryInterval_MS { get; set; } + public int PingInterval_MS { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject.sln b/src/CommunicationControl/DevOpsProject.sln new file mode 100644 index 0000000..988ed94 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.sln @@ -0,0 +1,40 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35707.178 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevOpsProject.CommunicationControl.API", "DevOpsProject\DevOpsProject.CommunicationControl.API.csproj", "{BB9B9EA1-0281-4242-9344-07DFF6A20574}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevOpsProject.CommunicationControl.Logic", "DevOpsProject.CommunicationControl.Logic\DevOpsProject.CommunicationControl.Logic.csproj", "{5B279B4B-5842-413A-8E76-158C7472F45D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevOpsProject.Shared", "DevOpsProject.Shared\DevOpsProject.Shared.csproj", "{7C98DF1D-D8B9-4DC5-A0AB-723FE2E658BE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevOpsProject.Example.MessageListener", "DevOpsProject.Example.MessageListener\DevOpsProject.Example.MessageListener.csproj", "{CBB302CE-D22A-4DA0-8811-E4F8FDFC1C4B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BB9B9EA1-0281-4242-9344-07DFF6A20574}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB9B9EA1-0281-4242-9344-07DFF6A20574}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB9B9EA1-0281-4242-9344-07DFF6A20574}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB9B9EA1-0281-4242-9344-07DFF6A20574}.Release|Any CPU.Build.0 = Release|Any CPU + {5B279B4B-5842-413A-8E76-158C7472F45D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B279B4B-5842-413A-8E76-158C7472F45D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B279B4B-5842-413A-8E76-158C7472F45D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B279B4B-5842-413A-8E76-158C7472F45D}.Release|Any CPU.Build.0 = Release|Any CPU + {7C98DF1D-D8B9-4DC5-A0AB-723FE2E658BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7C98DF1D-D8B9-4DC5-A0AB-723FE2E658BE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7C98DF1D-D8B9-4DC5-A0AB-723FE2E658BE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7C98DF1D-D8B9-4DC5-A0AB-723FE2E658BE}.Release|Any CPU.Build.0 = Release|Any CPU + {CBB302CE-D22A-4DA0-8811-E4F8FDFC1C4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CBB302CE-D22A-4DA0-8811-E4F8FDFC1C4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CBB302CE-D22A-4DA0-8811-E4F8FDFC1C4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CBB302CE-D22A-4DA0-8811-E4F8FDFC1C4B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/CommunicationControl/DevOpsProject.sln.DotSettings.user b/src/CommunicationControl/DevOpsProject.sln.DotSettings.user new file mode 100644 index 0000000..35b3a77 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.sln.DotSettings.user @@ -0,0 +1,2 @@ + + ForceIncluded \ No newline at end of file diff --git a/src/CommunicationControl/DevOpsProject/Controllers/ClientController.cs b/src/CommunicationControl/DevOpsProject/Controllers/ClientController.cs new file mode 100644 index 0000000..46219ca --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/Controllers/ClientController.cs @@ -0,0 +1,67 @@ +using DevOpsProject.CommunicationControl.API.DTO.Client.Request; +using DevOpsProject.CommunicationControl.Logic.Services.Interfaces; +using DevOpsProject.Shared.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; + +namespace DevOpsProject.CommunicationControl.API.Controllers +{ + + [ApiController] + [Route("api/client")] + public class ClientController : Controller + { + private readonly ICommunicationControlService _communicationControlService; + private readonly IOptionsMonitor _operationalAreaConfig; + + public ClientController(ICommunicationControlService communicationControlService, IOptionsMonitor operationalAreaConfig) + { + _communicationControlService = communicationControlService; + _operationalAreaConfig = operationalAreaConfig; + } + + [HttpGet("area")] + public async Task GetOperationalArea() + { + return Ok(_operationalAreaConfig.CurrentValue); + } + + [HttpGet("hive/{hiveId}")] + public async Task GetHive(string hiveId) + { + var hiveModel = await _communicationControlService.GetHiveModel(hiveId); + + return Ok(hiveModel); + } + + [HttpGet("hive")] + public async Task GetHives() + { + + var hives = await _communicationControlService.GetAllHives(); + + return Ok(hives); + } + + [HttpDelete("hive/{hiveId}")] + public async Task DisconnectHive(string hiveId) + { + var disconnetResult = await _communicationControlService.DisconnectHive(hiveId); + return Ok(disconnetResult); + } + + [HttpPatch("hive")] + public async Task SendBulkHiveMovingSignal(MoveHivesRequest request) + { + if (request?.Hives == null || !request.Hives.Any()) + return BadRequest("No hive IDs provided."); + + foreach (var id in request.Hives) + { + Task.Run(async () => await _communicationControlService.SendHiveControlSignal(id, request.Destination)); + } + + return Accepted("Hives are being moved asynchronously."); + } + } +} diff --git a/src/CommunicationControl/DevOpsProject/Controllers/HiveController.cs b/src/CommunicationControl/DevOpsProject/Controllers/HiveController.cs new file mode 100644 index 0000000..e16b0ce --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/Controllers/HiveController.cs @@ -0,0 +1,63 @@ +using DevOpsProject.CommunicationControl.API.DTO.Hive.Request; +using DevOpsProject.CommunicationControl.API.DTO.Hive.Response; +using DevOpsProject.CommunicationControl.Logic.Services.Interfaces; +using DevOpsProject.Shared.Models; +using Microsoft.AspNetCore.Mvc; + +namespace DevOpsProject.CommunicationControl.API.Controllers +{ + [ApiController] + [Route("api/hive")] + public class HiveController : Controller + { + private readonly ICommunicationControlService _communicationControlService; + + public HiveController(ICommunicationControlService communicationControlService) + { + _communicationControlService = communicationControlService; + } + + [HttpPost("connect")] + public async Task Connect(HiveConnectRequest request) + { + var hiveModel = new HiveModel + { + HiveID = request.HiveID, + HiveIP = request.HiveIP, + HivePort = request.HivePort, + }; + + var hiveOperationalArea = await _communicationControlService.ConnectHive(hiveModel); + var connectResponse = new HiveConnectResponse + { + ConnectResult = true, + OperationalArea = hiveOperationalArea, + }; + + return Ok(connectResponse); + } + + [HttpPost("telemetry")] + public async Task Telemetry(HiveTelemetryRequest request) + { + var hiveTelemetryModel = new HiveTelemetryModel + { + HiveID = request.HiveID, + Location = request.Location, + Speed = request.Speed, + Height = request.Height, + State = request.State, + Timestamp = DateTime.Now + }; + + var telemetryUpdateTimestamp = await _communicationControlService.AddTelemetry(hiveTelemetryModel); + var telemetryResponse = new HiveTelemetryResponse + { + Timestamp = telemetryUpdateTimestamp + }; + + return Ok(telemetryResponse); + } + + } +} diff --git a/src/CommunicationControl/DevOpsProject/DI/LogicConfiguration.cs b/src/CommunicationControl/DevOpsProject/DI/LogicConfiguration.cs new file mode 100644 index 0000000..e5bfa63 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DI/LogicConfiguration.cs @@ -0,0 +1,18 @@ +using DevOpsProject.CommunicationControl.Logic.Services; +using DevOpsProject.CommunicationControl.Logic.Services.Interfaces; + +namespace DevOpsProject.CommunicationControl.API.DI +{ + public static class LogicConfiguration + { + public static IServiceCollection AddCommunicationControlLogic(this IServiceCollection serviceCollection) + { + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + + return serviceCollection; + } + + + } +} diff --git a/src/CommunicationControl/DevOpsProject/DI/RedisConfiguration.cs b/src/CommunicationControl/DevOpsProject/DI/RedisConfiguration.cs new file mode 100644 index 0000000..0e0d20a --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DI/RedisConfiguration.cs @@ -0,0 +1,31 @@ +using DevOpsProject.CommunicationControl.Logic.Services.Interfaces; +using DevOpsProject.CommunicationControl.Logic.Services; +using DevOpsProject.Shared.Configuration; +using StackExchange.Redis; + +namespace DevOpsProject.CommunicationControl.API.DI +{ + public static class RedisConfiguration + { + public static IServiceCollection AddRedis(this IServiceCollection serviceCollection, IConfiguration configuration) + { + var redisConfiguration = configuration.GetSection("Redis").Get(); + var redis = ConnectionMultiplexer.Connect(redisConfiguration.ConnectionString); + + serviceCollection.AddSingleton(redis); + + serviceCollection.Configure( + configuration.GetSection("Redis")); + + serviceCollection.Configure( + configuration.GetSection("RedisKeys")); + + serviceCollection.AddTransient(); + + // add message bus here - currently using Redis implementation + serviceCollection.AddTransient(); + + return serviceCollection; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject/DTO/Client/Request/MoveHivesRequest.cs b/src/CommunicationControl/DevOpsProject/DTO/Client/Request/MoveHivesRequest.cs new file mode 100644 index 0000000..725fa7d --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DTO/Client/Request/MoveHivesRequest.cs @@ -0,0 +1,10 @@ +using DevOpsProject.Shared.Models; + +namespace DevOpsProject.CommunicationControl.API.DTO.Client.Request +{ + public class MoveHivesRequest + { + public List Hives { get;set;} + public Location Destination { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject/DTO/Hive/Request/HiveConnectRequest.cs b/src/CommunicationControl/DevOpsProject/DTO/Hive/Request/HiveConnectRequest.cs new file mode 100644 index 0000000..a62dde8 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DTO/Hive/Request/HiveConnectRequest.cs @@ -0,0 +1,9 @@ +namespace DevOpsProject.CommunicationControl.API.DTO.Hive.Request +{ + public class HiveConnectRequest + { + public string HiveIP { get; set; } + public int HivePort { get; set; } + public string HiveID { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject/DTO/Hive/Request/HiveTelemetryRequest.cs b/src/CommunicationControl/DevOpsProject/DTO/Hive/Request/HiveTelemetryRequest.cs new file mode 100644 index 0000000..9aac085 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DTO/Hive/Request/HiveTelemetryRequest.cs @@ -0,0 +1,14 @@ +using DevOpsProject.Shared.Enums; +using DevOpsProject.Shared.Models; + +namespace DevOpsProject.CommunicationControl.API.DTO.Hive.Request +{ + public class HiveTelemetryRequest + { + public string HiveID { get; set; } + public Location Location { get; set; } + public float Speed { get; set; } + public float Height { get; set; } + public State State { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject/DTO/Hive/Response/HiveConnectResponse.cs b/src/CommunicationControl/DevOpsProject/DTO/Hive/Response/HiveConnectResponse.cs new file mode 100644 index 0000000..5c79d8a --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DTO/Hive/Response/HiveConnectResponse.cs @@ -0,0 +1,10 @@ +using DevOpsProject.Shared.Models; + +namespace DevOpsProject.CommunicationControl.API.DTO.Hive.Response +{ + public class HiveConnectResponse + { + public bool ConnectResult { get; set; } + public HiveOperationalArea OperationalArea { get;set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject/DTO/Hive/Response/HiveTelemetryResponse.cs b/src/CommunicationControl/DevOpsProject/DTO/Hive/Response/HiveTelemetryResponse.cs new file mode 100644 index 0000000..f0f6e31 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DTO/Hive/Response/HiveTelemetryResponse.cs @@ -0,0 +1,7 @@ +namespace DevOpsProject.CommunicationControl.API.DTO.Hive.Response +{ + public class HiveTelemetryResponse + { + public DateTime Timestamp { get; set; } + } +} diff --git a/src/CommunicationControl/DevOpsProject/DevOpsProject.CommunicationControl.API.csproj b/src/CommunicationControl/DevOpsProject/DevOpsProject.CommunicationControl.API.csproj new file mode 100644 index 0000000..43a5b2f --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DevOpsProject.CommunicationControl.API.csproj @@ -0,0 +1,29 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/CommunicationControl/DevOpsProject/DevOpsProject.CommunicationControl.API.csproj.user b/src/CommunicationControl/DevOpsProject/DevOpsProject.CommunicationControl.API.csproj.user new file mode 100644 index 0000000..5740f7d --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DevOpsProject.CommunicationControl.API.csproj.user @@ -0,0 +1,8 @@ + + + + https + MvcControllerEmptyScaffolder + root/Common/MVC/Controller + + \ No newline at end of file diff --git a/src/CommunicationControl/DevOpsProject/DevOpsProject.http b/src/CommunicationControl/DevOpsProject/DevOpsProject.http new file mode 100644 index 0000000..abf8b7b --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DevOpsProject.http @@ -0,0 +1,6 @@ +@DevOpsProject_HostAddress = http://localhost:5134 + +GET {{DevOpsProject_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/src/CommunicationControl/DevOpsProject/Middleware/ExceptionHandlingMiddleware.cs b/src/CommunicationControl/DevOpsProject/Middleware/ExceptionHandlingMiddleware.cs new file mode 100644 index 0000000..c4314b5 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/Middleware/ExceptionHandlingMiddleware.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Diagnostics; +using System.Text.Json; + +namespace DevOpsProject.CommunicationControl.API.Middleware +{ + public class ExceptionHandlingMiddleware : IExceptionHandler + { + private readonly ILogger _logger; + private readonly IHostEnvironment _hostEnvironment; + + public ExceptionHandlingMiddleware(ILogger logger, IHostEnvironment hostEnvironment) + { + _hostEnvironment = hostEnvironment; + _logger = logger; + } + + public async ValueTask TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken) + { + _logger.LogError(exception, "Unhandled exception occured: {Message}", exception.Message); + + httpContext.Response.StatusCode = StatusCodes.Status500InternalServerError; + httpContext.Response.ContentType = "application/json"; + + var errorResponse = new + { + Message = "Unexpected error occured", + Detail = _hostEnvironment.IsDevelopment() ? exception.ToString() : null + }; + + var jsonResponse = JsonSerializer.Serialize(errorResponse, new JsonSerializerOptions { WriteIndented = true }); + await httpContext.Response.WriteAsync(jsonResponse, cancellationToken); + return true; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject/Program.cs b/src/CommunicationControl/DevOpsProject/Program.cs new file mode 100644 index 0000000..8076fb8 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/Program.cs @@ -0,0 +1,85 @@ +using DevOpsProject.CommunicationControl.API.DI; +using DevOpsProject.CommunicationControl.API.Middleware; +using DevOpsProject.Shared.Clients; +using DevOpsProject.Shared.Models; +using Microsoft.Extensions.Options; +using Polly; +using Polly.Extensions.Http; +using Serilog; + +internal class Program +{ + private static void Main(string[] args) + { + var builder = WebApplication.CreateBuilder(args); + + builder.Host.UseSerilog((context, services, loggerConfig) => + loggerConfig.ReadFrom.Configuration(context.Configuration) + .ReadFrom.Services(services) + .Enrich.FromLogContext()); + + builder.Services.AddControllers(); + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle + builder.Services.AddEndpointsApiExplorer(); + builder.Services.AddSwaggerGen(); + + // TODO: LATER - ADD OpenTelemtry + + builder.Services.AddRedis(builder.Configuration); + builder.Services.AddCommunicationControlLogic(); + + builder.Services.Configure(builder.Configuration.GetSection("OperationalArea")); + builder.Services.AddSingleton, OptionsMonitor>(); + + + var hiveRetryPolicy = HttpPolicyExtensions + .HandleTransientHttpError() + .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); + builder.Services.AddHttpClient() + .AddPolicyHandler(hiveRetryPolicy); + + + var corsPolicyName = "AllowReactApp"; + var localCorsPolicyName = "AllowLocalHtml"; + builder.Services.AddCors(options => + { + options.AddPolicy(name: corsPolicyName, + policy => + { + policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins + .AllowAnyMethod() + .AllowAnyHeader(); + }); + + options.AddPolicy(name: localCorsPolicyName, + policy => + { + policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins + .AllowAnyMethod() + .AllowAnyHeader(); + }); + }); + + builder.Services.AddExceptionHandler(); + builder.Services.AddProblemDetails(); + + var app = builder.Build(); + + app.UseExceptionHandler(); + + if (app.Environment.IsDevelopment()) + { + app.UseSwagger(); + app.UseSwaggerUI(); + } + + app.UseCors(corsPolicyName); + //app.UseCors(localCorsPolicyName); + + app.UseAuthorization(); + + app.MapControllers(); + + app.Run(); + } +} \ No newline at end of file diff --git a/src/CommunicationControl/DevOpsProject/Properties/launchSettings.json b/src/CommunicationControl/DevOpsProject/Properties/launchSettings.json new file mode 100644 index 0000000..8a8dfef --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:3542", + "sslPort": 44340 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://0.0.0.0:8080", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://0.0.0.0:7097;http://0.0.0.0:8080", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/src/CommunicationControl/DevOpsProject/appsettings.Development.json b/src/CommunicationControl/DevOpsProject/appsettings.Development.json new file mode 100644 index 0000000..ff66ba6 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/src/CommunicationControl/DevOpsProject/appsettings.json b/src/CommunicationControl/DevOpsProject/appsettings.json new file mode 100644 index 0000000..0b17802 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/appsettings.json @@ -0,0 +1,50 @@ +{ + "Serilog": { + "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ], + "MinimumLevel": { + "Default": "Information", + "Override": { + "Microsoft": "Information", + "System": "Information" + } + }, + "WriteTo": [ + { + "Name": "Console" + }, + { + "Name": "File", + "Args": { + "path": "Logs/log-.txt", + "rollingInterval": "Day", + "rollOnFileSizeLimit": true, + "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + } + } + ], + "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ], + "Properties": { + "Application": "DevOpsProject.CommunicationControl", + "Environment": "Development" + } + }, + "Redis": { + "ConnectionString": "localhost:6379", + "PublishChannel": "HiveChannel" + }, + "RedisKeys": { + "HiveKey": "Hive" + }, + "OperationalArea": { + "Latitude": 48.697189, + "Longitude": 38.066246, + "Radius_KM": 5, + "InitialHeight_KM": 1, + "InitialSpeed_KM": 5, + "TelemetryInterval_MS": 30000, + "PingInterval_MS": 15000 + + }, + "AllowedHosts": "*", + "Urls": "http://0.0.0.0:8080" +} diff --git a/src/MapClient/.devcontainer/devcontainer.json b/src/MapClient/.devcontainer/devcontainer.json new file mode 100644 index 0000000..bee8139 --- /dev/null +++ b/src/MapClient/.devcontainer/devcontainer.json @@ -0,0 +1,22 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node +{ + "name": "Node.js", + "image": "mcr.microsoft.com/devcontainers/javascript-node:1-22-bookworm", + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + "runArgs": ["--name", "map_control_devcontainer", "--network=host"], + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [3000], + "appPort": ["3000:3000"] + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "yarn install", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/src/MapClient/README.md b/src/MapClient/README.md new file mode 100644 index 0000000..0b5fc25 --- /dev/null +++ b/src/MapClient/README.md @@ -0,0 +1,20 @@ +# Map UI for Communication Control + +## Installation + +1. Clone the repository: +```bash + git clone <> +``` + +2. Install dependencies: + +```bash + npm install + ``` + + 3. Run + + ```bash + npm run dev + ``` \ No newline at end of file diff --git a/src/MapClient/eslint.config.js b/src/MapClient/eslint.config.js new file mode 100644 index 0000000..238d2e4 --- /dev/null +++ b/src/MapClient/eslint.config.js @@ -0,0 +1,38 @@ +import js from '@eslint/js' +import globals from 'globals' +import react from 'eslint-plugin-react' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' + +export default [ + { ignores: ['dist'] }, + { + files: ['**/*.{js,jsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + parserOptions: { + ecmaVersion: 'latest', + ecmaFeatures: { jsx: true }, + sourceType: 'module', + }, + }, + settings: { react: { version: '18.3' } }, + plugins: { + react, + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...js.configs.recommended.rules, + ...react.configs.recommended.rules, + ...react.configs['jsx-runtime'].rules, + ...reactHooks.configs.recommended.rules, + 'react/jsx-no-target-blank': 'off', + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, + }, +] diff --git a/src/MapClient/index.html b/src/MapClient/index.html new file mode 100644 index 0000000..0c589ec --- /dev/null +++ b/src/MapClient/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + + +
+ + + diff --git a/src/MapClient/package-lock.json b/src/MapClient/package-lock.json new file mode 100644 index 0000000..e583dc3 --- /dev/null +++ b/src/MapClient/package-lock.json @@ -0,0 +1,4955 @@ +{ + "name": "client", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "client", + "version": "0.0.0", + "dependencies": { + "axios": "^1.7.9", + "ol": "^10.4.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^7.1.4" + }, + "devDependencies": { + "@eslint/js": "^9.17.0", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "@vitejs/plugin-react": "^4.3.4", + "eslint": "^9.17.0", + "eslint-plugin-react": "^7.37.2", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.16", + "globals": "^15.14.0", + "vite": "^6.0.5" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", + "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz", + "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.5", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.7", + "@babel/parser": "^7.26.7", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.26.7", + "@babel/types": "^7.26.7", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", + "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.26.5", + "@babel/types": "^7.26.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.7.tgz", + "integrity": "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", + "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", + "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", + "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz", + "integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.7", + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz", + "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", + "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", + "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.5", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", + "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", + "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", + "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.10.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@petamoriken/float16": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.1.tgz", + "integrity": "sha512-j+ejhYwY6PeB+v1kn7lZFACUIG97u90WxMuGosILFsl9d4Ovi0sjk0GlPfoEcx+FzvXZDAfioD+NGnnPamXgMA==", + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.1.tgz", + "integrity": "sha512-/pqA4DmqyCm8u5YIDzIdlLcEmuvxb0v8fZdFhVMszSpDTgbQKdw3/mB3eMUHIbubtJ6F9j+LtmyCnHTEqIHyzA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.1.tgz", + "integrity": "sha512-If3PDskT77q7zgqVqYuj7WG3WC08G1kwXGVFi9Jr8nY6eHucREHkfpX79c0ACAjLj3QIWKPJR7w4i+f5EdLH5Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.1.tgz", + "integrity": "sha512-zCpKHioQ9KgZToFp5Wvz6zaWbMzYQ2LJHQ+QixDKq52KKrF65ueu6Af4hLlLWHjX1Wf/0G5kSJM9PySW9IrvHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.1.tgz", + "integrity": "sha512-sFvF+t2+TyUo/ZQqUcifrJIgznx58oFZbdHS9TvHq3xhPVL9nOp+yZ6LKrO9GWTP+6DbFtoyLDbjTpR62Mbr3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.1.tgz", + "integrity": "sha512-NbOa+7InvMWRcY9RG+B6kKIMD/FsnQPH0MWUvDlQB1iXnF/UcKSudCXZtv4lW+C276g3w5AxPbfry5rSYvyeYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.1.tgz", + "integrity": "sha512-JRBRmwvHPXR881j2xjry8HZ86wIPK2CcDw0EXchE1UgU0ubWp9nvlT7cZYKc6bkypBt745b4bglf3+xJ7hXWWw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.1.tgz", + "integrity": "sha512-PKvszb+9o/vVdUzCCjL0sKHukEQV39tD3fepXxYrHE3sTKrRdCydI7uldRLbjLmDA3TFDmh418XH19NOsDRH8g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.1.tgz", + "integrity": "sha512-9WHEMV6Y89eL606ReYowXuGF1Yb2vwfKWKdD1A5h+OYnPZSJvxbEjxTRKPgi7tkP2DSnW0YLab1ooy+i/FQp/Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.1.tgz", + "integrity": "sha512-tZWc9iEt5fGJ1CL2LRPw8OttkCBDs+D8D3oEM8mH8S1ICZCtFJhD7DZ3XMGM8kpqHvhGUTvNUYVDnmkj4BDXnw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.1.tgz", + "integrity": "sha512-FTYc2YoTWUsBz5GTTgGkRYYJ5NGJIi/rCY4oK/I8aKowx1ToXeoVVbIE4LGAjsauvlhjfl0MYacxClLld1VrOw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.1.tgz", + "integrity": "sha512-F51qLdOtpS6P1zJVRzYM0v6MrBNypyPEN1GfMiz0gPu9jN8ScGaEFIZQwteSsGKg799oR5EaP7+B2jHgL+d+Kw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.1.tgz", + "integrity": "sha512-wO0WkfSppfX4YFm5KhdCCpnpGbtgQNj/tgvYzrVYFKDpven8w2N6Gg5nB6w+wAMO3AIfSTWeTjfVe+uZ23zAlg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.1.tgz", + "integrity": "sha512-iWswS9cIXfJO1MFYtI/4jjlrGb/V58oMu4dYJIKnR5UIwbkzR0PJ09O0PDZT0oJ3LYWXBSWahNf/Mjo6i1E5/g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.1.tgz", + "integrity": "sha512-RKt8NI9tebzmEthMnfVgG3i/XeECkMPS+ibVZjZ6mNekpbbUmkNWuIN2yHsb/mBPyZke4nlI4YqIdFPgKuoyQQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.32.1.tgz", + "integrity": "sha512-WQFLZ9c42ECqEjwg/GHHsouij3pzLXkFdz0UxHa/0OM12LzvX7DzedlY0SIEly2v18YZLRhCRoHZDxbBSWoGYg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.32.1.tgz", + "integrity": "sha512-BLoiyHDOWoS3uccNSADMza6V6vCNiphi94tQlVIL5de+r6r/CCQuNnerf+1g2mnk2b6edp5dk0nhdZ7aEjOBsA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.1.tgz", + "integrity": "sha512-w2l3UnlgYTNNU+Z6wOR8YdaioqfEnwPjIsJ66KxKAf0p+AuL2FHeTX6qvM+p/Ue3XPBVNyVSfCrfZiQh7vZHLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.1.tgz", + "integrity": "sha512-Am9H+TGLomPGkBnaPWie4F3x+yQ2rr4Bk2jpwy+iV+Gel9jLAu/KqT8k3X4jxFPW6Zf8OMnehyutsd+eHoq1WQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.32.1.tgz", + "integrity": "sha512-ar80GhdZb4DgmW3myIS9nRFYcpJRSME8iqWgzH2i44u+IdrzmiXVxeFnExQ5v4JYUSpg94bWjevMG8JHf1Da5Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/rbush": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/rbush/-/rbush-4.0.0.tgz", + "integrity": "sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", + "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz", + "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", + "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.26.0", + "@babel/plugin-transform-react-jsx-self": "^7.25.9", + "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001696", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001696.tgz", + "integrity": "sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-parse": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-2.0.2.tgz", + "integrity": "sha512-eCtOz5w5ttWIUcaKLiktF+DxZO1R9KLNY/xhbV6CkhM7sR3GhVghmt6X6yOnzeaM24po+Z9/S1apbXMwA3Iepw==", + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + } + }, + "node_modules/color-parse/node_modules/color-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.0.tgz", + "integrity": "sha512-SbtvAMWvASO5TE2QP07jHBMXKafgdZz8Vrsrn96fiL+O92/FN/PLARzUW5sKt013fjAprK2d2iCn2hk2Xb5oow==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/color-rgba": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color-rgba/-/color-rgba-3.0.0.tgz", + "integrity": "sha512-PPwZYkEY3M2THEHHV6Y95sGUie77S7X8v+h1r6LSAPF3/LL2xJ8duUXSrkic31Nzc4odPwHgUbiX/XuTYzQHQg==", + "license": "MIT", + "dependencies": { + "color-parse": "^2.0.0", + "color-space": "^2.0.0" + } + }, + "node_modules/color-space": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/color-space/-/color-space-2.1.1.tgz", + "integrity": "sha512-XbeoH4Zpc20jdDau6NOyJ0uVMsKgAGn6dLR+qS2i9wu5U5pvI1InK34r4ODCS3Gmm2Wjmz20nTfhwqED7rY8AQ==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/earcut": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.1.tgz", + "integrity": "sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==", + "license": "ISC" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.90", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.90.tgz", + "integrity": "sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug==", + "dev": true, + "license": "ISC" + }, + "node_modules/es-abstract": { + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.6", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", + "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.10.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.19.0", + "@eslint/plugin-kit": "^0.2.5", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", + "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0.tgz", + "integrity": "sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.18.tgz", + "integrity": "sha512-IRGEoFn3OKalm3hjfolEWGqoF/jPqeEYFp+C8B0WMzwGwBMvlRDQd06kghDhF0C61uJ6WfSDhEZE/sAQjduKgw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.4.tgz", + "integrity": "sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/geotiff": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/geotiff/-/geotiff-2.1.3.tgz", + "integrity": "sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==", + "license": "MIT", + "dependencies": { + "@petamoriken/float16": "^3.4.7", + "lerc": "^3.0.0", + "pako": "^2.0.4", + "parse-headers": "^2.0.2", + "quick-lru": "^6.1.1", + "web-worker": "^1.2.0", + "xml-utils": "^1.0.2", + "zstddec": "^0.1.0" + }, + "engines": { + "node": ">=10.19" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "function-bind": "^1.1.2", + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "15.14.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", + "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", + "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", + "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lerc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lerc/-/lerc-3.0.0.tgz", + "integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==", + "license": "Apache-2.0" + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ol": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ol/-/ol-10.4.0.tgz", + "integrity": "sha512-gv3voS4wgej1WVvdCz2ZIBq3lPWy8agaf0094E79piz8IGQzHiOWPs2in1pdoPmuTNvcqGqyUFG3IbxNE6n08g==", + "license": "BSD-2-Clause", + "dependencies": { + "@types/rbush": "4.0.0", + "color-rgba": "^3.0.0", + "color-space": "^2.0.1", + "earcut": "^3.0.0", + "geotiff": "^2.1.3", + "pbf": "4.0.1", + "rbush": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/openlayers" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-headers": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", + "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==", + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/pbf": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-4.0.1.tgz", + "integrity": "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==", + "license": "BSD-3-Clause", + "dependencies": { + "resolve-protobuf-schema": "^2.1.0" + }, + "bin": { + "pbf": "bin/pbf" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", + "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/protocol-buffers-schema": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==", + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/quick-lru": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.2.tgz", + "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/quickselect": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==", + "license": "ISC" + }, + "node_modules/rbush": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/rbush/-/rbush-4.0.1.tgz", + "integrity": "sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==", + "license": "MIT", + "dependencies": { + "quickselect": "^3.0.0" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.4.tgz", + "integrity": "sha512-aJWVrKoLI0nIK1lfbTU3d5al1ZEUiwtSus/xjYL8K5sv2hyPesiOIojHM7QnaNLVtroOB1McZsWk37fMQVoc6A==", + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.6.0", + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0", + "turbo-stream": "2.4.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.1.4.tgz", + "integrity": "sha512-p474cAeRKfPNp+9QtpdVEa025iWLIIIBhYCnjsSwFmZH3c5DBHOc7vB7zmL6lL747o0ArfrLblNTebtL6lt0lA==", + "license": "MIT", + "dependencies": { + "react-router": "7.1.4" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "license": "MIT", + "dependencies": { + "protocol-buffers-schema": "^3.3.1" + } + }, + "node_modules/rollup": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.32.1.tgz", + "integrity": "sha512-z+aeEsOeEa3mEbS1Tjl6sAZ8NE3+AalQz1RJGj81M+fizusbdDMoEJwdJNHfaB40Scr4qNu+welOfes7maKonA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.32.1", + "@rollup/rollup-android-arm64": "4.32.1", + "@rollup/rollup-darwin-arm64": "4.32.1", + "@rollup/rollup-darwin-x64": "4.32.1", + "@rollup/rollup-freebsd-arm64": "4.32.1", + "@rollup/rollup-freebsd-x64": "4.32.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.32.1", + "@rollup/rollup-linux-arm-musleabihf": "4.32.1", + "@rollup/rollup-linux-arm64-gnu": "4.32.1", + "@rollup/rollup-linux-arm64-musl": "4.32.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.32.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.32.1", + "@rollup/rollup-linux-riscv64-gnu": "4.32.1", + "@rollup/rollup-linux-s390x-gnu": "4.32.1", + "@rollup/rollup-linux-x64-gnu": "4.32.1", + "@rollup/rollup-linux-x64-musl": "4.32.1", + "@rollup/rollup-win32-arm64-msvc": "4.32.1", + "@rollup/rollup-win32-ia32-msvc": "4.32.1", + "@rollup/rollup-win32-x64-msvc": "4.32.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/turbo-stream": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", + "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==", + "license": "ISC" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", + "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.24.2", + "postcss": "^8.4.49", + "rollup": "^4.23.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/web-worker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.3.0.tgz", + "integrity": "sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==", + "license": "Apache-2.0" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", + "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/xml-utils": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/xml-utils/-/xml-utils-1.10.1.tgz", + "integrity": "sha512-Dn6vJ1Z9v1tepSjvnCpwk5QqwIPcEFKdgnjqfYOABv1ngSofuAhtlugcUC3ehS1OHdgDWSG6C5mvj+Qm15udTQ==", + "license": "CC0-1.0" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zstddec": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.1.0.tgz", + "integrity": "sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==", + "license": "MIT AND BSD-3-Clause" + } + } +} diff --git a/src/MapClient/package.json b/src/MapClient/package.json new file mode 100644 index 0000000..431f144 --- /dev/null +++ b/src/MapClient/package.json @@ -0,0 +1,31 @@ +{ + "name": "client", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "axios": "^1.7.9", + "ol": "^10.4.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^7.1.4" + }, + "devDependencies": { + "@eslint/js": "^9.17.0", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "@vitejs/plugin-react": "^4.3.4", + "eslint": "^9.17.0", + "eslint-plugin-react": "^7.37.2", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.16", + "globals": "^15.14.0", + "vite": "^6.0.5" + } +} diff --git a/src/MapClient/public/256x256.ico b/src/MapClient/public/256x256.ico new file mode 100644 index 0000000000000000000000000000000000000000..f09607d17ee83862014fe7848be5a63088f382fa GIT binary patch literal 104937 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 literal 0 HcmV?d00001 diff --git a/src/MapClient/public/256x256.png b/src/MapClient/public/256x256.png new file mode 100644 index 0000000000000000000000000000000000000000..5e2384f120a90f4ed1e9393b57a2f8bc36eef4aa GIT binary patch literal 17276 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 literal 0 HcmV?d00001 diff --git a/src/MapClient/public/vite.svg b/src/MapClient/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/src/MapClient/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/MapClient/src/App.css b/src/MapClient/src/App.css new file mode 100644 index 0000000..b9d355d --- /dev/null +++ b/src/MapClient/src/App.css @@ -0,0 +1,42 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/src/MapClient/src/App.jsx b/src/MapClient/src/App.jsx new file mode 100644 index 0000000..4d4eab8 --- /dev/null +++ b/src/MapClient/src/App.jsx @@ -0,0 +1,8 @@ +import React from "react"; +import Home from "./pages/Home"; + +const App = () => { + return ; +}; + +export default App; diff --git a/src/MapClient/src/api/mapService.js b/src/MapClient/src/api/mapService.js new file mode 100644 index 0000000..63cc2a1 --- /dev/null +++ b/src/MapClient/src/api/mapService.js @@ -0,0 +1,48 @@ +import axios from "axios"; + +const API_BASE_URL = "http://localhost:8080/api/client"; + +// Fetch the center coordinates for the initial map load +export const fetchCenterCoordinates = async () => { + try { + const response = await axios.get(`${API_BASE_URL}/area`); + return response.data; + } catch (error) { + console.error("Error fetching center coordinates:", error); + return null; + } +}; + +// Fetch all hives and extract their latitude/longitude +export const fetchHives = async () => { + try { + const response = await axios.get(`${API_BASE_URL}/hive`); + + return response.data.map(hive => ({ + id: hive.hiveID, + lat: hive.telemetry?.location?.latitude ?? null, + lon: hive.telemetry?.location?.longitude ?? null, + })).filter(hive => hive.lat !== null && hive.lon !== null); // Remove invalid locations + + } catch (error) { + console.error("Error fetching hives:", error); + return []; + } +}; + +// Move all hives to a new location +export const moveHives = async (lat, lon, ids) => { + try { + await axios.patch(`${API_BASE_URL}/hive`, { + Hives: ids, + Destination: { + Latitude: lat, + Longitude: lon + } + }); + console.log(`Moved hives to: ${lat}, ${lon}`); + } catch (error) { + console.error("Error moving hives:", error); + throw error; + } +}; diff --git a/src/MapClient/src/assets/react.svg b/src/MapClient/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/src/MapClient/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/MapClient/src/components/MapView.jsx b/src/MapClient/src/components/MapView.jsx new file mode 100644 index 0000000..97de528 --- /dev/null +++ b/src/MapClient/src/components/MapView.jsx @@ -0,0 +1,182 @@ +import React, { useEffect, useRef, useState } from "react"; +import "ol/ol.css"; +import { Map, View } from "ol"; +import TileLayer from "ol/layer/Tile"; +import { OSM } from "ol/source"; +import VectorLayer from "ol/layer/Vector"; +import VectorSource from "ol/source/Vector"; +import { fromLonLat, toLonLat } from "ol/proj"; +import { Point } from "ol/geom"; +import { Feature } from "ol"; +import { Style, Icon, Text, Fill, Stroke } from "ol/style"; +import Popup from "./Popup"; +import { fetchCenterCoordinates, fetchHives, moveHives } from "../api/mapService"; + +// TODO: Hardcoded marker icon path +const MARKER_ICON_URL = "/256x256.png"; + +const MapView = () => { + const mapRef = useRef(null); + const vectorLayerRef = useRef(null); + const initialized = useRef(false); + const [hives, setHives] = useState([]); + const [popup, setPopup] = useState({ visible: false, coords: null }); + const [mouseCoords, setMouseCoords] = useState({ lat: "", lon: "" }); + const popoverRef = useRef(null); + + useEffect(() => { + const initializeMap = async () => { + if (initialized.current) return; + initialized.current = true; + + try { + const center = await fetchCenterCoordinates(); + if (center) { + initMap(center.latitude, center.longitude); + await fetchAndDrawHives(); + } + + // 🔄 Auto-fetch hives every 30 seconds + const interval = setInterval(fetchAndDrawHives, 5000); + return () => clearInterval(interval); + } catch (error) { + console.error("Error initializing map:", error); + } + }; + + initializeMap(); + }, []); + + // Initialize OpenLayers Map + const initMap = (lat, lon) => { + const map = new Map({ + target: "map-container", + layers: [new TileLayer({ source: new OSM() })], + view: new View({ center: fromLonLat([lon, lat]), zoom: 12 }), + }); + + map.on("pointermove", (event) => handleMouseMove(event, map)); + map.on("singleclick", (event) => handleMapClick(event, map)); + + mapRef.current = map; + }; + + // Fetch hives and draw them on the map + const fetchAndDrawHives = async () => { + try { + const data = await fetchHives(); + setHives(data); + drawHives(data); + } catch (error) { + console.error("❌ Error fetching hives:", error); + } + }; + + // Draw markers for all hives + const drawHives = (hives) => { + if (!mapRef.current) return; + if (vectorLayerRef.current) mapRef.current.removeLayer(vectorLayerRef.current); + + const vectorSource = new VectorSource(); + hives.forEach((hive) => { + const feature = new Feature({ + geometry: new Point(fromLonLat([hive.lon, hive.lat])), + }); + + feature.setId(hive.id); + feature.setStyle( + new Style({ + image: new Icon({ src: MARKER_ICON_URL, scale: 0.05 }), + text: new Text({ + text: hive.id, + fill: new Fill({ color: "#000" }), + stroke: new Stroke({ color: "#fff", width: 2 }), + offsetY: -20, + }), + }) + ); + + feature.set("id", hive.id); + feature.set("lat", hive.lat); + feature.set("lon", hive.lon); + + vectorSource.addFeature(feature); + }); + + const vectorLayer = new VectorLayer({ source: vectorSource }); + vectorLayerRef.current = vectorLayer; + mapRef.current.addLayer(vectorLayer); + + mapRef.current.on("pointermove", (event) => handleMarkerHover(event, mapRef.current)); + }; + + // Handle Mouse Move (Show live coordinates) + const handleMouseMove = (event, map) => { + if (!map) return; + const coords = toLonLat(event.coordinate); + setMouseCoords({ + lat: coords[1].toFixed(6), + lon: coords[0].toFixed(6), + }); + }; + + // Show popover when hovering over a marker + const handleMarkerHover = (event, map) => { + if (!popoverRef.current) return; + const features = map.getFeaturesAtPixel(event.pixel); + if (features.length > 0) { + const feature = features[0]; + popoverRef.current.innerHTML = `ID: ${feature.get("id")}
Lat: ${feature.get("lat")}
Lon: ${feature.get("lon")}`; + popoverRef.current.style.left = `${event.pixel[0] + 10}px`; + popoverRef.current.style.top = `${event.pixel[1] + 10}px`; + popoverRef.current.style.display = "block"; + } else { + popoverRef.current.style.display = "none"; + } + }; + + // Show popup when clicking an empty spot (Move Hives) + const handleMapClick = (event, map) => { + if (!map.getFeaturesAtPixel(event.pixel).length) { + const coords = toLonLat(event.coordinate); + setPopup({ visible: true, coords: { lat: coords[1].toFixed(6), lon: coords[0].toFixed(6) } }); + } + }; + + return ( +
+

Hive Map

+ + {/* Latitude & Longitude Inputs */} +
+ + +
+ + {/* Map Container */} +
+ + {/* Tooltip for Marker Hover */} +
+ + {/* Move All Hives Popup (Centered Modal) */} + moveHives(popup.coords.lat, popup.coords.lon, hives.map(h => h.id))} + onCancel={() => setPopup({ visible: false })} + /> +
+ ); +}; + +export default MapView; diff --git a/src/MapClient/src/components/Popup.jsx b/src/MapClient/src/components/Popup.jsx new file mode 100644 index 0000000..2a6594b --- /dev/null +++ b/src/MapClient/src/components/Popup.jsx @@ -0,0 +1,52 @@ +import React from "react"; + +const Popup = ({ isVisible, coords, onConfirm, onCancel }) => { + if (!isVisible || !coords) return null; + + // Copy coordinates to clipboard + const copyCoordinates = async () => { + const textToCopy = `[${coords.lat}, ${coords.lon}]`; + try { + await navigator.clipboard.writeText(textToCopy); + alert("Coordinates copied to clipboard!"); + } catch (error) { + console.error("Error copying coordinates:", error); + } + }; + + return ( +
+
+

Move all hives to:

+

Lat: {coords.lat} | Lon: {coords.lon}

+ + {/* Copy Coordinates Button */} + + + {/* Move Hives & Cancel Buttons */} + + +
+
+ ); +}; + +export default Popup; diff --git a/src/MapClient/src/index.css b/src/MapClient/src/index.css new file mode 100644 index 0000000..6119ad9 --- /dev/null +++ b/src/MapClient/src/index.css @@ -0,0 +1,68 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/src/MapClient/src/main.jsx b/src/MapClient/src/main.jsx new file mode 100644 index 0000000..e746106 --- /dev/null +++ b/src/MapClient/src/main.jsx @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; +import './styles/global.css'; // Optional global styles + +ReactDOM.createRoot(document.getElementById('root')).render( + + + +); \ No newline at end of file diff --git a/src/MapClient/src/pages/Home.jsx b/src/MapClient/src/pages/Home.jsx new file mode 100644 index 0000000..164bb4a --- /dev/null +++ b/src/MapClient/src/pages/Home.jsx @@ -0,0 +1,12 @@ +import React from "react"; +import MapView from "../components/MapView"; + +const Home = () => { + return ( +
+ +
+ ); +}; + +export default Home; diff --git a/src/MapClient/src/styles/global.css b/src/MapClient/src/styles/global.css new file mode 100644 index 0000000..7e6145a --- /dev/null +++ b/src/MapClient/src/styles/global.css @@ -0,0 +1,5 @@ +body { + margin: 0; + font-family: Arial, sans-serif; + background-color: #f5f5f5; +} \ No newline at end of file diff --git a/src/MapClient/src/styles/map.css b/src/MapClient/src/styles/map.css new file mode 100644 index 0000000..e69de29 diff --git a/src/MapClient/vite.config.js b/src/MapClient/vite.config.js new file mode 100644 index 0000000..8d6e2e6 --- /dev/null +++ b/src/MapClient/vite.config.js @@ -0,0 +1,10 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [react()], + server: { + host: '0.0.0.0', + port: 3000 + } +})