don't know what I did, I did a lot

Took 4 hours 33 minutes
This commit is contained in:
Tobias Hopp 2025-05-21 10:27:20 +02:00
parent 64d211d9e8
commit bb60ed7a0c
45 changed files with 1829 additions and 590 deletions

View File

@ -7,6 +7,13 @@
"license": "MIT",
"devDependencies": {
"@types/node": "^22.15.14",
"concurrently": "^9.1.2",
"typescript": "^5.8.3"
},
"scripts": {
"dev": "concurrently \"npm run --prefix web dev\" \"npm run --prefix server watchTS\""
},
"dependencies": {
"nodemon": "^3.1.10"
}
}

1
server/.env Normal file
View File

@ -0,0 +1 @@
DEBUG=itender:*

View File

@ -1,15 +1,16 @@
{
"name": "itender",
"name": "itender-server",
"version": "2.2.8",
"private": true,
"author": "Tobias Hopp <tobi@gaminggeneration.de>",
"license": "UNLICENSED",
"main": "dist/main.js",
"scripts": {
"start": "node --trace-warnings ./dist/main.js",
"compile": "tsc && webpack",
"compileStart": "yarn run compile && yarn start",
"watchTS": "tsc --watch",
"watchWP": "webpack --watch",
"watch": "nodemon -w src/ -e ts src/main.ts",
"doc": "typedoc"
},
"dependencies": {
@ -19,6 +20,7 @@
"cookie-parser": "^1.4.6",
"debug": "^4.3.4",
"detect-rpi": "^1.4.0",
"dotenv": "^16.5.0",
"express": "5.0.0",
"express-ws": "^5.0.2",
"hc-sr04": "^0.0.1",

View File

@ -14,51 +14,84 @@ export class ContainerHelper {
/**
* Measure all containers based on their sensor values
*/
static measureContainers(): Promise<void> {
static async measureContainers() {
log("Measuring containers...");
return new Promise(async resolve => {
for (let c of (await Container.find({}))) {
if (c.sensorType != SensorType.NONE) {
for (let c of (await Container.find({}))) {
if (c.sensorType != SensorType.NONE) {
let weight;
try {
weight = await SensorHelper.measureRaw(c);
} catch (e) {
await WebSocketHandler.send(new WebSocketPayload(WebSocketEvent.ERROR, "Ein Sensor hat beim Austarieren einen ungültigen Wert zurückgegeben.<br>Dies weist auf eine Fehlkonfiguration oder kaputten Sensor hin.<br>Aus Sicherheitsgründen wurde der Sensor für diesen Behälter deaktiviert."));
continue;
}
// V2: New calculation method
/*
(WEIGHT_VAL - NO_WEIGHT_VAL) / Sensitivitätsfaktor = Gewicht in Gramm
(WEIGHT_VAL - NO_WEIGHT_VAL) / (100g_val /100) ist die Formel zur Berechnung des Gewichts in Gramm nach der Kalibrierung mit einem 100 Gramm Gewicht.
100g_val /100 gibt den Sensitivitätsfaktor an, der angibt, wie viel sich der Sensorwert ändert, wenn sich das Gewicht um ein Gramm ändert.
Durch die Division von 100g_val durch 100 wird der Sensitivitätsfaktor berechnet, und durch die Division von (WEIGHT_VAL - NO_WEIGHT_VAL) durch den Sensitivitätsfaktor wird das Gewicht in Gramm berechnet.
Beispiel:
(WEIGHT_VAL - NO_WEIGHT_VAL) / (100g_val /100) = Gewicht in Gramm
(2400 - 2000) / (2450 /100) = 80 Gramm
*/
let newFilled = weight - c.sensorDelta / iTender.sensitivityFactor;
if (newFilled <= 3 && c.filled != -1) {
c.filled = -1;
// Container is empty!
} else {
// Container > 2
c.filled = newFilled;
}
await c.save();
let weight: number;
try {
weight = await SensorHelper.measureRaw(c);
} catch (e) {
log(e);
await WebSocketHandler.send(new WebSocketPayload(WebSocketEvent.ERROR, "Ein Sensor hat beim Austarieren einen ungültigen Wert zurückgegeben.<br>Dies weist auf eine Fehlkonfiguration oder kaputten Sensor hin.<br>Aus Sicherheitsgründen wurde der Sensor für diesen Behälter deaktiviert."));
continue;
}
}
log("Containers measured!");
resolve();
await WebSocketHandler.sendContainers();
});
// V2: New calculation method
/*
(WEIGHT_VAL - NO_WEIGHT_VAL) / Sensitivitätsfaktor = Gewicht in Gramm
(WEIGHT_VAL - NO_WEIGHT_VAL) / (100g_val /100) ist die Formel zur Berechnung des Gewichts in Gramm nach der Kalibrierung mit einem 100 Gramm Gewicht.
100g_val /100 gibt den Sensitivitätsfaktor an, der angibt, wie viel sich der Sensorwert ändert, wenn sich das Gewicht um ein Gramm ändert.
Durch die Division von 100g_val durch 100 wird der Sensitivitätsfaktor berechnet, und durch die Division von (WEIGHT_VAL - NO_WEIGHT_VAL) durch den Sensitivitätsfaktor wird das Gewicht in Gramm berechnet.
Beispiel:
(WEIGHT_VAL - NO_WEIGHT_VAL) / (100g_val /100) = Gewicht in Gramm
(2400 - 2000) / (2450 /100) = 80 Gramm
*/
let newFilled = weight - c.sensorDelta / iTender.sensitivityFactor;
if (newFilled <= 3 && c.filled != -1) {
c.filled = -1;
// Container is empty!
} else {
// Container > 2
c.filled = newFilled;
}
await c.save();
}
}
await WebSocketHandler.sendContainers();
log("Containers measured!");
}
static async tare() {
// Start TARE
for (let c of await Container.find({})) {
if (c.sensorType != SensorType.NONE) {
c.sensorTare = 0;
await c.save();
}
}
let timeouts: Array<NodeJS.Timeout> = [];
async function measureAndSave() {
await SensorHelper.measureAllRaw();
for (let c of await Container.find({})) {
if (c.sensorType != SensorType.NONE) {
c.sensorTare += c.rawData;
}
}
}
timeouts.push(setTimeout(measureAndSave, 500));
timeouts.push(setTimeout(measureAndSave, 1000));
timeouts.push(setTimeout(measureAndSave, 2000));
timeouts.push(setTimeout(measureAndSave, 3000));
await Promise.all(timeouts);
for (let c of await Container.find({})) {
if (c.sensorType != SensorType.NONE) {
c.sensorTare = c.sensorTare / 4;
await c.save();
}
}
}
}

View File

@ -1,6 +1,6 @@
export enum RequestType {
CONTAINERS = "CONTAINERS",
INGREDIENTS = "INGREDIENTS",
CONTAINERS = "CONTAINERS", // duplicated, try to use from event
INGREDIENTS = "INGREDIENTS", // duplicated, try to use from event
STATS = "STATS",
JOB = "JOB",
STARTFILL = "STARTFILL",

View File

@ -1,10 +1,14 @@
/**
* File for backend
*/
export enum WebSocketEvent {
STATUS= "STATUS",
DRINKS = "DRINKS",
CONTAINERS = "CONTAINERS",
INGREDIENTS = "INGREDIENTS",
CONTAINER_UPDATE = "CONTAINER_UPDATE",
CONFIG = "CONFIG",
TARE = "TARE",
SETUP = "SETUP",
REQUEST = "REQUEST",
RESPONSE = "RESPONSE",

View File

@ -12,29 +12,26 @@ import debug from "debug";
const log = debug("itender:WShandler");
export class WebSocketHandler {
private static _ws: WebSocket|any;
private static _ws: WebSocket | any;
static get ws(): WebSocket {
return this._ws;
}
static set ws(value: WebSocket|any) {
static set ws(value: WebSocket | any) {
this._ws = value;
}
public static send(payload: WebSocketPayload): Promise<void> {
return new Promise(async (resolve, reject) => {
try {
if (this.ws && this.ws.readyState == 1) {
log("Sending " + payload.event);
await this.ws.send(payload.toString());
resolve();
}
} catch (e) {
public static send(payload: WebSocketPayload) {
try {
if (this.ws && this.ws.readyState == 1) {
log("Sending " + payload.event);
this.ws.send(payload.toString());
}
});
} catch {
log("There was no open ws client, so no data sent (" + payload.event + ")");
}
}
public static answerRequest(type: RequestType, data: any) {
@ -45,70 +42,68 @@ export class WebSocketHandler {
}
public static sendStatus() {
return new Promise(resolve => {
let payload = new WebSocketPayload(WebSocketEvent.STATUS, {status: iTender.status});
WebSocketHandler.send(payload).then(resolve);
});
log("Sending status " + iTender.status);
let payload = new WebSocketPayload(WebSocketEvent.STATUS, {status: iTender.status});
WebSocketHandler.send(payload);
}
static sendRunningConfig() {
return new Promise(resolve => {
let payload = new WebSocketPayload(WebSocketEvent.CONFIG, Settings.json);
WebSocketHandler.send(payload).then(resolve);
});
let payload = new WebSocketPayload(WebSocketEvent.CONFIG, Settings.json);
WebSocketHandler.send(payload)
}
static sendStats() {
return new Promise(async resolve => {
static async sendStats() {
let counts: any[] = [];
let drinks = await Drink.find();
for (let drink of drinks) {
console.log(drink._id);
console.log( (await Job.countDocuments( )) );
let count = await Job.countDocuments({drink: drink._id});
console.log(count);
let counts: any[] = [];
let drinks = await Drink.find();
for (let drink of drinks) {
console.log(drink._id);
console.log((await Job.countDocuments()));
let count = await Job.countDocuments({drink: drink._id});
console.log(count);
counts.push([drink, count]);
}
counts.push([drink, count]);
}
counts = counts.sort((a, b) => {
if (a[1] > b[1])
return -1;
else if (a[1] < b[1])
return 1;
else
return 0;
});
let stats = {
"drinks_finished": (await Job.countDocuments({successful: true})),
"drink_most": (counts.length == 0) ? "Keiner" : counts[0][0].name,
"count_ingredients": (await Ingredient.countDocuments()),
"count_cocktails": (await Drink.countDocuments())
};
let payload = new WebSocketPayload(WebSocketEvent.RESPONSE, {
type: RequestType.STATS,
data: stats
});
WebSocketHandler.send(payload).then(resolve);
counts = counts.sort((a, b) => {
if (a[1] > b[1])
return -1;
else if (a[1] < b[1])
return 1;
else
return 0;
});
let stats = {
"drinks_finished": (await Job.countDocuments({successful: true})),
"drink_most": (counts.length == 0) ? "Keiner" : counts[0][0].name,
"count_ingredients": (await Ingredient.countDocuments()),
"count_cocktails": (await Drink.countDocuments())
};
let payload = new WebSocketPayload(WebSocketEvent.RESPONSE, {
type: RequestType.STATS,
data: stats
});
WebSocketHandler.send(payload)
}
static sendContainers() {
return new Promise(async resolve => {
let payload = new WebSocketPayload(WebSocketEvent.CONTAINERS, (await Container.find().populate("content")));
WebSocketHandler.send(payload).then(resolve);
})
public static async sendContainers() {
let payload = new WebSocketPayload(WebSocketEvent.CONTAINERS, (await Container.find().sort({"slot": 1}).populate("content")));
WebSocketHandler.send(payload);
}
public static async sendIngredients() {
let payload = new WebSocketPayload(WebSocketEvent.INGREDIENTS, (await Ingredient.find().sort({"name": 1})));
WebSocketHandler.send(payload);
}
static sendDrinks() {
return new Promise(async resolve => {
let payload = new WebSocketPayload(WebSocketEvent.DRINKS, iTender.drinks);
WebSocketHandler.send(payload).then(resolve);
})
let payload = new WebSocketPayload(WebSocketEvent.DRINKS, iTender.drinks);
WebSocketHandler.send(payload);
}
}

View File

@ -1,5 +1,4 @@
import {WebSocketEvent} from "./WebSocketEvent";
import {Buffer} from "buffer";
export class WebSocketPayload {
set event(value: WebSocketEvent) {

View File

@ -13,7 +13,7 @@ export const ContainerSchema = new Mongoose.Schema<IContainer>({
content: {type: mongoose.Types.ObjectId, ref: "Ingredient"},
sensorDelta: Number, // V2: Now sensorDelta - Differenz, welche beim Einstellen der Zutat aus Gewicht(Sensor) - Volumen errechnet wird
sensorTare: Number, // V2: Now sensorTare
useProxy: { type: Boolean, default: false },
useProxy: {type: Boolean, default: false},
filled: Number,
enabled: {type: Boolean, default: false},
});

View File

@ -28,6 +28,7 @@ export interface IContainer extends mongoose.Document {
rawData: number;
pumpPin: number;
// Filled up to?
filled: number;
enabled: boolean;
}

View File

@ -6,7 +6,7 @@ export interface IDrink extends mongoose.Document {
name: string;
// Ingredients
ingredients: { type: IIngredient, amount: Number }[];
ingredients: { type: IIngredient, amount: number }[];
}

View File

@ -15,6 +15,7 @@ import Ingredient from "./database/Ingredient";
import {RejectReason} from "./RejectReason";
import axios from "axios";
import {Mixer} from "./Mixer";
import mongoose from "mongoose";
const log = debug("itender:station");
@ -97,12 +98,12 @@ export class iTender {
* also calculates the amount of time, the drink will need to be done
* @param data
*/
static onReceiveFill(data: { drink: IDrink, amounts?: { ingredient: String, amount: number }[], amount?: number }): Promise<IJob> {
static onReceiveFill(data: { drink: IDrink, amounts?: { ingredient: mongoose.Types.ObjectId, amount: number }[], amount?: number }): Promise<IJob> {
return new Promise(async (resolve, reject) => {
mixLog("Receiving fill");
let drink = await Drink.findById(data.drink).populate("ingredients.type");
if (!drink) {
reject();
reject(new Error("Drink could not be found"));
return;
}
@ -145,7 +146,7 @@ export class iTender {
let c = await Container.findOne({$and: [{enabled: true}, {filled: {$gt: x.amount + tolerance}}, {content: x.ingredient}]});
if (!c) {
mixLog("Not enough ingredients!");
reject(RejectReason.NOT_ENOUGH_INGREDIENTS);
reject(new Error(RejectReason.NOT_ENOUGH_INGREDIENTS));
return;
}
x.container = c;
@ -166,8 +167,6 @@ export class iTender {
await Mixer.startFill(job);
});
}

View File

@ -1,4 +1,7 @@
import {App} from "./App";
require('dotenv').config();
console.log("iTender - Node " + process.version);
import debug from "debug";
import {WebsocketApp} from "./WebsocketApp";
import {Database} from "./database/Database";
@ -12,14 +15,10 @@ import {ContainerHelper} from "./ContainerHelper";
import {ArduinoProxy} from "./ArduinoProxy";
import path from "path";
import {ErrorHandler, InternalError} from "./ErrorHandler";
//import {LEDHandler} from "./LEDHandler";
import {AppMaintenance} from "./maintenance/AppMaintenance";
const log = debug("itender:server");
const maintenance = new AppMaintenance();
const app = new App();
const wsApp = new WebsocketApp();
@ -46,22 +45,22 @@ process.on("unhandledRejection", (reason, promise) => {
if (Settings.get("arduino_proxy_enabled") as boolean) {
try {
await ArduinoProxy.connect();
} catch (e) {
} catch {
Settings.set("arduino_proxy_enabled", false);
Settings.setupDone = false;
log("Force iTender to setup, because proxy not connected!");
}
}
//await test();
/*//await test();
try {
await maintenance.listen();
//await maintenance.listen();
} catch( e )
{
log("Could not start maintenance web app");
console.error(e);
}
}*/
await app.listen();
//await app.listen();
await wsApp.listen();

View File

@ -22,6 +22,7 @@ import {ErrorHandler, InternalError} from "../../ErrorHandler";
import {NextFunction, Request} from "express";
import WebsocketContainers from "./WebsocketContainers";
import WebsocketContainerUpdate from "./WebsocketContainerUpdate";
import {ContainerHelper} from "../../ContainerHelper";
const exec = promisify(require('child_process').exec)
@ -38,11 +39,12 @@ export async function handleWebSocket(ws: WebSocket | any, req: Request, next: N
await WebSocketHandler.sendRunningConfig();
await WebSocketHandler.sendContainers();
await WebSocketHandler.sendIngredients();
await WebSocketHandler.sendStatus();
await WebSocketHandler.sendDrinks();
ws.on('message', async (raw, bool) => {
ws.on('message', async (raw: any, bool: any) => {
try {
let msg = WebSocketPayload.parseFromBase64Json(raw);
// If message is null, close the socket because it could not be decompiled
@ -79,11 +81,9 @@ export async function handleWebSocket(ws: WebSocket | any, req: Request, next: N
case WebSocketEvent.SETUP: {
if ((msg.data as boolean)) {
iTender.setStatus(iTenderStatus.SETUP);
} else {
if (Settings.setupDone) {
iTender.setStatus(iTenderStatus.READY);
await WebSocketHandler.sendRunningConfig();
}
} else if (Settings.setupDone) {
iTender.setStatus(iTenderStatus.READY);
await WebSocketHandler.sendRunningConfig();
}
await WebSocketHandler.sendContainers();
break;
@ -103,11 +103,11 @@ export async function handleWebSocket(ws: WebSocket | any, req: Request, next: N
break;
}
case RequestType.CONTAINERS: {
WebSocketHandler.answerRequest(msg.data["type"] as RequestType, (await Container.find().sort({"slot": 1}).populate("content")));
await WebSocketHandler.sendContainers();
break;
}
case RequestType.INGREDIENTS: {
WebSocketHandler.answerRequest(msg.data["type"] as RequestType, (await Ingredient.find().sort({"name": 1})));
await WebSocketHandler.sendIngredients();
break;
}
case RequestType.STARTFILL: {
@ -154,8 +154,8 @@ export async function handleWebSocket(ws: WebSocket | any, req: Request, next: N
if (conf["arduino_proxy_enabled"]) {
try {
ArduinoProxy.disconnect();
} catch (e) {
} catch {
//ignored
}
try {
await ArduinoProxy.connect();
@ -189,50 +189,15 @@ export async function handleWebSocket(ws: WebSocket | any, req: Request, next: N
}
case RequestType.TARE: {
let type = msg.data["type"];
// Start TARE
let success = true;
for (let c of await Container.find({})) {
if (c.sensorType != SensorType.NONE) {
c.sensorTare = 0;
await c.save();
}
try {
await ContainerHelper.tare()
WebSocketHandler.answerRequest(type, {success: true, msg: "OK"});
} catch (e) {
console.error(e);
WebSocketHandler.answerRequest(type, {success: false, msg: "failed" + e});
}
let timeouts: Array<NodeJS.Timeout> = [];
async function measureAndSafe() {
try {
await SensorHelper.measureAllRaw();
for (let c of await Container.find({})) {
if (c.sensorType != SensorType.NONE) {
c.sensorTare += c.rawData;
}
}
} catch (e) {
WebSocketHandler.answerRequest(type, {success: false, msg: e});
success = false;
for (let t of timeouts)
clearTimeout(t);
}
}
timeouts.push(setTimeout(measureAndSafe, 500));
timeouts.push(setTimeout(measureAndSafe, 1000));
timeouts.push(setTimeout(measureAndSafe, 2000));
timeouts.push(setTimeout(measureAndSafe, 3000));
setTimeout(async () => {
if (success) {
for (let c of await Container.find({})) {
if (c.sensorType != SensorType.NONE) {
c.sensorTare = c.sensorTare / 4;
await c.save();
}
}
WebSocketHandler.answerRequest(type, {success: true, msg: "OK"});
}
}, 4000);
break;
}
@ -269,8 +234,7 @@ export async function handleWebSocket(ws: WebSocket | any, req: Request, next: N
case RequestType.INFO: {
let nets = os.networkInterfaces();
let net = nets["wlan0"];
if (!net)
net = nets["wlp0s20f3"];
net ??= nets["wlp0s20f3"];
let ipAddr: string = "";
if (net)
@ -284,7 +248,7 @@ export async function handleWebSocket(ws: WebSocket | any, req: Request, next: N
try {
wifi = (await exec("iwgetid")).stdout
uptime = (await exec("uptime -p")).stdout;
} catch (e) {
} catch {
}
wifi = wifi.substring(wifi.indexOf('"') + 1, wifi.length - 2);

View File

@ -9,7 +9,6 @@ import {IContainer} from "../database/IContainer";
import {SensorType} from "../SensorType";
import {RequestType} from "../RequestType";
export class Setup {
public static arduinoProxyCheckboxes: HTMLInputElement[] = [];
@ -277,7 +276,7 @@ Die Gewichtssensoren werden beim Bestätigen austariert<br><br>Zum fortfahren Ta
ul = document.createElement("ul");
modal.addContent(ul);
let tareInterval: NodeJS.Timer | number = 0;
let tareInterval: NodeJS.Timeout | number = 0;
let btn = document.createElement("button");
btn.classList.add("btn", "btn-primary");
@ -439,9 +438,9 @@ Mindestens ein Sensor konnte nicht kalibriert werden.<br>${data.msg}<br>`;
buttonCalibrateSeconds.innerText = "Füllzeit Kalibrieren";
containerDiv.append(buttonCalibrateSeconds);
buttonCalibrateSeconds.onclick = () => {
/* WebWebSocketHandler.send(new WebSocketPayload()).then(() => {
/* WebWebSocketHandler.send(new WebSocketPayload()).then(() => {
});*/
});*/
let modal = new Modal("calibration", "Kalibrierung");
let txt = document.createElement("p");
txt.innerHTML = `Während der Kalibrierung wird der Behälter solange entleert, bis die 100ml erreicht wurden.<br>

View File

@ -156,7 +156,7 @@ function setupOnClickEvents() {
}
let wsHandler;
let wsHandler: WebWebSocketHandler;
function connect(): Promise<void> {
return new Promise(resolve => {

View File

@ -24,6 +24,7 @@
"./src/"
],
"exclude": [
"../node_modules"
"../node_modules",
"./src/web"
]
}

View File

@ -1008,6 +1008,11 @@ doctypes@^1.1.0:
resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9"
integrity sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==
dotenv@^16.5.0:
version "16.5.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.5.0.tgz#092b49f25f808f020050051d1ff258e404c78692"
integrity sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==
dunder-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"

View File

@ -5,8 +5,8 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>iTender</title>
<link rel='stylesheet' href='/stylesheets/reset.css'/>
<link rel='stylesheet' href='/stylesheets/style.css'/>
<link rel='stylesheet' href='/assets/stylesheets/reset.css'/>
<link rel='stylesheet' href='/assets/stylesheets/style.css'/>
<link rel='preload' as='image' href='/static/shot.png'/>
<link rel='preload' as='image' href='/static/small.png'/>
<link rel='preload' as='image' href='/static/normal.png'/>

View File

@ -1,8 +1,11 @@
{
"name": "my-vite-app",
"name": "itender-web",
"private": true,
"version": "0.0.0",
"version": "0.0.1",
"type": "module",
"author": "Tobias Hopp <tobi@gaminggeneration.de>",
"license": "UNLICENSED",
"proxy": "http://localhost:3000",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
@ -10,6 +13,11 @@
"preview": "vite preview"
},
"dependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@fontsource/roboto": "^5.2.5",
"@mui/icons-material": "^7.1.0",
"@mui/material": "^7.1.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-router": "^7.5.3"
@ -17,8 +25,8 @@
"devDependencies": {
"@eslint/js": "^9.22.0",
"@types/node": "^22.15.3",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.3",
"@types/react-router": "^5.1.20",
"@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.22.0",

View File

@ -1,19 +1,78 @@
import {Route, Routes} from 'react-router';
import './App.css'
import {BrowserRouter} from "react-router";
import {Route, Routes, useNavigate} from 'react-router';
import {Layout} from "./components/Layout.tsx";
import {PaneMain} from "./routes/PaneMain.tsx";
import {PaneMenu} from "./routes/PaneMenu.tsx";
import {WebSocketHandler} from "./utils/WebSocketHandler.ts";
import {useEffect, useRef, useState} from "react";
import {iTenderStatus} from "./interfaces/iTenderStatus.ts";
import {Pane} from "./interfaces/Pane.ts";
import {PaneStartup} from "./routes/PaneStartup.tsx";
import {WebSocketEvent} from "./interfaces/WebSocketEvent.ts";
function App() {
const navigate = useNavigate();
const [currentStatus, setCurrentStatus] = useState<iTenderStatus>(iTenderStatus.CONNECTING);
const [currentPane, setCurrentPane] = useState<Pane>(Pane.NONE);
const cleanupHook = useRef<undefined | (() => void)>(undefined);
return (
<BrowserRouter>
const connect = () => {
console.log("[App.tsx] Connecting...");
WebSocketHandler.connect(() => {
// now open
if (cleanupHook.current)
cleanupHook.current();
cleanupHook.current = WebSocketHandler.registerForEvent(WebSocketEvent.STATUS, (payload) => {
setCurrentStatus(payload.data.status);
});
/*console.log("setting pane main");
setCurrentPane(Pane.MAIN);*/
}, (wasClean: boolean) => {
setCurrentStatus(iTenderStatus.CONNECTING);
if (wasClean) {
// loop???????????????????
console.log("[App] WS was closed clean, trying to reconnect in 1s");
setTimeout(connect, 1000);
}
});
}
useEffect(() => {
connect();
}, []);
useEffect(() => {
switch (currentStatus) {
case iTenderStatus.CONNECTING:
setCurrentPane(Pane.NONE);
break;
case iTenderStatus.READY:
setCurrentPane(Pane.MAIN);
break;
}
}, [currentStatus]);
useEffect(() => {
console.log("Changing pane", currentPane);
if (currentPane == Pane.NONE) {
setCurrentStatus(iTenderStatus.STARTING);
navigate("/");
} else
navigate("panes/" + currentPane);
}, [currentPane]);
return (
<Routes>
<Route path="/" element={<Layout/>}>
</Route>
</Routes>
</BrowserRouter>
)
<Route path={"/"} element={<Layout/>}>
<Route index path="/" element={<PaneStartup onRetryClick={() => connect()}/>}/>
</Route>
<Route path="/panes" element={<Layout/>}>
<Route path={"/panes/paneMain"} element={<PaneMain/>}/>
<Route path="/panes/paneMenu" element={<PaneMenu/>}/>
</Route>
</Routes>)
}
export default App

View File

@ -1,8 +1,8 @@
#main::-webkit-scrollbar {
display: none;
}
#main {
#main::-webkit-scrollbar {
display: none;
}
display: grid;
grid-template-columns: repeat(3, calc(90% / 3));
grid-template-rows: repeat(2, calc(90% / 2));
@ -77,60 +77,63 @@ body {
margin: auto auto 2%;
color: white;
font-size: 1.5em;
}
.water::before {
content: "";
width: 200%;
height: 200%;
background-color: #ececec;
position: absolute;
top: -90%;
left: -50%;
border-radius: 40%;
animation: animWater 7s linear infinite, animFillIn var(--fillTime) linear forwards;
}
.water::after {
content: "";
width: 204%;
height: 204%;
background-color: #ececec80;
position: absolute;
top: -100%;
left: -52%;
border-radius: 40%;
animation: animWater 7s linear infinite, animFillIn var(--fillTime) linear forwards;
animation-delay: 0.4s;
}
.water::before {
content: "";
width: 200%;
height: 200%;
background-color: #ececec;
position: absolute;
top: -90%;
left: -50%;
border-radius: 40%;
animation: animWater 7s linear infinite, animFillIn var(--fillTime) linear forwards;
}
.waterCancel {
background-color: red;
transition: background-color 1s;
}
.waterFinished {
background-color: green;
transition: background-color 2s;
}
@keyframes animFillIn {
0% {
.water::after {
content: "";
width: 204%;
height: 204%;
background-color: #ececec80;
position: absolute;
top: -100%;
left: -52%;
border-radius: 40%;
animation: animWater 7s linear infinite, animFillIn var(--fillTime) linear forwards;
animation-delay: 0.4s;
}
100% {
top: -188%;
.waterCancel {
background-color: red;
transition: background-color 1s;
}
.waterFinished {
background-color: green;
transition: background-color 2s;
}
@keyframes animFillIn {
0% {
top: -100%;
}
100% {
top: -188%;
}
}
@keyframes animWater {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
}
@keyframes animWater {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
#main_fillTxt {
margin-bottom: 1.3%;

View File

@ -101,6 +101,7 @@ h2 {
#overlay {
#top {
display: grid;
grid-template-columns: calc(100%/3) calc(100%/3) calc(100%/3);
grid-gap: 0;
position: fixed;
top: 0;
@ -114,27 +115,31 @@ h2 {
padding-top: 5px;
background-color: #167FCC;
box-shadow: inset 11px 45px 50px 3px rgba(181, 15, 15, 0.66);
align-items: center;
#title {
text-align: center;
margin-top: 0.6%;
grid-row: 4;
grid-row-end: 4;
}
#left {
font-size: 0.5em;
grid-row: 4;
text-align: left;
padding-top: 1.6%;
padding-left: 10px;
grid-row: 4;
grid-row-end: 4;
}
#right {
grid-row: 4;
text-align: right;
font-size: 0.8em;
padding-top: 1.2%;
padding-right: 10px;
grid-row: 4;
grid-row-end: 4;
}
}
@ -213,7 +218,7 @@ h2 {
top: 50px;
left: 0;
right: 0;
height:calc(100vh - 100px);
height: calc(100vh - 100px);
color: white;
background-color: #0E1F31;
@ -282,24 +287,27 @@ h2 {
position: relative;
display: inline-block;
overflow: visible;
}
.tooltiptext {
opacity: 0;
.tooltip .tooltiptext {
opacity: 0;
background-color: #214B74;
color: #FFFFFF;
text-align: center;
border-radius: 9px;
padding: 5px 0;
/* Position the tooltip */
position: absolute;
z-index: 1;
bottom: -55%;
left: 50%;
margin-left: -80px;
background-color: #214B74;
color: #FFFFFF;
text-align: center;
border-radius: 9px;
padding: 5px 0;
/* Position the tooltip */
position: absolute;
z-index: 1;
bottom: -55%;
left: 50%;
margin-left: -80px;
}
&:hover .tooltiptext {
animation: blendIn 0.5s ease forwards;
}
}
@ -313,6 +321,3 @@ h2 {
}
.tooltip:hover .tooltiptext {
animation: blendIn 0.5s ease forwards;
}

View File

@ -1,8 +1,72 @@
import {Outlet} from "react-router";
import {useEffect, useState} from "react";
import {WebSocketHandler} from "../utils/WebSocketHandler.ts";
import {WebSocketEvent} from "../interfaces/WebSocketEvent.ts";
import IContainer from "../interfaces/db/IContainer.ts";
export function Layout () {
export function Layout() {
const [currentTime, setCurrentTime] = useState("00:00");
const [status, setStatus] = useState("Booting up...");
const [containers, setContainers] = useState<IContainer[]>([]);
useEffect(() => {
console.log("hooks applied")
let currentTimeInterval = setInterval(() => {
let date = new Date();
setCurrentTime((date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":" + (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()));
}, 1000);
const statusHook = WebSocketHandler.registerForEvent(WebSocketEvent.STATUS, (payload) => {
console.log(payload);
setStatus(payload.data.status);
});
const containerHook = WebSocketHandler.registerForEvent(WebSocketEvent.CONTAINERS, (payload) => {
setContainers(payload.data);
});
return () => {
clearInterval(currentTimeInterval);
statusHook();
containerHook();
}
}, []);
return (
<Outlet/>
<>
<div id={"overlay"}>
<div id={"top"}>
<span id="left">
<strong>Status: </strong>
<span id="status">{status}</span>
</span>
<span id="title">iTender</span>
<span id="right">{currentTime}</span>
</div>
<div id={"bottom"}>
<div>
<button id={"menuBtn"} className={"btn"}>Menü</button>
</div>
<div id={"menuContainers"}>
{containers.map((container) => (
<div key={container._id} className={"container"}>
<div className={"tooltip"}>
{!container.content ? "-" : Math.round(container.filled * 100 / container.volume)}%
<span
className={"tooltiptext"}>{container.content ? container.content.name : "-"} {Math.ceil(container.filled)}ml</span>
</div>
<span className={"tooltiptext"}></span>
</div>
))}
{/*<div className={"container"}>
<span>3%</span>
</div>*/}
</div>
</div>
</div>
<div id={"pane_container"}>
<Outlet/>
</div>
</>
)
}

View File

@ -1,68 +0,0 @@
:root {
font-family: 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;
}
}

View File

@ -0,0 +1,8 @@
export enum Pane {
MAIN= "paneMain",
MENU = "paneMenu",
SETTINGS = "paneSettings",
SETUP = "paneSetup",
NONE = "paneNone",
CONTAINERS = "paneContainers",
}

View File

@ -0,0 +1,40 @@
import {IJob} from "./db/IJob.ts";
export enum RequestType {
STATS = "STATS",
JOB = "JOB",
STARTFILL = "STARTFILL",
STOPFILL = "STOPFILL",
DOWNLOAD_DRINKS = "DOWNLOAD_DRINKS",
TARE = "TARE",
CHECK = "CHECK",
UPDATE = "UPDATE",
INFO = "INFO",
CLEAR_DB = "CLEAR_DB",
SHUTDOWN = "SHUTDOWN",
}
// Define a mapping from RequestType to the expected data type of the RESPONSE payload
// You need to define these types based on the data your backend sends back for each request type
export interface RequestTypeResponseMap {
[RequestType.STATS]: any;
[RequestType.JOB]: IJob;
[RequestType.STARTFILL]: { success: boolean, job: IJob };
[RequestType.STOPFILL]: any;
[RequestType.DOWNLOAD_DRINKS]: string;
[RequestType.TARE]: { success: boolean, msg: string };
[RequestType.CHECK]: { success: boolean, msg: string };
[RequestType.UPDATE]: boolean;
[RequestType.INFO]: {
internet: boolean,
ip: string,
network: string,
uptime: string,
version: string,
author: string,
contact: string
};
[RequestType.CLEAR_DB]: true;
[RequestType.SHUTDOWN]: undefined;
// Add other request types and their response data types as needed
}

View File

@ -0,0 +1,35 @@
/**
* File for web
*/
import {iTenderStatus} from "./iTenderStatus.ts";
import {IDrink} from "./db/IDrink.ts";
import IContainer from "./db/IContainer.ts";
export enum WebSocketEvent {
STATUS= "STATUS",
DRINKS = "DRINKS",
CONTAINERS = "CONTAINERS",
INGREDIENTS = "INGREDIENTS",
CONTAINER_UPDATE = "CONTAINER_UPDATE",
CONFIG = "CONFIG",
SETUP = "SETUP",
REQUEST = "REQUEST",
RESPONSE = "RESPONSE",
CANCEL = "CANCEL",
ERROR = "ERROR",
}
export interface WebSocketEventPayloadMap {
[WebSocketEvent.STATUS]: {status: iTenderStatus}; // Example: STATUS event carries a string status message
[WebSocketEvent.DRINKS]: IDrink[]; // Example: DRINKS event carries an array of drinks
[WebSocketEvent.CONTAINERS]: IContainer[]; // Example: CONTAINERS event carries an array of containers
[WebSocketEvent.CONTAINER_UPDATE]: any; // Example: CONTAINER_UPDATE carries a single container update
[WebSocketEvent.CONFIG]: any; // Example: CONFIG carries configuration data
[WebSocketEvent.INGREDIENTS]: any; // Example: TARE carries tare data
[WebSocketEvent.SETUP]: any; // Example: SETUP carries setup data
[WebSocketEvent.REQUEST]: any; // REQUEST payload structure (type and data)
[WebSocketEvent.RESPONSE]: any; // RESPONSE payload structure (type and data)
[WebSocketEvent.CANCEL]: any; // CANCEL payload
[WebSocketEvent.ERROR]: string; // ERROR event carries an error message
// Add other events and their types as needed
}

View File

@ -0,0 +1,55 @@
import {WebSocketEvent} from "./WebSocketEvent.ts";
export class WebSocketPayload<T> {
set event(value: WebSocketEvent) {
this._event = value;
}
set data(value: T) {
this._data = value;
}
private _event: WebSocketEvent;
private _data: T;
get event(): WebSocketEvent {
return this._event;
}
get data(): T {
return this._data;
}
constructor(event: WebSocketEvent, data?: any) {
this._event = event;
this._data = data;
}
public static parseFromBase64Json(json: any): WebSocketPayload<any> | null {
//json = (typeof window != 'undefined') ? atob(json).toString() : Buffer.from(json, "base64").toString("utf-8");
json = atob(json);
let rawPayload: { event: string, data: any };
try {
rawPayload = JSON.parse(json);
} catch {
return null;
}
let wsEvent = WebSocketEvent[<keyof typeof WebSocketEvent>rawPayload.event];
return new WebSocketPayload(wsEvent, rawPayload.data);
}
/**
* Returns the payload as base64 encoded json string
*/
public toString(): string {
let json = JSON.stringify({"event": this._event, data: this._data});
json = ((typeof window != 'undefined') ? btoa(json) : Buffer.from(json).toString("base64"));
return json;
}
}

View File

@ -0,0 +1,33 @@
import IIngredient from "./IIngredient.ts";
import {ISensorType} from "./ISensorType.ts";
export default interface IContainer {
_id: string,
slot: number;
content: IIngredient | undefined;
volume: number;
sensorDelta: number;
sensorTare: number;
// Sensor Type
sensorType: ISensorType;
/**
* HX711 DATA-Pin
*/
sensorPin1: number;
/**
* HX711 CLOCK-Pin
*/
sensorPin2: number;
/**
* Is the arduino used as proxy?
*/
useProxy: boolean
rawData: number;
pumpPin: number;
filled: number;
enabled: boolean;
}

View File

@ -0,0 +1,15 @@
import IIngredient from "./IIngredient.ts";
/**
* IDrink interface for web
*
*/
export interface IDrink {
// Name for the Drink
name: string;
// Ingredients
ingredients: { type: IIngredient, amount: number }[];
}

View File

@ -0,0 +1,14 @@
/**
* IIngredient interface for web
*
*/
export default interface IIngredient {
_id: string;
// Name of the ingredient
name: string;
// Category of the ingredient
category: Category;
}

View File

@ -0,0 +1,13 @@
import {IDrink} from "./IDrink.ts";
import IIngredient from "./IIngredient.ts";
import IContainer from "./IContainer.ts";
export interface IJob {
drink: IDrink;
amounts: { ingredient: IIngredient, amount: number, container: IContainer }[];
completeAmount: number
startedAt: Date;
endAt: Date;
estimatedTime : number;
successful: boolean;
}

View File

@ -0,0 +1,5 @@
export enum ISensorType {
NONE="NONE",
ULTRASOUND="ULTRASOUND",
LOADCELL="LOADCELL"
}

View File

@ -0,0 +1,19 @@
export enum iTenderStatus {
CONNECTING = "CONNECTING",
// Machine is going to start
STARTING= "STARTING",
// Machine is ready
READY = "READY",
// Machine is filling your drink and destroying your leberwurst
FILLING = "FILLING",
// Drinks will be refreshed
REFRESHING = "REFRESHING",
// Drinks will be calculated (check containers and which drinks can be done)
CALCULATING = "CALCULATING",
// Download drinks from the world wide web
DOWNLOADING = "DOWNLOADING",
// Device is in setup mode for first setup
SETUP = "SETUP",
// An error happened; Oh no :(
ERROR = "ERROR"
}

View File

@ -1,11 +1,14 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import {StrictMode} from 'react'
import {createRoot} from 'react-dom/client'
import App from './App.tsx'
import './assets/stylesheets/style.css'
import {BrowserRouter} from "react-router";
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
<StrictMode>
<BrowserRouter>
<App/>
</BrowserRouter>
</StrictMode>,
)

View File

@ -0,0 +1,16 @@
import { useNavigate } from "react-router";
import {useEffect} from "react";
export function PaneMain () {
const navigate = useNavigate();
useEffect(() => {
}, []);
return (
<div id={"main"}>hallo</div>
)
}

View File

@ -0,0 +1,5 @@
export function PaneMenu () {
return (
<div id={"menu"}>hallo ich bin menu</div>
)
}

View File

@ -0,0 +1,39 @@
import {Button, Typography} from "@mui/material";
import {useEffect, useState} from "react";
interface StartupProps {
onRetryClick: () => void;
}
export function PaneStartup({onRetryClick}: Readonly<StartupProps>) {
const [connectionIssue, setConnectionIssue] = useState(false);
const init = () => {
setConnectionIssue(false);
return setTimeout(() => {
setConnectionIssue(true);
}, 10000);
}
useEffect(() => {
let t = init();
return () => clearTimeout(t);
}, []);
return (
<>
<div style={{padding: "15px", textAlign: "center"}}>
<Typography variant="h1">Willkommen</Typography>
<Typography
variant="subtitle1">{connectionIssue ? "Verbindungsfehler" : "iTender wird gestartet..."}</Typography>
{connectionIssue && <Button variant={"contained"} onClick={() => {
onRetryClick();
init();
}} color={"primary"}>Erneut
versuchen</Button>}
</div>
</>
)
}

View File

@ -0,0 +1,295 @@
import {WebSocketEvent, WebSocketEventPayloadMap} from "../interfaces/WebSocketEvent.ts";
import {WebSocketPayload} from "../interfaces/WebSocketPayload.ts";
import {RequestType, RequestTypeResponseMap} from "../interfaces/RequestType.ts";
// Cleanup function
type cleanup = () => void;
export class WebSocketHandler {
public static isConnected: boolean = false;
private static socket: WebSocket;
private static readonly url = (window.location.protocol == "http:" ? "ws://" : "wss://") + window.location.hostname + ":3005";
private static eventRegister: { event: WebSocketEvent, fn: (payload: WebSocketPayload<any>) => void }[] = [];
public static connect(onConnect: (() => void), onDisconnect: (wasClean: boolean) => void) {
if (this.socket) {
try {
this.socket.close(0, "reconnect");
} catch {
// ignored
}
}
console.log("[WS] Connecting...");
WebSocketHandler.socket = new WebSocket(WebSocketHandler.url);
WebSocketHandler.socket.onopen = (x) => {
this.isConnected = true;
this.onOpen(x);
onConnect();
};
WebSocketHandler.socket.onclose = (ev) => {
this.isConnected = false;
this.onClose();
onDisconnect(ev.wasClean);
}
WebSocketHandler.socket.onerror = this.onError;
WebSocketHandler.socket.onmessage = this.onMessage;
}
/**
* Registers for an event, returns a cleanup function
* The payload type is inferred from the WebSocketEventPayloadMap
* @param event The WebSocketEvent to register for
* @param fn The callback function to handle the event payload
* @return Cleanup-Function
*/
public static registerForEvent<E extends WebSocketEvent>(
event: E,
fn: (payload: WebSocketPayload<WebSocketEventPayloadMap[E]>) => void
): cleanup {
// The type assertion 'as any' is necessary here because the eventRegister array
// is typed to accept WebSocketPayload<any> for flexibility in the onMessage handler.
// TypeScript cannot statically guarantee that the payload type for a specific event
// matches the generic constraint E at this point, but we handle the type safety
// at the call site of registerForEvent.
let obj = {event: event, fn: fn as any};
WebSocketHandler.eventRegister.push(obj);
/**
* cleanup function
*/
return () => {
WebSocketHandler.eventRegister = WebSocketHandler.eventRegister.filter((e) => e != obj);
}
}
/**
* Request and response
* The response payload data type is inferred from the RequestTypeResponseMap
* @return Promise<WebSocketPayload<RequestTypeResponseMap[T]>> A promise that resolves with the response payload data
* @param type The RequestType
* @param content The request content
* @param timeout Time in seconds for timeout
*/
public static request<T extends RequestType>(
type: T,
content: object | any = null,
timeout: number = 30
): Promise<RequestTypeResponseMap[T]> { // Use the mapped response type here
console.log("[WS] Request to " + type)
return new Promise((resolve, reject) => {
let cancel = setTimeout(() => {
// Check if cleanup is defined before calling it
if (cleanup)
cleanup();
reject(new Error("timeout"));
}, timeout * 1000);
// Use registerForEvent with the specific RESPONSE event type
let cleanup = WebSocketHandler.registerForEvent(WebSocketEvent.RESPONSE, (payload) => {
// The payload.data here is typed as WebSocketEventPayloadMap[WebSocketEvent.RESPONSE] (which is 'any' in our current map)
// We rely on the check `(payload.data["type"] as RequestType) == type` to match the request type
// and then assert the data type based on the RequestTypeResponseMap.
if (payload.data && (payload.data["type"] as RequestType) == type) {
clearTimeout(cancel);
// Check if cleanup is defined before calling it
if (cleanup)
cleanup();
// Assert the data type based on the RequestTypeResponseMap
resolve(payload.data.data as RequestTypeResponseMap[T]); // Resolve with the actual data part of the response
}
});
WebSocketHandler.send(new WebSocketPayload(WebSocketEvent.REQUEST, {
type: type,
data: content
})).catch(reject);
});
}
public static async send(payload: WebSocketPayload<any>): Promise<void> {
console.log("[WS] Sending " + payload.event + " Event", payload);
if (this.socket && this.socket.readyState == 1) {
this.socket.send(payload.toString());
} else {
console.warn("[WS] No socket or readyState is not 1");
}
}
private static checkConnection(): Promise<boolean> {
return new Promise(async resolve => {
const xhr = new XMLHttpRequest();
xhr.open("GET", '/status', true);
//Send the proper header information along with the request
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = () => { // Call a function when the state changes.
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
resolve(true);
} else if (xhr.readyState == XMLHttpRequest.DONE) {
resolve(false);
}
}
try {
xhr.send();
} catch (e) {
resolve(false);
}
});
}
private static onMessage(msgEvent: MessageEvent) {
let payload = WebSocketPayload.parseFromBase64Json(msgEvent.data);
if (!payload) {
console.log("[WS] Could not parse message: ", msgEvent);
return;
}
console.log("[WS] Received " + payload.event + " Event", payload);
for (let evReg of WebSocketHandler.eventRegister) {
if (evReg.event == payload.event)
evReg.fn(payload);
}
/*switch (payload.event) {
case WebSocketEvent.CONFIG: {
Setup.onConfigUpdate(payload);
break;
}
case WebSocketEvent.DRINKS: {
WebHandler.onDrinkUpdate(payload);
break;
}
case WebSocketEvent.ERROR: {
/!* let modal = new Modal("error", "Aww crap!");
let txt = document.createElement("p");
txt.innerHTML = payload.data;
modal.addContent(txt);
modal.addContent(document.createElement("br"));
modal.addButton(ButtonType.SECONDARY, "Schließen", () => modal.close());
modal.open();
Settings.inUpdate = false;*!/
console.error(payload);
break;
}
// Incoming WebSocketStatus
case WebSocketEvent.STATUS: {
let statusElement = document.getElementById("status");
if (statusElement)
statusElement.innerText = payload.data.status;
let status: iTenderStatus = payload.data.status;
switch (status) {
case iTenderStatus.READY: {
Modal.close("start");
Modal.close("setup");
Modal.close("fill");
Modal.close("download");
if (WebHandler.currentPane != Pane.MENU)
WebHandler.openPane(Pane.MAIN);
(document.getElementById("menuBtn") as HTMLButtonElement).disabled = false;
break;
}
case iTenderStatus.STARTING: {
let modal = new Modal("start", "Willkommen!");
let txt = document.createElement("p");
txt.innerHTML = `Einen Augenblick bitte<br>iTender startet...`;
modal.addContent(txt);
modal.loader = true;
modal.open();
break;
}
case iTenderStatus.DOWNLOADING: {
let modal = new Modal("download", "Aktualisieren");
let txt = document.createElement("p");
txt.innerHTML = `Einen Augenblick bitte<br>iTender synchronisiert die Datenbank mit der Cloud...`;
modal.addContent(txt);
modal.loader = true;
modal.open();
setTimeout(() => {
if (txt) {
txt.innerHTML = txt.innerHTML + "<br><br>Der Vorgang dauert länger als gewöhnlich.<br>Überprüfe deine Internetverbindung!"
}
}, 1000 * 15)
break;
}
case iTenderStatus.SETUP: {
Modal.close("start");
Setup.openSetup();
break;
}
case iTenderStatus.FILLING: {
Fill.onFillEvent(payload);
break;
}
default: {
console.log("Unknown to handle " + status);
}
}
break;
}
}*/
}
private static onOpen(event: Event) {
console.log("[WS] Connected", event);
}
private static onClose() {
console.error("[WS] Closed!");
/*if (event.wasClean) {
let modal = new Modal("socketClosed", "Sitzung beendet!");
let txt = document.createElement("p");
txt.innerHTML = `Diese Sitzung wurde beendet, da der iTender nun an einem anderen Gerät bzw. an dem Hauptgerät gesteuert wird.<br><br>`;
modal.addContent(txt);
modal.addButton(ButtonType.PRIMARY, "Sitzung wiederherstellen", () => {
window.location.reload();
});
modal.open();
} else {
setInterval(async () => {
if ((await WebWebSocketHandler.checkConnection()))
window.location.reload();
}, 2000);
if (Settings.inUpdate)
return;
let modal = new Modal("socketClosed", "Verbindungsproblem!");
let txt = document.createElement("p");
txt.innerHTML = `Die Benutzeroberfläche hat die Verbindung mit dem Gerät verloren.<br>Die Verbindung wird wiederhergestellt...<br>`;
modal.addContent(txt);
modal.loader = true;
modal.open();
}
/!* let connectionElement = document.getElementById("right");
if (connectionElement) {
connectionElement.innerText = "Getrennt";
connectionElement.style.color = "red";
}*!/*/
}
private static onError(event: any) {
console.error("[WS] Error", event);
/*let connectionElement = document.getElementById("right");
if (connectionElement)
connectionElement.innerText = "Fehler";*/
//openModal("Einen Augenblick...", `Es wurde ein kritischer Fehler festgestellt.\nBitte warten Sie, während der Prozess neu gestartet wird...` );
//window.location.reload();
}
}

View File

@ -17,8 +17,8 @@
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},

View File

@ -16,8 +16,8 @@
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},

View File

@ -10,7 +10,7 @@
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.24"
"@babel/code-frame@^7.26.2":
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.26.2":
version "7.26.2"
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz"
integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==
@ -24,7 +24,7 @@
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz"
integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==
"@babel/core@^7.26.10":
"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.26.10":
version "7.26.10"
resolved "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz"
integrity sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==
@ -67,7 +67,7 @@
lru-cache "^5.1.1"
semver "^6.3.1"
"@babel/helper-module-imports@^7.25.9":
"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.25.9":
version "7.25.9"
resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz"
integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==
@ -133,6 +133,11 @@
dependencies:
"@babel/helper-plugin-utils" "^7.25.9"
"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.27.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
version "7.27.1"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz"
integrity sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==
"@babel/template@^7.26.9", "@babel/template@^7.27.0":
version "7.27.0"
resolved "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz"
@ -163,125 +168,112 @@
"@babel/helper-string-parser" "^7.25.9"
"@babel/helper-validator-identifier" "^7.25.9"
"@esbuild/aix-ppc64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz#014180d9a149cffd95aaeead37179433f5ea5437"
integrity sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==
"@emotion/babel-plugin@^11.13.5":
version "11.13.5"
resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz"
integrity sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==
dependencies:
"@babel/helper-module-imports" "^7.16.7"
"@babel/runtime" "^7.18.3"
"@emotion/hash" "^0.9.2"
"@emotion/memoize" "^0.9.0"
"@emotion/serialize" "^1.3.3"
babel-plugin-macros "^3.1.0"
convert-source-map "^1.5.0"
escape-string-regexp "^4.0.0"
find-root "^1.1.0"
source-map "^0.5.7"
stylis "4.2.0"
"@esbuild/android-arm64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz#649e47e04ddb24a27dc05c395724bc5f4c55cbfe"
integrity sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==
"@emotion/cache@^11.13.5", "@emotion/cache@^11.14.0":
version "11.14.0"
resolved "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz"
integrity sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==
dependencies:
"@emotion/memoize" "^0.9.0"
"@emotion/sheet" "^1.4.0"
"@emotion/utils" "^1.4.2"
"@emotion/weak-memoize" "^0.4.0"
stylis "4.2.0"
"@esbuild/android-arm@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.3.tgz#8a0f719c8dc28a4a6567ef7328c36ea85f568ff4"
integrity sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==
"@emotion/hash@^0.9.2":
version "0.9.2"
resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz"
integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==
"@esbuild/android-x64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.3.tgz#e2ab182d1fd06da9bef0784a13c28a7602d78009"
integrity sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==
"@emotion/is-prop-valid@^1.3.0":
version "1.3.1"
resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz"
integrity sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==
dependencies:
"@emotion/memoize" "^0.9.0"
"@esbuild/darwin-arm64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz#c7f3166fcece4d158a73dcfe71b2672ca0b1668b"
integrity sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==
"@emotion/memoize@^0.9.0":
version "0.9.0"
resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz"
integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
"@esbuild/darwin-x64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz#d8c5342ec1a4bf4b1915643dfe031ba4b173a87a"
integrity sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==
"@emotion/react@^11.0.0-rc.0", "@emotion/react@^11.14.0", "@emotion/react@^11.4.1", "@emotion/react@^11.5.0":
version "11.14.0"
resolved "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz"
integrity sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==
dependencies:
"@babel/runtime" "^7.18.3"
"@emotion/babel-plugin" "^11.13.5"
"@emotion/cache" "^11.14.0"
"@emotion/serialize" "^1.3.3"
"@emotion/use-insertion-effect-with-fallbacks" "^1.2.0"
"@emotion/utils" "^1.4.2"
"@emotion/weak-memoize" "^0.4.0"
hoist-non-react-statics "^3.3.1"
"@esbuild/freebsd-arm64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz#9f7d789e2eb7747d4868817417cc968ffa84f35b"
integrity sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==
"@emotion/serialize@^1.3.3":
version "1.3.3"
resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz"
integrity sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==
dependencies:
"@emotion/hash" "^0.9.2"
"@emotion/memoize" "^0.9.0"
"@emotion/unitless" "^0.10.0"
"@emotion/utils" "^1.4.2"
csstype "^3.0.2"
"@esbuild/freebsd-x64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz#8ad35c51d084184a8e9e76bb4356e95350a64709"
integrity sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==
"@emotion/sheet@^1.4.0":
version "1.4.0"
resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz"
integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
"@esbuild/linux-arm64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz#3af0da3d9186092a9edd4e28fa342f57d9e3cd30"
integrity sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==
"@emotion/styled@^11.14.0", "@emotion/styled@^11.3.0":
version "11.14.0"
resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz"
integrity sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==
dependencies:
"@babel/runtime" "^7.18.3"
"@emotion/babel-plugin" "^11.13.5"
"@emotion/is-prop-valid" "^1.3.0"
"@emotion/serialize" "^1.3.3"
"@emotion/use-insertion-effect-with-fallbacks" "^1.2.0"
"@emotion/utils" "^1.4.2"
"@esbuild/linux-arm@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz#e91cafa95e4474b3ae3d54da12e006b782e57225"
integrity sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==
"@emotion/unitless@^0.10.0":
version "0.10.0"
resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz"
integrity sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==
"@esbuild/linux-ia32@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz#81025732d85b68ee510161b94acdf7e3007ea177"
integrity sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==
"@emotion/use-insertion-effect-with-fallbacks@^1.2.0":
version "1.2.0"
resolved "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz"
integrity sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==
"@esbuild/linux-loong64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz#3c744e4c8d5e1148cbe60a71a11b58ed8ee5deb8"
integrity sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==
"@emotion/utils@^1.4.2":
version "1.4.2"
resolved "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz"
integrity sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==
"@esbuild/linux-mips64el@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz#1dfe2a5d63702db9034cc6b10b3087cc0424ec26"
integrity sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==
"@esbuild/linux-ppc64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz#2e85d9764c04a1ebb346dc0813ea05952c9a5c56"
integrity sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==
"@esbuild/linux-riscv64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz#a9ea3334556b09f85ccbfead58c803d305092415"
integrity sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==
"@esbuild/linux-s390x@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz#f6a7cb67969222b200974de58f105dfe8e99448d"
integrity sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==
"@esbuild/linux-x64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz#a237d3578ecdd184a3066b1f425e314ade0f8033"
integrity sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==
"@esbuild/netbsd-arm64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz#4c15c68d8149614ddb6a56f9c85ae62ccca08259"
integrity sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==
"@esbuild/netbsd-x64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz#12f6856f8c54c2d7d0a8a64a9711c01a743878d5"
integrity sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==
"@esbuild/openbsd-arm64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz#ca078dad4a34df192c60233b058db2ca3d94bc5c"
integrity sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==
"@esbuild/openbsd-x64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz#c9178adb60e140e03a881d0791248489c79f95b2"
integrity sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==
"@esbuild/sunos-x64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz#03765eb6d4214ff27e5230af779e80790d1ee09f"
integrity sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==
"@esbuild/win32-arm64@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz#f1c867bd1730a9b8dfc461785ec6462e349411ea"
integrity sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==
"@esbuild/win32-ia32@0.25.3":
version "0.25.3"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz#77491f59ef6c9ddf41df70670d5678beb3acc322"
integrity sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==
"@emotion/weak-memoize@^0.4.0":
version "0.4.0"
resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz"
integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==
"@esbuild/win32-x64@0.25.3":
version "0.25.3"
@ -336,7 +328,7 @@
minimatch "^3.1.2"
strip-json-comments "^3.1.1"
"@eslint/js@9.25.1", "@eslint/js@^9.22.0":
"@eslint/js@^9.22.0", "@eslint/js@9.25.1":
version "9.25.1"
resolved "https://registry.npmjs.org/@eslint/js/-/js-9.25.1.tgz"
integrity sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==
@ -354,6 +346,11 @@
"@eslint/core" "^0.13.0"
levn "^0.4.1"
"@fontsource/roboto@^5.2.5":
version "5.2.5"
resolved "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.5.tgz"
integrity sha512-70r2UZ0raqLn5W+sPeKhqlf8wGvUXFWlofaDlcbt/S3d06+17gXKr3VNqDODB0I1ASme3dGT5OJj9NABt7OTZQ==
"@humanfs/core@^0.19.1":
version "0.19.1"
resolved "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz"
@ -414,6 +411,90 @@
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"
"@mui/core-downloads-tracker@^7.1.0":
version "7.1.0"
resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.0.tgz"
integrity sha512-E0OqhZv548Qdc0PwWhLVA2zmjJZSTvaL4ZhoswmI8NJEC1tpW2js6LLP827jrW9MEiXYdz3QS6+hask83w74yQ==
"@mui/icons-material@^7.1.0":
version "7.1.0"
resolved "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.1.0.tgz"
integrity sha512-1mUPMAZ+Qk3jfgL5ftRR06ATH/Esi0izHl1z56H+df6cwIlCWG66RXciUqeJCttbOXOQ5y2DCjLZI/4t3Yg3LA==
dependencies:
"@babel/runtime" "^7.27.1"
"@mui/material@^7.1.0":
version "7.1.0"
resolved "https://registry.npmjs.org/@mui/material/-/material-7.1.0.tgz"
integrity sha512-ahUJdrhEv+mCp4XHW+tHIEYzZMSRLg8z4AjUOsj44QpD1ZaMxQoVOG2xiHvLFdcsIPbgSRx1bg1eQSheHBgvtg==
dependencies:
"@babel/runtime" "^7.27.1"
"@mui/core-downloads-tracker" "^7.1.0"
"@mui/system" "^7.1.0"
"@mui/types" "^7.4.2"
"@mui/utils" "^7.1.0"
"@popperjs/core" "^2.11.8"
"@types/react-transition-group" "^4.4.12"
clsx "^2.1.1"
csstype "^3.1.3"
prop-types "^15.8.1"
react-is "^19.1.0"
react-transition-group "^4.4.5"
"@mui/private-theming@^7.1.0":
version "7.1.0"
resolved "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.1.0.tgz"
integrity sha512-4Kck4jxhqF6YxNwJdSae1WgDfXVg0lIH6JVJ7gtuFfuKcQCgomJxPvUEOySTFRPz1IZzwz5OAcToskRdffElDA==
dependencies:
"@babel/runtime" "^7.27.1"
"@mui/utils" "^7.1.0"
prop-types "^15.8.1"
"@mui/styled-engine@^7.1.0":
version "7.1.0"
resolved "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.1.0.tgz"
integrity sha512-m0mJ0c6iRC+f9hMeRe0W7zZX1wme3oUX0+XTVHjPG7DJz6OdQ6K/ggEOq7ZdwilcpdsDUwwMfOmvO71qDkYd2w==
dependencies:
"@babel/runtime" "^7.27.1"
"@emotion/cache" "^11.13.5"
"@emotion/serialize" "^1.3.3"
"@emotion/sheet" "^1.4.0"
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/system@^7.1.0":
version "7.1.0"
resolved "https://registry.npmjs.org/@mui/system/-/system-7.1.0.tgz"
integrity sha512-iedAWgRJMCxeMHvkEhsDlbvkK+qKf9me6ofsf7twk/jfT4P1ImVf7Rwb5VubEA0sikrVL+1SkoZM41M4+LNAVA==
dependencies:
"@babel/runtime" "^7.27.1"
"@mui/private-theming" "^7.1.0"
"@mui/styled-engine" "^7.1.0"
"@mui/types" "^7.4.2"
"@mui/utils" "^7.1.0"
clsx "^2.1.1"
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/types@^7.4.2":
version "7.4.2"
resolved "https://registry.npmjs.org/@mui/types/-/types-7.4.2.tgz"
integrity sha512-edRc5JcLPsrlNFYyTPxds+d5oUovuUxnnDtpJUbP6WMeV4+6eaX/mqai1ZIWT62lCOe0nlrON0s9HDiv5en5bA==
dependencies:
"@babel/runtime" "^7.27.1"
"@mui/utils@^7.1.0":
version "7.1.0"
resolved "https://registry.npmjs.org/@mui/utils/-/utils-7.1.0.tgz"
integrity sha512-/OM3S8kSHHmWNOP+NH9xEtpYSG10upXeQ0wLZnfDgmgadTAk5F4MQfFLyZ5FCRJENB3eRzltMmaNl6UtDnPovw==
dependencies:
"@babel/runtime" "^7.27.1"
"@mui/types" "^7.4.2"
"@types/prop-types" "^15.7.14"
clsx "^2.1.1"
prop-types "^15.8.1"
react-is "^19.1.0"
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
@ -422,7 +503,7 @@
"@nodelib/fs.stat" "2.0.5"
run-parallel "^1.1.9"
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5":
version "2.0.5"
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
@ -435,100 +516,10 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
"@rollup/rollup-android-arm-eabi@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.1.tgz#e1562d360bca73c7bef6feef86098de3a2f1d442"
integrity sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw==
"@rollup/rollup-android-arm64@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.1.tgz#37ba63940211673e15dcc5f469a78e34276dbca7"
integrity sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw==
"@rollup/rollup-darwin-arm64@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.1.tgz#58b1eb86d997d71dabc5b78903233a3c27438ca0"
integrity sha512-VWXGISWFY18v/0JyNUy4A46KCFCb9NVsH+1100XP31lud+TzlezBbz24CYzbnA4x6w4hx+NYCXDfnvDVO6lcAA==
"@rollup/rollup-darwin-x64@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.1.tgz#5e22dab3232b1e575d930ce891abb18fe19c58c9"
integrity sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw==
"@rollup/rollup-freebsd-arm64@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.1.tgz#04c892d9ff864d66e31419634726ab0bebb33707"
integrity sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw==
"@rollup/rollup-freebsd-x64@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.1.tgz#f4b1e091f7cf5afc9e3a029d70128ad56409ecfb"
integrity sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q==
"@rollup/rollup-linux-arm-gnueabihf@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.1.tgz#c8814bb5ce047a81b1fe4a33628dfd4ac52bd864"
integrity sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg==
"@rollup/rollup-linux-arm-musleabihf@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.1.tgz#5b4e7bd83cbebbf5ffe958802dcfd4ee34bf73a3"
integrity sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg==
"@rollup/rollup-linux-arm64-gnu@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.1.tgz#141c848e53cee011e82a11777b8a51f1b3e8d77c"
integrity sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg==
"@rollup/rollup-linux-arm64-musl@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.1.tgz#22ebeaf2fa301aa4aa6c84b760e6cd1d1ac7eb1e"
integrity sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ==
"@rollup/rollup-linux-loongarch64-gnu@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.1.tgz#20b77dc78e622f5814ff8e90c14c938ceb8043bc"
integrity sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ==
"@rollup/rollup-linux-powerpc64le-gnu@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.1.tgz#2c90f99c987ef1198d4f8d15d754c286e1f07b13"
integrity sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg==
"@rollup/rollup-linux-riscv64-gnu@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.1.tgz#9336fd5e47d7f4760d02aa85f76976176eef53ca"
integrity sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ==
"@rollup/rollup-linux-riscv64-musl@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.1.tgz#d75b4d54d46439bb5c6c13762788f57e798f5670"
integrity sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA==
"@rollup/rollup-linux-s390x-gnu@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.1.tgz#e9f09b802f1291839247399028beaef9ce034c81"
integrity sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg==
"@rollup/rollup-linux-x64-gnu@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.1.tgz#0413169dc00470667dea8575c1129d4e7a73eb29"
integrity sha512-XiK5z70PEFEFqcNj3/zRSz/qX4bp4QIraTy9QjwJAb/Z8GM7kVUsD0Uk8maIPeTyPCP03ChdI+VVmJriKYbRHQ==
"@rollup/rollup-linux-x64-musl@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.1.tgz#c76fd593323c60ea219439a00da6c6d33ffd0ea6"
integrity sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ==
"@rollup/rollup-win32-arm64-msvc@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.1.tgz#c7724c386eed0bda5ae7143e4081c1910cab349b"
integrity sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg==
"@rollup/rollup-win32-ia32-msvc@4.40.1":
version "4.40.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.1.tgz#7749e1b65cb64fe6d41ad1ad9e970a0ccc8ac350"
integrity sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA==
"@popperjs/core@^2.11.8":
version "2.11.8"
resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz"
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
"@rollup/rollup-win32-x64-msvc@4.40.1":
version "4.40.1"
@ -568,14 +559,14 @@
dependencies:
"@babel/types" "^7.20.7"
"@types/estree@1.0.7", "@types/estree@^1.0.6":
"@types/estree@^1.0.6", "@types/estree@1.0.7":
version "1.0.7"
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz"
integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==
"@types/history@^4.7.11":
version "4.7.11"
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64"
resolved "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz"
integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==
"@types/json-schema@^7.0.15":
@ -583,27 +574,42 @@
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz"
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
"@types/node@^22.15.3":
"@types/node@^18.0.0 || ^20.0.0 || >=22.0.0", "@types/node@^22.15.3":
version "22.15.3"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.3.tgz#b7fb9396a8ec5b5dfb1345d8ac2502060e9af68b"
resolved "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz"
integrity sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==
dependencies:
undici-types "~6.21.0"
"@types/react-dom@^19.0.4":
version "19.1.2"
resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.2.tgz"
integrity sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==
"@types/parse-json@^4.0.0":
version "4.0.2"
resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz"
integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==
"@types/prop-types@^15.7.14":
version "15.7.14"
resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz"
integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==
"@types/react-dom@^19.1.3":
version "19.1.3"
resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.3.tgz"
integrity sha512-rJXC08OG0h3W6wDMFxQrZF00Kq6qQvw0djHRdzl3U5DnIERz0MRce3WVc7IS6JYBwtaP/DwYtRRjVlvivNveKg==
"@types/react-router@^5.1.20":
version "5.1.20"
resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.20.tgz#88eccaa122a82405ef3efbcaaa5dcdd9f021387c"
resolved "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz"
integrity sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==
dependencies:
"@types/history" "^4.7.11"
"@types/react" "*"
"@types/react@*", "@types/react@^19.0.10":
"@types/react-transition-group@^4.4.12":
version "4.4.12"
resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz"
integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==
"@types/react@*", "@types/react@^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react@^19.0.0", "@types/react@^19.1.2":
version "19.1.2"
resolved "https://registry.npmjs.org/@types/react/-/react-19.1.2.tgz"
integrity sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==
@ -625,7 +631,7 @@
natural-compare "^1.4.0"
ts-api-utils "^2.0.1"
"@typescript-eslint/parser@8.31.1":
"@typescript-eslint/parser@^8.0.0 || ^8.0.0-alpha.0", "@typescript-eslint/parser@8.31.1":
version "8.31.1"
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.31.1.tgz"
integrity sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q==
@ -707,7 +713,7 @@ acorn-jsx@^5.3.2:
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
acorn@^8.14.0:
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.14.0:
version "8.14.1"
resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz"
integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==
@ -734,6 +740,15 @@ argparse@^2.0.1:
resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
babel-plugin-macros@^3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz"
integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==
dependencies:
"@babel/runtime" "^7.12.5"
cosmiconfig "^7.0.0"
resolve "^1.19.0"
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
@ -761,7 +776,7 @@ braces@^3.0.3:
dependencies:
fill-range "^7.1.1"
browserslist@^4.24.0:
browserslist@^4.24.0, "browserslist@>= 4.21.0":
version "4.24.4"
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz"
integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==
@ -789,6 +804,11 @@ chalk@^4.0.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
clsx@^2.1.1:
version "2.1.1"
resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz"
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
@ -806,6 +826,11 @@ concat-map@0.0.1:
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
convert-source-map@^1.5.0:
version "1.9.0"
resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz"
integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
convert-source-map@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz"
@ -813,9 +838,20 @@ convert-source-map@^2.0.0:
cookie@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-1.0.2.tgz#27360701532116bd3f1f9416929d176afe1e4610"
resolved "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz"
integrity sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==
cosmiconfig@^7.0.0:
version "7.1.0"
resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz"
integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==
dependencies:
"@types/parse-json" "^4.0.0"
import-fresh "^3.2.1"
parse-json "^5.0.0"
path-type "^4.0.0"
yaml "^1.10.0"
cross-spawn@^7.0.6:
version "7.0.6"
resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz"
@ -825,7 +861,7 @@ cross-spawn@^7.0.6:
shebang-command "^2.0.0"
which "^2.0.1"
csstype@^3.0.2:
csstype@^3.0.2, csstype@^3.1.3:
version "3.1.3"
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
@ -842,11 +878,26 @@ deep-is@^0.1.3:
resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz"
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
dom-helpers@^5.0.1:
version "5.2.1"
resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz"
integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
dependencies:
"@babel/runtime" "^7.8.7"
csstype "^3.0.2"
electron-to-chromium@^1.5.73:
version "1.5.144"
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.144.tgz"
integrity sha512-eJIaMRKeAzxfBSxtjYnoIAw/tdD6VIH6tHBZepZnAbE3Gyqqs5mGN87DvcldPUbVkIljTK8pY0CMcUljP64lfQ==
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz"
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
dependencies:
is-arrayish "^0.2.1"
esbuild@^0.25.0:
version "0.25.3"
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz"
@ -916,7 +967,7 @@ eslint-visitor-keys@^4.2.0:
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz"
integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
eslint@^9.22.0:
"eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^8.57.0 || ^9.0.0", eslint@^9.22.0, eslint@>=8.40:
version "9.25.1"
resolved "https://registry.npmjs.org/eslint/-/eslint-9.25.1.tgz"
integrity sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==
@ -1042,6 +1093,11 @@ fill-range@^7.1.1:
dependencies:
to-regex-range "^5.0.1"
find-root@^1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz"
integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
find-up@^5.0.0:
version "5.0.0"
resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz"
@ -1063,10 +1119,10 @@ flatted@^3.2.9:
resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz"
integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==
fsevents@~2.3.2, fsevents@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
function-bind@^1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
gensync@^1.0.0-beta.2:
version "1.0.0-beta.2"
@ -1112,6 +1168,20 @@ has-flag@^4.0.0:
resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
hasown@^2.0.2:
version "2.0.2"
resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz"
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
dependencies:
function-bind "^1.1.2"
hoist-non-react-statics@^3.3.1:
version "3.3.2"
resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies:
react-is "^16.7.0"
ignore@^5.2.0, ignore@^5.3.1:
version "5.3.2"
resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz"
@ -1130,6 +1200,18 @@ imurmurhash@^0.1.4:
resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz"
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz"
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
is-core-module@^2.16.0:
version "2.16.1"
resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz"
integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==
dependencies:
hasown "^2.0.2"
is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz"
@ -1152,7 +1234,7 @@ isexe@^2.0.0:
resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
js-tokens@^4.0.0:
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
@ -1174,6 +1256,11 @@ json-buffer@3.0.1:
resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz"
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
json-parse-even-better-errors@^2.3.0:
version "2.3.1"
resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz"
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz"
@ -1204,6 +1291,11 @@ levn@^0.4.1:
prelude-ls "^1.2.1"
type-check "~0.4.0"
lines-and-columns@^1.1.6:
version "1.2.4"
resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz"
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
locate-path@^6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz"
@ -1216,6 +1308,13 @@ lodash.merge@^4.6.2:
resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
lru-cache@^5.1.1:
version "5.1.1"
resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz"
@ -1270,6 +1369,11 @@ node-releases@^2.0.19:
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz"
integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==
object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
optionator@^0.9.3:
version "0.9.4"
resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz"
@ -1303,6 +1407,16 @@ parent-module@^1.0.0:
dependencies:
callsites "^3.0.0"
parse-json@^5.0.0:
version "5.2.0"
resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz"
integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
dependencies:
"@babel/code-frame" "^7.0.0"
error-ex "^1.3.1"
json-parse-even-better-errors "^2.3.0"
lines-and-columns "^1.1.6"
path-exists@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz"
@ -1313,6 +1427,16 @@ path-key@^3.1.0:
resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
path-parse@^1.0.7:
version "1.0.7"
resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
path-type@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
picocolors@^1.0.0, picocolors@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz"
@ -1323,7 +1447,7 @@ picomatch@^2.3.1:
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
picomatch@^4.0.2:
"picomatch@^3 || ^4", picomatch@^4.0.2:
version "4.0.2"
resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz"
integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==
@ -1342,6 +1466,15 @@ prelude-ls@^1.2.1:
resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz"
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
prop-types@^15.6.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
dependencies:
loose-envify "^1.4.0"
object-assign "^4.1.1"
react-is "^16.13.1"
punycode@^2.1.0:
version "2.3.1"
resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz"
@ -1352,13 +1485,28 @@ queue-microtask@^1.2.2:
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
react-dom@^19.0.0:
"react-dom@^17.0.0 || ^18.0.0 || ^19.0.0", react-dom@^19.0.0, react-dom@>=16.6.0, react-dom@>=18:
version "19.1.0"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz"
integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==
dependencies:
scheduler "^0.26.0"
react-is@^16.13.1:
version "16.13.1"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^19.1.0:
version "19.1.0"
resolved "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz"
integrity sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==
react-refresh@^0.17.0:
version "0.17.0"
resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz"
@ -1366,14 +1514,24 @@ react-refresh@^0.17.0:
react-router@^7.5.3:
version "7.5.3"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-7.5.3.tgz#9e5420832af8c3690740c1797d4fa54613fea06d"
resolved "https://registry.npmjs.org/react-router/-/react-router-7.5.3.tgz"
integrity sha512-3iUDM4/fZCQ89SXlDa+Ph3MevBrozBAI655OAfWQlTm9nBR0IKlrmNwFow5lPHttbwvITZfkeeeZFP6zt3F7pw==
dependencies:
cookie "^1.0.1"
set-cookie-parser "^2.6.0"
turbo-stream "2.4.0"
react@^19.0.0:
react-transition-group@^4.4.5:
version "4.4.5"
resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz"
integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==
dependencies:
"@babel/runtime" "^7.5.5"
dom-helpers "^5.0.1"
loose-envify "^1.4.0"
prop-types "^15.6.2"
"react@^17.0.0 || ^18.0.0 || ^19.0.0", react@^19.0.0, react@^19.1.0, react@>=16.6.0, react@>=16.8.0, react@>=18:
version "19.1.0"
resolved "https://registry.npmjs.org/react/-/react-19.1.0.tgz"
integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==
@ -1383,6 +1541,15 @@ resolve-from@^4.0.0:
resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz"
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
resolve@^1.19.0:
version "1.22.10"
resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz"
integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==
dependencies:
is-core-module "^2.16.0"
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
reusify@^1.0.4:
version "1.1.0"
resolved "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz"
@ -1441,7 +1608,7 @@ semver@^7.6.0:
set-cookie-parser@^2.6.0:
version "2.7.1"
resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943"
resolved "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz"
integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==
shebang-command@^2.0.0:
@ -1461,11 +1628,21 @@ source-map-js@^1.2.1:
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz"
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
source-map@^0.5.7:
version "0.5.7"
resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz"
integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
strip-json-comments@^3.1.1:
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==
stylis@4.2.0:
version "4.2.0"
resolved "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz"
integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==
supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
@ -1473,6 +1650,11 @@ supports-color@^7.1.0:
dependencies:
has-flag "^4.0.0"
supports-preserve-symlinks-flag@^1.0.0:
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==
tinyglobby@^0.2.13:
version "0.2.13"
resolved "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz"
@ -1495,7 +1677,7 @@ ts-api-utils@^2.0.1:
turbo-stream@2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/turbo-stream/-/turbo-stream-2.4.0.tgz#1e4fca6725e90fa14ac4adb782f2d3759a5695f0"
resolved "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz"
integrity sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==
type-check@^0.4.0, type-check@~0.4.0:
@ -1514,14 +1696,14 @@ typescript-eslint@^8.26.1:
"@typescript-eslint/parser" "8.31.1"
"@typescript-eslint/utils" "8.31.1"
typescript@~5.7.2:
typescript@>=4.8.4, "typescript@>=4.8.4 <5.9.0", typescript@~5.7.2:
version "5.7.3"
resolved "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz"
integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==
undici-types@~6.21.0:
version "6.21.0"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz"
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
update-browserslist-db@^1.1.1:
@ -1539,7 +1721,7 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
vite@^6.3.1:
"vite@^4.2.0 || ^5.0.0 || ^6.0.0", vite@^6.3.1:
version "6.3.3"
resolved "https://registry.npmjs.org/vite/-/vite-6.3.3.tgz"
integrity sha512-5nXH+QsELbFKhsEfWLkHrvgRpTdGJzqOZ+utSdmPTvwHmvU6ITTm3xx+mRusihkcI8GeC7lCDyn3kDtiki9scw==
@ -1570,6 +1752,16 @@ yallist@^3.0.2:
resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
yaml@^1.10.0:
version "1.10.2"
resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
yaml@^2.4.2:
version "2.7.1"
resolved "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz"
integrity sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"

372
yarn.lock
View File

@ -9,12 +9,384 @@
dependencies:
undici-types "~6.21.0"
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
dependencies:
color-convert "^2.0.1"
anymatch@~3.1.2:
version "3.1.3"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
dependencies:
normalize-path "^3.0.0"
picomatch "^2.0.4"
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
binary-extensions@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
braces@~3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
dependencies:
fill-range "^7.1.1"
chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chokidar@^3.5.2:
version "3.6.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
dependencies:
anymatch "~3.1.2"
braces "~3.0.2"
glob-parent "~5.1.2"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.6.0"
optionalDependencies:
fsevents "~2.3.2"
cliui@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
dependencies:
string-width "^4.2.0"
strip-ansi "^6.0.1"
wrap-ansi "^7.0.0"
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
dependencies:
color-name "~1.1.4"
color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
concurrently@^9.1.2:
version "9.1.2"
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-9.1.2.tgz#22d9109296961eaee773e12bfb1ce9a66bc9836c"
integrity sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==
dependencies:
chalk "^4.1.2"
lodash "^4.17.21"
rxjs "^7.8.1"
shell-quote "^1.8.1"
supports-color "^8.1.1"
tree-kill "^1.2.2"
yargs "^17.7.2"
debug@^4:
version "4.4.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b"
integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==
dependencies:
ms "^2.1.3"
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
escalade@^3.1.1:
version "3.2.0"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
fill-range@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
dependencies:
to-regex-range "^5.0.1"
fsevents@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
has-flag@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
ignore-by-default@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==
is-binary-path@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
dependencies:
binary-extensions "^2.0.0"
is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
is-glob@^4.0.1, is-glob@~4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
dependencies:
is-extglob "^2.1.1"
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
dependencies:
brace-expansion "^1.1.7"
ms@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
nodemon@^3.1.10:
version "3.1.10"
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.10.tgz#5015c5eb4fffcb24d98cf9454df14f4fecec9bc1"
integrity sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==
dependencies:
chokidar "^3.5.2"
debug "^4"
ignore-by-default "^1.0.1"
minimatch "^3.1.2"
pstree.remy "^1.1.8"
semver "^7.5.3"
simple-update-notifier "^2.0.0"
supports-color "^5.5.0"
touch "^3.1.0"
undefsafe "^2.0.5"
normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
picomatch@^2.0.4, picomatch@^2.2.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
pstree.remy@^1.1.8:
version "1.1.8"
resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a"
integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
dependencies:
picomatch "^2.2.1"
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
rxjs@^7.8.1:
version "7.8.2"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b"
integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==
dependencies:
tslib "^2.1.0"
semver@^7.5.3:
version "7.7.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58"
integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==
shell-quote@^1.8.1:
version "1.8.2"
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.2.tgz#d2d83e057959d53ec261311e9e9b8f51dcb2934a"
integrity sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==
simple-update-notifier@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb"
integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==
dependencies:
semver "^7.5.3"
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
supports-color@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
dependencies:
has-flag "^3.0.0"
supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
dependencies:
has-flag "^4.0.0"
supports-color@^8.1.1:
version "8.1.1"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
dependencies:
has-flag "^4.0.0"
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
dependencies:
is-number "^7.0.0"
touch@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.1.tgz#097a23d7b161476435e5c1344a95c0f75b4a5694"
integrity sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==
tree-kill@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
tslib@^2.1.0:
version "2.8.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
typescript@^5.8.3:
version "5.8.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
undefsafe@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c"
integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==
undici-types@~6.21.0:
version "6.21.0"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
y18n@^5.0.5:
version "5.0.8"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
yargs-parser@^21.1.1:
version "21.1.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
yargs@^17.7.2:
version "17.7.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
dependencies:
cliui "^8.0.1"
escalade "^3.1.1"
get-caller-file "^2.0.5"
require-directory "^2.1.1"
string-width "^4.2.3"
y18n "^5.0.5"
yargs-parser "^21.1.1"