diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index c1a44d6..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,41 +0,0 @@ -# Casino Gaming Platform - Claude Assistant Guide - -## Build Commands - -### Frontend -- Build: `bun run build` or `bunx @angular/cli build` -- Start dev server: `bun run start` or `bunx @angular/cli serve --proxy-config src/proxy.conf.json` -- Format: `bun run format` or `prettier --write "src/**/*.{ts,html,css,scss}"` - -### Backend -- Build: `./gradlew build` or `./gradlew clean build` -- Run: `./gradlew bootRun` -- Generate JAR: `./gradlew bootJar` - -## Lint/Test Commands - -### Frontend -- Lint: `bun run lint` or `ng lint` -- Test all: `bun run test` or `bunx @angular/cli test` -- Test single file: `bunx @angular/cli test --include=path/to/test.spec.ts` - -### Backend -- Test all: `./gradlew test` -- Test single class: `./gradlew test --tests "FullyQualifiedClassName"` -- Checkstyle: `./gradlew checkstyleMain checkstyleTest` - -## Code Style Guidelines - -### Frontend (Angular) -- Use PascalCase for class names with suffixes (Component, Service) -- Use kebab-case for component selectors with "app-" prefix -- File naming: `name.component.ts`, `name.service.ts` -- Import order: Angular → third-party → local -- Use RxJS catchError for HTTP error handling - -### Backend (Java) -- Use PascalCase for classes with descriptive suffixes (Controller, Service, Entity) -- Use camelCase for methods and variables -- Domain-driven package organization -- Prefix DTOs with domain and suffix with "Dto" -- Use Spring's global exception handling with custom exceptions \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 27f6edc..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 Casino Gaming Platform - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index aba23fe..0000000 --- a/README.md +++ /dev/null @@ -1,172 +0,0 @@ -# Casino Gaming Platform - -An online gaming platform offering various casino-style games with virtual currency support. This project features a modern tech stack with Angular frontend, Spring Boot backend, and complete user authentication. - -Please refer to our [Style Guide](https://git.kjan.de/SZUT/casino/wiki/Frontend#design-system) for design guidelines and component standards. - -## Features - -- Multiple casino games: Poker, Blackjack, Slots, Plinko, Liars Dice, and Lootboxes -- User authentication and account management via Keycloak -- Virtual currency deposit system using Stripe payments -- Transaction history tracking -- Responsive modern UI built with Angular and TailwindCSS - -## Tech Stack - -### Frontend -- Angular 19 -- TailwindCSS -- Keycloak integration -- Stripe payment integration - -### Backend -- Spring Boot (Java) -- PostgreSQL database -- Keycloak for authentication/authorization -- Stripe API for payment processing - -### Infrastructure -- Docker containerization for all services - -## Getting Started - -### Prerequisites -* [Docker](https://docs.docker.com/get-docker/) -* [Docker Compose](https://docs.docker.com/compose/install/) (included with Docker Desktop for Windows and Mac) -* Java JDK 17+ -* Node.js 18+ - -### Setting Up the Environment - -1. Clone the repository -```bash -git clone -cd casino -``` - -2. Start the Docker services -```bash -cd docker -docker-compose up -d -``` - -This will start: -- PostgreSQL database -- Keycloak authentication server - -### Running the Backend - -1. Navigate to the backend directory -```bash -cd backend -``` - -2. Start the Spring Boot application -```bash -./gradlew bootRun -``` - -You may optionally install [watchexec](https://github.com/watchexec/watchexec?tab=readme-ov-file) and use this command to autorecompile the backend on file changes: -```bash -watchexec -r -e java ./gradlew :bootRun -``` - -The backend will be available at: -- API endpoint: http://localhost:8080 -- Swagger documentation: http://localhost:8080/swagger - -### Running the Frontend - -1. Navigate to the frontend directory -```bash -cd frontend -``` - -2. Install dependencies -```bash -npm install -``` - -3. Start the development server -```bash -npm run dev -``` - -The frontend will be available at http://localhost:4200 - -### Local Stripe integration -1. Install the Stripe CLI - https://stripe.com/docs/stripe-cli - -2. Login to the casino stripe account -``` -stripe login --api-key -``` - -3. Start webhook forwarding -``` -stripe listen --forward-to localhost:8080/webhook -``` - -## Database Management - -### Postgres Management - -#### Database cleanup (if needed) -```bash -cd docker -docker-compose down -docker volume rm local_lf8_starter_postgres_data -docker-compose up -d -``` - -#### Setting up IntelliJ Database View -1. Run the Docker container with PostgreSQL database -2. Open `application.properties` in the resources folder and copy the database URL -3. Open the Database tab in IntelliJ -4. Click on the database icon with key in the Database toolbar -5. Click the plus sign and select "Datasource from URL" -6. Paste the DB URL and select PostgreSQL driver, confirm with OK -7. Enter username `lf8_starter` and password `secret` -8. In the Schemas tab, uncheck all options and only check `lf8_starter_db` and `public` - -## Authentication - -The application uses Keycloak for authentication. To get a bearer token for API testing: - -1. Open `requests/getBearerToken.http` -2. Click the green arrow next to the request -3. Copy the `access_token` from the response - -## Development Guidelines - -### Commit Message Format - -We follow semantic commit messages to maintain clear project history. - -Format: `(): ` - -Where `` is one of: -- `feat`: New feature -- `fix`: Bug fix -- `docs`: Documentation changes -- `style`: Formatting, missing semicolons, etc; no code change -- `refactor`: Code refactoring -- `test`: Adding or refactoring tests -- `chore`: Updating build tasks, etc; no production code change - -Examples: -``` -feat: add user balance display -fix(auth): resolve token expiration issue -docs: update API documentation -``` - -References: -- [Conventional Commits](https://www.conventionalcommits.org/) -- [Semantic Commit Messages](https://seesparkbox.com/foundry/semantic_commit_messages) - -## License - -This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. diff --git a/backend/.docker/Dockerfile b/backend/.docker/Dockerfile deleted file mode 100644 index cbb743f..0000000 --- a/backend/.docker/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM gradle:jdk23 AS builder -WORKDIR /app - -COPY gradlew build.gradle.kts settings.gradle.kts config ./ -COPY gradle gradle - -RUN chmod +x gradlew -RUN gradle dependencies - -COPY src src - -RUN gradle clean build -x test -x checkstyleMain -x checkstyleTest -x compileTestJava - -FROM openjdk:23-jdk-slim AS runtime -WORKDIR /app - -COPY --from=builder /app/build/libs/*.jar app.jar - -EXPOSE 8080 -ENTRYPOINT ["java", "-jar", "app.jar"] diff --git a/backend/.dockerignore b/backend/.dockerignore deleted file mode 100644 index f06dfad..0000000 --- a/backend/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -.gradle -build \ No newline at end of file diff --git a/backend/.gitignore b/backend/.gitignore deleted file mode 100644 index c2065bc..0000000 --- a/backend/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -HELP.md -.gradle -build/ -!gradle/wrapper/gradle-wrapper.jar -!**/src/main/**/build/ -!**/src/test/**/build/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache -bin/ -!**/src/main/**/bin/ -!**/src/test/**/bin/ - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr -out/ -!**/src/main/**/out/ -!**/src/test/**/out/ - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ - -### VS Code ### -.vscode/ diff --git a/backend/Readme.md b/backend/Readme.md deleted file mode 100644 index 8f945dc..0000000 --- a/backend/Readme.md +++ /dev/null @@ -1,59 +0,0 @@ -# Starter für das LF08 Projekt - -## Requirements -* Docker https://docs.docker.com/get-docker/ -* Docker compose (bei Windows und Mac schon in Docker enthalten) https://docs.docker.com/compose/install/ - -## Endpunkt -``` -http://localhost:8080 -``` -## Swagger -``` -http://localhost:8080/swagger -``` - - -# Postgres -### Terminal öffnen -für alles gilt, im Terminal im Ordner docker/local sein -```bash -cd docker/local -``` -### Postgres starten -```bash -docker compose up -``` -Achtung: Der Docker-Container läuft dauerhaft! Wenn er nicht mehr benötigt wird, sollten Sie ihn stoppen. - -### Postgres stoppen -```bash -docker compose down -``` - -### Postgres Datenbank wipen, z.B. bei Problemen -```bash -docker compose down -docker volume rm local_lf8_starter_postgres_data -docker compose up -``` - -### Intellij-Ansicht für Postgres Datenbank einrichten -```bash -1. Lasse den Docker-Container mit der PostgreSQL-Datenbank laufen -2. im Ordner resources die Datei application.properties öffnen und die URL der Datenbank kopieren -3. rechts im Fenster den Reiter Database öffnen -4. In der Database-Symbolleiste auf das Datenbanksymbol mit dem Schlüssel klicken -5. auf das Pluszeichen klicken -6. Datasource from URL auswählen -7. URL der DB einfügen und PostgreSQL-Treiber auswählen, mit OK bestätigen -8. Username lf8_starter und Passwort secret eintragen (siehe application.properties), mit Apply bestätigen -9. im Reiter Schemas alle Häkchen entfernen und lediglich vor lf8_starter_db und public Häkchen setzen -10. mit Apply und ok bestätigen -``` -# Keycloak - -### Keycloak Token -1. Auf der Projektebene [GetBearerToken.http](../GetBearerToken.http) öffnen. -2. Neben der Request auf den grünen Pfeil drücken -3. Aus dem Reponse das access_token kopieren \ No newline at end of file diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts deleted file mode 100644 index 1d73b90..0000000 --- a/backend/build.gradle.kts +++ /dev/null @@ -1,62 +0,0 @@ -plugins { - java - id("org.springframework.boot") version "3.5.0" - id("io.spring.dependency-management") version "1.1.7" - id("checkstyle") -} - -checkstyle { - configFile = file("$rootDir/config/checkstyle/checkstyle.xml") -} - -tasks.withType { - reports { - // Disable HTML report - html.required.set(false) - - // Disable XML report - xml.required.set(false) - } -} - -group = "de.szut" -version = "0.0.1-SNAPSHOT" - -java { - toolchain { - languageVersion = JavaLanguageVersion.of(23) - } -} - -configurations { - compileOnly { - extendsFrom(configurations.annotationProcessor.get()) - } -} - -repositories { - mavenCentral() -} - -dependencies { - implementation("com.stripe:stripe-java:29.1.0") - implementation("org.springframework.boot:spring-boot-starter-data-jpa") - implementation("org.springframework.boot:spring-boot-starter-web") - compileOnly("org.projectlombok:lombok") - annotationProcessor("org.projectlombok:lombok") - testImplementation("org.springframework.boot:spring-boot-starter-test") - testRuntimeOnly("org.junit.platform:junit-platform-launcher") - implementation("org.springframework.boot:spring-boot-starter-security") - implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server:3.4.5") - implementation("org.springframework.boot:spring-boot-starter-oauth2-client:3.4.5") - runtimeOnly("org.postgresql:postgresql") - implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8") - implementation("io.jsonwebtoken:jjwt-api:0.11.5") - runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.5") - runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.5") - implementation("org.springframework.boot:spring-boot-starter-mail") -} - -tasks.withType { - useJUnitPlatform() -} diff --git a/backend/config/checkstyle/checkstyle.xml b/backend/config/checkstyle/checkstyle.xml deleted file mode 100644 index bdcefb8..0000000 --- a/backend/config/checkstyle/checkstyle.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/backend/gradle/wrapper/gradle-wrapper.jar b/backend/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 1b33c55..0000000 Binary files a/backend/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/backend/gradle/wrapper/gradle-wrapper.properties b/backend/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 002b867..0000000 --- a/backend/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/backend/gradlew b/backend/gradlew deleted file mode 100755 index 23d15a9..0000000 --- a/backend/gradlew +++ /dev/null @@ -1,251 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH="\\\"\\\"" - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/backend/gradlew.bat b/backend/gradlew.bat deleted file mode 100644 index 5eed7ee..0000000 --- a/backend/gradlew.bat +++ /dev/null @@ -1,94 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH= - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/backend/settings.gradle.kts b/backend/settings.gradle.kts deleted file mode 100644 index c0e0823..0000000 --- a/backend/settings.gradle.kts +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = "casino" diff --git a/backend/src/main/java/de/szut/casino/CasinoApplication.java b/backend/src/main/java/de/szut/casino/CasinoApplication.java deleted file mode 100644 index 9e1f3b2..0000000 --- a/backend/src/main/java/de/szut/casino/CasinoApplication.java +++ /dev/null @@ -1,95 +0,0 @@ -package de.szut.casino; - -import de.szut.casino.lootboxes.LootBoxEntity; -import de.szut.casino.lootboxes.LootBoxRepository; -import de.szut.casino.lootboxes.RewardEntity; -import de.szut.casino.lootboxes.RewardRepository; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.mail.javamail.JavaMailSenderImpl; -import org.springframework.web.client.RestTemplate; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; - -@SpringBootApplication -public class CasinoApplication { - - public static void main(String[] args) { - SpringApplication.run(CasinoApplication.class, args); - } - - @Bean - public static RestTemplate restTemplate() { - return new RestTemplate(); - } - - @Bean - public static JavaMailSenderImpl javaMailSenderImpl() { - return new JavaMailSenderImpl(); - } - - @Bean - public CommandLineRunner initData(LootBoxRepository lootBoxRepository, RewardRepository rewardRepository) { - return _ -> { - if (lootBoxRepository.count() == 0) { - LootBoxEntity basicLootBox = new LootBoxEntity(); - basicLootBox.setName("Basic LootBox"); - basicLootBox.setPrice(new BigDecimal("2")); - basicLootBox.setRewards(new ArrayList<>()); // Initialize the list - - LootBoxEntity premiumLootBox = new LootBoxEntity(); - premiumLootBox.setName("Premium LootBox"); - premiumLootBox.setPrice(new BigDecimal("5")); - premiumLootBox.setRewards(new ArrayList<>()); // Initialize the list - - lootBoxRepository.saveAll(Arrays.asList(basicLootBox, premiumLootBox)); - - RewardEntity commonReward = new RewardEntity(); - commonReward.setValue(new BigDecimal("0.50")); - commonReward.setProbability(new BigDecimal("0.7")); - - RewardEntity rareReward = new RewardEntity(); - rareReward.setValue(new BigDecimal("2.00")); - rareReward.setProbability(new BigDecimal("0.25")); - - RewardEntity epicReward = new RewardEntity(); - epicReward.setValue(new BigDecimal("5.00")); - epicReward.setProbability(new BigDecimal("0.5")); - - RewardEntity premiumCommon = new RewardEntity(); - premiumCommon.setValue(new BigDecimal("2.00")); - premiumCommon.setProbability(new BigDecimal("0.6")); - - RewardEntity premiumRare = new RewardEntity(); - premiumRare.setValue(new BigDecimal("5.00")); - premiumRare.setProbability(new BigDecimal("0.3")); - - RewardEntity legendaryReward = new RewardEntity(); - legendaryReward.setValue(new BigDecimal("15.00")); - legendaryReward.setProbability(new BigDecimal("0.10")); - - rewardRepository.saveAll(Arrays.asList( - commonReward, rareReward, epicReward, - premiumCommon, premiumRare, legendaryReward - )); - - basicLootBox.getRewards().add(commonReward); - basicLootBox.getRewards().add(premiumRare); - - premiumLootBox.getRewards().add(premiumCommon); - premiumLootBox.getRewards().add(premiumRare); - premiumLootBox.getRewards().add(legendaryReward); - - lootBoxRepository.saveAll(Arrays.asList(basicLootBox, premiumLootBox)); - - System.out.println("Initial LootBoxes and rewards created successfully"); - } else { - System.out.println("LootBoxes already exist, skipping initialization"); - } - }; - } -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java deleted file mode 100644 index 61051ad..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java +++ /dev/null @@ -1,68 +0,0 @@ -package de.szut.casino.blackjack; - -import de.szut.casino.exceptionHandling.exceptions.UserBlackJackGameMismatchException; -import de.szut.casino.shared.dto.BetDto; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserService; -import jakarta.validation.Valid; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.Objects; - -@Slf4j -@RestController -public class BlackJackGameController { - - private final UserService userService; - private final BlackJackService blackJackService; - - public BlackJackGameController(UserService userService, BlackJackService blackJackService) { - this.blackJackService = blackJackService; - this.userService = userService; - } - - @GetMapping("/blackjack/{id}") - public ResponseEntity getGame(@PathVariable Long id) { - BlackJackGameEntity game = getBlackJackGame(id); - - return ResponseEntity.ok(game); - } - - @PostMapping("/blackjack/{id}/hit") - public ResponseEntity hit(@PathVariable Long id) { - BlackJackGameEntity game = getBlackJackGame(id); - - return ResponseEntity.ok(blackJackService.hit(game)); - } - - @PostMapping("/blackjack/{id}/stand") - public ResponseEntity stand(@PathVariable Long id) { - BlackJackGameEntity game = getBlackJackGame(id); - - return ResponseEntity.ok(blackJackService.stand(game)); - } - - @PostMapping("/blackjack/{id}/doubleDown") - public ResponseEntity doubleDown(@PathVariable Long id) { - BlackJackGameEntity game = getBlackJackGame(id); - - return ResponseEntity.ok(blackJackService.doubleDown(game)); - } - - @PostMapping("/blackjack/start") - public ResponseEntity createBlackJackGame(@RequestBody @Valid BetDto betDto) { - return ResponseEntity.ok(blackJackService.createBlackJackGame(betDto)); - } - - private BlackJackGameEntity getBlackJackGame(Long gameId) { - UserEntity user = userService.getCurrentUser(); - BlackJackGameEntity game = blackJackService.getBlackJackGame(gameId); - if (game == null || !Objects.equals(game.getUserId(), user.getId())) { - throw new UserBlackJackGameMismatchException(gameId); - } - - return game; - } -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameEntity.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameEntity.java deleted file mode 100644 index 4f22c9d..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameEntity.java +++ /dev/null @@ -1,54 +0,0 @@ -package de.szut.casino.blackjack; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonManagedReference; -import de.szut.casino.user.UserEntity; -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.hibernate.annotations.SQLRestriction; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -@Entity -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor -public class BlackJackGameEntity { - @Id - @GeneratedValue - private Long id; - - @ManyToOne - @JoinColumn(name = "user_id", nullable = false) - @JsonIgnore - private UserEntity user; - - public Long getUserId() { - return user != null ? user.getId() : null; - } - - @Enumerated(EnumType.STRING) - private BlackJackState state; - private BigDecimal bet; - - @OneToMany(mappedBy = "game", cascade = CascadeType.ALL, orphanRemoval = true) - @JsonIgnore - @SQLRestriction("card_type = 'DECK'") - private List deck = new ArrayList<>(); - - @OneToMany(mappedBy = "game", cascade = CascadeType.ALL, orphanRemoval = true) - @JsonManagedReference - @SQLRestriction("card_type = 'PLAYER'") - private List playerCards = new ArrayList<>(); - - @OneToMany(mappedBy = "game", cascade = CascadeType.ALL, orphanRemoval = true) - @JsonManagedReference - @SQLRestriction("card_type = 'DEALER'") - private List dealerCards = new ArrayList<>(); -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameRepository.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameRepository.java deleted file mode 100644 index aafea4f..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.szut.casino.blackjack; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Service; - -@Service -public interface BlackJackGameRepository extends JpaRepository { -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java deleted file mode 100644 index 272334d..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java +++ /dev/null @@ -1,210 +0,0 @@ -package de.szut.casino.blackjack; - -import de.szut.casino.exceptionHandling.exceptions.InsufficientFundsException; -import de.szut.casino.shared.dto.BetDto; -import de.szut.casino.shared.service.BalanceService; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserRepository; -import de.szut.casino.user.UserService; -import jakarta.transaction.Transactional; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; -import java.util.List; - -@Service -public class BlackJackService { - private final BlackJackGameRepository blackJackGameRepository; - private final UserRepository userRepository; - private final BalanceService balanceService; - private final UserService userService; - private final DeckService deckService; - - public BlackJackService( - BlackJackGameRepository blackJackGameRepository, - UserRepository userRepository, - BalanceService balanceService, - UserService userService, - DeckService deckService - ) { - this.blackJackGameRepository = blackJackGameRepository; - this.userRepository = userRepository; - this.balanceService = balanceService; - this.userService = userService; - this.deckService = deckService; - } - - public BlackJackGameEntity getBlackJackGame(Long id) { - return blackJackGameRepository.findById(id).orElse(null); - } - - @Transactional - public BlackJackGameEntity createBlackJackGame(BetDto betDto) { - UserEntity user = userService.getCurrentUser(); - - if (!this.balanceService.hasFunds(user, betDto)) { - throw new InsufficientFundsException(); - } - - this.balanceService.subtractFunds(user, betDto.getBetAmount()); - - BlackJackGameEntity game = new BlackJackGameEntity(); - game.setUser(user); - game.setBet(betDto.getBetAmount()); - - this.deckService.initializeDeck(game); - this.deckService.dealInitialCards(game); - - game.setState(getState(game)); - - return processGameBasedOnState(game); - } - - @Transactional - public BlackJackGameEntity hit(BlackJackGameEntity game) { - if (game.getState() != BlackJackState.IN_PROGRESS) { - return game; - } - - this.deckService.dealCardToPlayer(game); - updateGameStateAndBalance(game); - - return processGameBasedOnState(game); - } - - @Transactional - public BlackJackGameEntity stand(BlackJackGameEntity game) { - if (game.getState() != BlackJackState.IN_PROGRESS) { - return game; - } - - dealCardsToDealerUntilMinimumScore(game); - determineWinnerAndUpdateBalance(game); - - return processGameBasedOnState(game); - } - - @Transactional - public BlackJackGameEntity doubleDown(BlackJackGameEntity game) { - if (game.getState() != BlackJackState.IN_PROGRESS || game.getPlayerCards().size() != 2) { - return game; - } - - UserEntity user = game.getUser(); - BigDecimal additionalBet = game.getBet(); - - this.balanceService.subtractFunds(user, additionalBet); - - game.setBet(game.getBet().add(additionalBet)); - - this.deckService.dealCardToPlayer(game); - updateGameStateAndBalance(game); - - if (game.getState() == BlackJackState.IN_PROGRESS) { - return stand(game); - } - - return game; - } - - private BlackJackGameEntity processGameBasedOnState(BlackJackGameEntity game) { - if (game.getState() != BlackJackState.IN_PROGRESS) { - this.blackJackGameRepository.delete(game); - return game; - } - - return blackJackGameRepository.save(game); - } - - private void updateGameStateAndBalance(BlackJackGameEntity game) { - game.setState(getState(game)); - - if (game.getState() == BlackJackState.PLAYER_WON) { - updateUserBalance(game, true); - } else if (game.getState() == BlackJackState.PLAYER_LOST) { - updateUserBalance(game, false); - } - } - - private void determineWinnerAndUpdateBalance(BlackJackGameEntity game) { - int playerValue = calculateHandValue(game.getPlayerCards()); - int dealerValue = calculateHandValue(game.getDealerCards()); - - if (dealerValue > 21 || playerValue > dealerValue) { - game.setState(BlackJackState.PLAYER_WON); - updateUserBalance(game, true); - } else if (playerValue < dealerValue) { - game.setState(BlackJackState.PLAYER_LOST); - updateUserBalance(game, false); - } else { - game.setState(BlackJackState.DRAW); - updateUserBalance(game, false); - } - } - - protected void updateUserBalance(BlackJackGameEntity game, boolean isWin) { - UserEntity user = game.getUser(); - BigDecimal totalBet = game.getBet(); - BigDecimal balance = user.getBalance(); - - if (isWin) { - balance = balance.add(totalBet.multiply(BigDecimal.valueOf(2))); - } else if (game.getState() == BlackJackState.DRAW) { - balance = balance.add(totalBet); - } - - user.setBalance(balance); - userRepository.save(user); - } - - private BlackJackState getState(BlackJackGameEntity game) { - int playerHandValue = calculateHandValue(game.getPlayerCards()); - - if (playerHandValue == 21) { - CardEntity hole = this.deckService.drawCardFromDeck(game); - hole.setCardType(CardType.DEALER); - game.getDealerCards().add(hole); - - int dealerHandValue = calculateHandValue(game.getDealerCards()); - - if (dealerHandValue == 21) { - return BlackJackState.DRAW; - } else { - BigDecimal blackjackWinnings = game.getBet().multiply(new BigDecimal("1.5")); - UserEntity user = game.getUser(); - user.setBalance(user.getBalance().add(blackjackWinnings)); - return BlackJackState.PLAYER_BLACKJACK; - } - } else if (playerHandValue > 21) { - return BlackJackState.PLAYER_LOST; - } - - return BlackJackState.IN_PROGRESS; - } - - private int calculateHandValue(List hand) { - int sum = 0; - int aceCount = 0; - for (CardEntity card : hand) { - sum += card.getRank().getValue(); - if (card.getRank() == Rank.ACE) { - aceCount++; - } - } - - while (sum > 21 && aceCount > 0) { - sum -= 10; - aceCount--; - } - - return sum; - } - - private void dealCardsToDealerUntilMinimumScore(BlackJackGameEntity game) { - while (calculateHandValue(game.getDealerCards()) < 17) { - this.deckService.dealCardToDealer(game); - } - } -} - - diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackState.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackState.java deleted file mode 100644 index 3f3e6fc..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackState.java +++ /dev/null @@ -1,9 +0,0 @@ -package de.szut.casino.blackjack; - -public enum BlackJackState { - IN_PROGRESS, - PLAYER_BLACKJACK, - PLAYER_LOST, - PLAYER_WON, - DRAW, -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/CardEntity.java b/backend/src/main/java/de/szut/casino/blackjack/CardEntity.java deleted file mode 100644 index 3b6903a..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/CardEntity.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.szut.casino.blackjack; - -import com.fasterxml.jackson.annotation.JsonBackReference; -import com.fasterxml.jackson.annotation.JsonIgnore; -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Entity -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor -public class CardEntity { - @Id - @GeneratedValue - @JsonIgnore - private Long id; - - @ManyToOne - @JoinColumn(name = "game_id", nullable = false) - @JsonBackReference - private BlackJackGameEntity game; - - @Enumerated(EnumType.STRING) - private Suit suit; - - @Enumerated(EnumType.STRING) - private Rank rank; - - @Enumerated(EnumType.STRING) - @JsonIgnore - private CardType cardType; -} - -enum CardType { - DECK, PLAYER, DEALER -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/DeckService.java b/backend/src/main/java/de/szut/casino/blackjack/DeckService.java deleted file mode 100644 index 0511abd..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/DeckService.java +++ /dev/null @@ -1,57 +0,0 @@ -package de.szut.casino.blackjack; - -import org.springframework.stereotype.Service; - -import java.util.Random; - -@Service -public class DeckService { - private final Random random; - - public DeckService(Random random) { - this.random = random; - } - - public void initializeDeck(BlackJackGameEntity game) { - for (Suit suit : Suit.values()) { - for (Rank rank : Rank.values()) { - CardEntity card = new CardEntity(); - card.setGame(game); - card.setSuit(suit); - card.setRank(rank); - card.setCardType(CardType.DECK); - game.getDeck().add(card); - } - } - - java.util.Collections.shuffle(game.getDeck(), random); - } - - public CardEntity drawCardFromDeck(BlackJackGameEntity game) { - if (game.getDeck().isEmpty()) { - throw new IllegalStateException("Deck is empty"); - } - - return game.getDeck().removeFirst(); - } - - public void dealInitialCards(BlackJackGameEntity game) { - for (int i = 0; i < 2; i++) { - dealCardToPlayer(game); - } - - dealCardToDealer(game); - } - - public void dealCardToPlayer(BlackJackGameEntity game) { - CardEntity card = drawCardFromDeck(game); - card.setCardType(CardType.PLAYER); - game.getPlayerCards().add(card); - } - - public void dealCardToDealer(BlackJackGameEntity game) { - CardEntity card = drawCardFromDeck(game); - card.setCardType(CardType.DEALER); - game.getDealerCards().add(card); - } -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/Rank.java b/backend/src/main/java/de/szut/casino/blackjack/Rank.java deleted file mode 100644 index 8f9a3b8..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/Rank.java +++ /dev/null @@ -1,31 +0,0 @@ -package de.szut.casino.blackjack; - -import lombok.Getter; - -@Getter -public enum Rank { - TWO("2", "Two", 2), - THREE("3", "Three", 3), - FOUR("4", "Four", 4), - FIVE("5", "Five", 5), - SIX("6", "Six", 6), - SEVEN("7", "Seven", 7), - EIGHT("8", "Eight", 8), - NINE("9", "Nine", 9), - TEN("10", "Ten", 10), - JACK("J", "Jack", 10), - QUEEN("Q", "Queen", 10), - KING("K", "King", 10), - ACE("A", "Ace", 11); - - private final String symbol; - private final String displayName; - private final int value; - - Rank(String symbol, String displayName, int value) { - this.symbol = symbol; - this.displayName = displayName; - this.value = value; - } - -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/Suit.java b/backend/src/main/java/de/szut/casino/blackjack/Suit.java deleted file mode 100644 index 8ee80a9..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/Suit.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.szut.casino.blackjack; - -import lombok.Getter; - -@Getter -public enum Suit { - HEARTS("H", "Hearts"), - DIAMONDS("D", "Diamonds"), - CLUBS("C", "Clubs"), - SPADES("S", "Spades"); - - private final String symbol; - private final String displayName; - - Suit(String symbol, String displayName) { - this.symbol = symbol; - this.displayName = displayName; - } - -} diff --git a/backend/src/main/java/de/szut/casino/coinflip/CoinSide.java b/backend/src/main/java/de/szut/casino/coinflip/CoinSide.java deleted file mode 100644 index f369cb4..0000000 --- a/backend/src/main/java/de/szut/casino/coinflip/CoinSide.java +++ /dev/null @@ -1,6 +0,0 @@ -package de.szut.casino.coinflip; - -public enum CoinSide { - HEAD, - TAILS; -} diff --git a/backend/src/main/java/de/szut/casino/coinflip/CoinflipController.java b/backend/src/main/java/de/szut/casino/coinflip/CoinflipController.java deleted file mode 100644 index 7cc0c83..0000000 --- a/backend/src/main/java/de/szut/casino/coinflip/CoinflipController.java +++ /dev/null @@ -1,39 +0,0 @@ -package de.szut.casino.coinflip; - -import de.szut.casino.exceptionHandling.exceptions.InsufficientFundsException; -import de.szut.casino.exceptionHandling.exceptions.UserNotFoundException; -import de.szut.casino.shared.service.BalanceService; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserService; -import jakarta.validation.Valid; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Optional; - -@RestController -public class CoinflipController { - private final UserService userService; - private final BalanceService balanceService; - private final CoinflipService coinflipService; - - public CoinflipController(UserService userService, BalanceService balanceService, CoinflipService coinflipService) { - this.userService = userService; - this.balanceService = balanceService; - this.coinflipService = coinflipService; - } - - - @PostMapping("/coinflip") - public ResponseEntity coinFlip(@RequestBody @Valid CoinflipDto coinflipDto) { - UserEntity user = userService.getCurrentUser(); - - if (!this.balanceService.hasFunds(user, coinflipDto)) { - throw new InsufficientFundsException(); - } - - return ResponseEntity.ok(coinflipService.play(user, coinflipDto)); - } -} diff --git a/backend/src/main/java/de/szut/casino/coinflip/CoinflipDto.java b/backend/src/main/java/de/szut/casino/coinflip/CoinflipDto.java deleted file mode 100644 index a7f9adb..0000000 --- a/backend/src/main/java/de/szut/casino/coinflip/CoinflipDto.java +++ /dev/null @@ -1,23 +0,0 @@ -package de.szut.casino.coinflip; - -import de.szut.casino.shared.dto.BetDto; -import jakarta.validation.constraints.NotNull; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; - -@Getter -@Setter -@NoArgsConstructor -public class CoinflipDto extends BetDto { - @NotNull(message = "chosen side cannot be null") - private CoinSide coinSide; - - public CoinflipDto(BigDecimal betAmount, CoinSide coinSide) { - super(betAmount); - this.coinSide = coinSide; - } -} diff --git a/backend/src/main/java/de/szut/casino/coinflip/CoinflipResult.java b/backend/src/main/java/de/szut/casino/coinflip/CoinflipResult.java deleted file mode 100644 index 4c8fbdf..0000000 --- a/backend/src/main/java/de/szut/casino/coinflip/CoinflipResult.java +++ /dev/null @@ -1,16 +0,0 @@ -package de.szut.casino.coinflip; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; - -import java.math.BigDecimal; - -@AllArgsConstructor -@Setter -@Getter -public class CoinflipResult { - private boolean isWin; - private BigDecimal payout; - private CoinSide coinSide; -} diff --git a/backend/src/main/java/de/szut/casino/coinflip/CoinflipService.java b/backend/src/main/java/de/szut/casino/coinflip/CoinflipService.java deleted file mode 100644 index c6c39d7..0000000 --- a/backend/src/main/java/de/szut/casino/coinflip/CoinflipService.java +++ /dev/null @@ -1,35 +0,0 @@ -package de.szut.casino.coinflip; - -import de.szut.casino.shared.service.BalanceService; -import de.szut.casino.user.UserEntity; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; -import java.util.Random; - -@Service -public class CoinflipService { - private final Random random; - private final BalanceService balanceService; - - public CoinflipService(BalanceService balanceService, Random random) { - this.balanceService = balanceService; - this.random = random; - } - - public CoinflipResult play(UserEntity user, CoinflipDto coinflipDto) { - this.balanceService.subtractFunds(user, coinflipDto.getBetAmount()); - - CoinSide coinSide = this.random.nextBoolean() ? CoinSide.HEAD : CoinSide.TAILS; - CoinflipResult coinflipResult = new CoinflipResult(false, BigDecimal.ZERO, coinSide); - if (coinSide == coinflipDto.getCoinSide()) { - coinflipResult.setWin(true); - - BigDecimal payout = coinflipDto.getBetAmount().multiply(BigDecimal.TWO); - this.balanceService.addFunds(user, payout); - coinflipResult.setPayout(payout); - } - - return coinflipResult; - } -} diff --git a/backend/src/main/java/de/szut/casino/config/AppConfig.java b/backend/src/main/java/de/szut/casino/config/AppConfig.java deleted file mode 100644 index 9d9c869..0000000 --- a/backend/src/main/java/de/szut/casino/config/AppConfig.java +++ /dev/null @@ -1,15 +0,0 @@ -package de.szut.casino.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import java.util.Random; - -@Configuration -public class AppConfig { - - @Bean - public Random random() { - return new Random(); - } -} diff --git a/backend/src/main/java/de/szut/casino/config/OpenAPIConfiguration.java b/backend/src/main/java/de/szut/casino/config/OpenAPIConfiguration.java deleted file mode 100644 index 75cac52..0000000 --- a/backend/src/main/java/de/szut/casino/config/OpenAPIConfiguration.java +++ /dev/null @@ -1,60 +0,0 @@ -package de.szut.casino.config; - - -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.info.Info; -import io.swagger.v3.oas.models.security.SecurityRequirement; -import io.swagger.v3.oas.models.security.SecurityScheme; -import io.swagger.v3.oas.models.servers.Server; -import jakarta.servlet.ServletContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - - -@Configuration -public class OpenAPIConfiguration { - - private ServletContext context; - - public OpenAPIConfiguration(ServletContext context) { - this.context = context; - } - - - @Bean - public OpenAPI springShopOpenAPI( - // @Value("${info.app.version}") String appVersion, - ) { - final String securitySchemeName = "bearerAuth"; - - return new OpenAPI() - .addServersItem(new Server().url(this.context.getContextPath())) - .info(new Info() - .title("LF12 project starter") - .description("\n## Auth\n" + - "\n## Authentication\n" + "\nThis Hello service uses JWTs to authenticate requests. You will receive a bearer token by making a POST-Request in IntelliJ on:\n\n" + - "\n" + - "```\nPOST http://localhost:9090/realms/LF12/protocol/openid-connect/token\n" + - "Content-Type: application/x-www-form-urlencoded\n" + - "\n" + - "grant_type=password&client_id=lf12&username=lf12_test_user&password=secret\n```\n" + - "\n" + - "\nTo get a bearer-token in Postman, you have to follow the instructions in \n [Postman-Documentation](https://documenter.getpostman.com/view/7294517/SzmfZHnd).") - - .version("0.1")) - .addSecurityItem(new SecurityRequirement().addList(securitySchemeName)) - .components( - new Components() - .addSecuritySchemes(securitySchemeName, - new SecurityScheme() - .name(securitySchemeName) - .type(SecurityScheme.Type.HTTP) - .scheme("bearer") - .bearerFormat("JWT") - ) - ); - } - - -} diff --git a/backend/src/main/java/de/szut/casino/config/WebConfig.java b/backend/src/main/java/de/szut/casino/config/WebConfig.java deleted file mode 100644 index ecc21be..0000000 --- a/backend/src/main/java/de/szut/casino/config/WebConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -package de.szut.casino.config; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.CorsRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -@Configuration -public class WebConfig { - - @Value("${app.frontend-host}") - private String frontendHost; - - @Bean - public WebMvcConfigurer corsConfigurer() { - return new WebMvcConfigurer() { - @Override - public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**") - .allowedOrigins(frontendHost) - .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") - .allowedHeaders("*") - .exposedHeaders("*") - .allowCredentials(true) - .maxAge(3600); - } - }; - } -} diff --git a/backend/src/main/java/de/szut/casino/deposit/DepositController.java b/backend/src/main/java/de/szut/casino/deposit/DepositController.java deleted file mode 100644 index d99da00..0000000 --- a/backend/src/main/java/de/szut/casino/deposit/DepositController.java +++ /dev/null @@ -1,66 +0,0 @@ -package de.szut.casino.deposit; - -import com.stripe.Stripe; -import com.stripe.exception.StripeException; -import com.stripe.model.checkout.Session; -import com.stripe.param.checkout.SessionCreateParams; -import de.szut.casino.deposit.dto.AmountDto; -import de.szut.casino.deposit.dto.SessionIdDto; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserService; -import jakarta.validation.Valid; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class DepositController { - - @Value("${stripe.secret.key}") - private String stripeKey; - - @Value("${app.frontend-host}") - private String frontendHost; - - private final TransactionService transactionService; - - private final UserService userService; - - public DepositController(TransactionService transactionService, UserService userService) { - this.transactionService = transactionService; - this.userService = userService; - } - - @PostMapping("/deposit/checkout") - public ResponseEntity checkout(@RequestBody @Valid AmountDto amountDto, @RequestHeader("Authorization") String token) throws StripeException { - Stripe.apiKey = stripeKey; - - UserEntity user = userService.getCurrentUser(); - - SessionCreateParams params = SessionCreateParams.builder() - .addLineItem(SessionCreateParams.LineItem.builder() - .setPriceData(SessionCreateParams.LineItem.PriceData.builder() - .setCurrency("EUR") - .setUnitAmount((long) amountDto.getAmount() * 100) - .setProductData(SessionCreateParams.LineItem.PriceData.ProductData.builder() - .setName("Einzahlung") - .build()) - .build()) - .setQuantity(1L) - .build()) - .setSuccessUrl(frontendHost + "/home?success=true") - .setCancelUrl(frontendHost + "/home?success=false") - .setMode(SessionCreateParams.Mode.PAYMENT) - .build(); - - Session session = Session.create(params); - - transactionService.createTransaction(user, session.getId(), amountDto.getAmount()); - - return ResponseEntity.ok(new SessionIdDto(session.getId())); - } -} - diff --git a/backend/src/main/java/de/szut/casino/deposit/TransactionEntity.java b/backend/src/main/java/de/szut/casino/deposit/TransactionEntity.java deleted file mode 100644 index 7c43af9..0000000 --- a/backend/src/main/java/de/szut/casino/deposit/TransactionEntity.java +++ /dev/null @@ -1,32 +0,0 @@ -package de.szut.casino.deposit; - -import de.szut.casino.user.UserEntity; -import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; - -import java.util.Date; - -@Setter -@Getter -@Entity -public class TransactionEntity { - @Id - @GeneratedValue - private Long id; - - @ManyToOne - @JoinColumn(name = "user_id", nullable = false) - private UserEntity user; - - @Column(unique = true) - private String sessionId = null; - - private double amount = 0; - - @Enumerated(EnumType.STRING) - private TransactionStatus status = TransactionStatus.PROCESSING; - - @Column(name = "created_at") - private Date createdAt = new Date(); -} diff --git a/backend/src/main/java/de/szut/casino/deposit/TransactionRepository.java b/backend/src/main/java/de/szut/casino/deposit/TransactionRepository.java deleted file mode 100644 index 5a16f0d..0000000 --- a/backend/src/main/java/de/szut/casino/deposit/TransactionRepository.java +++ /dev/null @@ -1,24 +0,0 @@ -package de.szut.casino.deposit; - -import de.szut.casino.user.UserEntity; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Optional; - -@Service -public interface TransactionRepository extends JpaRepository { - @Query("SELECT t FROM TransactionEntity t WHERE t.sessionId = ?1") - Optional findOneBySessionID(String sessionId); - - @Query("SELECT t FROM TransactionEntity t WHERE t.user = ?1") - List findAllByUserId(UserEntity id); - - @Query("SELECT t FROM TransactionEntity t WHERE t.user = ?1 ORDER BY t.createdAt DESC LIMIT ?2 OFFSET ?3") - List findByUserIdWithLimit(UserEntity userEntity, Integer limit, Integer offset); - - @Query("SELECT COUNT(t) > ?2 + ?3 FROM TransactionEntity t WHERE t.user = ?1") - Boolean hasMore(UserEntity userEntity, Integer limit, Integer offset); -} diff --git a/backend/src/main/java/de/szut/casino/deposit/TransactionService.java b/backend/src/main/java/de/szut/casino/deposit/TransactionService.java deleted file mode 100644 index 26f2e25..0000000 --- a/backend/src/main/java/de/szut/casino/deposit/TransactionService.java +++ /dev/null @@ -1,70 +0,0 @@ -package de.szut.casino.deposit; - -import com.stripe.exception.StripeException; -import com.stripe.model.checkout.Session; -import com.stripe.param.checkout.SessionRetrieveParams; -import de.szut.casino.security.service.EmailService; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserRepository; -import jakarta.mail.MessagingException; -import org.springframework.stereotype.Service; - -import java.io.IOException; -import java.math.BigDecimal; -import java.util.Optional; - -@Service -public class TransactionService { - private final TransactionRepository transactionRepository; - private final UserRepository userRepository; - private final EmailService emailService; - - public TransactionService(TransactionRepository transactionRepository, UserRepository userRepository, EmailService emailService) { - this.transactionRepository = transactionRepository; - this.userRepository = userRepository; - this.emailService = emailService; - } - - public void createTransaction( - UserEntity user, - String sessionID, - Double amount - ) { - TransactionEntity transaction = new TransactionEntity(); - - transaction.setUser(user); - transaction.setSessionId(sessionID); - transaction.setAmount(amount); - - transactionRepository.save(transaction); - } - - public void fulfillCheckout(String sessionID) throws StripeException, MessagingException, IOException { - SessionRetrieveParams params = SessionRetrieveParams.builder() - .addExpand("line_items") - .build(); - Session checkoutSession = Session.retrieve(sessionID, params, null); - - if (!"paid".equals(checkoutSession.getPaymentStatus())) { - return; - } - - Optional optionalTransaction = transactionRepository.findOneBySessionID(sessionID); - if (optionalTransaction.isEmpty()) { - throw new RuntimeException("Transaction not found"); - } - - TransactionEntity transaction = optionalTransaction.get(); - transaction.setStatus(TransactionStatus.SUCCEEDED); - - UserEntity user = transaction.getUser(); - Long amountTotal = checkoutSession.getAmountTotal(); - if (amountTotal != null) { - user.addBalance(BigDecimal.valueOf(amountTotal).movePointLeft(2)); - } - - userRepository.save(user); - transactionRepository.save(transaction); - emailService.sendDepositEmail(transaction); - } -} diff --git a/backend/src/main/java/de/szut/casino/deposit/TransactionStatus.java b/backend/src/main/java/de/szut/casino/deposit/TransactionStatus.java deleted file mode 100644 index 93ae142..0000000 --- a/backend/src/main/java/de/szut/casino/deposit/TransactionStatus.java +++ /dev/null @@ -1,6 +0,0 @@ -package de.szut.casino.deposit; - -public enum TransactionStatus { - PROCESSING, - SUCCEEDED, -} diff --git a/backend/src/main/java/de/szut/casino/deposit/WebhookController.java b/backend/src/main/java/de/szut/casino/deposit/WebhookController.java deleted file mode 100644 index 45ba4c1..0000000 --- a/backend/src/main/java/de/szut/casino/deposit/WebhookController.java +++ /dev/null @@ -1,54 +0,0 @@ -package de.szut.casino.deposit; - -import com.stripe.Stripe; -import com.stripe.exception.StripeException; -import com.stripe.model.Event; -import com.stripe.model.checkout.Session; -import com.stripe.net.Webhook; -import jakarta.annotation.PostConstruct; -import jakarta.mail.MessagingException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RestController; - -import java.io.IOException; -import java.util.Objects; - -@RestController -public class WebhookController { - private static final Logger logger = LoggerFactory.getLogger(WebhookController.class); - @Value("${stripe.secret.key}") - private String stripeSecretKey; - - @Value("${stripe.webhook.secret}") - private String webhookSecret; - - private final TransactionService transactionService; - - public WebhookController(TransactionService transactionService) { - this.transactionService = transactionService; - } - - @PostConstruct - public void init() { - Stripe.apiKey = stripeSecretKey; - } - - @PostMapping("/webhook") - public ResponseEntity webhook(@RequestBody String payload, @RequestHeader("Stripe-Signature") String sigHeader) throws StripeException, MessagingException, IOException { - Event event = Webhook.constructEvent(payload, sigHeader, webhookSecret); - - if (Objects.equals(event.getType(), "checkout.session.completed") || Objects.equals(event.getType(), "checkout.session.async_payment_succeeded")) { - Session session = (Session) event.getData().getObject(); - - this.transactionService.fulfillCheckout(session.getId()); - } - - return ResponseEntity.ok().body(null); - } -} diff --git a/backend/src/main/java/de/szut/casino/deposit/dto/AmountDto.java b/backend/src/main/java/de/szut/casino/deposit/dto/AmountDto.java deleted file mode 100644 index 1f1708e..0000000 --- a/backend/src/main/java/de/szut/casino/deposit/dto/AmountDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package de.szut.casino.deposit.dto; - -import jakarta.validation.constraints.Min; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Setter -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class AmountDto { - @Min(50) - private double amount; -} - diff --git a/backend/src/main/java/de/szut/casino/deposit/dto/SessionIdDto.java b/backend/src/main/java/de/szut/casino/deposit/dto/SessionIdDto.java deleted file mode 100644 index b3de1bc..0000000 --- a/backend/src/main/java/de/szut/casino/deposit/dto/SessionIdDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package de.szut.casino.deposit.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Setter -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class SessionIdDto { - private String sessionId; -} - diff --git a/backend/src/main/java/de/szut/casino/dice/DiceController.java b/backend/src/main/java/de/szut/casino/dice/DiceController.java deleted file mode 100644 index 1341d96..0000000 --- a/backend/src/main/java/de/szut/casino/dice/DiceController.java +++ /dev/null @@ -1,38 +0,0 @@ -package de.szut.casino.dice; - -import de.szut.casino.exceptionHandling.exceptions.InsufficientFundsException; -import de.szut.casino.exceptionHandling.exceptions.UserNotFoundException; -import de.szut.casino.shared.service.BalanceService; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserService; -import jakarta.validation.Valid; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Optional; - -@RestController -public class DiceController { - private final UserService userService; - private final BalanceService balanceService; - private final DiceService diceService; - - public DiceController(UserService userService, BalanceService balanceService, DiceService diceService) { - this.userService = userService; - this.balanceService = balanceService; - this.diceService = diceService; - } - - @PostMapping("/dice") - public ResponseEntity rollDice(@RequestBody @Valid DiceDto diceDto) { - UserEntity user = userService.getCurrentUser(); - - if (!this.balanceService.hasFunds(user, diceDto)) { - throw new InsufficientFundsException(); - } - - return ResponseEntity.ok(diceService.play(user, diceDto)); - } -} diff --git a/backend/src/main/java/de/szut/casino/dice/DiceDto.java b/backend/src/main/java/de/szut/casino/dice/DiceDto.java deleted file mode 100644 index f0caf48..0000000 --- a/backend/src/main/java/de/szut/casino/dice/DiceDto.java +++ /dev/null @@ -1,29 +0,0 @@ -package de.szut.casino.dice; - -import de.szut.casino.shared.dto.BetDto; -import jakarta.validation.constraints.DecimalMax; -import jakarta.validation.constraints.DecimalMin; -import jakarta.validation.constraints.NotNull; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; - -@Getter -@Setter -@NoArgsConstructor -public class DiceDto extends BetDto { - private boolean rollOver; - - @NotNull - @DecimalMin(value = "1.00") - @DecimalMax(value = "100") - private BigDecimal targetValue; - - public DiceDto(BigDecimal betAmount, boolean rollOver, BigDecimal targetValue) { - super(betAmount); - this.rollOver = rollOver; - this.targetValue = targetValue; - } -} diff --git a/backend/src/main/java/de/szut/casino/dice/DiceResult.java b/backend/src/main/java/de/szut/casino/dice/DiceResult.java deleted file mode 100644 index 65a7f69..0000000 --- a/backend/src/main/java/de/szut/casino/dice/DiceResult.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.szut.casino.dice; - -import lombok.Getter; -import lombok.Setter; - -import java.math.BigDecimal; - -@Setter -@Getter -public class DiceResult { - private boolean win; - private BigDecimal payout; - private BigDecimal rolledValue; - - public DiceResult(boolean win, BigDecimal payout, BigDecimal rolledValue) { - this.win = win; - this.payout = payout; - this.rolledValue = rolledValue; - } -} diff --git a/backend/src/main/java/de/szut/casino/dice/DiceService.java b/backend/src/main/java/de/szut/casino/dice/DiceService.java deleted file mode 100644 index 836620b..0000000 --- a/backend/src/main/java/de/szut/casino/dice/DiceService.java +++ /dev/null @@ -1,69 +0,0 @@ -package de.szut.casino.dice; - -import de.szut.casino.shared.service.BalanceService; -import de.szut.casino.user.UserEntity; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.Random; - -@Service -public class DiceService { - private static final int MAX_DICE_VALUE = 100; - private final Random random; - private final BalanceService balanceService; - - public DiceService(Random random, BalanceService balanceService) { - this.random = random; - this.balanceService = balanceService; - } - - public DiceResult play(UserEntity user, DiceDto diceDto) { - balanceService.subtractFunds(user, diceDto.getBetAmount()); - - int rolledValue = random.nextInt(MAX_DICE_VALUE) + 1; - BigDecimal rolledValueDecimal = BigDecimal.valueOf(rolledValue); - - BigDecimal targetValue = diceDto.getTargetValue(); - boolean isRollOver = diceDto.isRollOver(); - - boolean winConditionMet = isWinConditionMet(rolledValueDecimal, targetValue, isRollOver); - - if (!winConditionMet) { - return new DiceResult(false, BigDecimal.ZERO, rolledValueDecimal); - } - - BigDecimal winChance = calculateWinChance(targetValue, isRollOver); - BigDecimal multiplier = calculateMultiplier(winChance); - - BigDecimal payout = diceDto.getBetAmount().multiply(multiplier); - balanceService.addFunds(user, payout); - - return new DiceResult(true, payout, rolledValueDecimal); - } - - private boolean isWinConditionMet(BigDecimal rolledValue, BigDecimal targetValue, boolean isRollOver) { - if (isRollOver) { - return rolledValue.compareTo(targetValue) > 0; - } - - return rolledValue.compareTo(targetValue) < 0; - } - - private BigDecimal calculateWinChance(BigDecimal targetValue, boolean isRollOver) { - if (isRollOver) { - return BigDecimal.valueOf(MAX_DICE_VALUE).subtract(targetValue); - } - - return targetValue.subtract(BigDecimal.ONE); - } - - private BigDecimal calculateMultiplier(BigDecimal winChance) { - if (winChance.compareTo(BigDecimal.ZERO) > 0) { - return BigDecimal.valueOf(MAX_DICE_VALUE - 1).divide(winChance, 4, RoundingMode.HALF_UP); - } - - return BigDecimal.ZERO; - } -} diff --git a/backend/src/main/java/de/szut/casino/exceptionHandling/ErrorDetails.java b/backend/src/main/java/de/szut/casino/exceptionHandling/ErrorDetails.java deleted file mode 100644 index cf287c7..0000000 --- a/backend/src/main/java/de/szut/casino/exceptionHandling/ErrorDetails.java +++ /dev/null @@ -1,14 +0,0 @@ -package de.szut.casino.exceptionHandling; - -import lombok.AllArgsConstructor; -import lombok.Data; - -import java.util.Date; - -@Data -@AllArgsConstructor -public class ErrorDetails { - private Date timestamp; - private String message; - private String details; -} diff --git a/backend/src/main/java/de/szut/casino/exceptionHandling/GlobalExceptionHandler.java b/backend/src/main/java/de/szut/casino/exceptionHandling/GlobalExceptionHandler.java deleted file mode 100644 index f07c03a..0000000 --- a/backend/src/main/java/de/szut/casino/exceptionHandling/GlobalExceptionHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -package de.szut.casino.exceptionHandling; - -import de.szut.casino.exceptionHandling.exceptions.EmailNotVerifiedException; -import de.szut.casino.exceptionHandling.exceptions.InsufficientFundsException; -import de.szut.casino.exceptionHandling.exceptions.UserBlackJackGameMismatchException; -import de.szut.casino.exceptionHandling.exceptions.UserNotFoundException; -import jakarta.persistence.EntityExistsException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.context.request.WebRequest; - -import java.util.Date; - -@ControllerAdvice -public class GlobalExceptionHandler { - - @ExceptionHandler(UserNotFoundException.class) - public ResponseEntity handleUserNotFoundException(UserNotFoundException ex, WebRequest request) { - ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); - return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(InsufficientFundsException.class) - public ResponseEntity handleInsufficientFundsException(InsufficientFundsException ex, WebRequest request) { - ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); - return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler(EntityExistsException.class) - public ResponseEntity handleEntityExistsException(EntityExistsException ex, WebRequest request) { - ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); - return new ResponseEntity<>(errorDetails, HttpStatus.CONFLICT); - } - - @ExceptionHandler(EmailNotVerifiedException.class) - public ResponseEntity handleEmailNotVerifiedException(EmailNotVerifiedException ex, WebRequest request) { - ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); - return new ResponseEntity<>(errorDetails, HttpStatus.UNAUTHORIZED); - } - - @ExceptionHandler(UserBlackJackGameMismatchException.class) - public ResponseEntity handleUserBlackJackGameMismatchException(UserBlackJackGameMismatchException ex, WebRequest request) { - ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); - return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND); - } -} diff --git a/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/EmailNotVerifiedException.java b/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/EmailNotVerifiedException.java deleted file mode 100644 index af97d4e..0000000 --- a/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/EmailNotVerifiedException.java +++ /dev/null @@ -1,7 +0,0 @@ -package de.szut.casino.exceptionHandling.exceptions; - -public class EmailNotVerifiedException extends Exception { - public EmailNotVerifiedException() { - super("Email not verified"); - } -} diff --git a/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/InsufficientFundsException.java b/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/InsufficientFundsException.java deleted file mode 100644 index 7c87acc..0000000 --- a/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/InsufficientFundsException.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.szut.casino.exceptionHandling.exceptions; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(value = HttpStatus.BAD_REQUEST) -public class InsufficientFundsException extends RuntimeException { - public InsufficientFundsException() { - super("insufficient funds"); - } -} diff --git a/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/OAuth2AuthenticationProcessingException.java b/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/OAuth2AuthenticationProcessingException.java deleted file mode 100644 index b4f421e..0000000 --- a/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/OAuth2AuthenticationProcessingException.java +++ /dev/null @@ -1,9 +0,0 @@ -package de.szut.casino.exceptionHandling.exceptions; - -import org.springframework.security.core.AuthenticationException; - -public class OAuth2AuthenticationProcessingException extends AuthenticationException { - public OAuth2AuthenticationProcessingException(String msg) { - super(msg); - } -} diff --git a/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/UserBlackJackGameMismatchException.java b/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/UserBlackJackGameMismatchException.java deleted file mode 100644 index 22a93cc..0000000 --- a/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/UserBlackJackGameMismatchException.java +++ /dev/null @@ -1,7 +0,0 @@ -package de.szut.casino.exceptionHandling.exceptions; - -public class UserBlackJackGameMismatchException extends RuntimeException { - public UserBlackJackGameMismatchException(Long gameId) { - super(String.format("Blackjack game with ID %d not found or does not belong to the current user.", gameId)); - } -} diff --git a/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/UserNotFoundException.java b/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/UserNotFoundException.java deleted file mode 100644 index d843af7..0000000 --- a/backend/src/main/java/de/szut/casino/exceptionHandling/exceptions/UserNotFoundException.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.szut.casino.exceptionHandling.exceptions; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(value = HttpStatus.NOT_FOUND) -public class UserNotFoundException extends RuntimeException { - public UserNotFoundException() { - super("User not found"); - } -} diff --git a/backend/src/main/java/de/szut/casino/health/HealthController.java b/backend/src/main/java/de/szut/casino/health/HealthController.java deleted file mode 100644 index da05352..0000000 --- a/backend/src/main/java/de/szut/casino/health/HealthController.java +++ /dev/null @@ -1,15 +0,0 @@ -package de.szut.casino.health; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Map; - -@RestController -public class HealthController { - - @GetMapping("/health") - public Map healthCheck() { - return Map.of("status", "UP"); - } -} diff --git a/backend/src/main/java/de/szut/casino/lootboxes/CreateLootBoxDto.java b/backend/src/main/java/de/szut/casino/lootboxes/CreateLootBoxDto.java deleted file mode 100644 index 10e1b4e..0000000 --- a/backend/src/main/java/de/szut/casino/lootboxes/CreateLootBoxDto.java +++ /dev/null @@ -1,30 +0,0 @@ -package de.szut.casino.lootboxes; - -import jakarta.validation.constraints.DecimalMin; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor -public class CreateLootBoxDto { - @NotEmpty(message = "Loot box name cannot be empty") - @Size(min = 3, max = 50, message = "Loot box name must be between 3 and 50 characters") - private String name; - - @NotNull(message = "Price cannot be null") - @DecimalMin(value = "0.01", message = "Price must be greater than 0") - private BigDecimal price; - - private List rewards = new ArrayList<>(); -} diff --git a/backend/src/main/java/de/szut/casino/lootboxes/CreateRewardDto.java b/backend/src/main/java/de/szut/casino/lootboxes/CreateRewardDto.java deleted file mode 100644 index 0dbe819..0000000 --- a/backend/src/main/java/de/szut/casino/lootboxes/CreateRewardDto.java +++ /dev/null @@ -1,26 +0,0 @@ -package de.szut.casino.lootboxes; - -import jakarta.validation.constraints.DecimalMax; -import jakarta.validation.constraints.DecimalMin; -import jakarta.validation.constraints.NotNull; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; - -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor -public class CreateRewardDto { - @NotNull(message = "Reward value cannot be null") - @DecimalMin(value = "0.00", message = "Reward value must be positive") - private BigDecimal value; - - @NotNull(message = "Probability cannot be null") - @DecimalMin(value = "0.0", message = "Probability must be at least 0.0") - @DecimalMax(value = "1.0", message = "Probability must be at most 1.0") - private BigDecimal probability; -} diff --git a/backend/src/main/java/de/szut/casino/lootboxes/LootBoxController.java b/backend/src/main/java/de/szut/casino/lootboxes/LootBoxController.java deleted file mode 100644 index 4b7d971..0000000 --- a/backend/src/main/java/de/szut/casino/lootboxes/LootBoxController.java +++ /dev/null @@ -1,85 +0,0 @@ -package de.szut.casino.lootboxes; - -import de.szut.casino.exceptionHandling.exceptions.InsufficientFundsException; -import de.szut.casino.exceptionHandling.exceptions.UserNotFoundException; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserService; -import jakarta.validation.Valid; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -@RestController -public class LootBoxController { - private final LootBoxRepository lootBoxRepository; - private final UserService userService; - private final LootBoxService lootBoxService; - - public LootBoxController(LootBoxRepository lootBoxRepository, UserService userService, LootBoxService lootBoxService) { - this.lootBoxRepository = lootBoxRepository; - this.userService = userService; - this.lootBoxService = lootBoxService; - } - - @GetMapping("/lootboxes") - public List getAllLootBoxes() { - return lootBoxRepository.findAll(); - } - - @PostMapping("/lootboxes/{id}") - public ResponseEntity purchaseLootBox(@PathVariable Long id) { - Optional optionalLootBox = lootBoxRepository.findById(id); - if (optionalLootBox.isEmpty()) { - return ResponseEntity.notFound().build(); - } - - LootBoxEntity lootBox = optionalLootBox.get(); - UserEntity user = userService.getCurrentUser(); - - if (lootBoxService.hasSufficientBalance(user, lootBox.getPrice())) { - throw new InsufficientFundsException(); - } - - RewardEntity reward = lootBoxService.determineReward(lootBox); - lootBoxService.handleBalance(user, lootBox, reward); - - return ResponseEntity.ok(reward); - } - - @PostMapping("/lootboxes") - public ResponseEntity createLootbox(@RequestBody @Valid CreateLootBoxDto createLootBoxDto) { - List rewardEntities = new ArrayList<>(); - - for (CreateRewardDto createRewardDto : createLootBoxDto.getRewards()) { - rewardEntities.add(new RewardEntity(createRewardDto.getValue(), createRewardDto.getProbability())); - } - - LootBoxEntity lootBoxEntity = new LootBoxEntity( - createLootBoxDto.getName(), - createLootBoxDto.getPrice(), - rewardEntities - ); - - this.lootBoxRepository.save(lootBoxEntity); - - return ResponseEntity.ok(lootBoxEntity); - } - - @DeleteMapping("/lootboxes/{id}") - public ResponseEntity deleteLootbox(@PathVariable Long id) { - Optional optionalLootBox = lootBoxRepository.findById(id); - if (optionalLootBox.isEmpty()) { - return ResponseEntity.notFound().build(); - } - - LootBoxEntity lootBox = optionalLootBox.get(); - lootBoxRepository.delete(lootBox); - - return ResponseEntity.ok(Collections.singletonMap("message", "successfully deleted lootbox")); - } - -} diff --git a/backend/src/main/java/de/szut/casino/lootboxes/LootBoxEntity.java b/backend/src/main/java/de/szut/casino/lootboxes/LootBoxEntity.java deleted file mode 100644 index 8a3e9a9..0000000 --- a/backend/src/main/java/de/szut/casino/lootboxes/LootBoxEntity.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.szut.casino.lootboxes; - -import jakarta.persistence.*; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -@Entity -@Getter -@Setter -@NoArgsConstructor -public class LootBoxEntity { - - public LootBoxEntity(String name, BigDecimal price, List rewards) { - this.name = name; - this.price = price; - this.rewards = rewards; - } - - @Id - @GeneratedValue - private Long id; - - private String name; - - @Column(precision = 19, scale = 2) - private BigDecimal price; - - @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) - @JoinTable( - name = "lootbox_reward", - joinColumns = @JoinColumn(name = "lootbox_id"), - inverseJoinColumns = @JoinColumn(name = "reward_id") - ) - private List rewards = new ArrayList<>(); -} diff --git a/backend/src/main/java/de/szut/casino/lootboxes/LootBoxRepository.java b/backend/src/main/java/de/szut/casino/lootboxes/LootBoxRepository.java deleted file mode 100644 index 472388e..0000000 --- a/backend/src/main/java/de/szut/casino/lootboxes/LootBoxRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.szut.casino.lootboxes; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Service; - -@Service -public interface LootBoxRepository extends JpaRepository { -} diff --git a/backend/src/main/java/de/szut/casino/lootboxes/LootBoxService.java b/backend/src/main/java/de/szut/casino/lootboxes/LootBoxService.java deleted file mode 100644 index 647b69b..0000000 --- a/backend/src/main/java/de/szut/casino/lootboxes/LootBoxService.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.szut.casino.lootboxes; - -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserRepository; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; - -@Service -public class LootBoxService { - private final UserRepository userRepository; - - public LootBoxService(UserRepository userRepository) { - this.userRepository = userRepository; - } - - public boolean hasSufficientBalance(UserEntity user, BigDecimal price) { - return user.getBalance().compareTo(price) < 0; - } - - public RewardEntity determineReward(LootBoxEntity lootBox) { - double randomValue = Math.random(); - BigDecimal cumulativeProbability = BigDecimal.ZERO; - - for (RewardEntity reward : lootBox.getRewards()) { - cumulativeProbability = cumulativeProbability.add(reward.getProbability()); - if (randomValue <= cumulativeProbability.doubleValue()) { - return reward; - } - } - - return lootBox.getRewards().getLast(); - } - - public void handleBalance(UserEntity user, LootBoxEntity lootBox, RewardEntity reward) { - user.setBalance(user.getBalance().subtract(lootBox.getPrice())); - user.setBalance(user.getBalance().add(reward.getValue())); - userRepository.save(user); - } -} diff --git a/backend/src/main/java/de/szut/casino/lootboxes/RewardEntity.java b/backend/src/main/java/de/szut/casino/lootboxes/RewardEntity.java deleted file mode 100644 index 1abd2df..0000000 --- a/backend/src/main/java/de/szut/casino/lootboxes/RewardEntity.java +++ /dev/null @@ -1,37 +0,0 @@ -package de.szut.casino.lootboxes; - -import com.fasterxml.jackson.annotation.JsonBackReference; -import jakarta.persistence.*; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -@Getter -@Setter -@Entity -@NoArgsConstructor -public class RewardEntity { - - public RewardEntity(BigDecimal value, BigDecimal probability) { - this.value = value; - this.probability = probability; - } - - @Id - @GeneratedValue - private Long id; - - @Column(precision = 19, scale = 2) - private BigDecimal value; - - @Column(precision = 5, scale = 2) - private BigDecimal probability; - - @ManyToMany(mappedBy = "rewards") - @JsonBackReference - private List lootBoxes = new ArrayList<>(); -} diff --git a/backend/src/main/java/de/szut/casino/lootboxes/RewardRepository.java b/backend/src/main/java/de/szut/casino/lootboxes/RewardRepository.java deleted file mode 100644 index 7878000..0000000 --- a/backend/src/main/java/de/szut/casino/lootboxes/RewardRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.szut.casino.lootboxes; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Service; - -@Service -public interface RewardRepository extends JpaRepository { -} diff --git a/backend/src/main/java/de/szut/casino/security/AuthController.java b/backend/src/main/java/de/szut/casino/security/AuthController.java deleted file mode 100644 index f0387c7..0000000 --- a/backend/src/main/java/de/szut/casino/security/AuthController.java +++ /dev/null @@ -1,60 +0,0 @@ -package de.szut.casino.security; - -import de.szut.casino.exceptionHandling.exceptions.EmailNotVerifiedException; -import de.szut.casino.security.dto.AuthResponseDto; -import de.szut.casino.security.dto.LoginRequestDto; -import de.szut.casino.security.dto.ResetPasswordDto; -import de.szut.casino.security.service.AuthService; -import de.szut.casino.user.dto.CreateUserDto; -import de.szut.casino.user.dto.GetUserDto; -import jakarta.mail.MessagingException; -import jakarta.validation.Valid; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.io.IOException; - -@RestController -@RequestMapping("/auth") -public class AuthController { - - - private final AuthService authService; - - public AuthController(AuthService authService) { - this.authService = authService; - } - - @PostMapping("/login") - public ResponseEntity authenticateUser(@Valid @RequestBody LoginRequestDto loginRequest) throws EmailNotVerifiedException { - AuthResponseDto response = authService.login(loginRequest); - return ResponseEntity.ok(response); - } - - @PostMapping("/register") - public ResponseEntity registerUser(@Valid @RequestBody CreateUserDto signUpRequest) throws MessagingException, IOException { - GetUserDto response = authService.register(signUpRequest); - return ResponseEntity.ok(response); - } - - @PostMapping("/verify") - public ResponseEntity verifyEmail(@RequestParam("token") String token) throws MessagingException, IOException { - if (authService.verifyEmail(token)) { - return ResponseEntity.badRequest().build(); - } - - return ResponseEntity.ok().build(); - } - - @PostMapping("/recover-password") - public ResponseEntity recoverPassword(@RequestParam("email") String email) throws MessagingException, IOException { - authService.recoverPassword(email); - return ResponseEntity.ok().build(); - } - - @PostMapping("/reset-password") - public ResponseEntity resetPassword(@Valid @RequestBody ResetPasswordDto passwordDto) throws MessagingException, IOException { - authService.resetPassword(passwordDto); - return ResponseEntity.ok().build(); - } -} diff --git a/backend/src/main/java/de/szut/casino/security/CorsFilter.java b/backend/src/main/java/de/szut/casino/security/CorsFilter.java deleted file mode 100644 index b1c1b3b..0000000 --- a/backend/src/main/java/de/szut/casino/security/CorsFilter.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.szut.casino.security; - -import jakarta.servlet.*; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -@Component -@Order(Ordered.HIGHEST_PRECEDENCE) -public class CorsFilter implements Filter { - - @Value("${app.frontend-host}") - private String frontendHost; - - @Override - public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { - - HttpServletResponse response = (HttpServletResponse) res; - HttpServletRequest request = (HttpServletRequest) req; - - response.setHeader("Access-Control-Allow-Origin", frontendHost); - response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS"); - response.setHeader("Access-Control-Allow-Headers", "*"); - response.setHeader("Access-Control-Expose-Headers", "*"); - response.setHeader("Access-Control-Allow-Credentials", "true"); - response.setHeader("Access-Control-Max-Age", "3600"); - - if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { - response.setStatus(HttpServletResponse.SC_OK); - return; - } - - chain.doFilter(req, res); - } -} diff --git a/backend/src/main/java/de/szut/casino/security/CustomJwtAuthenticationConverter.java b/backend/src/main/java/de/szut/casino/security/CustomJwtAuthenticationConverter.java deleted file mode 100644 index 1997ac7..0000000 --- a/backend/src/main/java/de/szut/casino/security/CustomJwtAuthenticationConverter.java +++ /dev/null @@ -1,24 +0,0 @@ -package de.szut.casino.security; - -import org.springframework.core.convert.converter.Converter; -import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.oauth2.jwt.Jwt; -import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; -import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter; - -public class CustomJwtAuthenticationConverter implements Converter { - - @Override - public AbstractAuthenticationToken convert(Jwt source) { - JwtGrantedAuthoritiesConverter authoritiesConverter = new JwtGrantedAuthoritiesConverter(); - JwtAuthenticationConverter converter = new JwtAuthenticationConverter(); - converter.setJwtGrantedAuthoritiesConverter(authoritiesConverter); - - return converter.convert(source); - } - - public Converter andThen(Converter after) { - return Converter.super.andThen(after); - } -} - diff --git a/backend/src/main/java/de/szut/casino/security/SecurityConfig.java b/backend/src/main/java/de/szut/casino/security/SecurityConfig.java deleted file mode 100644 index 9268cf2..0000000 --- a/backend/src/main/java/de/szut/casino/security/SecurityConfig.java +++ /dev/null @@ -1,94 +0,0 @@ -package de.szut.casino.security; - -import de.szut.casino.security.jwt.JwtAuthenticationFilter; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.dao.DaoAuthenticationProvider; -import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; -import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.CorsConfigurationSource; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; - -import java.util.Arrays; -import java.util.List; - -@Configuration -@EnableWebSecurity -@EnableMethodSecurity -public class SecurityConfig { - - @Value("${app.frontend-host}") - private String frontendHost; - - private final UserDetailsService userDetailsService; - private final JwtAuthenticationFilter jwtAuthenticationFilter; - - public SecurityConfig(UserDetailsService userDetailsService, JwtAuthenticationFilter jwtAuthenticationFilter) { - this.userDetailsService = userDetailsService; - this.jwtAuthenticationFilter = jwtAuthenticationFilter; - } - - - @Bean - public DaoAuthenticationProvider authenticationProvider() { - DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); - - authProvider.setUserDetailsService(userDetailsService); - authProvider.setPasswordEncoder(passwordEncoder()); - - return authProvider; - } - - @Bean - public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception { - return authConfig.getAuthenticationManager(); - } - - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } - - @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http - .cors(cors -> cors.configurationSource(corsConfigurationSource())) - .csrf(csrf -> csrf.disable()) - .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .authorizeHttpRequests(auth -> { - auth.requestMatchers("/auth/**", "/webhook", "/swagger/**", "/swagger-ui/**", "/health", "/error", "/oauth2/**").permitAll() - .requestMatchers(org.springframework.http.HttpMethod.OPTIONS, "/**").permitAll() - .anyRequest().authenticated(); - }) - .authenticationProvider(authenticationProvider()) - .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); - - return http.build(); - } - - @Bean - public CorsConfigurationSource corsConfigurationSource() { - CorsConfiguration configuration = new CorsConfiguration(); - configuration.setAllowedOrigins(List.of(this.frontendHost)); - configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")); - configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type", "Accept", "Origin", "X-Requested-With", "Access-Control-Request-Method", "Access-Control-Request-Headers", "x-auth-token")); - configuration.setExposedHeaders(Arrays.asList("Authorization", "Content-Type", "x-auth-token", "Access-Control-Allow-Origin", "Access-Control-Allow-Methods", "Access-Control-Allow-Headers")); - configuration.setAllowCredentials(true); - configuration.setMaxAge(3600L); - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - source.registerCorsConfiguration("/**", configuration); - return source; - } -} - diff --git a/backend/src/main/java/de/szut/casino/security/dto/AuthResponseDto.java b/backend/src/main/java/de/szut/casino/security/dto/AuthResponseDto.java deleted file mode 100644 index 4dfe79a..0000000 --- a/backend/src/main/java/de/szut/casino/security/dto/AuthResponseDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.szut.casino.security.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Getter -@Setter -@NoArgsConstructor -@AllArgsConstructor -public class AuthResponseDto { - private String token; - private String tokenType = "Bearer"; - - public AuthResponseDto(String token) { - this.token = token; - } -} diff --git a/backend/src/main/java/de/szut/casino/security/dto/LoginRequestDto.java b/backend/src/main/java/de/szut/casino/security/dto/LoginRequestDto.java deleted file mode 100644 index 767a6d3..0000000 --- a/backend/src/main/java/de/szut/casino/security/dto/LoginRequestDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.szut.casino.security.dto; - -import jakarta.validation.constraints.NotBlank; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Getter -@Setter -@NoArgsConstructor -@AllArgsConstructor -public class LoginRequestDto { - @NotBlank(message = "Username or email is required") - private String usernameOrEmail; - - @NotBlank(message = "Password is required") - private String password; -} diff --git a/backend/src/main/java/de/szut/casino/security/dto/ResetPasswordDto.java b/backend/src/main/java/de/szut/casino/security/dto/ResetPasswordDto.java deleted file mode 100644 index 192d928..0000000 --- a/backend/src/main/java/de/szut/casino/security/dto/ResetPasswordDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package de.szut.casino.security.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@AllArgsConstructor -@NoArgsConstructor -@Getter -@Setter -public class ResetPasswordDto { - private String token; - private String password; -} diff --git a/backend/src/main/java/de/szut/casino/security/jwt/JwtAuthenticationFilter.java b/backend/src/main/java/de/szut/casino/security/jwt/JwtAuthenticationFilter.java deleted file mode 100644 index 4766f4a..0000000 --- a/backend/src/main/java/de/szut/casino/security/jwt/JwtAuthenticationFilter.java +++ /dev/null @@ -1,65 +0,0 @@ -package de.szut.casino.security.jwt; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; -import org.springframework.web.filter.OncePerRequestFilter; - -import java.io.IOException; - -@Component -public class JwtAuthenticationFilter extends OncePerRequestFilter { - - private final JwtUtils jwtUtils; - private final UserDetailsService userDetailsService; - - public JwtAuthenticationFilter(JwtUtils jwtUtils, UserDetailsService userDetailsService) { - this.jwtUtils = jwtUtils; - this.userDetailsService = userDetailsService; - } - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) - throws ServletException, IOException { - try { - String jwt = parseJwt(request); - if (jwt != null) { - String username = jwtUtils.extractUsername(jwt); - - if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { - UserDetails userDetails = userDetailsService.loadUserByUsername(username); - - if (jwtUtils.validateToken(jwt, userDetails)) { - UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken( - userDetails, null, userDetails.getAuthorities()); - - authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - SecurityContextHolder.getContext().setAuthentication(authToken); - } - } - } - } catch (Exception e) { - logger.error("Cannot set user authentication: {}", e); - } - - filterChain.doFilter(request, response); - } - - private String parseJwt(HttpServletRequest request) { - String headerAuth = request.getHeader("Authorization"); - - if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) { - return headerAuth.substring(7); - } - - return null; - } -} diff --git a/backend/src/main/java/de/szut/casino/security/jwt/JwtUtils.java b/backend/src/main/java/de/szut/casino/security/jwt/JwtUtils.java deleted file mode 100644 index 1a7d08d..0000000 --- a/backend/src/main/java/de/szut/casino/security/jwt/JwtUtils.java +++ /dev/null @@ -1,109 +0,0 @@ -package de.szut.casino.security.jwt; - -import de.szut.casino.security.oauth2.UserPrincipal; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import io.jsonwebtoken.security.Keys; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.stereotype.Component; - -import java.security.Key; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - -@Component -public class JwtUtils { - private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class); - - @Value("${jwt.secret}") - private String jwtSecret; - - @Value("${jwt.expiration.ms}") - private int jwtExpirationMs; - - private Key getSigningKey() { - return Keys.hmacShaKeyFor(jwtSecret.getBytes()); - } - - public String generateToken(Authentication authentication) { - String subject = null; - Map claims = new HashMap<>(); - - if (authentication.getPrincipal() instanceof UserPrincipal) { - UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); - subject = userPrincipal.getEmail(); - claims.put("id", userPrincipal.getId()); - claims.put("username", userPrincipal.getDisplayUsername()); - logger.info("Generating token for UserPrincipal: {}", subject); - } else if (authentication.getPrincipal() instanceof OAuth2User) { - OAuth2User oauth2User = (OAuth2User) authentication.getPrincipal(); - subject = (String) oauth2User.getAttributes().get("email"); - logger.info("Generating token for OAuth2User: {}", subject); - } else { - UserDetails userDetails = (UserDetails) authentication.getPrincipal(); - subject = userDetails.getUsername(); - logger.info("Generating token for UserDetails: {}", subject); - } - - return createToken(claims, subject); - } - - public String generateToken(String username) { - Map claims = new HashMap<>(); - return createToken(claims, username); - } - - private String createToken(Map claims, String subject) { - Date now = new Date(); - logger.info("now: {}", now); - logger.info("jwtExpirationMs: {}", jwtExpirationMs); - logger.info("expiryDate: {}", new Date(now.getTime() + jwtExpirationMs)); - Date expiryDate = new Date(now.getTime() + jwtExpirationMs); - - return Jwts.builder() - .setClaims(claims) - .setSubject(subject) - .setIssuedAt(now) - .setExpiration(expiryDate) - .signWith(getSigningKey(), SignatureAlgorithm.HS256) - .compact(); - } - - public String extractUsername(String token) { - return extractClaim(token, Claims::getSubject); - } - - public Date extractExpiration(String token) { - return extractClaim(token, Claims::getExpiration); - } - - public T extractClaim(String token, Function claimsResolver) { - final Claims claims = extractAllClaims(token); - return claimsResolver.apply(claims); - } - - private Claims extractAllClaims(String token) { - return Jwts.parserBuilder() - .setSigningKey(getSigningKey()) - .build() - .parseClaimsJws(token) - .getBody(); - } - - private Boolean isTokenExpired(String token) { - return extractExpiration(token).before(new Date()); - } - - public Boolean validateToken(String token, UserDetails userDetails) { - final String username = extractUsername(token); - return (username.equals(userDetails.getUsername()) && !isTokenExpired(token)); - } -} diff --git a/backend/src/main/java/de/szut/casino/security/oauth2/CustomOAuth2UserService.java b/backend/src/main/java/de/szut/casino/security/oauth2/CustomOAuth2UserService.java deleted file mode 100644 index a8bda84..0000000 --- a/backend/src/main/java/de/szut/casino/security/oauth2/CustomOAuth2UserService.java +++ /dev/null @@ -1,106 +0,0 @@ -package de.szut.casino.security.oauth2; - -import de.szut.casino.exceptionHandling.exceptions.OAuth2AuthenticationProcessingException; -import de.szut.casino.user.AuthProvider; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserRepository; -import org.springframework.security.authentication.InternalAuthenticationServiceException; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; -import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; -import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; - -import java.math.BigDecimal; -import java.util.Optional; -import java.util.UUID; - -@Service -public class CustomOAuth2UserService extends DefaultOAuth2UserService { - - private final UserRepository userRepository; - private final PasswordEncoder oauth2PasswordEncoder; - - public CustomOAuth2UserService(UserRepository userRepository, PasswordEncoder oauth2PasswordEncoder) { - this.userRepository = userRepository; - this.oauth2PasswordEncoder = oauth2PasswordEncoder; - } - - @Override - public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2AuthenticationException { - OAuth2User oAuth2User = super.loadUser(oAuth2UserRequest); - - try { - return processOAuth2User(oAuth2UserRequest, oAuth2User); - } catch (AuthenticationException ex) { - throw ex; - } catch (Exception ex) { - throw new InternalAuthenticationServiceException(ex.getMessage(), ex.getCause()); - } - } - - private OAuth2User processOAuth2User(OAuth2UserRequest oAuth2UserRequest, OAuth2User oAuth2User) { - String registrationId = oAuth2UserRequest.getClientRegistration().getRegistrationId(); - OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(registrationId, oAuth2User.getAttributes()); - - String email = oAuth2UserInfo.getEmail(); - if (StringUtils.isEmpty(email)) { - email = oAuth2UserInfo.getName() + "@github.user"; - } - - Optional userOptional = userRepository.findByEmail(email); - UserEntity user; - - if (userOptional.isPresent()) { - user = userOptional.get(); - - if (!user.getProvider().equals(AuthProvider.valueOf(registrationId.toUpperCase()))) { - throw new OAuth2AuthenticationProcessingException("You're signed up with " + - user.getProvider() + ". Please use your " + user.getProvider() + - " account to login."); - } - - user = updateExistingUser(user, oAuth2UserInfo); - } else { - user = registerNewUser(oAuth2UserRequest, oAuth2UserInfo, email); - } - - return UserPrincipal.create(user, oAuth2User.getAttributes()); - } - - private UserEntity registerNewUser(OAuth2UserRequest oAuth2UserRequest, OAuth2UserInfo oAuth2UserInfo, String email) { - UserEntity user = new UserEntity(); - - String username = oAuth2UserInfo.getName(); - if (StringUtils.isEmpty(username)) { - username = "github_" + oAuth2UserInfo.getId(); - } - - if (userRepository.findByUsername(username).isPresent()) { - username = username + "_" + UUID.randomUUID().toString().substring(0, 8); - } - - user.setProvider(AuthProvider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId().toUpperCase())); - user.setProviderId(oAuth2UserInfo.getId()); - user.setUsername(username); - user.setEmail(email); - user.setEmailVerified(true); - - String randomPassword = UUID.randomUUID().toString(); - user.setPassword(oauth2PasswordEncoder.encode(randomPassword)); - - user.setBalance(new BigDecimal("100.00")); // Starting balance - - return userRepository.save(user); - } - - private UserEntity updateExistingUser(UserEntity existingUser, OAuth2UserInfo oAuth2UserInfo) { - if (!StringUtils.isEmpty(oAuth2UserInfo.getName())) { - existingUser.setUsername(oAuth2UserInfo.getName()); - } - return userRepository.save(existingUser); - } -} diff --git a/backend/src/main/java/de/szut/casino/security/oauth2/OAuth2AuthenticationSuccessHandler.java b/backend/src/main/java/de/szut/casino/security/oauth2/OAuth2AuthenticationSuccessHandler.java deleted file mode 100644 index 75eb6b6..0000000 --- a/backend/src/main/java/de/szut/casino/security/oauth2/OAuth2AuthenticationSuccessHandler.java +++ /dev/null @@ -1,57 +0,0 @@ -package de.szut.casino.security.oauth2; - -import de.szut.casino.security.jwt.JwtUtils; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; -import org.springframework.stereotype.Component; -import org.springframework.web.util.UriComponentsBuilder; - -import java.io.IOException; - -@Component -public class OAuth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { - private static final Logger logger = LoggerFactory.getLogger(OAuth2AuthenticationSuccessHandler.class); - - @Value("${app.oauth2.authorizedRedirectUris}") - private String redirectUri; - - private final JwtUtils jwtUtils; - - public OAuth2AuthenticationSuccessHandler(JwtUtils jwtUtils) { - this.jwtUtils = jwtUtils; - } - - @Override - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) - throws IOException { - String targetUrl = determineTargetUrl(authentication); - - logger.info("OAuth2 Authentication successful, redirecting to: {}", targetUrl); - - if (response.isCommitted()) { - logger.debug("Response has already been committed. Unable to redirect to " + targetUrl); - return; - } - - clearAuthenticationAttributes(request); - getRedirectStrategy().sendRedirect(request, response, targetUrl); - } - - private String determineTargetUrl(Authentication authentication) { - String token = jwtUtils.generateToken(authentication); - - if (authentication.getPrincipal() instanceof UserPrincipal) { - UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); - logger.info("User authenticated: ID={}, Email={}", userPrincipal.getId(), userPrincipal.getEmail()); - } - - return UriComponentsBuilder.fromUriString(redirectUri) - .queryParam("token", token) - .build().toUriString(); - } -} diff --git a/backend/src/main/java/de/szut/casino/security/oauth2/OAuth2Config.java b/backend/src/main/java/de/szut/casino/security/oauth2/OAuth2Config.java deleted file mode 100644 index 32104ed..0000000 --- a/backend/src/main/java/de/szut/casino/security/oauth2/OAuth2Config.java +++ /dev/null @@ -1,15 +0,0 @@ -package de.szut.casino.security.oauth2; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; - -@Configuration -public class OAuth2Config { - - @Bean - public PasswordEncoder oauth2PasswordEncoder() { - return new BCryptPasswordEncoder(); - } -} diff --git a/backend/src/main/java/de/szut/casino/security/oauth2/OAuth2UserInfo.java b/backend/src/main/java/de/szut/casino/security/oauth2/OAuth2UserInfo.java deleted file mode 100644 index 14e2bcc..0000000 --- a/backend/src/main/java/de/szut/casino/security/oauth2/OAuth2UserInfo.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.szut.casino.security.oauth2; - -import lombok.Getter; - -import java.util.Map; - -@Getter -public abstract class OAuth2UserInfo { - protected Map attributes; - - public OAuth2UserInfo(Map attributes) { - this.attributes = attributes; - } - - public abstract String getId(); - - public abstract String getName(); - - public abstract String getEmail(); -} diff --git a/backend/src/main/java/de/szut/casino/security/oauth2/OAuth2UserInfoFactory.java b/backend/src/main/java/de/szut/casino/security/oauth2/OAuth2UserInfoFactory.java deleted file mode 100644 index 66633e0..0000000 --- a/backend/src/main/java/de/szut/casino/security/oauth2/OAuth2UserInfoFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -package de.szut.casino.security.oauth2; - -import de.szut.casino.exceptionHandling.exceptions.OAuth2AuthenticationProcessingException; -import de.szut.casino.security.oauth2.github.GitHubOAuth2UserInfo; -import de.szut.casino.security.oauth2.google.GoogleOAuth2UserInfo; -import de.szut.casino.user.AuthProvider; - -import java.util.Map; - -public class OAuth2UserInfoFactory { - - public static OAuth2UserInfo getOAuth2UserInfo(String registrationId, Map attributes) { - if (registrationId.equalsIgnoreCase(AuthProvider.GITHUB.toString())) { - return new GitHubOAuth2UserInfo(attributes); - } else if (registrationId.equalsIgnoreCase(AuthProvider.GOOGLE.toString())) { - return new GoogleOAuth2UserInfo(attributes); - } else { - throw new OAuth2AuthenticationProcessingException("Sorry! Login with " + registrationId + " is not supported yet."); - } - } -} diff --git a/backend/src/main/java/de/szut/casino/security/oauth2/UserPrincipal.java b/backend/src/main/java/de/szut/casino/security/oauth2/UserPrincipal.java deleted file mode 100644 index 8ec25e0..0000000 --- a/backend/src/main/java/de/szut/casino/security/oauth2/UserPrincipal.java +++ /dev/null @@ -1,102 +0,0 @@ -package de.szut.casino.security.oauth2; - -import de.szut.casino.user.UserEntity; -import lombok.Getter; -import lombok.Setter; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.oauth2.core.user.OAuth2User; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -public class UserPrincipal implements OAuth2User, UserDetails { - @Getter - private Long id; - @Getter - private String email; - private String username; - private String password; - private Collection authorities; - @Setter - private Map attributes; - - public UserPrincipal(Long id, String email, String username, String password, Collection authorities) { - this.id = id; - this.email = email; - this.username = username; - this.password = password; - this.authorities = authorities; - } - - public static UserPrincipal create(UserEntity user) { - List authorities = Collections. - singletonList(new SimpleGrantedAuthority("ROLE_USER")); - - return new UserPrincipal( - user.getId(), - user.getEmail(), - user.getUsername(), - user.getPassword(), - authorities - ); - } - - public static UserPrincipal create(UserEntity user, Map attributes) { - UserPrincipal userPrincipal = UserPrincipal.create(user); - userPrincipal.setAttributes(attributes); - return userPrincipal; - } - - @Override - public String getPassword() { - return password; - } - - @Override - public String getUsername() { - return email; - } - - public String getDisplayUsername() { - return username; - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return true; - } - - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - public boolean isEnabled() { - return true; - } - - @Override - public Collection getAuthorities() { - return authorities; - } - - @Override - public Map getAttributes() { - return attributes; - } - - @Override - public String getName() { - return String.valueOf(id); - } -} diff --git a/backend/src/main/java/de/szut/casino/security/oauth2/github/GitHubController.java b/backend/src/main/java/de/szut/casino/security/oauth2/github/GitHubController.java deleted file mode 100644 index 2fe6279..0000000 --- a/backend/src/main/java/de/szut/casino/security/oauth2/github/GitHubController.java +++ /dev/null @@ -1,50 +0,0 @@ -package de.szut.casino.security.oauth2.github; - -import de.szut.casino.security.dto.AuthResponseDto; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.servlet.view.RedirectView; - -@RestController -@RequestMapping("/oauth2/github") -public class GitHubController { - private static final Logger logger = LoggerFactory.getLogger(GitHubController.class); - - @Value("${spring.security.oauth2.client.registration.github.client-id}") - private String clientId; - - @Value("${spring.security.oauth2.client.provider.github.authorization-uri}") - private String authorizationUri; - - @Value("${spring.security.oauth2.client.registration.github.redirect-uri}") - private String redirectUri; - - private final GitHubService githubService; - - public GitHubController(GitHubService githubService) { - this.githubService = githubService; - } - - @GetMapping("/authorize") - public RedirectView authorizeGithub() { - logger.info("Redirecting to GitHub for authorization"); - - String authUrl = authorizationUri + - "?client_id=" + clientId + - "&redirect_uri=" + redirectUri + - "&scope=user:email,read:user"; - - return new RedirectView(authUrl); - } - - - @PostMapping("/callback") - public ResponseEntity githubCallback(@RequestBody GithubCallbackDto githubCallbackDto) { - String code = githubCallbackDto.getCode(); - AuthResponseDto response = githubService.processGithubCode(code); - return ResponseEntity.ok(response); - } -} diff --git a/backend/src/main/java/de/szut/casino/security/oauth2/github/GitHubOAuth2UserInfo.java b/backend/src/main/java/de/szut/casino/security/oauth2/github/GitHubOAuth2UserInfo.java deleted file mode 100644 index c764fc7..0000000 --- a/backend/src/main/java/de/szut/casino/security/oauth2/github/GitHubOAuth2UserInfo.java +++ /dev/null @@ -1,27 +0,0 @@ -package de.szut.casino.security.oauth2.github; - -import de.szut.casino.security.oauth2.OAuth2UserInfo; - -import java.util.Map; - -public class GitHubOAuth2UserInfo extends OAuth2UserInfo { - - public GitHubOAuth2UserInfo(Map attributes) { - super(attributes); - } - - @Override - public String getId() { - return ((Integer) attributes.get("id")).toString(); - } - - @Override - public String getName() { - return (String) attributes.get("name"); - } - - @Override - public String getEmail() { - return (String) attributes.get("email"); - } -} diff --git a/backend/src/main/java/de/szut/casino/security/oauth2/github/GitHubService.java b/backend/src/main/java/de/szut/casino/security/oauth2/github/GitHubService.java deleted file mode 100644 index 3c7d22f..0000000 --- a/backend/src/main/java/de/szut/casino/security/oauth2/github/GitHubService.java +++ /dev/null @@ -1,162 +0,0 @@ -package de.szut.casino.security.oauth2.github; - -import de.szut.casino.security.dto.AuthResponseDto; -import de.szut.casino.security.jwt.JwtUtils; -import de.szut.casino.user.AuthProvider; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserRepository; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; - -import java.math.BigDecimal; -import java.util.*; - -@Service -public class GitHubService { - @Value("${spring.security.oauth2.client.registration.github.client-id}") - private String clientId; - - @Value("${spring.security.oauth2.client.registration.github.client-secret}") - private String clientSecret; - - private final AuthenticationManager authenticationManager; - private final UserRepository userRepository; - private final JwtUtils jwtUtils; - private final PasswordEncoder oauth2PasswordEncoder; - - public GitHubService(AuthenticationManager authenticationManager, UserRepository userRepository, JwtUtils jwtUtils, PasswordEncoder oauth2PasswordEncoder) { - this.authenticationManager = authenticationManager; - this.userRepository = userRepository; - this.jwtUtils = jwtUtils; - this.oauth2PasswordEncoder = oauth2PasswordEncoder; - } - - public AuthResponseDto processGithubCode(String code) { - try { - RestTemplate restTemplate = new RestTemplate(); - - Map requestBody = new HashMap<>(); - requestBody.put("client_id", clientId); - requestBody.put("client_secret", clientSecret); - requestBody.put("code", code); - - HttpHeaders headers = new HttpHeaders(); - headers.set("Accept", "application/json"); - - HttpEntity> requestEntity = new HttpEntity<>(requestBody, headers); - - ResponseEntity response = restTemplate.exchange( - "https://github.com/login/oauth/access_token", - HttpMethod.POST, - requestEntity, - Map.class - ); - - Map responseBody = response.getBody(); - - if (responseBody.containsKey("error")) { - String error = (String) responseBody.get("error"); - String errorDescription = (String) responseBody.get("error_description"); - - throw new RuntimeException("GitHub OAuth error: " + errorDescription); - } - - String accessToken = (String) responseBody.get("access_token"); - if (accessToken == null || accessToken.isEmpty()) { - - throw new RuntimeException("Failed to receive access token from GitHub"); - } - - HttpHeaders userInfoHeaders = new HttpHeaders(); - userInfoHeaders.set("Authorization", "Bearer " + accessToken); - - HttpEntity userInfoRequestEntity = new HttpEntity<>(null, userInfoHeaders); - - ResponseEntity userResponse = restTemplate.exchange( - "https://api.github.com/user", - HttpMethod.GET, - userInfoRequestEntity, - Map.class - ); - - Map userAttributes = userResponse.getBody(); - - HttpHeaders emailsHeaders = new HttpHeaders(); - emailsHeaders.set("Authorization", "Bearer " + accessToken); - - HttpEntity emailsRequestEntity = new HttpEntity<>(null, emailsHeaders); - - ResponseEntity emailsResponse = restTemplate.exchange( - "https://api.github.com/user/emails", - HttpMethod.GET, - emailsRequestEntity, - List.class - ); - - List> emails = emailsResponse.getBody(); - String email = null; - - for (Map emailInfo : emails) { - Boolean primary = (Boolean) emailInfo.get("primary"); - if (primary != null && primary) { - email = (String) emailInfo.get("email"); - break; - } - } - - if (email == null && !emails.isEmpty()) { - email = (String) emails.get(0).get("email"); - } - - String githubId = userAttributes.get("id").toString(); - String username = (String) userAttributes.get("login"); - - Optional userOptional = userRepository.findByProviderId(githubId); - UserEntity user; - - if (userOptional.isPresent()) { - user = userOptional.get(); - } else { - userOptional = userRepository.findByEmail(email); - - if (userOptional.isPresent()) { - user = userOptional.get(); - user.setProvider(AuthProvider.GITHUB); - user.setProviderId(githubId); - } else { - user = new UserEntity(); - user.setEmail(email); - user.setUsername(username); - user.setProvider(AuthProvider.GITHUB); - user.setProviderId(githubId); - user.setEmailVerified(true); - - user.setBalance(new BigDecimal("1000.00")); - } - } - - String randomPassword = UUID.randomUUID().toString(); - user.setPassword(oauth2PasswordEncoder.encode(randomPassword)); - - userRepository.save(user); - - Authentication authentication = this.authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getEmail(), randomPassword)); - - String token = jwtUtils.generateToken(authentication); - - return new AuthResponseDto(token); - - } catch (Exception e) { - throw new RuntimeException("Failed to process GitHub authentication", e); - } - } -} diff --git a/backend/src/main/java/de/szut/casino/security/oauth2/github/GithubCallbackDto.java b/backend/src/main/java/de/szut/casino/security/oauth2/github/GithubCallbackDto.java deleted file mode 100644 index 620a708..0000000 --- a/backend/src/main/java/de/szut/casino/security/oauth2/github/GithubCallbackDto.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.szut.casino.security.oauth2.github; - -import lombok.Data; - -@Data -public class GithubCallbackDto { - private String code; -} diff --git a/backend/src/main/java/de/szut/casino/security/oauth2/google/GoogleController.java b/backend/src/main/java/de/szut/casino/security/oauth2/google/GoogleController.java deleted file mode 100644 index 9a50f65..0000000 --- a/backend/src/main/java/de/szut/casino/security/oauth2/google/GoogleController.java +++ /dev/null @@ -1,51 +0,0 @@ -package de.szut.casino.security.oauth2.google; - -import de.szut.casino.security.dto.AuthResponseDto; -import de.szut.casino.security.oauth2.github.GithubCallbackDto; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.servlet.view.RedirectView; - -@RestController -@RequestMapping("/oauth2/google") -public class GoogleController { - private static final Logger logger = LoggerFactory.getLogger(GoogleController.class); - - @Value("${spring.security.oauth2.client.registration.google.client-id}") - private String clientId; - - @Value("${spring.security.oauth2.client.provider.google.authorization-uri}") - private String authorizationUri; - - @Value("${spring.security.oauth2.client.registration.google.redirect-uri}") - private String redirectUri; - - private final GoogleService googleService; - - public GoogleController(GoogleService googleService) { - this.googleService = googleService; - } - - @GetMapping("/authorize") - public RedirectView authorizeGoogle() { - logger.info("Redirecting to Google for authorization"); - - String authUrl = authorizationUri + - "?client_id=" + clientId + - "&redirect_uri=" + redirectUri + - "&response_type=code" + - "&scope=email profile"; - - return new RedirectView(authUrl); - } - - @PostMapping("/callback") - public ResponseEntity googleCallback(@RequestBody GithubCallbackDto callbackDto) { - String code = callbackDto.getCode(); - AuthResponseDto response = googleService.processGoogleCode(code); - return ResponseEntity.ok(response); - } -} diff --git a/backend/src/main/java/de/szut/casino/security/oauth2/google/GoogleOAuth2UserInfo.java b/backend/src/main/java/de/szut/casino/security/oauth2/google/GoogleOAuth2UserInfo.java deleted file mode 100644 index 819a9b3..0000000 --- a/backend/src/main/java/de/szut/casino/security/oauth2/google/GoogleOAuth2UserInfo.java +++ /dev/null @@ -1,27 +0,0 @@ -package de.szut.casino.security.oauth2.google; - -import de.szut.casino.security.oauth2.OAuth2UserInfo; - -import java.util.Map; - -public class GoogleOAuth2UserInfo extends OAuth2UserInfo { - - public GoogleOAuth2UserInfo(Map attributes) { - super(attributes); - } - - @Override - public String getId() { - return (String) attributes.get("sub"); - } - - @Override - public String getName() { - return (String) attributes.get("name"); - } - - @Override - public String getEmail() { - return (String) attributes.get("email"); - } -} diff --git a/backend/src/main/java/de/szut/casino/security/oauth2/google/GoogleService.java b/backend/src/main/java/de/szut/casino/security/oauth2/google/GoogleService.java deleted file mode 100644 index f369052..0000000 --- a/backend/src/main/java/de/szut/casino/security/oauth2/google/GoogleService.java +++ /dev/null @@ -1,165 +0,0 @@ -package de.szut.casino.security.oauth2.google; - -import de.szut.casino.security.dto.AuthResponseDto; -import de.szut.casino.security.jwt.JwtUtils; -import de.szut.casino.user.AuthProvider; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserRepository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.math.BigDecimal; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; - -@Service -public class GoogleService { - private static final Logger logger = LoggerFactory.getLogger(GoogleService.class); - - @Value("${spring.security.oauth2.client.registration.google.client-id}") - private String clientId; - - @Value("${spring.security.oauth2.client.registration.google.client-secret}") - private String clientSecret; - - @Value("${spring.security.oauth2.client.registration.google.redirect-uri}") - private String redirectUri; - - @Value("${spring.security.oauth2.client.provider.google.token-uri}") - private String tokenUri; - - @Value("${spring.security.oauth2.client.provider.google.user-info-uri}") - private String userInfoUri; - - private final AuthenticationManager authenticationManager; - private final UserRepository userRepository; - private final JwtUtils jwtUtils; - private final PasswordEncoder oauth2PasswordEncoder; - - public GoogleService(AuthenticationManager authenticationManager, UserRepository userRepository, JwtUtils jwtUtils, PasswordEncoder oauth2PasswordEncoder) { - this.authenticationManager = authenticationManager; - this.userRepository = userRepository; - this.jwtUtils = jwtUtils; - this.oauth2PasswordEncoder = oauth2PasswordEncoder; - } - - public AuthResponseDto processGoogleCode(String code) { - try { - RestTemplate restTemplate = new RestTemplate(); - - HttpHeaders tokenHeaders = new HttpHeaders(); - tokenHeaders.set("Content-Type", "application/x-www-form-urlencoded"); - - MultiValueMap tokenRequestBody = new LinkedMultiValueMap<>(); - tokenRequestBody.add("client_id", clientId); - tokenRequestBody.add("client_secret", clientSecret); - tokenRequestBody.add("code", code); - tokenRequestBody.add("redirect_uri", redirectUri); - tokenRequestBody.add("grant_type", "authorization_code"); - - HttpEntity> tokenRequestEntity = new HttpEntity<>(tokenRequestBody, tokenHeaders); - - ResponseEntity tokenResponse = restTemplate.exchange( - tokenUri, - HttpMethod.POST, - tokenRequestEntity, - Map.class - ); - - Map tokenResponseBody = tokenResponse.getBody(); - - if (tokenResponseBody == null || tokenResponseBody.containsKey("error")) { - String error = tokenResponseBody != null ? (String) tokenResponseBody.get("error") : "Unknown error"; - throw new RuntimeException("Google OAuth error: " + error); - } - - String accessToken = (String) tokenResponseBody.get("access_token"); - if (accessToken == null || accessToken.isEmpty()) { - throw new RuntimeException("Failed to receive access token from Google"); - } - - HttpHeaders userInfoHeaders = new HttpHeaders(); - userInfoHeaders.set("Authorization", "Bearer " + accessToken); - - HttpEntity userInfoRequestEntity = new HttpEntity<>(null, userInfoHeaders); - - ResponseEntity userResponse = restTemplate.exchange( - userInfoUri, - HttpMethod.GET, - userInfoRequestEntity, - Map.class - ); - - Map userAttributes = userResponse.getBody(); - if (userAttributes == null) { - throw new RuntimeException("Failed to fetch user data from Google"); - } - - String googleId = (String) userAttributes.get("sub"); - String email = (String) userAttributes.get("email"); - String name = (String) userAttributes.get("name"); - Boolean emailVerified = (Boolean) userAttributes.getOrDefault("email_verified", false); - - if (email == null) { - throw new RuntimeException("Google account does not have an email"); - } - - String username = name != null ? name.replaceAll("\\s+", "") : email.split("@")[0]; - - Optional userOptional = userRepository.findByProviderId(googleId); - UserEntity user; - - if (userOptional.isPresent()) { - user = userOptional.get(); - } else { - userOptional = userRepository.findByEmail(email); - - if (userOptional.isPresent()) { - user = userOptional.get(); - user.setProvider(AuthProvider.GOOGLE); - user.setProviderId(googleId); - } else { - user = new UserEntity(); - user.setEmail(email); - user.setUsername(username); - user.setProvider(AuthProvider.GOOGLE); - user.setProviderId(googleId); - user.setEmailVerified(emailVerified); - - user.setBalance(new BigDecimal("100.00")); - } - } - - String randomPassword = UUID.randomUUID().toString(); - user.setPassword(oauth2PasswordEncoder.encode(randomPassword)); - - userRepository.save(user); - - Authentication authentication = authenticationManager.authenticate( - new UsernamePasswordAuthenticationToken(user.getEmail(), randomPassword) - ); - - String token = jwtUtils.generateToken(authentication); - - return new AuthResponseDto(token); - - } catch (Exception e) { - logger.error("Failed to process Google authentication", e); - throw new RuntimeException("Failed to process Google authentication", e); - } - } -} diff --git a/backend/src/main/java/de/szut/casino/security/service/AuthService.java b/backend/src/main/java/de/szut/casino/security/service/AuthService.java deleted file mode 100644 index 734cf9f..0000000 --- a/backend/src/main/java/de/szut/casino/security/service/AuthService.java +++ /dev/null @@ -1,108 +0,0 @@ -package de.szut.casino.security.service; - -import de.szut.casino.exceptionHandling.exceptions.EmailNotVerifiedException; -import de.szut.casino.security.dto.AuthResponseDto; -import de.szut.casino.security.dto.LoginRequestDto; -import de.szut.casino.security.dto.ResetPasswordDto; -import de.szut.casino.security.jwt.JwtUtils; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserService; -import de.szut.casino.user.dto.CreateUserDto; -import de.szut.casino.user.dto.GetUserDto; -import jakarta.mail.MessagingException; -import org.apache.commons.lang3.RandomStringUtils; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; - -import java.io.IOException; -import java.util.Optional; - -@Service -public class AuthService { - - private final AuthenticationManager authenticationManager; - private final JwtUtils jwtUtils; - private final UserService userService; - private final EmailService emailService; - private final PasswordEncoder passwordEncoder; - - public AuthService(AuthenticationManager authenticationManager, JwtUtils jwtUtils, UserService userService, EmailService emailService, PasswordEncoder passwordEncoder) { - this.authenticationManager = authenticationManager; - this.jwtUtils = jwtUtils; - this.userService = userService; - this.emailService = emailService; - this.passwordEncoder = passwordEncoder; - } - - public AuthResponseDto login(LoginRequestDto loginRequest) throws EmailNotVerifiedException { - if (!userService.isVerified(loginRequest.getUsernameOrEmail())) { - throw new EmailNotVerifiedException(); - } - - Authentication authentication = authenticationManager.authenticate( - new UsernamePasswordAuthenticationToken( - loginRequest.getUsernameOrEmail(), - loginRequest.getPassword())); - - SecurityContextHolder.getContext().setAuthentication(authentication); - String jwt = jwtUtils.generateToken(authentication); - - return new AuthResponseDto(jwt); - } - - public GetUserDto register(CreateUserDto signUpRequest) throws MessagingException, IOException { - UserEntity user = userService.createUser(signUpRequest); - - this.emailService.sendEmailVerificationEmail(user); - - return new GetUserDto( - user.getId(), - user.getEmail(), - user.getUsername(), - user.getBalance() - ); - } - - public Boolean verifyEmail(String token) throws MessagingException, IOException { - Optional optionalUser = userService.getUserByVerificationToken(token); - - if (!optionalUser.isPresent()) { - return false; - } - - UserEntity user = optionalUser.get(); - - user.setEmailVerified(true); - user.setVerificationToken(null); - userService.saveUser(user); - this.emailService.sendWelcomeEmail(user); - - return true; - } - - public void recoverPassword(String email) throws MessagingException, IOException { - Optional optionalUser = userService.getUserByEmail(email); - - if (optionalUser.isPresent()) { - UserEntity user = optionalUser.get(); - user.setPasswordResetToken(RandomStringUtils.randomAlphanumeric(64)); - userService.saveUser(user); - this.emailService.sendPasswordRecoveryEmail(user); - } - } - - public void resetPassword(ResetPasswordDto passwordDto) { - Optional optionalUser = userService.getUserByPasswordResetToken(passwordDto.getToken()); - - if (optionalUser.isPresent()) { - UserEntity user = optionalUser.get(); - user.setPassword(passwordEncoder.encode(passwordDto.getPassword())); - user.setPasswordResetToken(null); - userService.saveUser(user); - } - } -} diff --git a/backend/src/main/java/de/szut/casino/security/service/EmailService.java b/backend/src/main/java/de/szut/casino/security/service/EmailService.java deleted file mode 100644 index 83d65e0..0000000 --- a/backend/src/main/java/de/szut/casino/security/service/EmailService.java +++ /dev/null @@ -1,115 +0,0 @@ -package de.szut.casino.security.service; - -import de.szut.casino.deposit.TransactionEntity; -import de.szut.casino.user.UserEntity; -import jakarta.mail.MessagingException; -import jakarta.mail.internet.MimeMessage; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.io.ClassPathResource; -import org.springframework.mail.javamail.JavaMailSenderImpl; -import org.springframework.mail.javamail.MimeMessageHelper; -import org.springframework.stereotype.Service; -import org.springframework.util.FileCopyUtils; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; - -@Service -public class EmailService { - private JavaMailSenderImpl mailSender; - private MailConfig mailConfig; - @Value("${app.frontend-host}") - private String feUrl; - - public EmailService(JavaMailSenderImpl mailSender, MailConfig mailConfig) { - this.mailSender = mailSender; - this.mailConfig = mailConfig; - this.mailSender.setHost(mailConfig.host); - this.mailSender.setPort(mailConfig.port); - this.mailSender.setProtocol(mailConfig.protocol); - if (mailConfig.authenticationEnabled) { - this.mailSender.setUsername(mailConfig.username); - this.mailSender.setPassword(mailConfig.password); - } - } - - public void sendEmailVerificationEmail(UserEntity user) throws IOException, MessagingException { - String template = loadTemplate("email/verify.html"); - String htmlContent = template - .replace("${username}", user.getUsername()) - .replace("${feUrl}", feUrl) - .replace("${token}", user.getVerificationToken()); - - MimeMessage message = mailSender.createMimeMessage(); - MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); - - helper.setFrom(mailConfig.fromAddress); - helper.setTo(user.getEmailAddress()); - helper.setSubject("E-Mail Bestätigung"); - helper.setText(htmlContent, true); - - mailSender.send(message); - } - - public void sendWelcomeEmail(UserEntity user) throws IOException, MessagingException { - String template = loadTemplate("email/welcome.html"); - String htmlContent = template - .replace("${username}", user.getUsername()) - .replace("${feUrl}", feUrl); - - MimeMessage message = mailSender.createMimeMessage(); - MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); - - helper.setFrom(mailConfig.fromAddress); - helper.setTo(user.getEmailAddress()); - helper.setSubject("Willkommen bei Trustworthy Casino©"); - helper.setText(htmlContent, true); - - mailSender.send(message); - } - - public void sendDepositEmail(TransactionEntity transaction) throws IOException, MessagingException { - String template = loadTemplate("email/deposit.html"); - String htmlContent = template - .replace("${username}", transaction.getUser().getUsername()) - .replace("${amount}", String.valueOf(transaction.getAmount())) - .replace("${feUrl}", feUrl); - - MimeMessage message = mailSender.createMimeMessage(); - MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); - - helper.setFrom(mailConfig.fromAddress); - helper.setTo(transaction.getUser().getEmailAddress()); - helper.setSubject("Einzahlung über ${amount}€ Erfolgreich".replace("${amount}", String.valueOf(transaction.getAmount()))); - helper.setText(htmlContent, true); - - mailSender.send(message); - } - - public void sendPasswordRecoveryEmail(UserEntity user) throws IOException, MessagingException { - String template = loadTemplate("email/recover-password.html"); - String htmlContent = template - .replace("${username}", user.getUsername()) - .replace("${resetToken}", user.getPasswordResetToken()) - .replace("${feUrl}", feUrl); - - MimeMessage message = mailSender.createMimeMessage(); - MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); - - helper.setFrom(mailConfig.fromAddress); - helper.setTo(user.getEmailAddress()); - helper.setSubject("Zurücksetzen ihres Passworts"); - helper.setText(htmlContent, true); - - mailSender.send(message); - } - - private String loadTemplate(String templatePath) throws IOException { - ClassPathResource resource = new ClassPathResource("templates/" + templatePath); - try (Reader reader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8)) { - return FileCopyUtils.copyToString(reader); - } - } -} diff --git a/backend/src/main/java/de/szut/casino/security/service/MailConfig.java b/backend/src/main/java/de/szut/casino/security/service/MailConfig.java deleted file mode 100644 index 8a516fd..0000000 --- a/backend/src/main/java/de/szut/casino/security/service/MailConfig.java +++ /dev/null @@ -1,28 +0,0 @@ -package de.szut.casino.security.service; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -@Service -public class MailConfig { - @Value("${app.mail.host}") - public String host; - - @Value("${app.mail.port}") - public Integer port; - - @Value("${app.mail.authentication}") - public Boolean authenticationEnabled; - - @Value("${app.mail.username}") - public String username; - - @Value("${app.mail.password}") - public String password; - - @Value("${app.mail.from-address}") - public String fromAddress; - - @Value("${app.mail.protocol}") - public String protocol; -} diff --git a/backend/src/main/java/de/szut/casino/security/service/UserDetailsServiceImpl.java b/backend/src/main/java/de/szut/casino/security/service/UserDetailsServiceImpl.java deleted file mode 100644 index 2b710fc..0000000 --- a/backend/src/main/java/de/szut/casino/security/service/UserDetailsServiceImpl.java +++ /dev/null @@ -1,38 +0,0 @@ -package de.szut.casino.security.service; - -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserRepository; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.Optional; - -@Service -public class UserDetailsServiceImpl implements UserDetailsService { - - private final UserRepository userRepository; - - public UserDetailsServiceImpl(UserRepository userRepository) { - this.userRepository = userRepository; - } - - @Override - public UserDetails loadUserByUsername(String usernameOrEmail) throws UsernameNotFoundException { - Optional user = userRepository.findByUsername(usernameOrEmail); - - if (user.isEmpty()) { - user = userRepository.findByEmail(usernameOrEmail); - } - - UserEntity userEntity = user.orElseThrow(() -> - new UsernameNotFoundException("User not found with username or email: " + usernameOrEmail)); - - return new org.springframework.security.core.userdetails.User( - userEntity.getUsername(), - userEntity.getPassword(), - new ArrayList<>()); - } -} diff --git a/backend/src/main/java/de/szut/casino/shared/dto/BetDto.java b/backend/src/main/java/de/szut/casino/shared/dto/BetDto.java deleted file mode 100644 index cc00c2a..0000000 --- a/backend/src/main/java/de/szut/casino/shared/dto/BetDto.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.szut.casino.shared.dto; - -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Positive; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; - -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor -public class BetDto { - @NotNull(message = "Bet amount cannot be null") - @Positive(message = "Bet amount must be positive") - private BigDecimal betAmount; -} diff --git a/backend/src/main/java/de/szut/casino/shared/service/BalanceService.java b/backend/src/main/java/de/szut/casino/shared/service/BalanceService.java deleted file mode 100644 index 048840b..0000000 --- a/backend/src/main/java/de/szut/casino/shared/service/BalanceService.java +++ /dev/null @@ -1,36 +0,0 @@ -package de.szut.casino.shared.service; - -import de.szut.casino.shared.dto.BetDto; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserRepository; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; - -@Service -public class BalanceService { - private final UserRepository userRepository; - - public BalanceService(UserRepository userRepository) { - this.userRepository = userRepository; - } - - public boolean hasFunds(UserEntity user, BetDto betDto) { - BigDecimal balance = user.getBalance(); - BigDecimal betAmount = betDto.getBetAmount(); - - return betAmount.compareTo(balance) <= 0; - } - - public void addFunds(UserEntity user, BigDecimal amount) { - user.addBalance(amount); - - this.userRepository.save(user); - } - - public void subtractFunds(UserEntity user, BigDecimal amount) { - user.subtractBalance(amount); - - this.userRepository.save(user); - } -} diff --git a/backend/src/main/java/de/szut/casino/slots/SlotController.java b/backend/src/main/java/de/szut/casino/slots/SlotController.java deleted file mode 100644 index ff29d3d..0000000 --- a/backend/src/main/java/de/szut/casino/slots/SlotController.java +++ /dev/null @@ -1,59 +0,0 @@ -package de.szut.casino.slots; - -import de.szut.casino.exceptionHandling.exceptions.InsufficientFundsException; -import de.szut.casino.exceptionHandling.exceptions.UserNotFoundException; -import de.szut.casino.shared.dto.BetDto; -import de.szut.casino.shared.service.BalanceService; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserService; -import jakarta.validation.Valid; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import java.math.BigDecimal; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -@RestController -public class SlotController { - private final UserService userService; - private final BalanceService balanceService; - private final SlotService slotService; - - public SlotController(UserService userService, BalanceService balanceService, SlotService slotService) { - this.userService = userService; - this.balanceService = balanceService; - this.slotService = slotService; - } - - @PostMapping("/slots/spin") - public ResponseEntity spinSlots(@RequestBody @Valid BetDto betDto) { - UserEntity user = userService.getCurrentUser(); - - if (!this.balanceService.hasFunds(user, betDto)) { - throw new InsufficientFundsException(); - } - - SpinResult spinResult = this.slotService.spin( - betDto.getBetAmount(), - user - ); - - return ResponseEntity.ok(spinResult); - } - - @GetMapping("/slots/info") - public ResponseEntity spinSlots() { - Map info = new HashMap<>(); - - for (Symbol symbol : Symbol.values()) { - info.put(symbol.getDisplayName(), symbol.getPayoutMultiplier()); - } - - return ResponseEntity.ok(info); - } -} diff --git a/backend/src/main/java/de/szut/casino/slots/SlotService.java b/backend/src/main/java/de/szut/casino/slots/SlotService.java deleted file mode 100644 index 7905636..0000000 --- a/backend/src/main/java/de/szut/casino/slots/SlotService.java +++ /dev/null @@ -1,137 +0,0 @@ -package de.szut.casino.slots; - -import de.szut.casino.shared.service.BalanceService; -import de.szut.casino.user.UserEntity; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Random; - -import static de.szut.casino.slots.Symbol.*; - -@Service -public class SlotService { - private final int REEL_LENGTH = 32; - - private final List firstReel; - private final List secondReel; - private final List thirdReel; - - private final Random random; - private final BalanceService balanceService; - - public SlotService(BalanceService balanceService) { - this.random = new Random(); - this.balanceService = balanceService; - - List reelStrip = createReelStrip(); - this.firstReel = shuffleReel(reelStrip); - this.secondReel = shuffleReel(reelStrip); - this.thirdReel = shuffleReel(reelStrip); - } - - public SpinResult spin(BigDecimal betAmount, UserEntity user) { - int index1 = this.random.nextInt(REEL_LENGTH); - int index2 = this.random.nextInt(REEL_LENGTH); - int index3 = this.random.nextInt(REEL_LENGTH); - - Symbol symbol1 = getSymbolAt(this.firstReel, index1); - Symbol symbol2 = getSymbolAt(this.secondReel, index2); - Symbol symbol3 = getSymbolAt(this.thirdReel, index3); - - Status status = determineStatus(symbol1, symbol2, symbol3); - - SpinResult spinResult = processResult(betAmount, user, status, symbol1); - buildResultMatrix(spinResult, index1, index2, index3); - - return spinResult; - } - - private SpinResult processResult(BigDecimal betAmount, UserEntity user, Status status, Symbol winSymbol) { - SpinResult spinResult = new SpinResult(); - spinResult.setStatus(status.name().toLowerCase()); - - this.balanceService.subtractFunds(user, betAmount); - - if (status == Status.WIN) { - BigDecimal winAmount = betAmount.multiply(winSymbol.getPayoutMultiplier()); - this.balanceService.addFunds(user, winAmount); - spinResult.setAmount(winAmount); - } else { - spinResult.setAmount(betAmount); - } - - return spinResult; - } - - private void buildResultMatrix(SpinResult spinResult, int index1, int index2, int index3) { - List> resultMatrix = new ArrayList<>(3); - - for (int i = 0; i < 3; i++) { - resultMatrix.add(new ArrayList<>(3)); - } - - resultMatrix.getFirst().add(getSymbolAt(this.firstReel, index1 - 1)); - resultMatrix.getFirst().add(getSymbolAt(this.secondReel, index2 - 1)); - resultMatrix.getFirst().add(getSymbolAt(this.thirdReel, index3 - 1)); - - resultMatrix.get(1).add(getSymbolAt(this.firstReel, index1)); - resultMatrix.get(1).add(getSymbolAt(this.secondReel, index2)); - resultMatrix.get(1).add(getSymbolAt(this.thirdReel, index3)); - - resultMatrix.getLast().add(getSymbolAt(this.firstReel, index1 + 1)); - resultMatrix.getLast().add(getSymbolAt(this.secondReel, index2 + 1)); - resultMatrix.getLast().add(getSymbolAt(this.thirdReel, index3 + 1)); - - spinResult.setResultMatrix(resultMatrix); - } - - private List shuffleReel(List reelStrip) { - Collections.shuffle(reelStrip, this.random); - - return reelStrip; - } - - private List createReelStrip() { - List reelStrip = new ArrayList<>(REEL_LENGTH); - addSymbolsToStrip(reelStrip, CHERRY, CHERRY.getCountPerStrip()); - addSymbolsToStrip(reelStrip, BELL, BELL.getCountPerStrip()); - addSymbolsToStrip(reelStrip, BAR, BAR.getCountPerStrip()); - addSymbolsToStrip(reelStrip, SEVEN, SEVEN.getCountPerStrip()); - addSymbolsToStrip(reelStrip, BLANK, BLANK.getCountPerStrip()); - return reelStrip; - } - - private void addSymbolsToStrip(List strip, Symbol symbol, int count) { - for (int i = 0; i < count; i++) { - strip.add(symbol); - } - } - - private Symbol getSymbolAt(List reel, int index) { - int effectiveIndex = index % REEL_LENGTH; - - if (effectiveIndex < 0) { - effectiveIndex += REEL_LENGTH; - } - - return reel.get(effectiveIndex); - } - - private Status determineStatus(Symbol symbol1, Symbol symbol2, Symbol symbol3) { - boolean allSymbolsMatch = symbol1.equals(symbol2) && symbol1.equals(symbol3); - - if (allSymbolsMatch) { - if (symbol1 == Symbol.BLANK) { - return Status.BLANK; - } else { - return Status.WIN; - } - } - - return Status.LOSE; - } -} diff --git a/backend/src/main/java/de/szut/casino/slots/SpinResult.java b/backend/src/main/java/de/szut/casino/slots/SpinResult.java deleted file mode 100644 index 0bfb317..0000000 --- a/backend/src/main/java/de/szut/casino/slots/SpinResult.java +++ /dev/null @@ -1,17 +0,0 @@ -package de.szut.casino.slots; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; -import java.util.List; - -@Getter -@Setter -@NoArgsConstructor -public class SpinResult { - private String status; - private BigDecimal amount; - private List> resultMatrix; -} diff --git a/backend/src/main/java/de/szut/casino/slots/Status.java b/backend/src/main/java/de/szut/casino/slots/Status.java deleted file mode 100644 index c53611f..0000000 --- a/backend/src/main/java/de/szut/casino/slots/Status.java +++ /dev/null @@ -1,7 +0,0 @@ -package de.szut.casino.slots; - -public enum Status { - WIN, - LOSE, - BLANK -} diff --git a/backend/src/main/java/de/szut/casino/slots/Symbol.java b/backend/src/main/java/de/szut/casino/slots/Symbol.java deleted file mode 100644 index 3cf0f72..0000000 --- a/backend/src/main/java/de/szut/casino/slots/Symbol.java +++ /dev/null @@ -1,24 +0,0 @@ -package de.szut.casino.slots; - -import lombok.Getter; - -import java.math.BigDecimal; - -@Getter -public enum Symbol { - SEVEN("seven", new BigDecimal("1000"), 1), - BAR("bar", new BigDecimal("85"), 4), - BELL("bell", new BigDecimal("40"), 7), - CHERRY("cherry", new BigDecimal("10"), 10), - BLANK("blank", new BigDecimal("0"), 10); - - private final String displayName; - private final BigDecimal payoutMultiplier; - private final int countPerStrip; - - Symbol(String displayName, BigDecimal payoutMultiplier, int count) { - this.displayName = displayName; - this.payoutMultiplier = payoutMultiplier; - this.countPerStrip = count; - } -} diff --git a/backend/src/main/java/de/szut/casino/user/AuthProvider.java b/backend/src/main/java/de/szut/casino/user/AuthProvider.java deleted file mode 100644 index c26b45c..0000000 --- a/backend/src/main/java/de/szut/casino/user/AuthProvider.java +++ /dev/null @@ -1,7 +0,0 @@ -package de.szut.casino.user; - -public enum AuthProvider { - LOCAL, - GITHUB, - GOOGLE -} diff --git a/backend/src/main/java/de/szut/casino/user/UserController.java b/backend/src/main/java/de/szut/casino/user/UserController.java deleted file mode 100644 index f08721d..0000000 --- a/backend/src/main/java/de/szut/casino/user/UserController.java +++ /dev/null @@ -1,30 +0,0 @@ -package de.szut.casino.user; - -import de.szut.casino.user.dto.GetUserDto; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@Slf4j -@RestController -@CrossOrigin -@RequestMapping("/users") -public class UserController { - - private final UserService userService; - - private final UserMappingService userMappingService; - - public UserController(UserService userService, UserMappingService userMappingService) { - this.userService = userService; - this.userMappingService = userMappingService; - } - - @GetMapping("/me") - public ResponseEntity getCurrentUser() { - return ResponseEntity.ok(userMappingService.mapToGetUserDto(userService.getCurrentUser())); - } -} diff --git a/backend/src/main/java/de/szut/casino/user/UserEntity.java b/backend/src/main/java/de/szut/casino/user/UserEntity.java deleted file mode 100644 index 534859f..0000000 --- a/backend/src/main/java/de/szut/casino/user/UserEntity.java +++ /dev/null @@ -1,92 +0,0 @@ -package de.szut.casino.user; - -import jakarta.persistence.*; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; - -@Setter -@Getter -@Entity -@NoArgsConstructor -public class UserEntity { - @Id - @GeneratedValue - private Long id; - - @Version - private Long version; - - @Column(unique = true) - private String email; - - @Column(unique = true) - private String username; - - private String password; - - @Column(precision = 19, scale = 2) - private BigDecimal balance; - - private Boolean emailVerified = false; - - private String verificationToken; - - private String passwordResetToken; - - @Enumerated(EnumType.STRING) - private AuthProvider provider = AuthProvider.LOCAL; - - private String providerId; - - public UserEntity(String email, String username, String password, BigDecimal balance, String verificationToken) { - this.email = email; - this.username = username; - this.password = password; - this.balance = balance; - this.verificationToken = verificationToken; - } - - public UserEntity(String email, String username, AuthProvider provider, String providerId, BigDecimal balance) { - this.email = email; - this.username = username; - this.provider = provider; - this.providerId = providerId; - this.balance = balance; - this.emailVerified = true; // OAuth providers verify emails - } - - public void addBalance(BigDecimal amountToAdd) { - if (amountToAdd == null || amountToAdd.compareTo(BigDecimal.ZERO) <= 0) { - return; - } - - if (this.balance == null) { - this.balance = BigDecimal.ZERO; - } - - this.balance = this.balance.add(amountToAdd); - } - - public void subtractBalance(BigDecimal amountToSubtract) { - if (amountToSubtract == null || amountToSubtract.compareTo(BigDecimal.ZERO) <= 0) { - throw new IllegalArgumentException("Amount to subtract must be positive."); - } - - if (this.balance == null) { - this.balance = BigDecimal.ZERO; - } - - if (this.balance.compareTo(amountToSubtract) < 0) { - throw new IllegalStateException("Insufficient funds to subtract " + amountToSubtract); - } - - this.balance = this.balance.subtract(amountToSubtract); - } - - public String getEmailAddress() { - return "${name} <${email}>".replace("${name}", this.username).replace("${email}", this.email); - } -} diff --git a/backend/src/main/java/de/szut/casino/user/UserMappingService.java b/backend/src/main/java/de/szut/casino/user/UserMappingService.java deleted file mode 100644 index c93c132..0000000 --- a/backend/src/main/java/de/szut/casino/user/UserMappingService.java +++ /dev/null @@ -1,13 +0,0 @@ -package de.szut.casino.user; - -import de.szut.casino.user.dto.GetUserDto; -import org.springframework.stereotype.Service; - -@Service -public class UserMappingService { - - public GetUserDto mapToGetUserDto(UserEntity user) { - return new GetUserDto(user.getId(), user.getEmail(), user.getUsername(), user.getBalance()); - } -} - diff --git a/backend/src/main/java/de/szut/casino/user/UserRepository.java b/backend/src/main/java/de/szut/casino/user/UserRepository.java deleted file mode 100644 index db28f49..0000000 --- a/backend/src/main/java/de/szut/casino/user/UserRepository.java +++ /dev/null @@ -1,29 +0,0 @@ -package de.szut.casino.user; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.stereotype.Service; - -import java.util.Optional; - -@Service -public interface UserRepository extends JpaRepository { - Optional findByUsername(String username); - - Optional findByEmail(String email); - - Optional findByProviderId(String providerId); - - boolean existsByUsername(String username); - - boolean existsByEmail(String email); - - @Query("SELECT u FROM UserEntity u WHERE u.verificationToken = ?1") - Optional findOneByVerificationToken(String token); - - @Query("SELECT u FROM UserEntity u WHERE u.username = ?1 OR u.email = ?1") - Optional findOneByUsernameOrEmail(String usernameOrEmail); - - @Query("SELECT u FROM UserEntity u WHERE u.passwordResetToken = ?1") - Optional findOneByPasswordResetToken(String token); -} diff --git a/backend/src/main/java/de/szut/casino/user/UserService.java b/backend/src/main/java/de/szut/casino/user/UserService.java deleted file mode 100644 index 341db86..0000000 --- a/backend/src/main/java/de/szut/casino/user/UserService.java +++ /dev/null @@ -1,80 +0,0 @@ -package de.szut.casino.user; - -import de.szut.casino.exceptionHandling.exceptions.UserNotFoundException; -import de.szut.casino.user.dto.CreateUserDto; -import jakarta.persistence.EntityExistsException; -import org.apache.commons.lang3.RandomStringUtils; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; -import java.util.Optional; - -@Service -public class UserService { - private final UserRepository userRepository; - private final PasswordEncoder passwordEncoder; - - public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) { - this.userRepository = userRepository; - this.passwordEncoder = passwordEncoder; - } - - public UserEntity createUser(CreateUserDto createUserDto) { - if (userRepository.existsByUsername(createUserDto.getUsername())) { - throw new EntityExistsException("Username is already taken"); - } - - if (userRepository.existsByEmail(createUserDto.getEmail())) { - throw new EntityExistsException("Email is already in use"); - } - - UserEntity user = new UserEntity( - createUserDto.getEmail(), - createUserDto.getUsername(), - passwordEncoder.encode(createUserDto.getPassword()), - BigDecimal.valueOf(100), - RandomStringUtils.randomAlphanumeric(64) - ); - - return userRepository.save(user); - } - - public UserEntity getCurrentUser() { - String username = SecurityContextHolder.getContext().getAuthentication().getName(); - - Optional optionalUser = userRepository.findByUsername(username); - if (optionalUser.isEmpty()) { - throw new UserNotFoundException(); - } - - return optionalUser.get(); - } - - public Optional getUserByVerificationToken(String token) { - return this.userRepository.findOneByVerificationToken(token); - } - - public void saveUser(UserEntity user) { - userRepository.save(user); - } - - public boolean isVerified(String usernameOrEmail) { - Optional optionalUser = userRepository.findOneByUsernameOrEmail(usernameOrEmail); - - if (!optionalUser.isPresent()) { - return false; - } - - return optionalUser.get().getEmailVerified(); - } - - public Optional getUserByEmail(String email) { - return userRepository.findByEmail(email); - } - - public Optional getUserByPasswordResetToken(String token) { - return this.userRepository.findOneByPasswordResetToken(token); - } -} diff --git a/backend/src/main/java/de/szut/casino/user/dto/CreateUserDto.java b/backend/src/main/java/de/szut/casino/user/dto/CreateUserDto.java deleted file mode 100644 index 1be6ae3..0000000 --- a/backend/src/main/java/de/szut/casino/user/dto/CreateUserDto.java +++ /dev/null @@ -1,27 +0,0 @@ -package de.szut.casino.user.dto; - -import jakarta.validation.constraints.Email; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.Size; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor -public class CreateUserDto { - @NotBlank(message = "Email is required") - @Email(message = "Email should be valid") - private String email; - - @NotBlank(message = "Username is required") - @Size(min = 3, max = 20, message = "Username must be between 3 and 20 characters") - private String username; - - @NotBlank(message = "Password is required") - @Size(min = 6, message = "Password must be at least 6 characters") - private String password; -} diff --git a/backend/src/main/java/de/szut/casino/user/dto/GetUserDto.java b/backend/src/main/java/de/szut/casino/user/dto/GetUserDto.java deleted file mode 100644 index 2c41f0d..0000000 --- a/backend/src/main/java/de/szut/casino/user/dto/GetUserDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.szut.casino.user.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; - -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor -public class GetUserDto { - private Long id; - private String email; - private String username; - private BigDecimal balance; -} diff --git a/backend/src/main/java/de/szut/casino/user/transaction/GetTransactionService.java b/backend/src/main/java/de/szut/casino/user/transaction/GetTransactionService.java deleted file mode 100644 index 11fff4f..0000000 --- a/backend/src/main/java/de/szut/casino/user/transaction/GetTransactionService.java +++ /dev/null @@ -1,43 +0,0 @@ -package de.szut.casino.user.transaction; - -import de.szut.casino.deposit.TransactionEntity; -import de.szut.casino.deposit.TransactionRepository; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserService; -import de.szut.casino.user.transaction.dto.GetTransactionDto; -import de.szut.casino.user.transaction.dto.UserTransactionsDto; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -public class GetTransactionService { - - private final UserService userService; - - private final TransactionRepository transactionRepository; - - public GetTransactionService(UserService userService, TransactionRepository transactionRepository) { - this.userService = userService; - this.transactionRepository = transactionRepository; - } - - public UserTransactionsDto getUserTransactionsDto(Integer limit, Integer offset) { - UserEntity user = userService.getCurrentUser(); - - List transactionEntities = this.transactionRepository.findByUserIdWithLimit(user, limit, offset); - Boolean hasMore = this.transactionRepository.hasMore(user, limit, offset); - - return new UserTransactionsDto(mapTransactionsToDtos(transactionEntities), hasMore); - } - - public List mapTransactionsToDtos(List transactions) { - return transactions.stream() - .map(transaction -> new GetTransactionDto( - transaction.getAmount(), - transaction.getStatus(), - transaction.getCreatedAt()) - ).toList(); - } -} - diff --git a/backend/src/main/java/de/szut/casino/user/transaction/TransactionController.java b/backend/src/main/java/de/szut/casino/user/transaction/TransactionController.java deleted file mode 100644 index f8a57de..0000000 --- a/backend/src/main/java/de/szut/casino/user/transaction/TransactionController.java +++ /dev/null @@ -1,28 +0,0 @@ -package de.szut.casino.user.transaction; - -import de.szut.casino.user.transaction.dto.UserTransactionsDto; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class TransactionController { - - private final GetTransactionService transactionService; - - public TransactionController(GetTransactionService transactionService) { - this.transactionService = transactionService; - } - - @GetMapping("/user/transactions") - public ResponseEntity getUserTransactions( - @RequestParam(value = "limit", required = false) Integer limit, - @RequestParam(value = "offset", required = false) Integer offset - ) { - UserTransactionsDto transactionEntities = this.transactionService.getUserTransactionsDto(limit, offset); - - return ResponseEntity.ok(transactionEntities); - } -} - diff --git a/backend/src/main/java/de/szut/casino/user/transaction/dto/GetTransactionDto.java b/backend/src/main/java/de/szut/casino/user/transaction/dto/GetTransactionDto.java deleted file mode 100644 index f37fbf4..0000000 --- a/backend/src/main/java/de/szut/casino/user/transaction/dto/GetTransactionDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package de.szut.casino.user.transaction.dto; - -import de.szut.casino.deposit.TransactionStatus; -import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; - -import java.util.Date; - -@AllArgsConstructor -@NoArgsConstructor -public class GetTransactionDto { - public double amount = 0; - public TransactionStatus status = TransactionStatus.PROCESSING; - public Date createdAt = new Date(); -} - diff --git a/backend/src/main/java/de/szut/casino/user/transaction/dto/UserTransactionsDto.java b/backend/src/main/java/de/szut/casino/user/transaction/dto/UserTransactionsDto.java deleted file mode 100644 index 54e116b..0000000 --- a/backend/src/main/java/de/szut/casino/user/transaction/dto/UserTransactionsDto.java +++ /dev/null @@ -1,12 +0,0 @@ -package de.szut.casino.user.transaction.dto; - -import lombok.AllArgsConstructor; - -import java.util.List; - -@AllArgsConstructor -public class UserTransactionsDto { - public List transactions; - public Boolean hasMore; -} - diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties deleted file mode 100644 index 7b761a7..0000000 --- a/backend/src/main/resources/application.properties +++ /dev/null @@ -1,54 +0,0 @@ -spring.datasource.url=jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:postgresdb} -spring.datasource.username=${DB_USER:postgres_user} -spring.datasource.password=${DB_PASS:postgres_pass} -server.port=${HTTP_PORT:8080} -spring.jpa.hibernate.ddl-auto=update -stripe.secret.key=${STRIPE_SECRET_KEY:sk_test_51QrePYIvCfqz7ANgqam8rEwWcMeKiLOof3j6SCMgu2sl4sESP45DJxca16mWcYo1sQaiBv32CMR6Z4AAAGQPCJo300ubuZKO8I} -stripe.webhook.secret=${STRIPE_WEBHOOK_SECRET:whsec_746b6a488665f6057118bdb4a2b32f4916f16c277109eeaed5e8f8e8b81b8c15} - -app.frontend-host=${FE_URL:http://localhost:4200} - -app.mail.authentication=${MAIL_AUTHENTICATION:false} -app.mail.host=${MAIL_HOST:localhost} -app.mail.port=${MAIL_PORT:1025} -app.mail.username=${MAIL_USER:null} -app.mail.password=${MAIL_PASS:null} -app.mail.from-address=${MAIL_FROM:casino@localhost} -app.mail.protocol=${MAIL_PROTOCOL:smtp} - -spring.application.name=casino - -# JWT Configuration -jwt.secret=${JWT_SECRET:5367566B59703373367639792F423F4528482B4D6251655468576D5A71347437} -jwt.expiration.ms=${JWT_EXPIRATION_MS:86400000} - -# Logging -logging.level.org.springframework.security=DEBUG - -# Swagger -springdoc.swagger-ui.path=swagger -springdoc.swagger-ui.try-it-out-enabled=true - -# GitHub OAuth2 Configuration -spring.security.oauth2.client.registration.github.client-id=${GITHUB_CLIENT_ID:Ov23lingzZsPn1wwACoK} -spring.security.oauth2.client.registration.github.client-secret=${GITHUB_CLIENT_SECRET:4b327fb3b1ab67584a03bcb9d53fa6439fbccad7} -spring.security.oauth2.client.registration.github.redirect-uri=${app.frontend-host}/oauth2/callback/github -spring.security.oauth2.client.registration.github.scope=user:email,read:user -spring.security.oauth2.client.provider.github.authorization-uri=https://github.com/login/oauth/authorize -spring.security.oauth2.client.provider.github.token-uri=https://github.com/login/oauth/access_token -spring.security.oauth2.client.provider.github.user-info-uri=https://api.github.com/user -spring.security.oauth2.client.provider.github.user-name-attribute=login - -# OAuth Success and Failure URLs -app.oauth2.authorizedRedirectUris=${app.frontend-host}/auth/oauth2/callback - -# Google OAuth2 Configuration -spring.security.oauth2.client.registration.google.client-id=${GOOGLE_CLIENT_ID:350791038883-c1r7v4o793itq8a0rh7dut7itm7uneam.apps.googleusercontent.com} -spring.security.oauth2.client.registration.google.client-secret=${GOOGLE_CLIENT_SECRET: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} -spring.security.oauth2.client.registration.google.redirect-uri=${app.frontend-host}/oauth2/callback/google -spring.security.oauth2.client.registration.google.scope=email,profile -spring.security.oauth2.client.provider.google.authorization-uri=https://accounts.google.com/o/oauth2/v2/auth -spring.security.oauth2.client.provider.google.token-uri=https://oauth2.googleapis.com/token -spring.security.oauth2.client.provider.google.user-info-uri=https://www.googleapis.com/oauth2/v3/userinfo -spring.security.oauth2.client.provider.google.user-name-attribute=sub - diff --git a/backend/src/main/resources/templates/email/deposit.html b/backend/src/main/resources/templates/email/deposit.html deleted file mode 100644 index be54677..0000000 --- a/backend/src/main/resources/templates/email/deposit.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - Einzahlung bestätigt - Trustworthy Casino© - - - -
-
-

Trustworthy Casino

-
-
-

Hallo ${username},

- -

vielen Dank für Ihre Einzahlung bei Trustworthy Casino. Wir bestätigen den Eingang Ihres Guthabens.

- -
-

Eingezahlter Betrag

-
${amount}€
-
- -
- -

Ihr Guthaben wurde Ihrem Konto sofort gutgeschrieben und steht ab sofort zum Spielen zur Verfügung.

- - - -

Bei Fragen zu Ihrer Einzahlung kontaktieren Sie bitte unseren Kundenservice.

- -

Mit freundlichen Grüßen,
- Ihr Trustworthy Casino Team

-
- -
- - \ No newline at end of file diff --git a/backend/src/main/resources/templates/email/recover-password.html b/backend/src/main/resources/templates/email/recover-password.html deleted file mode 100644 index cf666d1..0000000 --- a/backend/src/main/resources/templates/email/recover-password.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - Passwort zurücksetzen - Trustworthy Casino© - - - -
-
-

Trustworthy Casino

-
-
-

Hallo ${username},

- -

wir haben eine Anfrage zum Zurücksetzen Ihres Passworts für Ihr Trustworthy Casino Konto erhalten. Um Ihr Passwort zurückzusetzen, klicken Sie bitte auf den folgenden Button:

- - - -
-

Hinweis: Dieser Link und Code sind aus Sicherheitsgründen vielleicht nur 60 Minuten gültig.

-
- -
- -
-

Falls Sie diese Anfrage nicht gestellt haben, ignorieren Sie diese E-Mail bitte. In diesem Fall empfehlen wir Ihnen, Ihr Passwort zu ändern und unseren Kundenservice zu kontaktieren, um die Sicherheit Ihres Kontos zu gewährleisten.

-
- -
- -

Bei Fragen steht Ihnen unser Support-Team nicht zur Verfügung.

- -

Mit freundlichen Grüßen,
- Ihr Trustworthy Casino Team

-
- -
- - \ No newline at end of file diff --git a/backend/src/main/resources/templates/email/verify.html b/backend/src/main/resources/templates/email/verify.html deleted file mode 100644 index 7076a7c..0000000 --- a/backend/src/main/resources/templates/email/verify.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - E-Mail-Verifizierung - Trustworthy Casino© - - - -
-
-

Trustworthy Casino

-
-
-

Hallo ${username},

- -

vielen Dank für Ihre Registrierung bei Trustworthy Casino. Um Ihr Konto zu aktivieren und Zugang zu allen Funktionen zu erhalten, bestätigen Sie bitte Ihre E-Mail-Adresse.

- -
- -

Klicken Sie auf den folgenden Button, um Ihre E-Mail-Adresse zu bestätigen:

- - - -
-

Hinweis: Der Bestätigungscode könnte nur 24 Stunden gültig sein und kann vielleicht auch nur einmal verwendet werden.

-
- -
- -

Nach der Bestätigung Ihrer E-Mail-Adresse können Sie sofort mit dem Spielen beginnen und alle Vorteile Ihres Kontos nutzen.

- -

Bei Fragen stehen wir Ihnen jederzeit zur Verfügung.

- -

Mit freundlichen Grüßen,
- Ihr Trustworthy Casino Team

-
- -
- - \ No newline at end of file diff --git a/backend/src/main/resources/templates/email/welcome.html b/backend/src/main/resources/templates/email/welcome.html deleted file mode 100644 index ed43938..0000000 --- a/backend/src/main/resources/templates/email/welcome.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - Willkommen bei Trustworthy Casino© - - - -
-
-

Trustworthy Casino

-
-
-

Hallo ${username},

- -

Herzlich willkommen bei Trustworthy Casino! Wir freuen uns, Sie an Bord zu haben.

- -
- -

Bei uns erwarten Sie:

-
    -
  • Spannende Casino-Spiele
  • -
  • Sichere Transaktionen
  • -
  • Exklusive Boni und Aktionen
  • -
- -
- -

Melden Sie sich jetzt an und beginnen Sie Ihr Spielerlebnis!

- - - -

Bei Fragen stehen wir Ihnen jederzeit zur Verfügung.

- -

Mit freundlichen Grüßen,
- Ihr Trustworthy Casino Team

-
- -
- - \ No newline at end of file diff --git a/backend/src/test/java/de/szut/casino/coinflip/CoinflipServiceTest.java b/backend/src/test/java/de/szut/casino/coinflip/CoinflipServiceTest.java deleted file mode 100644 index 2b15ba0..0000000 --- a/backend/src/test/java/de/szut/casino/coinflip/CoinflipServiceTest.java +++ /dev/null @@ -1,64 +0,0 @@ -package de.szut.casino.coinflip; - -import de.szut.casino.shared.service.BalanceService; -import de.szut.casino.user.UserEntity; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.math.BigDecimal; -import java.util.Random; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -class CoinflipServiceTest { - - @Mock - private BalanceService balanceService; - - @Mock - private Random random; - - @InjectMocks - private CoinflipService coinflipService; - - private UserEntity user; - private CoinflipDto coinflipDto; - - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - user = new UserEntity(); - user.setBalance(BigDecimal.valueOf(100)); - coinflipDto = new CoinflipDto(BigDecimal.valueOf(10), CoinSide.HEAD); - } - - @Test - void testPlay_userWins() { - when(random.nextBoolean()).thenReturn(true); - - CoinflipResult result = coinflipService.play(user, coinflipDto); - - assertTrue(result.isWin()); - assertEquals(BigDecimal.valueOf(20), result.getPayout()); - assertEquals(CoinSide.HEAD, result.getCoinSide()); - verify(balanceService, times(1)).subtractFunds(user, BigDecimal.valueOf(10)); - verify(balanceService, times(1)).addFunds(user, BigDecimal.valueOf(20)); - } - - @Test - void testPlay_userLoses() { - when(random.nextBoolean()).thenReturn(false); - - CoinflipResult result = coinflipService.play(user, coinflipDto); - - assertFalse(result.isWin()); - assertEquals(BigDecimal.ZERO, result.getPayout()); - assertEquals(CoinSide.TAILS, result.getCoinSide()); - verify(balanceService, times(1)).subtractFunds(user, BigDecimal.valueOf(10)); - verify(balanceService, never()).addFunds(any(), any()); - } -} diff --git a/backend/src/test/java/de/szut/casino/dice/DiceServiceTest.java b/backend/src/test/java/de/szut/casino/dice/DiceServiceTest.java deleted file mode 100644 index 6b2e230..0000000 --- a/backend/src/test/java/de/szut/casino/dice/DiceServiceTest.java +++ /dev/null @@ -1,251 +0,0 @@ -package de.szut.casino.dice; - -import de.szut.casino.shared.service.BalanceService; -import de.szut.casino.user.UserEntity; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.Random; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -class DiceServiceTest { - - @Mock - private BalanceService balanceService; - - @Mock - private Random random; - - @InjectMocks - private DiceService diceService; - - private UserEntity user; - private DiceDto diceDto; - - @BeforeEach - void setUp() { - user = new UserEntity(); - user.setId(1L); - user.setBalance(BigDecimal.valueOf(1000)); - - diceDto = new DiceDto(); - diceDto.setBetAmount(BigDecimal.valueOf(10)); - diceDto.setTargetValue(BigDecimal.valueOf(50)); - diceDto.setRollOver(true); - } - - @Test - void play_rollOver_win() { - diceDto.setRollOver(true); - diceDto.setTargetValue(BigDecimal.valueOf(50)); - when(random.nextInt(anyInt())).thenReturn(55); - - DiceResult result = diceService.play(user, diceDto); - - assertTrue(result.isWin()); - assertEquals(BigDecimal.valueOf(56), result.getRolledValue()); - verify(balanceService, times(1)).subtractFunds(user, diceDto.getBetAmount()); - verify(balanceService, times(1)).addFunds(eq(user), any(BigDecimal.class)); - } - - @Test - void play_rollOver_lose() { - diceDto.setRollOver(true); - diceDto.setTargetValue(BigDecimal.valueOf(50)); - when(random.nextInt(anyInt())).thenReturn(49); - - DiceResult result = diceService.play(user, diceDto); - - assertFalse(result.isWin()); - assertEquals(BigDecimal.valueOf(50), result.getRolledValue()); - assertEquals(BigDecimal.ZERO, result.getPayout()); - verify(balanceService, times(1)).subtractFunds(user, diceDto.getBetAmount()); - verify(balanceService, never()).addFunds(eq(user), any(BigDecimal.class)); - } - - @Test - void play_rollUnder_win() { - diceDto.setRollOver(false); - diceDto.setTargetValue(BigDecimal.valueOf(50)); - when(random.nextInt(anyInt())).thenReturn(48); - - DiceResult result = diceService.play(user, diceDto); - - assertTrue(result.isWin()); - assertEquals(BigDecimal.valueOf(49), result.getRolledValue()); - verify(balanceService, times(1)).subtractFunds(user, diceDto.getBetAmount()); - verify(balanceService, times(1)).addFunds(eq(user), any(BigDecimal.class)); - } - - @Test - void play_rollUnder_lose() { - diceDto.setRollOver(false); - diceDto.setTargetValue(BigDecimal.valueOf(50)); - when(random.nextInt(anyInt())).thenReturn(50); - - DiceResult result = diceService.play(user, diceDto); - - assertFalse(result.isWin()); - assertEquals(BigDecimal.valueOf(51), result.getRolledValue()); - assertEquals(BigDecimal.ZERO, result.getPayout()); - verify(balanceService, times(1)).subtractFunds(user, diceDto.getBetAmount()); - verify(balanceService, never()).addFunds(eq(user), any(BigDecimal.class)); - } - - @Test - void play_rollOver_targetValueOne_rolledOne_lose() { - diceDto.setRollOver(true); - diceDto.setTargetValue(BigDecimal.valueOf(1)); - when(random.nextInt(anyInt())).thenReturn(0); - - DiceResult result = diceService.play(user, diceDto); - - assertFalse(result.isWin()); - assertEquals(BigDecimal.valueOf(1), result.getRolledValue()); - assertEquals(BigDecimal.ZERO, result.getPayout()); - verify(balanceService, times(1)).subtractFunds(user, diceDto.getBetAmount()); - verify(balanceService, never()).addFunds(eq(user), any(BigDecimal.class)); - } - - @Test - void play_rollOver_targetValueOne_rolledTwo_win() { - diceDto.setRollOver(true); - diceDto.setTargetValue(BigDecimal.valueOf(1)); - when(random.nextInt(anyInt())).thenReturn(1); - - DiceResult result = diceService.play(user, diceDto); - - assertTrue(result.isWin()); - assertEquals(BigDecimal.valueOf(2), result.getRolledValue()); - // Win chance for target 1 (roll over) is 99. Multiplier = (100-1)/99 = 1 - assertEquals(diceDto.getBetAmount().stripTrailingZeros(), result.getPayout().stripTrailingZeros()); - verify(balanceService, times(1)).subtractFunds(user, diceDto.getBetAmount()); - verify(balanceService, times(1)).addFunds(eq(user), any(BigDecimal.class)); - } - - @Test - void play_rollUnder_targetValueOne_alwaysLose_winChanceZero() { - diceDto.setRollOver(false); - diceDto.setTargetValue(BigDecimal.valueOf(1)); - when(random.nextInt(anyInt())).thenReturn(0); - - DiceResult result = diceService.play(user, diceDto); - - assertFalse(result.isWin()); - assertEquals(BigDecimal.valueOf(1), result.getRolledValue()); - assertEquals(BigDecimal.ZERO, result.getPayout()); - verify(balanceService, times(1)).subtractFunds(user, diceDto.getBetAmount()); - verify(balanceService, never()).addFunds(eq(user), any(BigDecimal.class)); - } - - @Test - void play_rollOver_targetValueNinetyNine_rolledHundred_win() { - diceDto.setRollOver(true); - diceDto.setTargetValue(BigDecimal.valueOf(99)); - when(random.nextInt(anyInt())).thenReturn(99); - - DiceResult result = diceService.play(user, diceDto); - - assertTrue(result.isWin()); - assertEquals(BigDecimal.valueOf(100), result.getRolledValue()); - // Win chance for target 99 (roll over) is 1. Multiplier = (100-1)/1 = 99 - assertEquals(diceDto.getBetAmount().multiply(BigDecimal.valueOf(99)).stripTrailingZeros(), result.getPayout().stripTrailingZeros()); - verify(balanceService, times(1)).subtractFunds(user, diceDto.getBetAmount()); - verify(balanceService, times(1)).addFunds(eq(user), any(BigDecimal.class)); - } - - @Test - void play_rollUnder_targetValueNinetyNine_rolledNinetyEight_win() { - diceDto.setRollOver(false); - diceDto.setTargetValue(BigDecimal.valueOf(99)); - when(random.nextInt(anyInt())).thenReturn(97); - - DiceResult result = diceService.play(user, diceDto); - - assertTrue(result.isWin()); - assertEquals(BigDecimal.valueOf(98), result.getRolledValue()); - // Win chance for target 99 (roll under) is 98. Multiplier = (100-1)/98 = 99/98 - assertEquals(diceDto.getBetAmount().multiply(BigDecimal.valueOf(99).divide(BigDecimal.valueOf(98), 4, RoundingMode.HALF_UP)), result.getPayout()); - verify(balanceService, times(1)).subtractFunds(user, diceDto.getBetAmount()); - verify(balanceService, times(1)).addFunds(eq(user), any(BigDecimal.class)); - } - - @Test - void play_rollOver_targetValueOneHundred_alwaysLose_winChanceZero() { - diceDto.setRollOver(true); - diceDto.setTargetValue(BigDecimal.valueOf(100)); - when(random.nextInt(anyInt())).thenReturn(99); - - DiceResult result = diceService.play(user, diceDto); - - assertFalse(result.isWin()); - assertEquals(BigDecimal.valueOf(100), result.getRolledValue()); - assertEquals(BigDecimal.ZERO, result.getPayout()); - verify(balanceService, times(1)).subtractFunds(user, diceDto.getBetAmount()); - verify(balanceService, never()).addFunds(eq(user), any(BigDecimal.class)); - } - - @Test - void play_rollUnder_targetValueOneHundred_rolledNinetyNine_win() { - diceDto.setRollOver(false); - diceDto.setTargetValue(BigDecimal.valueOf(100)); - when(random.nextInt(anyInt())).thenReturn(98); - - DiceResult result = diceService.play(user, diceDto); - - assertTrue(result.isWin()); - assertEquals(BigDecimal.valueOf(99), result.getRolledValue()); - // Win chance for target 100 (roll under) is 99. Multiplier = (100-1)/99 = 1 - assertEquals(diceDto.getBetAmount().stripTrailingZeros(), result.getPayout().stripTrailingZeros()); - verify(balanceService, times(1)).subtractFunds(user, diceDto.getBetAmount()); - verify(balanceService, times(1)).addFunds(eq(user), any(BigDecimal.class)); - } - - @Test - void play_payoutCalculationCorrect() { - diceDto.setRollOver(true); - diceDto.setTargetValue(BigDecimal.valueOf(75)); - when(random.nextInt(anyInt())).thenReturn(75); - - // Multiplier for win chance 25: (100-1)/25 = 99/25 = 3.96 - // Payout: 10 * 3.96 = 39.6 - - DiceResult result = diceService.play(user, diceDto); - - assertTrue(result.isWin()); - assertEquals(BigDecimal.valueOf(39.6).stripTrailingZeros(), result.getPayout().stripTrailingZeros()); - } - - @Test - void play_payoutCalculationCorrect_rollUnder() { - diceDto.setRollOver(false); - diceDto.setTargetValue(BigDecimal.valueOf(25)); - when(random.nextInt(anyInt())).thenReturn(0); - - // Multiplier for win chance 24: (100-1)/24 = 99/24 = 4.125 - // Payout: 10 * 4.125 = 41.25 - - DiceResult result = diceService.play(user, diceDto); - - assertTrue(result.isWin()); - assertEquals(BigDecimal.valueOf(41.25).stripTrailingZeros(), result.getPayout().stripTrailingZeros()); - } - - @Test - void play_betAmountSubtracted() { - when(random.nextInt(anyInt())).thenReturn(50); - - diceService.play(user, diceDto); - - verify(balanceService, times(1)).subtractFunds(user, diceDto.getBetAmount()); - } -} diff --git a/backend/src/test/java/de/szut/casino/shared/service/BalanceServiceTest.java b/backend/src/test/java/de/szut/casino/shared/service/BalanceServiceTest.java deleted file mode 100644 index dfb96e5..0000000 --- a/backend/src/test/java/de/szut/casino/shared/service/BalanceServiceTest.java +++ /dev/null @@ -1,76 +0,0 @@ -package de.szut.casino.shared.service; - -import de.szut.casino.shared.dto.BetDto; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserRepository; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.math.BigDecimal; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -class BalanceServiceTest { - - @Mock - private UserRepository userRepository; - - @InjectMocks - private BalanceService balanceService; - - private UserEntity user; - private BetDto betDto; - - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - user = new UserEntity(); - user.setBalance(BigDecimal.valueOf(100)); - betDto = new BetDto(); - } - - @Test - void testHasFunds_sufficientFunds() { - betDto.setBetAmount(BigDecimal.valueOf(50)); - assertTrue(balanceService.hasFunds(user, betDto)); - } - - @Test - void testHasFunds_insufficientFunds() { - betDto.setBetAmount(BigDecimal.valueOf(150)); - assertFalse(balanceService.hasFunds(user, betDto)); - } - - @Test - void testHasFunds_exactFunds() { - betDto.setBetAmount(BigDecimal.valueOf(100)); - assertTrue(balanceService.hasFunds(user, betDto)); - } - - @Test - void testAddFunds() { - BigDecimal amountToAdd = BigDecimal.valueOf(50); - balanceService.addFunds(user, amountToAdd); - assertEquals(BigDecimal.valueOf(150), user.getBalance()); - verify(userRepository, times(1)).save(user); - } - - @Test - void testSubtractFunds_sufficientFunds() { - BigDecimal amountToSubtract = BigDecimal.valueOf(50); - balanceService.subtractFunds(user, amountToSubtract); - assertEquals(BigDecimal.valueOf(50), user.getBalance()); - verify(userRepository, times(1)).save(user); - } - - @Test - void testSubtractFunds_insufficientFunds() { - BigDecimal amountToSubtract = BigDecimal.valueOf(150); - assertThrows(IllegalStateException.class, () -> balanceService.subtractFunds(user, amountToSubtract)); - verify(userRepository, never()).save(user); - } -} diff --git a/compose.yml b/compose.yml deleted file mode 100644 index d3c7a87..0000000 --- a/compose.yml +++ /dev/null @@ -1,28 +0,0 @@ -volumes: - postgres_data: - -services: - db: - image: postgres:17.5 - container_name: casino-db - restart: unless-stopped - volumes: - - postgres_data:/var/lib/postgresql/data - environment: - POSTGRES_DB: postgresdb - POSTGRES_USER: postgres_user - POSTGRES_PASSWORD: postgres_pass - healthcheck: - test: "exit 0" - ports: - - "5432:5432" - mailpit: - image: axllent/mailpit - container_name: casino-mailpit - restart: unless-stopped - ports: - - 8025:8025 - - 1025:1025 - environment: - MP_SMTP_AUTH_ACCEPT_ANY: 1 - MP_SMTP_AUTH_ALLOW_INSECURE: 1 diff --git a/frontend/.docker/Dockerfile b/frontend/.docker/Dockerfile deleted file mode 100644 index 45a769c..0000000 --- a/frontend/.docker/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -FROM oven/bun:debian AS build -WORKDIR /app - -RUN apt-get update -y && \ - apt-get install -y --no-install-recommends curl ca-certificates gnupg && \ - curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ - apt-get install -y --no-install-recommends nodejs && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -ENV NODE_ENV=production - -COPY package.json bun.lock ./ -RUN bun install --frozen-lockfile - -COPY . . -RUN bun run build - -FROM nginx:alpine AS production - -RUN rm /etc/nginx/conf.d/default.conf -COPY .docker/casino.conf /etc/nginx/templates/nginx.conf.template -COPY .docker/entrypoint.sh /docker-entrypoint.d/40-custom-config-env.sh - -COPY --from=build /app/dist/casino /usr/share/nginx/html - -EXPOSE 80 -CMD ["nginx", "-g", "daemon off;"] diff --git a/frontend/.docker/casino.conf b/frontend/.docker/casino.conf deleted file mode 100644 index 40b9613..0000000 --- a/frontend/.docker/casino.conf +++ /dev/null @@ -1,19 +0,0 @@ -server { - listen 80; - root /usr/share/nginx/html/browser; - index index.html; - - location / { - try_files $uri $uri/ /index.html; - add_header Cache-Control "no-cache"; - } - - location /backend/ { - proxy_pass http://${BACKEND_HOST}:${BACKEND_PORT}/; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection 'upgrade'; - proxy_set_header Host $host; - proxy_cache_bypass $http_upgrade; - } -} diff --git a/frontend/.docker/entrypoint.sh b/frontend/.docker/entrypoint.sh deleted file mode 100755 index 7aa167e..0000000 --- a/frontend/.docker/entrypoint.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -# Default values if not provided -: ${BACKEND_HOST:=localhost} -: ${BACKEND_PORT:=8080} - -# Wait until the backend host is resolvable -echo "Waiting for backend host $BACKEND_HOST..." -until getent hosts "$BACKEND_HOST" > /dev/null; do - sleep 1 -done - -envsubst '$BACKEND_HOST $BACKEND_PORT' < /etc/nginx/templates/nginx.conf.template > /etc/nginx/conf.d/default.conf -exec nginx -g 'daemon off;' diff --git a/frontend/.dockerignore b/frontend/.dockerignore deleted file mode 100644 index 4e10341..0000000 --- a/frontend/.dockerignore +++ /dev/null @@ -1,15 +0,0 @@ -node_modules -dist -.angular -.git -.github -.vscode -.idea -*.md -!README.md -.DS_Store -.env* -npm-debug.log* -yarn-debug.log* -yarn-error.log* -bun-debug.log* \ No newline at end of file diff --git a/frontend/.editorconfig b/frontend/.editorconfig deleted file mode 100644 index 59d9a3a..0000000 --- a/frontend/.editorconfig +++ /dev/null @@ -1,16 +0,0 @@ -# Editor configuration, see https://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.ts] -quote_type = single - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/frontend/.gitignore b/frontend/.gitignore deleted file mode 100644 index cc7b141..0000000 --- a/frontend/.gitignore +++ /dev/null @@ -1,42 +0,0 @@ -# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. - -# Compiled output -/dist -/tmp -/out-tsc -/bazel-out - -# Node -/node_modules -npm-debug.log -yarn-error.log - -# IDEs and editors -.idea/ -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# Visual Studio Code -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -.history/* - -# Miscellaneous -/.angular/cache -.sass-cache/ -/connect.lock -/coverage -/libpeerconnection.log -testem.log -/typings - -# System files -.DS_Store -Thumbs.db diff --git a/frontend/.postcssrc.json b/frontend/.postcssrc.json deleted file mode 100644 index e092dc7..0000000 --- a/frontend/.postcssrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "plugins": { - "@tailwindcss/postcss": {} - } -} diff --git a/frontend/.prettierignore b/frontend/.prettierignore deleted file mode 100644 index f0c3bb3..0000000 --- a/frontend/.prettierignore +++ /dev/null @@ -1,4 +0,0 @@ -dist -coverage -node_modules -.angular diff --git a/frontend/.prettierrc b/frontend/.prettierrc deleted file mode 100644 index 837b4f9..0000000 --- a/frontend/.prettierrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "singleQuote": true, - "trailingComma": "es5", - "tabWidth": 2, - "semi": true, - "printWidth": 100, - "bracketSpacing": true, - "endOfLine": "lf" -} diff --git a/frontend/README.md b/frontend/README.md deleted file mode 100644 index daf35fe..0000000 --- a/frontend/README.md +++ /dev/null @@ -1,136 +0,0 @@ -# Casino Gaming Platform - Frontend - -This is the frontend application for the Casino Gaming Platform. It's built with Angular 18 and TailwindCSS, providing a responsive and modern UI for the casino gaming experience. - -## Development - -### Commands - -- **Build**: `bun run build` or `bunx @angular/cli build` -- **Start Dev Server**: `bun run start` or `bunx @angular/cli serve --proxy-config src/proxy.conf.json` -- **Format Code**: `bun run format` or `prettier --write "src/**/*.{ts,html,css,scss}"` -- **Lint**: `bun run lint` or `ng lint` -- **Test**: `bun run test` or `bunx @angular/cli test` -- **Test Single File**: `bunx @angular/cli test --include=path/to/test.spec.ts` - -## Style Guide - -### Color Palette - -#### Primary Colors -- Deep Blue: `#0a1219` (background) -- Deep Blue Light: `#121e27` (secondary background) -- Deep Blue Contrast: `#1a2835` (cards, elements) - -#### Accent Colors -- Emerald: `#10b981` (primary buttons) -- Emerald Dark: `#059669` (button hover) -- Emerald Light: `#34d399` (highlights) - -#### Text Colors -- Primary Text: `#ffffff` (white) -- Secondary Text: `#94a3b8` (light gray) -- Tertiary Text: `#64748b` (darker gray) - -#### Additional Accents -- Yellow: `#fbbf24` -- Red: `#ef4444` -- Purple: `#8b5cf6` - -### Typography - -#### Font Sizes -- Extra Small: Text-xs (footer disclaimers) -- Small: Text-sm (navigation links, footer links) -- Base: Text-base (general text) -- Large: Text-lg (section headings) -- Extra Large: Text-xl (stat numbers, game headings) -- Display: Text-4xl/5xl/7xl (welcome bonus text) - -#### Font Weights -- Normal: General text -- Medium: Labels -- Semibold: Navigation brand -- Bold: Headings, stats -- Extrabold: Welcome bonus text - -### Components - -#### Buttons -- Primary: Emerald background with hover state -- Secondary: Deep blue light background with hover state -- All buttons have active scale effect (95%) -- Transition duration: 200-300ms - -#### Cards -- Background: Deep blue contrast -- Rounded corners (lg) -- Shadow effects with hover transition -- Consistent padding (p-4) - -#### Navigation -- Desktop: Horizontal links with hover effects -- Mobile: Collapsible menu with toggle -- Links have color and background transitions - -#### Modals -- Backdrop blur with dark overlay -- Card-style container with emerald focus rings -- Consistent form styling with transitions - -### Forms - -#### Inputs -- Dark background with border -- Focus states with emerald accent -- Consistent padding and rounded corners -- Clear label positioning - -### Layout - -#### Grid System -- Mobile-first responsive grid -- Breakpoints: sm, md, lg -- Grid columns: 1 (mobile), 2 (tablet), 3 (desktop) -- Consistent gap spacing (gap-4) - -#### Spacing -- Consistent margin/padding scale -- Mobile-responsive spacing adjustments - -### Animation -- Transitions: 200-500ms duration -- Hover/active state animations -- Scale transformations (95-110%) -- Opacity transitions for navigation elements - -### Components & Classes - -#### Common UI Elements -- `.card` - Base card container -- `.button-primary` - Main CTA buttons -- `.button-secondary` - Alternative action buttons -- `.section-heading` - Section titles -- `.nav-link` - Navigation links -- `.modal-card` - Modal container - -#### Game Elements -- `.game-card-content` - Game information container -- `.game-heading-sm` - Small game titles -- `.game-heading-xl` - Large game titles -- `.game-text` - Game descriptions -- `.slider-container` - Game carousel container - -### Responsive Design -- Mobile-first approach -- Tailwind breakpoints (sm, md, lg) -- Different layouts based on screen size -- Responsive text sizing and spacing -- Hidden/visible elements using responsive classes - -### CSS Framework -- Tailwind CSS for utility classes -- Custom utility classes with @apply directive -- CSS variables for theming -- Component-based styling approach - diff --git a/frontend/angular.json b/frontend/angular.json deleted file mode 100644 index a9f9a84..0000000 --- a/frontend/angular.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "newProjectRoot": "projects", - "projects": { - "lf10Starter2024": { - "projectType": "application", - "schematics": {}, - "root": "", - "sourceRoot": "src", - "prefix": "app", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:application", - "options": { - "outputPath": "dist/casino", - "index": "src/index.html", - "browser": "src/main.ts", - "tsConfig": "tsconfig.app.json", - "assets": [ - { - "glob": "**/*", - "input": "public" - } - ], - "styles": [ - "src/styles.css" - ], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kB", - "maximumError": "1MB" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kB", - "maximumError": "4kB" - } - ], - "outputHashing": "all" - }, - "development": { - "optimization": false, - "extractLicenses": false, - "sourceMap": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "buildTarget": "lf10Starter2024:build:production" - }, - "development": { - "buildTarget": "lf10Starter2024:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n" - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "tsConfig": "tsconfig.spec.json", - "assets": [ - { - "glob": "**/*", - "input": "public" - } - ], - "styles": [ - "src/styles.css" - ], - "scripts": [] - } - }, - "lint": { - "builder": "@angular-eslint/builder:lint", - "options": { - "lintFilePatterns": [ - "src/**/*.ts", - "src/**/*.html" - ] - } - } - } - } - }, - "cli": { - "analytics": "33c8483f-3876-4eb5-9c9b-1001cab9b273", - "packageManager": "bun", - "schematicCollections": [ - "angular-eslint" - ] - } -} diff --git a/frontend/bun.lock b/frontend/bun.lock deleted file mode 100644 index 5275e49..0000000 --- a/frontend/bun.lock +++ /dev/null @@ -1,2379 +0,0 @@ -{ - "lockfileVersion": 1, - "workspaces": { - "": { - "name": "lf10-starter2024", - "dependencies": { - "@angular/animations": "^19.0.0", - "@angular/cdk": "~19.2.0", - "@angular/common": "^19.0.0", - "@angular/compiler": "^19.2.4", - "@angular/core": "^19.0.0", - "@angular/forms": "^19.0.0", - "@angular/platform-browser": "^19.0.0", - "@angular/platform-browser-dynamic": "^19.0.0", - "@angular/router": "^19.0.0", - "@fortawesome/angular-fontawesome": "^1.0.0", - "@fortawesome/fontawesome-svg-core": "^6.7.2", - "@fortawesome/free-brands-svg-icons": "^6.7.2", - "@fortawesome/free-solid-svg-icons": "^6.7.2", - "@stripe/stripe-js": "^7.0.0", - "@tailwindcss/postcss": "^4.0.3", - "ajv": "8.17.1", - "ajv-formats": "3.0.1", - "countup.js": "^2.8.0", - "gsap": "^3.12.7", - "postcss": "^8.5.1", - "rxjs": "~7.8.2", - "tailwindcss": "^4.0.3", - "tslib": "^2.3.0", - }, - "devDependencies": { - "@angular-devkit/build-angular": "^19.0.0", - "@angular/cli": "^19.2.5", - "@angular/compiler-cli": "^19.0.0", - "@types/jasmine": "~5.1.0", - "angular-eslint": "19.7.0", - "eslint": "^9.25.1", - "jasmine-core": "~5.7.0", - "karma": "~6.4.0", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.1.0", - "karma-jasmine-html-reporter": "~2.1.0", - "prettier": "^3.4.2", - "typescript": "~5.8.0", - "typescript-eslint": "8.33.1", - }, - }, - }, - "packages": { - "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], - - "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], - - "@angular-devkit/architect": ["@angular-devkit/architect@0.1902.6", "", { "dependencies": { "@angular-devkit/core": "19.2.6", "rxjs": "7.8.1" } }, "sha512-Dx6yPxpaE5AhP6UtrVRDCc9Ihq9B65LAbmIh3dNOyeehratuaQS0TYNKjbpaevevJojW840DTg80N+CrlfYp9g=="], - - "@angular-devkit/build-angular": ["@angular-devkit/build-angular@19.2.6", "", { "dependencies": { "@ampproject/remapping": "2.3.0", "@angular-devkit/architect": "0.1902.6", "@angular-devkit/build-webpack": "0.1902.6", "@angular-devkit/core": "19.2.6", "@angular/build": "19.2.6", "@babel/core": "7.26.10", "@babel/generator": "7.26.10", "@babel/helper-annotate-as-pure": "7.25.9", "@babel/helper-split-export-declaration": "7.24.7", "@babel/plugin-transform-async-generator-functions": "7.26.8", "@babel/plugin-transform-async-to-generator": "7.25.9", "@babel/plugin-transform-runtime": "7.26.10", "@babel/preset-env": "7.26.9", "@babel/runtime": "7.26.10", "@discoveryjs/json-ext": "0.6.3", "@ngtools/webpack": "19.2.6", "@vitejs/plugin-basic-ssl": "1.2.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.20", "babel-loader": "9.2.1", "browserslist": "^4.21.5", "copy-webpack-plugin": "12.0.2", "css-loader": "7.1.2", "esbuild-wasm": "0.25.1", "fast-glob": "3.3.3", "http-proxy-middleware": "3.0.3", "istanbul-lib-instrument": "6.0.3", "jsonc-parser": "3.3.1", "karma-source-map-support": "1.4.0", "less": "4.2.2", "less-loader": "12.2.0", "license-webpack-plugin": "4.0.2", "loader-utils": "3.3.1", "mini-css-extract-plugin": "2.9.2", "open": "10.1.0", "ora": "5.4.1", "picomatch": "4.0.2", "piscina": "4.8.0", "postcss": "8.5.2", "postcss-loader": "8.1.1", "resolve-url-loader": "5.0.0", "rxjs": "7.8.1", "sass": "1.85.0", "sass-loader": "16.0.5", "semver": "7.7.1", "source-map-loader": "5.0.0", "source-map-support": "0.5.21", "terser": "5.39.0", "tree-kill": "1.2.2", "tslib": "2.8.1", "webpack": "5.98.0", "webpack-dev-middleware": "7.4.2", "webpack-dev-server": "5.2.0", "webpack-merge": "6.0.1", "webpack-subresource-integrity": "5.1.0" }, "optionalDependencies": { "esbuild": "0.25.1" }, "peerDependencies": { "@angular/compiler-cli": "^19.0.0 || ^19.2.0-next.0", "@angular/localize": "^19.0.0 || ^19.2.0-next.0", "@angular/platform-server": "^19.0.0 || ^19.2.0-next.0", "@angular/service-worker": "^19.0.0 || ^19.2.0-next.0", "@angular/ssr": "^19.2.6", "@web/test-runner": "^0.20.0", "browser-sync": "^3.0.2", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "karma": "^6.3.0", "ng-packagr": "^19.0.0 || ^19.2.0-next.0", "protractor": "^7.0.0", "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", "typescript": ">=5.5 <5.9" }, "optionalPeers": ["@angular/localize", "@angular/platform-server", "@angular/service-worker", "@angular/ssr", "@web/test-runner", "browser-sync", "jest", "jest-environment-jsdom", "karma", "ng-packagr", "protractor", "tailwindcss"] }, "sha512-alYn3PSsiQML9PzU1VKbmYnIP2ULK/AqfjdeJFh8r6m8ZjUvX1zDy9TdAfC6fykQ2mGHyChteRckbx9uVOyhwQ=="], - - "@angular-devkit/build-webpack": ["@angular-devkit/build-webpack@0.1902.6", "", { "dependencies": { "@angular-devkit/architect": "0.1902.6", "rxjs": "7.8.1" }, "peerDependencies": { "webpack": "^5.30.0", "webpack-dev-server": "^5.0.2" } }, "sha512-SZe2Nk39lJIJmtXWU+zhKaFy0xoU8N7387bvjhO0AoNQeRBaaJ5SrRLXX2jUzGUuVgGVF+plaVooKrmEOeM6ug=="], - - "@angular-devkit/core": ["@angular-devkit/core@19.2.6", "", { "dependencies": { "ajv": "8.17.1", "ajv-formats": "3.0.1", "jsonc-parser": "3.3.1", "picomatch": "4.0.2", "rxjs": "7.8.1", "source-map": "0.7.4" }, "peerDependencies": { "chokidar": "^4.0.0" }, "optionalPeers": ["chokidar"] }, "sha512-WFgiYhrDMq83UNaGRAneIM7CYYdBozD+yYA9BjoU8AgBLKtrvn6S8ZcjKAk5heoHtY/u8pEb0mwDTz9gxFmJZQ=="], - - "@angular-devkit/schematics": ["@angular-devkit/schematics@19.2.6", "", { "dependencies": { "@angular-devkit/core": "19.2.6", "jsonc-parser": "3.3.1", "magic-string": "0.30.17", "ora": "5.4.1", "rxjs": "7.8.1" } }, "sha512-YTAxNnT++5eflx19OUHmOWu597/TbTel+QARiZCv1xQw99+X8DCKKOUXtqBRd53CAHlREDI33Rn/JLY3NYgMLQ=="], - - "@angular-eslint/builder": ["@angular-eslint/builder@19.7.0", "", { "dependencies": { "@angular-devkit/architect": ">= 0.1900.0 < 0.2000.0", "@angular-devkit/core": ">= 19.0.0 < 20.0.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, "sha512-tnanOOwUKzeS0FwhjJd/dNeb8gVzcF0+cI4/ZgohOjZxm8fZqtzXcKfGS1C7KsR/CPHBdY9cbF1OVPJEarrnsQ=="], - - "@angular-eslint/bundled-angular-compiler": ["@angular-eslint/bundled-angular-compiler@19.7.0", "", {}, "sha512-95Z30MhQ93s1G1mEnsVuG45te82I+6dp8Y0MamRgyh4OZvOajmEXpvCwT+hkr/9WAroLZ7p5nlMbzAA+OXZ+YQ=="], - - "@angular-eslint/eslint-plugin": ["@angular-eslint/eslint-plugin@19.7.0", "", { "dependencies": { "@angular-eslint/bundled-angular-compiler": "19.7.0", "@angular-eslint/utils": "19.7.0" }, "peerDependencies": { "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, "sha512-M8OqDgiFSSxMinW/Gkdrvy2O2Oeo8bGk1DQc0s3aEKB44PYAjXC49jMSihvdozqtu1qjPBcTN5kvUwzwN5oWxA=="], - - "@angular-eslint/eslint-plugin-template": ["@angular-eslint/eslint-plugin-template@19.7.0", "", { "dependencies": { "@angular-eslint/bundled-angular-compiler": "19.7.0", "@angular-eslint/utils": "19.7.0", "aria-query": "5.3.2", "axobject-query": "4.1.0" }, "peerDependencies": { "@angular-eslint/template-parser": "19.7.0", "@typescript-eslint/types": "^7.11.0 || ^8.0.0", "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, "sha512-gR+RH7ZDFctupUsCcxWWloD0I7m9pE8HiDX9TrwrSQbNgzvp/P7+Mgv709rR1Jju9GSVavPh7EG3VgiCyR2m5w=="], - - "@angular-eslint/schematics": ["@angular-eslint/schematics@19.7.0", "", { "dependencies": { "@angular-devkit/core": ">= 19.0.0 < 20.0.0", "@angular-devkit/schematics": ">= 19.0.0 < 20.0.0", "@angular-eslint/eslint-plugin": "19.7.0", "@angular-eslint/eslint-plugin-template": "19.7.0", "ignore": "7.0.5", "semver": "7.7.2", "strip-json-comments": "3.1.1" } }, "sha512-07j/qXfSLvLsUq8a7WJlGYgcgfVEJ1ODuwJ2R4686dh2lqZ5GRV75fpdOtOBdC38MILLwd5el+8LfdaIG19Yog=="], - - "@angular-eslint/template-parser": ["@angular-eslint/template-parser@19.7.0", "", { "dependencies": { "@angular-eslint/bundled-angular-compiler": "19.7.0", "eslint-scope": "^8.0.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, "sha512-XLPt6gk8VMOrUO9NWRpXN8zgwJuCDV+9y3KbVnd4WyakO0sOz9SVzktuI4AeY9jWS9/tqU6P8Uj0WZsMVz7F8w=="], - - "@angular-eslint/utils": ["@angular-eslint/utils@19.7.0", "", { "dependencies": { "@angular-eslint/bundled-angular-compiler": "19.7.0" }, "peerDependencies": { "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, "sha512-F4JcZtc2/Wl0AwRaeUywupPHdaOtldpwfrGYewT1dYDikFafyDk5T6E9JYv/HgLXROPNMDVPFquwikNvAPlfAg=="], - - "@angular/animations": ["@angular/animations@19.2.5", "", { "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { "@angular/common": "19.2.5", "@angular/core": "19.2.5" } }, "sha512-m4RtY3z1JuHFCh6OrOHxo25oKEigBDdR/XmdCfXIwfTiObZzNA7VQhysgdrb9IISO99kXbjZUYKDtLzgWT8Klg=="], - - "@angular/build": ["@angular/build@19.2.6", "", { "dependencies": { "@ampproject/remapping": "2.3.0", "@angular-devkit/architect": "0.1902.6", "@babel/core": "7.26.10", "@babel/helper-annotate-as-pure": "7.25.9", "@babel/helper-split-export-declaration": "7.24.7", "@babel/plugin-syntax-import-attributes": "7.26.0", "@inquirer/confirm": "5.1.6", "@vitejs/plugin-basic-ssl": "1.2.0", "beasties": "0.2.0", "browserslist": "^4.23.0", "esbuild": "0.25.1", "fast-glob": "3.3.3", "https-proxy-agent": "7.0.6", "istanbul-lib-instrument": "6.0.3", "listr2": "8.2.5", "magic-string": "0.30.17", "mrmime": "2.0.1", "parse5-html-rewriting-stream": "7.0.0", "picomatch": "4.0.2", "piscina": "4.8.0", "rollup": "4.34.8", "sass": "1.85.0", "semver": "7.7.1", "source-map-support": "0.5.21", "vite": "6.2.4", "watchpack": "2.4.2" }, "optionalDependencies": { "lmdb": "3.2.6" }, "peerDependencies": { "@angular/compiler": "^19.0.0 || ^19.2.0-next.0", "@angular/compiler-cli": "^19.0.0 || ^19.2.0-next.0", "@angular/localize": "^19.0.0 || ^19.2.0-next.0", "@angular/platform-server": "^19.0.0 || ^19.2.0-next.0", "@angular/service-worker": "^19.0.0 || ^19.2.0-next.0", "@angular/ssr": "^19.2.6", "karma": "^6.4.0", "less": "^4.2.0", "ng-packagr": "^19.0.0 || ^19.2.0-next.0", "postcss": "^8.4.0", "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", "typescript": ">=5.5 <5.9" }, "optionalPeers": ["@angular/localize", "@angular/platform-server", "@angular/service-worker", "@angular/ssr", "karma", "less", "ng-packagr", "postcss", "tailwindcss"] }, "sha512-+VBLb4ZPLswwJmgfsTFzGex+Sq/WveNc+uaIWyHYjwnuI17NXe1qAAg1rlp72CqGn0cirisfOyAUwPc/xZAgTg=="], - - "@angular/cdk": ["@angular/cdk@19.2.8", "", { "dependencies": { "parse5": "^7.1.2", "tslib": "^2.3.0" }, "peerDependencies": { "@angular/common": "^19.0.0 || ^20.0.0", "@angular/core": "^19.0.0 || ^20.0.0", "rxjs": "^6.5.3 || ^7.4.0" } }, "sha512-ZZqWVYFF80TdjWkk2sc9Pn2luhiYeC78VH3Yjeln4wXMsTGDsvKPBcuOxSxxpJ31saaVBehDjBUuXMqGRj8KuA=="], - - "@angular/cli": ["@angular/cli@19.2.6", "", { "dependencies": { "@angular-devkit/architect": "0.1902.6", "@angular-devkit/core": "19.2.6", "@angular-devkit/schematics": "19.2.6", "@inquirer/prompts": "7.3.2", "@listr2/prompt-adapter-inquirer": "2.0.18", "@schematics/angular": "19.2.6", "@yarnpkg/lockfile": "1.1.0", "ini": "5.0.0", "jsonc-parser": "3.3.1", "listr2": "8.2.5", "npm-package-arg": "12.0.2", "npm-pick-manifest": "10.0.0", "pacote": "20.0.0", "resolve": "1.22.10", "semver": "7.7.1", "symbol-observable": "4.0.0", "yargs": "17.7.2" }, "bin": { "ng": "bin/ng.js" } }, "sha512-eZhFOSsDUHKaciwcWdU5C54ViAvPPdZJf42So93G2vZWDtEq6Uk47huocn1FY9cMhDvURfYLNrrLMpUDtUSsSA=="], - - "@angular/common": ["@angular/common@19.2.5", "", { "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { "@angular/core": "19.2.5", "rxjs": "^6.5.3 || ^7.4.0" } }, "sha512-vFCBdas4C5PxP6ts/4TlRddWD3DUmI3aaO0QZdZvqyLHy428t84ruYdsJXKaeD8ie2U4/9F3a1tsklclRG/BBA=="], - - "@angular/compiler": ["@angular/compiler@19.2.5", "", { "dependencies": { "tslib": "^2.3.0" } }, "sha512-34J+HubQjwkbZ0AUtU5sa4Zouws9XtP/fKaysMQecoYJTZ3jewzLSRu3aAEZX1Y4gIrcVVKKIxM6oWoXKwYMOA=="], - - "@angular/compiler-cli": ["@angular/compiler-cli@19.2.5", "", { "dependencies": { "@babel/core": "7.26.9", "@jridgewell/sourcemap-codec": "^1.4.14", "chokidar": "^4.0.0", "convert-source-map": "^1.5.1", "reflect-metadata": "^0.2.0", "semver": "^7.0.0", "tslib": "^2.3.0", "yargs": "^17.2.1" }, "peerDependencies": { "@angular/compiler": "19.2.5", "typescript": ">=5.5 <5.9" }, "bin": { "ngc": "bundles/src/bin/ngc.js", "ngcc": "bundles/ngcc/index.js", "ng-xi18n": "bundles/src/bin/ng_xi18n.js" } }, "sha512-b2cG41r6lilApXLlvja1Ra2D00dM3BxmQhoElKC1tOnpD6S3/krlH1DOnBB2I55RBn9iv4zdmPz1l8zPUSh7DQ=="], - - "@angular/core": ["@angular/core@19.2.5", "", { "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { "rxjs": "^6.5.3 || ^7.4.0", "zone.js": "~0.15.0" } }, "sha512-NNEz1sEZz1mBpgf6Tz3aJ9b8KjqpTiMYhHfCYA9h9Ipe4D8gUmOsvPHPK2M755OX7p7PmUmzp1XCUHYrZMVHRw=="], - - "@angular/forms": ["@angular/forms@19.2.5", "", { "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { "@angular/common": "19.2.5", "@angular/core": "19.2.5", "@angular/platform-browser": "19.2.5", "rxjs": "^6.5.3 || ^7.4.0" } }, "sha512-2Zvy3qK1kOxiAX9fdSaeG48q7oyO/4RlMYlg1w+ra9qX1SrgwF3OQ2P2Vs+ojg1AxN3z9xFp4aYaaID/G2LZAw=="], - - "@angular/platform-browser": ["@angular/platform-browser@19.2.5", "", { "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { "@angular/animations": "19.2.5", "@angular/common": "19.2.5", "@angular/core": "19.2.5" }, "optionalPeers": ["@angular/animations"] }, "sha512-Lshy++X16cvl6OPvfzMySpsqEaCPKEJmDjz7q7oSt96oxlh6LvOeOUVLjsNyrNaIt9NadpWoqjlu/I9RTPJkpw=="], - - "@angular/platform-browser-dynamic": ["@angular/platform-browser-dynamic@19.2.5", "", { "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { "@angular/common": "19.2.5", "@angular/compiler": "19.2.5", "@angular/core": "19.2.5", "@angular/platform-browser": "19.2.5" } }, "sha512-15in8u4552EcdWNTXY2h0MKuJbk3AuXwWr0zVTum4CfB/Ss2tNTrDEdWhgAbhnUI0e9jZQee/fhBbA1rleMYrA=="], - - "@angular/router": ["@angular/router@19.2.5", "", { "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { "@angular/common": "19.2.5", "@angular/core": "19.2.5", "@angular/platform-browser": "19.2.5", "rxjs": "^6.5.3 || ^7.4.0" } }, "sha512-9pSfmdNXLjaOKj0kd4UxBC7sFdCFOnRGbftp397G3KWqsLsGSKmNFzqhXNeA5QHkaVxnpmpm8HzXU+zYV5JwSg=="], - - "@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], - - "@babel/compat-data": ["@babel/compat-data@7.26.8", "", {}, "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ=="], - - "@babel/core": ["@babel/core@7.26.10", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.10", "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-module-transforms": "^7.26.0", "@babel/helpers": "^7.26.10", "@babel/parser": "^7.26.10", "@babel/template": "^7.26.9", "@babel/traverse": "^7.26.10", "@babel/types": "^7.26.10", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ=="], - - "@babel/generator": ["@babel/generator@7.26.10", "", { "dependencies": { "@babel/parser": "^7.26.10", "@babel/types": "^7.26.10", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang=="], - - "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.25.9", "", { "dependencies": { "@babel/types": "^7.25.9" } }, "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g=="], - - "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.0", "", { "dependencies": { "@babel/compat-data": "^7.26.8", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA=="], - - "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.27.0", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-member-expression-to-functions": "^7.25.9", "@babel/helper-optimise-call-expression": "^7.25.9", "@babel/helper-replace-supers": "^7.26.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", "@babel/traverse": "^7.27.0", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg=="], - - "@babel/helper-create-regexp-features-plugin": ["@babel/helper-create-regexp-features-plugin@7.27.0", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "regexpu-core": "^6.2.0", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ=="], - - "@babel/helper-define-polyfill-provider": ["@babel/helper-define-polyfill-provider@0.6.4", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", "resolve": "^1.14.2" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw=="], - - "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ=="], - - "@babel/helper-module-imports": ["@babel/helper-module-imports@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw=="], - - "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.26.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw=="], - - "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.25.9", "", { "dependencies": { "@babel/types": "^7.25.9" } }, "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ=="], - - "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.26.5", "", {}, "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg=="], - - "@babel/helper-remap-async-to-generator": ["@babel/helper-remap-async-to-generator@7.25.9", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-wrap-function": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw=="], - - "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.26.5", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.25.9", "@babel/helper-optimise-call-expression": "^7.25.9", "@babel/traverse": "^7.26.5" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg=="], - - "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA=="], - - "@babel/helper-split-export-declaration": ["@babel/helper-split-export-declaration@7.24.7", "", { "dependencies": { "@babel/types": "^7.24.7" } }, "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA=="], - - "@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.9", "", {}, "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="], - - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], - - "@babel/helper-validator-option": ["@babel/helper-validator-option@7.25.9", "", {}, "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw=="], - - "@babel/helper-wrap-function": ["@babel/helper-wrap-function@7.25.9", "", { "dependencies": { "@babel/template": "^7.25.9", "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g=="], - - "@babel/helpers": ["@babel/helpers@7.27.0", "", { "dependencies": { "@babel/template": "^7.27.0", "@babel/types": "^7.27.0" } }, "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg=="], - - "@babel/parser": ["@babel/parser@7.27.0", "", { "dependencies": { "@babel/types": "^7.27.0" }, "bin": "./bin/babel-parser.js" }, "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg=="], - - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ["@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g=="], - - "@babel/plugin-bugfix-safari-class-field-initializer-scope": ["@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw=="], - - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ["@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug=="], - - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ["@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", "@babel/plugin-transform-optional-chaining": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.13.0" } }, "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g=="], - - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ["@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg=="], - - "@babel/plugin-proposal-private-property-in-object": ["@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2", "", { "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w=="], - - "@babel/plugin-syntax-import-assertions": ["@babel/plugin-syntax-import-assertions@7.26.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg=="], - - "@babel/plugin-syntax-import-attributes": ["@babel/plugin-syntax-import-attributes@7.26.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A=="], - - "@babel/plugin-syntax-unicode-sets-regex": ["@babel/plugin-syntax-unicode-sets-regex@7.18.6", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg=="], - - "@babel/plugin-transform-arrow-functions": ["@babel/plugin-transform-arrow-functions@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg=="], - - "@babel/plugin-transform-async-generator-functions": ["@babel/plugin-transform-async-generator-functions@7.26.8", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.26.5", "@babel/helper-remap-async-to-generator": "^7.25.9", "@babel/traverse": "^7.26.8" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg=="], - - "@babel/plugin-transform-async-to-generator": ["@babel/plugin-transform-async-to-generator@7.25.9", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-remap-async-to-generator": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ=="], - - "@babel/plugin-transform-block-scoped-functions": ["@babel/plugin-transform-block-scoped-functions@7.26.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.26.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ=="], - - "@babel/plugin-transform-block-scoping": ["@babel/plugin-transform-block-scoping@7.27.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.26.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ=="], - - "@babel/plugin-transform-class-properties": ["@babel/plugin-transform-class-properties@7.25.9", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q=="], - - "@babel/plugin-transform-class-static-block": ["@babel/plugin-transform-class-static-block@7.26.0", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.12.0" } }, "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ=="], - - "@babel/plugin-transform-classes": ["@babel/plugin-transform-classes@7.25.9", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-compilation-targets": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-replace-supers": "^7.25.9", "@babel/traverse": "^7.25.9", "globals": "^11.1.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg=="], - - "@babel/plugin-transform-computed-properties": ["@babel/plugin-transform-computed-properties@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/template": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA=="], - - "@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ=="], - - "@babel/plugin-transform-dotall-regex": ["@babel/plugin-transform-dotall-regex@7.25.9", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA=="], - - "@babel/plugin-transform-duplicate-keys": ["@babel/plugin-transform-duplicate-keys@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw=="], - - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": ["@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog=="], - - "@babel/plugin-transform-dynamic-import": ["@babel/plugin-transform-dynamic-import@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg=="], - - "@babel/plugin-transform-exponentiation-operator": ["@babel/plugin-transform-exponentiation-operator@7.26.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ=="], - - "@babel/plugin-transform-export-namespace-from": ["@babel/plugin-transform-export-namespace-from@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww=="], - - "@babel/plugin-transform-for-of": ["@babel/plugin-transform-for-of@7.26.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.26.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg=="], - - "@babel/plugin-transform-function-name": ["@babel/plugin-transform-function-name@7.25.9", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA=="], - - "@babel/plugin-transform-json-strings": ["@babel/plugin-transform-json-strings@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw=="], - - "@babel/plugin-transform-literals": ["@babel/plugin-transform-literals@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ=="], - - "@babel/plugin-transform-logical-assignment-operators": ["@babel/plugin-transform-logical-assignment-operators@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q=="], - - "@babel/plugin-transform-member-expression-literals": ["@babel/plugin-transform-member-expression-literals@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA=="], - - "@babel/plugin-transform-modules-amd": ["@babel/plugin-transform-modules-amd@7.25.9", "", { "dependencies": { "@babel/helper-module-transforms": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw=="], - - "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.26.3", "", { "dependencies": { "@babel/helper-module-transforms": "^7.26.0", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ=="], - - "@babel/plugin-transform-modules-systemjs": ["@babel/plugin-transform-modules-systemjs@7.25.9", "", { "dependencies": { "@babel/helper-module-transforms": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA=="], - - "@babel/plugin-transform-modules-umd": ["@babel/plugin-transform-modules-umd@7.25.9", "", { "dependencies": { "@babel/helper-module-transforms": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw=="], - - "@babel/plugin-transform-named-capturing-groups-regex": ["@babel/plugin-transform-named-capturing-groups-regex@7.25.9", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA=="], - - "@babel/plugin-transform-new-target": ["@babel/plugin-transform-new-target@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ=="], - - "@babel/plugin-transform-nullish-coalescing-operator": ["@babel/plugin-transform-nullish-coalescing-operator@7.26.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.26.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw=="], - - "@babel/plugin-transform-numeric-separator": ["@babel/plugin-transform-numeric-separator@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q=="], - - "@babel/plugin-transform-object-rest-spread": ["@babel/plugin-transform-object-rest-spread@7.25.9", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", "@babel/plugin-transform-parameters": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg=="], - - "@babel/plugin-transform-object-super": ["@babel/plugin-transform-object-super@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-replace-supers": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A=="], - - "@babel/plugin-transform-optional-catch-binding": ["@babel/plugin-transform-optional-catch-binding@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g=="], - - "@babel/plugin-transform-optional-chaining": ["@babel/plugin-transform-optional-chaining@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A=="], - - "@babel/plugin-transform-parameters": ["@babel/plugin-transform-parameters@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g=="], - - "@babel/plugin-transform-private-methods": ["@babel/plugin-transform-private-methods@7.25.9", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw=="], - - "@babel/plugin-transform-private-property-in-object": ["@babel/plugin-transform-private-property-in-object@7.25.9", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-create-class-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw=="], - - "@babel/plugin-transform-property-literals": ["@babel/plugin-transform-property-literals@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA=="], - - "@babel/plugin-transform-regenerator": ["@babel/plugin-transform-regenerator@7.27.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.26.5", "regenerator-transform": "^0.15.2" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA=="], - - "@babel/plugin-transform-regexp-modifiers": ["@babel/plugin-transform-regexp-modifiers@7.26.0", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw=="], - - "@babel/plugin-transform-reserved-words": ["@babel/plugin-transform-reserved-words@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg=="], - - "@babel/plugin-transform-runtime": ["@babel/plugin-transform-runtime@7.26.10", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-plugin-utils": "^7.26.5", "babel-plugin-polyfill-corejs2": "^0.4.10", "babel-plugin-polyfill-corejs3": "^0.11.0", "babel-plugin-polyfill-regenerator": "^0.6.1", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-NWaL2qG6HRpONTnj4JvDU6th4jYeZOJgu3QhmFTCihib0ermtOJqktA5BduGm3suhhVe9EMP9c9+mfJ/I9slqw=="], - - "@babel/plugin-transform-shorthand-properties": ["@babel/plugin-transform-shorthand-properties@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng=="], - - "@babel/plugin-transform-spread": ["@babel/plugin-transform-spread@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A=="], - - "@babel/plugin-transform-sticky-regex": ["@babel/plugin-transform-sticky-regex@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA=="], - - "@babel/plugin-transform-template-literals": ["@babel/plugin-transform-template-literals@7.26.8", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.26.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q=="], - - "@babel/plugin-transform-typeof-symbol": ["@babel/plugin-transform-typeof-symbol@7.27.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.26.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w=="], - - "@babel/plugin-transform-unicode-escapes": ["@babel/plugin-transform-unicode-escapes@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q=="], - - "@babel/plugin-transform-unicode-property-regex": ["@babel/plugin-transform-unicode-property-regex@7.25.9", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg=="], - - "@babel/plugin-transform-unicode-regex": ["@babel/plugin-transform-unicode-regex@7.25.9", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA=="], - - "@babel/plugin-transform-unicode-sets-regex": ["@babel/plugin-transform-unicode-sets-regex@7.25.9", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ=="], - - "@babel/preset-env": ["@babel/preset-env@7.26.9", "", { "dependencies": { "@babel/compat-data": "^7.26.8", "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-plugin-utils": "^7.26.5", "@babel/helper-validator-option": "^7.25.9", "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-import-assertions": "^7.26.0", "@babel/plugin-syntax-import-attributes": "^7.26.0", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.25.9", "@babel/plugin-transform-async-generator-functions": "^7.26.8", "@babel/plugin-transform-async-to-generator": "^7.25.9", "@babel/plugin-transform-block-scoped-functions": "^7.26.5", "@babel/plugin-transform-block-scoping": "^7.25.9", "@babel/plugin-transform-class-properties": "^7.25.9", "@babel/plugin-transform-class-static-block": "^7.26.0", "@babel/plugin-transform-classes": "^7.25.9", "@babel/plugin-transform-computed-properties": "^7.25.9", "@babel/plugin-transform-destructuring": "^7.25.9", "@babel/plugin-transform-dotall-regex": "^7.25.9", "@babel/plugin-transform-duplicate-keys": "^7.25.9", "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", "@babel/plugin-transform-dynamic-import": "^7.25.9", "@babel/plugin-transform-exponentiation-operator": "^7.26.3", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-for-of": "^7.26.9", "@babel/plugin-transform-function-name": "^7.25.9", "@babel/plugin-transform-json-strings": "^7.25.9", "@babel/plugin-transform-literals": "^7.25.9", "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", "@babel/plugin-transform-member-expression-literals": "^7.25.9", "@babel/plugin-transform-modules-amd": "^7.25.9", "@babel/plugin-transform-modules-commonjs": "^7.26.3", "@babel/plugin-transform-modules-systemjs": "^7.25.9", "@babel/plugin-transform-modules-umd": "^7.25.9", "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", "@babel/plugin-transform-new-target": "^7.25.9", "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", "@babel/plugin-transform-numeric-separator": "^7.25.9", "@babel/plugin-transform-object-rest-spread": "^7.25.9", "@babel/plugin-transform-object-super": "^7.25.9", "@babel/plugin-transform-optional-catch-binding": "^7.25.9", "@babel/plugin-transform-optional-chaining": "^7.25.9", "@babel/plugin-transform-parameters": "^7.25.9", "@babel/plugin-transform-private-methods": "^7.25.9", "@babel/plugin-transform-private-property-in-object": "^7.25.9", "@babel/plugin-transform-property-literals": "^7.25.9", "@babel/plugin-transform-regenerator": "^7.25.9", "@babel/plugin-transform-regexp-modifiers": "^7.26.0", "@babel/plugin-transform-reserved-words": "^7.25.9", "@babel/plugin-transform-shorthand-properties": "^7.25.9", "@babel/plugin-transform-spread": "^7.25.9", "@babel/plugin-transform-sticky-regex": "^7.25.9", "@babel/plugin-transform-template-literals": "^7.26.8", "@babel/plugin-transform-typeof-symbol": "^7.26.7", "@babel/plugin-transform-unicode-escapes": "^7.25.9", "@babel/plugin-transform-unicode-property-regex": "^7.25.9", "@babel/plugin-transform-unicode-regex": "^7.25.9", "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", "babel-plugin-polyfill-corejs3": "^0.11.0", "babel-plugin-polyfill-regenerator": "^0.6.1", "core-js-compat": "^3.40.0", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ=="], - - "@babel/preset-modules": ["@babel/preset-modules@0.1.6-no-external-plugins", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", "esutils": "^2.0.2" }, "peerDependencies": { "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA=="], - - "@babel/runtime": ["@babel/runtime@7.26.10", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw=="], - - "@babel/template": ["@babel/template@7.27.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/parser": "^7.27.0", "@babel/types": "^7.27.0" } }, "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA=="], - - "@babel/traverse": ["@babel/traverse@7.27.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.27.0", "@babel/parser": "^7.27.0", "@babel/template": "^7.27.0", "@babel/types": "^7.27.0", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA=="], - - "@babel/types": ["@babel/types@7.27.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg=="], - - "@colors/colors": ["@colors/colors@1.5.0", "", {}, "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="], - - "@discoveryjs/json-ext": ["@discoveryjs/json-ext@0.6.3", "", {}, "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ=="], - - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ=="], - - "@esbuild/android-arm": ["@esbuild/android-arm@0.25.1", "", { "os": "android", "cpu": "arm" }, "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q=="], - - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.1", "", { "os": "android", "cpu": "arm64" }, "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA=="], - - "@esbuild/android-x64": ["@esbuild/android-x64@0.25.1", "", { "os": "android", "cpu": "x64" }, "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw=="], - - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ=="], - - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA=="], - - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A=="], - - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww=="], - - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.1", "", { "os": "linux", "cpu": "arm" }, "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ=="], - - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ=="], - - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ=="], - - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.1", "", { "os": "linux", "cpu": "none" }, "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg=="], - - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.1", "", { "os": "linux", "cpu": "none" }, "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg=="], - - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg=="], - - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.1", "", { "os": "linux", "cpu": "none" }, "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ=="], - - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ=="], - - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA=="], - - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.1", "", { "os": "none", "cpu": "arm64" }, "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g=="], - - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.1", "", { "os": "none", "cpu": "x64" }, "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA=="], - - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg=="], - - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw=="], - - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg=="], - - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ=="], - - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A=="], - - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.1", "", { "os": "win32", "cpu": "x64" }, "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg=="], - - "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.5.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w=="], - - "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], - - "@eslint/config-array": ["@eslint/config-array@0.20.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ=="], - - "@eslint/config-helpers": ["@eslint/config-helpers@0.2.1", "", {}, "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw=="], - - "@eslint/core": ["@eslint/core@0.13.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw=="], - - "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], - - "@eslint/js": ["@eslint/js@9.25.1", "", {}, "sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg=="], - - "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], - - "@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.8", "", { "dependencies": { "@eslint/core": "^0.13.0", "levn": "^0.4.1" } }, "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA=="], - - "@fortawesome/angular-fontawesome": ["@fortawesome/angular-fontawesome@1.0.0", "", { "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.7.1", "tslib": "^2.8.1" }, "peerDependencies": { "@angular/core": "^19.0.0" } }, "sha512-EC2fYuXIuw2ld1kzJi+zysWus6OeGGfLQtbh0hW9zyyq5aBo8ZJkcJKBsVQ8E6Mg7nHyTWaXn+sdcXTPDWz+UQ=="], - - "@fortawesome/fontawesome-common-types": ["@fortawesome/fontawesome-common-types@6.7.2", "", {}, "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg=="], - - "@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@6.7.2", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "6.7.2" } }, "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA=="], - - "@fortawesome/free-brands-svg-icons": ["@fortawesome/free-brands-svg-icons@6.7.2", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "6.7.2" } }, "sha512-zu0evbcRTgjKfrr77/2XX+bU+kuGfjm0LbajJHVIgBWNIDzrhpRxiCPNT8DW5AdmSsq7Mcf9D1bH0aSeSUSM+Q=="], - - "@fortawesome/free-solid-svg-icons": ["@fortawesome/free-solid-svg-icons@6.7.2", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "6.7.2" } }, "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA=="], - - "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], - - "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], - - "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], - - "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.2", "", {}, "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ=="], - - "@inquirer/checkbox": ["@inquirer/checkbox@4.1.4", "", { "dependencies": { "@inquirer/core": "^10.1.9", "@inquirer/figures": "^1.0.11", "@inquirer/type": "^3.0.5", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-d30576EZdApjAMceijXA5jDzRQHT/MygbC+J8I7EqA6f/FRpYxlRtRJbHF8gHeWYeSdOuTEJqonn7QLB1ELezA=="], - - "@inquirer/confirm": ["@inquirer/confirm@5.1.6", "", { "dependencies": { "@inquirer/core": "^10.1.7", "@inquirer/type": "^3.0.4" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-6ZXYK3M1XmaVBZX6FCfChgtponnL0R6I7k8Nu+kaoNkT828FVZTcca1MqmWQipaW2oNREQl5AaPCUOOCVNdRMw=="], - - "@inquirer/core": ["@inquirer/core@10.1.9", "", { "dependencies": { "@inquirer/figures": "^1.0.11", "@inquirer/type": "^3.0.5", "ansi-escapes": "^4.3.2", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw=="], - - "@inquirer/editor": ["@inquirer/editor@4.2.9", "", { "dependencies": { "@inquirer/core": "^10.1.9", "@inquirer/type": "^3.0.5", "external-editor": "^3.1.0" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-8HjOppAxO7O4wV1ETUlJFg6NDjp/W2NP5FB9ZPAcinAlNT4ZIWOLe2pUVwmmPRSV0NMdI5r/+lflN55AwZOKSw=="], - - "@inquirer/expand": ["@inquirer/expand@4.0.11", "", { "dependencies": { "@inquirer/core": "^10.1.9", "@inquirer/type": "^3.0.5", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-OZSUW4hFMW2TYvX/Sv+NnOZgO8CHT2TU1roUCUIF2T+wfw60XFRRp9MRUPCT06cRnKL+aemt2YmTWwt7rOrNEA=="], - - "@inquirer/figures": ["@inquirer/figures@1.0.11", "", {}, "sha512-eOg92lvrn/aRUqbxRyvpEWnrvRuTYRifixHkYVpJiygTgVSBIHDqLh0SrMQXkafvULg3ck11V7xvR+zcgvpHFw=="], - - "@inquirer/input": ["@inquirer/input@4.1.8", "", { "dependencies": { "@inquirer/core": "^10.1.9", "@inquirer/type": "^3.0.5" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-WXJI16oOZ3/LiENCAxe8joniNp8MQxF6Wi5V+EBbVA0ZIOpFcL4I9e7f7cXse0HJeIPCWO8Lcgnk98juItCi7Q=="], - - "@inquirer/number": ["@inquirer/number@3.0.11", "", { "dependencies": { "@inquirer/core": "^10.1.9", "@inquirer/type": "^3.0.5" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-pQK68CsKOgwvU2eA53AG/4npRTH2pvs/pZ2bFvzpBhrznh8Mcwt19c+nMO7LHRr3Vreu1KPhNBF3vQAKrjIulw=="], - - "@inquirer/password": ["@inquirer/password@4.0.11", "", { "dependencies": { "@inquirer/core": "^10.1.9", "@inquirer/type": "^3.0.5", "ansi-escapes": "^4.3.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-dH6zLdv+HEv1nBs96Case6eppkRggMe8LoOTl30+Gq5Wf27AO/vHFgStTVz4aoevLdNXqwE23++IXGw4eiOXTg=="], - - "@inquirer/prompts": ["@inquirer/prompts@7.3.2", "", { "dependencies": { "@inquirer/checkbox": "^4.1.2", "@inquirer/confirm": "^5.1.6", "@inquirer/editor": "^4.2.7", "@inquirer/expand": "^4.0.9", "@inquirer/input": "^4.1.6", "@inquirer/number": "^3.0.9", "@inquirer/password": "^4.0.9", "@inquirer/rawlist": "^4.0.9", "@inquirer/search": "^3.0.9", "@inquirer/select": "^4.0.9" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-G1ytyOoHh5BphmEBxSwALin3n1KGNYB6yImbICcRQdzXfOGbuJ9Jske/Of5Sebk339NSGGNfUshnzK8YWkTPsQ=="], - - "@inquirer/rawlist": ["@inquirer/rawlist@4.0.11", "", { "dependencies": { "@inquirer/core": "^10.1.9", "@inquirer/type": "^3.0.5", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-uAYtTx0IF/PqUAvsRrF3xvnxJV516wmR6YVONOmCWJbbt87HcDHLfL9wmBQFbNJRv5kCjdYKrZcavDkH3sVJPg=="], - - "@inquirer/search": ["@inquirer/search@3.0.11", "", { "dependencies": { "@inquirer/core": "^10.1.9", "@inquirer/figures": "^1.0.11", "@inquirer/type": "^3.0.5", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-9CWQT0ikYcg6Ls3TOa7jljsD7PgjcsYEM0bYE+Gkz+uoW9u8eaJCRHJKkucpRE5+xKtaaDbrND+nPDoxzjYyew=="], - - "@inquirer/select": ["@inquirer/select@4.1.0", "", { "dependencies": { "@inquirer/core": "^10.1.9", "@inquirer/figures": "^1.0.11", "@inquirer/type": "^3.0.5", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-z0a2fmgTSRN+YBuiK1ROfJ2Nvrpij5lVN3gPDkQGhavdvIVGHGW29LwYZfM/j42Ai2hUghTI/uoBuTbrJk42bA=="], - - "@inquirer/type": ["@inquirer/type@1.5.5", "", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA=="], - - "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], - - "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], - - "@istanbuljs/schema": ["@istanbuljs/schema@0.1.3", "", {}, "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="], - - "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], - - "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], - - "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], - - "@jridgewell/source-map": ["@jridgewell/source-map@0.3.6", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ=="], - - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], - - "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], - - "@jsonjoy.com/base64": ["@jsonjoy.com/base64@1.1.2", "", { "peerDependencies": { "tslib": "2" } }, "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA=="], - - "@jsonjoy.com/json-pack": ["@jsonjoy.com/json-pack@1.2.0", "", { "dependencies": { "@jsonjoy.com/base64": "^1.1.1", "@jsonjoy.com/util": "^1.1.2", "hyperdyperid": "^1.2.0", "thingies": "^1.20.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-io1zEbbYcElht3tdlqEOFxZ0dMTYrHz9iMf0gqn1pPjZFTCgM5R4R5IMA20Chb2UPYYsxjzs8CgZ7Nb5n2K2rA=="], - - "@jsonjoy.com/util": ["@jsonjoy.com/util@1.5.0", "", { "peerDependencies": { "tslib": "2" } }, "sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA=="], - - "@leichtgewicht/ip-codec": ["@leichtgewicht/ip-codec@2.0.5", "", {}, "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw=="], - - "@listr2/prompt-adapter-inquirer": ["@listr2/prompt-adapter-inquirer@2.0.18", "", { "dependencies": { "@inquirer/type": "^1.5.5" }, "peerDependencies": { "@inquirer/prompts": ">= 3 < 8" } }, "sha512-0hz44rAcrphyXcA8IS7EJ2SCoaBZD2u5goE8S/e+q/DL+dOGpqpcLidVOFeLG3VgML62SXmfRLAhWt0zL1oW4Q=="], - - "@lmdb/lmdb-darwin-arm64": ["@lmdb/lmdb-darwin-arm64@3.2.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-yF/ih9EJJZc72psFQbwnn8mExIWfTnzWJg+N02hnpXtDPETYLmQswIMBn7+V88lfCaFrMozJsUvcEQIkEPU0Gg=="], - - "@lmdb/lmdb-darwin-x64": ["@lmdb/lmdb-darwin-x64@3.2.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-5BbCumsFLbCi586Bb1lTWQFkekdQUw8/t8cy++Uq251cl3hbDIGEwD9HAwh8H6IS2F6QA9KdKmO136LmipRNkg=="], - - "@lmdb/lmdb-linux-arm": ["@lmdb/lmdb-linux-arm@3.2.6", "", { "os": "linux", "cpu": "arm" }, "sha512-+6XgLpMb7HBoWxXj+bLbiiB4s0mRRcDPElnRS3LpWRzdYSe+gFk5MT/4RrVNqd2MESUDmb53NUXw1+BP69bjiQ=="], - - "@lmdb/lmdb-linux-arm64": ["@lmdb/lmdb-linux-arm64@3.2.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-l5VmJamJ3nyMmeD1ANBQCQqy7do1ESaJQfKPSm2IG9/ADZryptTyCj8N6QaYgIWewqNUrcbdMkJajRQAt5Qjfg=="], - - "@lmdb/lmdb-linux-x64": ["@lmdb/lmdb-linux-x64@3.2.6", "", { "os": "linux", "cpu": "x64" }, "sha512-nDYT8qN9si5+onHYYaI4DiauDMx24OAiuZAUsEqrDy+ja/3EbpXPX/VAkMV8AEaQhy3xc4dRC+KcYIvOFefJ4Q=="], - - "@lmdb/lmdb-win32-x64": ["@lmdb/lmdb-win32-x64@3.2.6", "", { "os": "win32", "cpu": "x64" }, "sha512-XlqVtILonQnG+9fH2N3Aytria7P/1fwDgDhl29rde96uH2sLB8CHORIf2PfuLVzFQJ7Uqp8py9AYwr3ZUCFfWg=="], - - "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw=="], - - "@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw=="], - - "@msgpackr-extract/msgpackr-extract-linux-arm": ["@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3", "", { "os": "linux", "cpu": "arm" }, "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw=="], - - "@msgpackr-extract/msgpackr-extract-linux-arm64": ["@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg=="], - - "@msgpackr-extract/msgpackr-extract-linux-x64": ["@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3", "", { "os": "linux", "cpu": "x64" }, "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg=="], - - "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ=="], - - "@napi-rs/nice": ["@napi-rs/nice@1.0.1", "", { "optionalDependencies": { "@napi-rs/nice-android-arm-eabi": "1.0.1", "@napi-rs/nice-android-arm64": "1.0.1", "@napi-rs/nice-darwin-arm64": "1.0.1", "@napi-rs/nice-darwin-x64": "1.0.1", "@napi-rs/nice-freebsd-x64": "1.0.1", "@napi-rs/nice-linux-arm-gnueabihf": "1.0.1", "@napi-rs/nice-linux-arm64-gnu": "1.0.1", "@napi-rs/nice-linux-arm64-musl": "1.0.1", "@napi-rs/nice-linux-ppc64-gnu": "1.0.1", "@napi-rs/nice-linux-riscv64-gnu": "1.0.1", "@napi-rs/nice-linux-s390x-gnu": "1.0.1", "@napi-rs/nice-linux-x64-gnu": "1.0.1", "@napi-rs/nice-linux-x64-musl": "1.0.1", "@napi-rs/nice-win32-arm64-msvc": "1.0.1", "@napi-rs/nice-win32-ia32-msvc": "1.0.1", "@napi-rs/nice-win32-x64-msvc": "1.0.1" } }, "sha512-zM0mVWSXE0a0h9aKACLwKmD6nHcRiKrPpCfvaKqG1CqDEyjEawId0ocXxVzPMCAm6kkWr2P025msfxXEnt8UGQ=="], - - "@napi-rs/nice-android-arm-eabi": ["@napi-rs/nice-android-arm-eabi@1.0.1", "", { "os": "android", "cpu": "arm" }, "sha512-5qpvOu5IGwDo7MEKVqqyAxF90I6aLj4n07OzpARdgDRfz8UbBztTByBp0RC59r3J1Ij8uzYi6jI7r5Lws7nn6w=="], - - "@napi-rs/nice-android-arm64": ["@napi-rs/nice-android-arm64@1.0.1", "", { "os": "android", "cpu": "arm64" }, "sha512-GqvXL0P8fZ+mQqG1g0o4AO9hJjQaeYG84FRfZaYjyJtZZZcMjXW5TwkL8Y8UApheJgyE13TQ4YNUssQaTgTyvA=="], - - "@napi-rs/nice-darwin-arm64": ["@napi-rs/nice-darwin-arm64@1.0.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-91k3HEqUl2fsrz/sKkuEkscj6EAj3/eZNCLqzD2AA0TtVbkQi8nqxZCZDMkfklULmxLkMxuUdKe7RvG/T6s2AA=="], - - "@napi-rs/nice-darwin-x64": ["@napi-rs/nice-darwin-x64@1.0.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-jXnMleYSIR/+TAN/p5u+NkCA7yidgswx5ftqzXdD5wgy/hNR92oerTXHc0jrlBisbd7DpzoaGY4cFD7Sm5GlgQ=="], - - "@napi-rs/nice-freebsd-x64": ["@napi-rs/nice-freebsd-x64@1.0.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-j+iJ/ezONXRQsVIB/FJfwjeQXX7A2tf3gEXs4WUGFrJjpe/z2KB7sOv6zpkm08PofF36C9S7wTNuzHZ/Iiccfw=="], - - "@napi-rs/nice-linux-arm-gnueabihf": ["@napi-rs/nice-linux-arm-gnueabihf@1.0.1", "", { "os": "linux", "cpu": "arm" }, "sha512-G8RgJ8FYXYkkSGQwywAUh84m946UTn6l03/vmEXBYNJxQJcD+I3B3k5jmjFG/OPiU8DfvxutOP8bi+F89MCV7Q=="], - - "@napi-rs/nice-linux-arm64-gnu": ["@napi-rs/nice-linux-arm64-gnu@1.0.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-IMDak59/W5JSab1oZvmNbrms3mHqcreaCeClUjwlwDr0m3BoR09ZiN8cKFBzuSlXgRdZ4PNqCYNeGQv7YMTjuA=="], - - "@napi-rs/nice-linux-arm64-musl": ["@napi-rs/nice-linux-arm64-musl@1.0.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-wG8fa2VKuWM4CfjOjjRX9YLIbysSVV1S3Kgm2Fnc67ap/soHBeYZa6AGMeR5BJAylYRjnoVOzV19Cmkco3QEPw=="], - - "@napi-rs/nice-linux-ppc64-gnu": ["@napi-rs/nice-linux-ppc64-gnu@1.0.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-lxQ9WrBf0IlNTCA9oS2jg/iAjQyTI6JHzABV664LLrLA/SIdD+I1i3Mjf7TsnoUbgopBcCuDztVLfJ0q9ubf6Q=="], - - "@napi-rs/nice-linux-riscv64-gnu": ["@napi-rs/nice-linux-riscv64-gnu@1.0.1", "", { "os": "linux", "cpu": "none" }, "sha512-3xs69dO8WSWBb13KBVex+yvxmUeEsdWexxibqskzoKaWx9AIqkMbWmE2npkazJoopPKX2ULKd8Fm9veEn0g4Ig=="], - - "@napi-rs/nice-linux-s390x-gnu": ["@napi-rs/nice-linux-s390x-gnu@1.0.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-lMFI3i9rlW7hgToyAzTaEybQYGbQHDrpRkg+1gJWEpH0PLAQoZ8jiY0IzakLfNWnVda1eTYYlxxFYzW8Rqczkg=="], - - "@napi-rs/nice-linux-x64-gnu": ["@napi-rs/nice-linux-x64-gnu@1.0.1", "", { "os": "linux", "cpu": "x64" }, "sha512-XQAJs7DRN2GpLN6Fb+ZdGFeYZDdGl2Fn3TmFlqEL5JorgWKrQGRUrpGKbgZ25UeZPILuTKJ+OowG2avN8mThBA=="], - - "@napi-rs/nice-linux-x64-musl": ["@napi-rs/nice-linux-x64-musl@1.0.1", "", { "os": "linux", "cpu": "x64" }, "sha512-/rodHpRSgiI9o1faq9SZOp/o2QkKQg7T+DK0R5AkbnI/YxvAIEHf2cngjYzLMQSQgUhxym+LFr+UGZx4vK4QdQ=="], - - "@napi-rs/nice-win32-arm64-msvc": ["@napi-rs/nice-win32-arm64-msvc@1.0.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-rEcz9vZymaCB3OqEXoHnp9YViLct8ugF+6uO5McifTedjq4QMQs3DHz35xBEGhH3gJWEsXMUbzazkz5KNM5YUg=="], - - "@napi-rs/nice-win32-ia32-msvc": ["@napi-rs/nice-win32-ia32-msvc@1.0.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-t7eBAyPUrWL8su3gDxw9xxxqNwZzAqKo0Szv3IjVQd1GpXXVkb6vBBQUuxfIYaXMzZLwlxRQ7uzM2vdUE9ULGw=="], - - "@napi-rs/nice-win32-x64-msvc": ["@napi-rs/nice-win32-x64-msvc@1.0.1", "", { "os": "win32", "cpu": "x64" }, "sha512-JlF+uDcatt3St2ntBG8H02F1mM45i5SF9W+bIKiReVE6wiy3o16oBP/yxt+RZ+N6LbCImJXJ6bXNO2kn9AXicg=="], - - "@ngtools/webpack": ["@ngtools/webpack@19.2.6", "", { "peerDependencies": { "@angular/compiler-cli": "^19.0.0 || ^19.2.0-next.0", "typescript": ">=5.5 <5.9", "webpack": "^5.54.0" } }, "sha512-/jWpZUoMru3YbRJAPZ2KroUSzE6Ak5Hav219raYQaBXVtyLAvFE5VC1/CiH0wTYnb/dyjxzWq38ftOr/vv0+tg=="], - - "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], - - "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], - - "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - - "@npmcli/agent": ["@npmcli/agent@3.0.0", "", { "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^10.0.1", "socks-proxy-agent": "^8.0.3" } }, "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q=="], - - "@npmcli/fs": ["@npmcli/fs@4.0.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q=="], - - "@npmcli/git": ["@npmcli/git@6.0.3", "", { "dependencies": { "@npmcli/promise-spawn": "^8.0.0", "ini": "^5.0.0", "lru-cache": "^10.0.1", "npm-pick-manifest": "^10.0.0", "proc-log": "^5.0.0", "promise-retry": "^2.0.1", "semver": "^7.3.5", "which": "^5.0.0" } }, "sha512-GUYESQlxZRAdhs3UhbB6pVRNUELQOHXwK9ruDkwmCv2aZ5y0SApQzUJCg02p3A7Ue2J5hxvlk1YI53c00NmRyQ=="], - - "@npmcli/installed-package-contents": ["@npmcli/installed-package-contents@3.0.0", "", { "dependencies": { "npm-bundled": "^4.0.0", "npm-normalize-package-bin": "^4.0.0" }, "bin": { "installed-package-contents": "bin/index.js" } }, "sha512-fkxoPuFGvxyrH+OQzyTkX2LUEamrF4jZSmxjAtPPHHGO0dqsQ8tTKjnIS8SAnPHdk2I03BDtSMR5K/4loKg79Q=="], - - "@npmcli/node-gyp": ["@npmcli/node-gyp@4.0.0", "", {}, "sha512-+t5DZ6mO/QFh78PByMq1fGSAub/agLJZDRfJRMeOSNCt8s9YVlTjmGpIPwPhvXTGUIJk+WszlT0rQa1W33yzNA=="], - - "@npmcli/package-json": ["@npmcli/package-json@6.1.1", "", { "dependencies": { "@npmcli/git": "^6.0.0", "glob": "^10.2.2", "hosted-git-info": "^8.0.0", "json-parse-even-better-errors": "^4.0.0", "proc-log": "^5.0.0", "semver": "^7.5.3", "validate-npm-package-license": "^3.0.4" } }, "sha512-d5qimadRAUCO4A/Txw71VM7UrRZzV+NPclxz/dc+M6B2oYwjWTjqh8HA/sGQgs9VZuJ6I/P7XIAlJvgrl27ZOw=="], - - "@npmcli/promise-spawn": ["@npmcli/promise-spawn@8.0.2", "", { "dependencies": { "which": "^5.0.0" } }, "sha512-/bNJhjc+o6qL+Dwz/bqfTQClkEO5nTQ1ZEcdCkAQjhkZMHIh22LPG7fNh1enJP1NKWDqYiiABnjFCY7E0zHYtQ=="], - - "@npmcli/redact": ["@npmcli/redact@3.1.1", "", {}, "sha512-3Hc2KGIkrvJWJqTbvueXzBeZlmvoOxc2jyX00yzr3+sNFquJg0N8hH4SAPLPVrkWIRQICVpVgjrss971awXVnA=="], - - "@npmcli/run-script": ["@npmcli/run-script@9.1.0", "", { "dependencies": { "@npmcli/node-gyp": "^4.0.0", "@npmcli/package-json": "^6.0.0", "@npmcli/promise-spawn": "^8.0.0", "node-gyp": "^11.0.0", "proc-log": "^5.0.0", "which": "^5.0.0" } }, "sha512-aoNSbxtkePXUlbZB+anS1LqsJdctG5n3UVhfU47+CDdwMi6uNTBMF9gPcQRnqghQd2FGzcwwIFBruFMxjhBewg=="], - - "@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="], - - "@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.1", "", { "os": "android", "cpu": "arm64" }, "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA=="], - - "@parcel/watcher-darwin-arm64": ["@parcel/watcher-darwin-arm64@2.5.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw=="], - - "@parcel/watcher-darwin-x64": ["@parcel/watcher-darwin-x64@2.5.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg=="], - - "@parcel/watcher-freebsd-x64": ["@parcel/watcher-freebsd-x64@2.5.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ=="], - - "@parcel/watcher-linux-arm-glibc": ["@parcel/watcher-linux-arm-glibc@2.5.1", "", { "os": "linux", "cpu": "arm" }, "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA=="], - - "@parcel/watcher-linux-arm-musl": ["@parcel/watcher-linux-arm-musl@2.5.1", "", { "os": "linux", "cpu": "arm" }, "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q=="], - - "@parcel/watcher-linux-arm64-glibc": ["@parcel/watcher-linux-arm64-glibc@2.5.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w=="], - - "@parcel/watcher-linux-arm64-musl": ["@parcel/watcher-linux-arm64-musl@2.5.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg=="], - - "@parcel/watcher-linux-x64-glibc": ["@parcel/watcher-linux-x64-glibc@2.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A=="], - - "@parcel/watcher-linux-x64-musl": ["@parcel/watcher-linux-x64-musl@2.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg=="], - - "@parcel/watcher-win32-arm64": ["@parcel/watcher-win32-arm64@2.5.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw=="], - - "@parcel/watcher-win32-ia32": ["@parcel/watcher-win32-ia32@2.5.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ=="], - - "@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="], - - "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], - - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.34.8", "", { "os": "android", "cpu": "arm" }, "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw=="], - - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.34.8", "", { "os": "android", "cpu": "arm64" }, "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q=="], - - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.34.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q=="], - - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.34.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw=="], - - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.34.8", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA=="], - - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.34.8", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q=="], - - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.34.8", "", { "os": "linux", "cpu": "arm" }, "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g=="], - - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.34.8", "", { "os": "linux", "cpu": "arm" }, "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA=="], - - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.34.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A=="], - - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.34.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q=="], - - "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.34.8", "", { "os": "linux", "cpu": "none" }, "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ=="], - - "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.34.8", "", { "os": "linux", "cpu": "ppc64" }, "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw=="], - - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.34.8", "", { "os": "linux", "cpu": "none" }, "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw=="], - - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.34.8", "", { "os": "linux", "cpu": "s390x" }, "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA=="], - - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.34.8", "", { "os": "linux", "cpu": "x64" }, "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA=="], - - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.34.8", "", { "os": "linux", "cpu": "x64" }, "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ=="], - - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.34.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ=="], - - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.34.8", "", { "os": "win32", "cpu": "ia32" }, "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w=="], - - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.34.8", "", { "os": "win32", "cpu": "x64" }, "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g=="], - - "@schematics/angular": ["@schematics/angular@19.2.6", "", { "dependencies": { "@angular-devkit/core": "19.2.6", "@angular-devkit/schematics": "19.2.6", "jsonc-parser": "3.3.1" } }, "sha512-fmbF9ONmEZqxHocCwOSWG2mHp4a22d1uW+DZUBUgZSBUFIrnFw42deOxDq8mkZOZ1Tc73UpLN2GKI7iJeUqS2A=="], - - "@sigstore/bundle": ["@sigstore/bundle@3.1.0", "", { "dependencies": { "@sigstore/protobuf-specs": "^0.4.0" } }, "sha512-Mm1E3/CmDDCz3nDhFKTuYdB47EdRFRQMOE/EAbiG1MJW77/w1b3P7Qx7JSrVJs8PfwOLOVcKQCHErIwCTyPbag=="], - - "@sigstore/core": ["@sigstore/core@2.0.0", "", {}, "sha512-nYxaSb/MtlSI+JWcwTHQxyNmWeWrUXJJ/G4liLrGG7+tS4vAz6LF3xRXqLH6wPIVUoZQel2Fs4ddLx4NCpiIYg=="], - - "@sigstore/protobuf-specs": ["@sigstore/protobuf-specs@0.4.0", "", {}, "sha512-o09cLSIq9EKyRXwryWDOJagkml9XgQCoCSRjHOnHLnvsivaW7Qznzz6yjfV7PHJHhIvyp8OH7OX8w0Dc5bQK7A=="], - - "@sigstore/sign": ["@sigstore/sign@3.1.0", "", { "dependencies": { "@sigstore/bundle": "^3.1.0", "@sigstore/core": "^2.0.0", "@sigstore/protobuf-specs": "^0.4.0", "make-fetch-happen": "^14.0.2", "proc-log": "^5.0.0", "promise-retry": "^2.0.1" } }, "sha512-knzjmaOHOov1Ur7N/z4B1oPqZ0QX5geUfhrVaqVlu+hl0EAoL4o+l0MSULINcD5GCWe3Z0+YJO8ues6vFlW0Yw=="], - - "@sigstore/tuf": ["@sigstore/tuf@3.1.0", "", { "dependencies": { "@sigstore/protobuf-specs": "^0.4.0", "tuf-js": "^3.0.1" } }, "sha512-suVMQEA+sKdOz5hwP9qNcEjX6B45R+hFFr4LAWzbRc5O+U2IInwvay/bpG5a4s+qR35P/JK/PiKiRGjfuLy1IA=="], - - "@sigstore/verify": ["@sigstore/verify@2.1.0", "", { "dependencies": { "@sigstore/bundle": "^3.1.0", "@sigstore/core": "^2.0.0", "@sigstore/protobuf-specs": "^0.4.0" } }, "sha512-kAAM06ca4CzhvjIZdONAL9+MLppW3K48wOFy1TbuaWFW/OMfl8JuTgW0Bm02JB1WJGT/ET2eqav0KTEKmxqkIA=="], - - "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@2.3.0", "", {}, "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg=="], - - "@socket.io/component-emitter": ["@socket.io/component-emitter@3.1.2", "", {}, "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA=="], - - "@stripe/stripe-js": ["@stripe/stripe-js@7.0.0", "", {}, "sha512-0AWkP+hoIXB5O34FGY7jh687ZPlOqLqMkJDkiSXcp4TaWWidnxjsZSp0xkjyAWbIz4+j1BFXDAK01Rqb7ceBRA=="], - - "@tailwindcss/node": ["@tailwindcss/node@4.1.1", "", { "dependencies": { "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.29.2", "tailwindcss": "4.1.1" } }, "sha512-xvlh4pvfG/bkv0fEtJDABAm1tjtSmSyi2QmS4zyj1EKNI1UiOYiUq1IphSwDsNJ5vJ9cWEGs4rJXpUdCN2kujQ=="], - - "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.1", "@tailwindcss/oxide-darwin-arm64": "4.1.1", "@tailwindcss/oxide-darwin-x64": "4.1.1", "@tailwindcss/oxide-freebsd-x64": "4.1.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.1", "@tailwindcss/oxide-linux-arm64-musl": "4.1.1", "@tailwindcss/oxide-linux-x64-gnu": "4.1.1", "@tailwindcss/oxide-linux-x64-musl": "4.1.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.1", "@tailwindcss/oxide-win32-x64-msvc": "4.1.1" } }, "sha512-7+YBgnPQ4+jv6B6WVOerJ6WOzDzNJXrRKDts674v6TKAqFqYRr9+EBtSziO7nNcwQ8JtoZNMeqA+WJDjtCM/7w=="], - - "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.1", "", { "os": "android", "cpu": "arm64" }, "sha512-gTyRzfdParpoCU1yyUC/iN6XK6T0Ra4bDlF8Aeul5NP9cLzKEZDogdNVNGv5WZmCDkVol7qlex7TMmcfytMmmw=="], - - "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-dI0QbdMWBvLB3MtaTKetzUKG9CUUQow8JSP4Nm+OxVokeZ+N+f1OmZW/hW1LzMxpx9RQCBgSRL+IIvKRat5Wdg=="], - - "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-2Y+NPQOTRBCItshPgY/CWg4bKi7E9evMg4bgdb6h9iZObCZLOe3doPcuSxGS3DB0dKyMFKE8pTdWtFUbxZBMSA=="], - - "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-N97NGMsB/7CHShbc5ube4dcsW/bYENkBrg8yWi8ieN9boYVRdw3cZviVryV/Nfu9bKbBV9kUvduFF2qBI7rEqg=="], - - "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.1", "", { "os": "linux", "cpu": "arm" }, "sha512-33Lk6KbHnUZbXqza6RWNFo9wqPQ4+H5BAn1CkUUfC1RZ1vYbyDN6+iJPj53wmnWJ3mhRI8jWt3Jt1fO02IVdUQ=="], - - "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-LyW35RzSUy+80WYScv03HKasAUmMFDaSbNpWfk1gG5gEE9kuRGnDzSrqMoLAmY/kzMCYP/1kqmUiAx8EFLkI2A=="], - - "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-1KPnDMlHdqjPTUSFjx55pafvs8RZXRgxfeRgUrukwDKkuj7gFk28vW3Mx65YdiugAc9NWs3VgueZWaM1Po6uGw=="], - - "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-4WdzA+MRlsinEEE6yxNMLJxpw0kE9XVipbAKdTL8BeUpyC2TdA3TL46lBulXzKp3BIxh3nqyR/UCqzl5o+3waQ=="], - - "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-q7Ugbw3ARcjCW2VMUYrcMbJ6aMQuWPArBBE2EqC/swPZTdGADvMQSlvR0VKusUM4HoSsO7ZbvcZ53YwR57+AKw=="], - - "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-0KpqsovgHcIzm7eAGzzEZsEs0/nPYXnRBv+aPq/GehpNQuE/NAQu+YgZXIIof+VflDFuyXOEnaFr7T5MZ1INhA=="], - - "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.1", "", { "os": "win32", "cpu": "x64" }, "sha512-B1mjeXNS26kBOHv5sXARf6Wd0PWHV9x1TDlW0ummrBUOUAxAy5wcy4Nii1wzNvCdvC448hgiL06ylhwAbNthmg=="], - - "@tailwindcss/postcss": ["@tailwindcss/postcss@4.1.1", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.1.1", "@tailwindcss/oxide": "4.1.1", "postcss": "^8.4.41", "tailwindcss": "4.1.1" } }, "sha512-GX9AEM+msH0i2Yh1b6CuDRaZRo3kmbvIrLbSfvJ53C3uaAgsQ//fTQAh9HMQ6t1a9zvoUptlYqG//plWsBQTCw=="], - - "@tufjs/canonical-json": ["@tufjs/canonical-json@2.0.0", "", {}, "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA=="], - - "@tufjs/models": ["@tufjs/models@3.0.1", "", { "dependencies": { "@tufjs/canonical-json": "2.0.0", "minimatch": "^9.0.5" } }, "sha512-UUYHISyhCU3ZgN8yaear3cGATHb3SMuKHsQ/nVbHXcmnBf+LzQ/cQfhNG+rfaSHgqGKNEm2cOCLVLELStUQ1JA=="], - - "@types/body-parser": ["@types/body-parser@1.19.5", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg=="], - - "@types/bonjour": ["@types/bonjour@3.5.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ=="], - - "@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="], - - "@types/connect-history-api-fallback": ["@types/connect-history-api-fallback@1.5.4", "", { "dependencies": { "@types/express-serve-static-core": "*", "@types/node": "*" } }, "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw=="], - - "@types/cors": ["@types/cors@2.8.17", "", { "dependencies": { "@types/node": "*" } }, "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA=="], - - "@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="], - - "@types/eslint-scope": ["@types/eslint-scope@3.7.7", "", { "dependencies": { "@types/eslint": "*", "@types/estree": "*" } }, "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg=="], - - "@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="], - - "@types/express": ["@types/express@4.17.21", "", { "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "*" } }, "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ=="], - - "@types/express-serve-static-core": ["@types/express-serve-static-core@5.0.6", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA=="], - - "@types/http-errors": ["@types/http-errors@2.0.4", "", {}, "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA=="], - - "@types/http-proxy": ["@types/http-proxy@1.17.16", "", { "dependencies": { "@types/node": "*" } }, "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w=="], - - "@types/jasmine": ["@types/jasmine@5.1.7", "", {}, "sha512-DVOfk9FaClQfNFpSfaML15jjB5cjffDMvjtph525sroR5BEAW2uKnTOYUTqTFuZFjNvH0T5XMIydvIctnUKufw=="], - - "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], - - "@types/mime": ["@types/mime@1.3.5", "", {}, "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="], - - "@types/node": ["@types/node@22.14.0", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA=="], - - "@types/node-forge": ["@types/node-forge@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ=="], - - "@types/qs": ["@types/qs@6.9.18", "", {}, "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA=="], - - "@types/range-parser": ["@types/range-parser@1.2.7", "", {}, "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="], - - "@types/retry": ["@types/retry@0.12.2", "", {}, "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow=="], - - "@types/send": ["@types/send@0.17.4", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA=="], - - "@types/serve-index": ["@types/serve-index@1.9.4", "", { "dependencies": { "@types/express": "*" } }, "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug=="], - - "@types/serve-static": ["@types/serve-static@1.15.7", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*", "@types/send": "*" } }, "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw=="], - - "@types/sockjs": ["@types/sockjs@0.3.36", "", { "dependencies": { "@types/node": "*" } }, "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q=="], - - "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], - - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.33.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.33.1", "@typescript-eslint/type-utils": "8.33.1", "@typescript-eslint/utils": "8.33.1", "@typescript-eslint/visitor-keys": "8.33.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.33.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A=="], - - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.33.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.33.1", "@typescript-eslint/types": "8.33.1", "@typescript-eslint/typescript-estree": "8.33.1", "@typescript-eslint/visitor-keys": "8.33.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA=="], - - "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.33.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.33.0", "@typescript-eslint/types": "^8.33.0", "debug": "^4.3.4" } }, "sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A=="], - - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.33.0", "", { "dependencies": { "@typescript-eslint/types": "8.33.0", "@typescript-eslint/visitor-keys": "8.33.0" } }, "sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw=="], - - "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.33.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug=="], - - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.33.1", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.33.1", "@typescript-eslint/utils": "8.33.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww=="], - - "@typescript-eslint/types": ["@typescript-eslint/types@8.33.0", "", {}, "sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg=="], - - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.33.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.33.0", "@typescript-eslint/tsconfig-utils": "8.33.0", "@typescript-eslint/types": "8.33.0", "@typescript-eslint/visitor-keys": "8.33.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ=="], - - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.33.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.33.0", "@typescript-eslint/types": "8.33.0", "@typescript-eslint/typescript-estree": "8.33.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw=="], - - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.33.1", "", { "dependencies": { "@typescript-eslint/types": "8.33.1", "eslint-visitor-keys": "^4.2.0" } }, "sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ=="], - - "@vitejs/plugin-basic-ssl": ["@vitejs/plugin-basic-ssl@1.2.0", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" } }, "sha512-mkQnxTkcldAzIsomk1UuLfAu9n+kpQ3JbHcpCp7d2Oo6ITtji8pHS3QToOWjhPFvNQSnhlkAjmGbhv2QvwO/7Q=="], - - "@webassemblyjs/ast": ["@webassemblyjs/ast@1.14.1", "", { "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ=="], - - "@webassemblyjs/floating-point-hex-parser": ["@webassemblyjs/floating-point-hex-parser@1.13.2", "", {}, "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA=="], - - "@webassemblyjs/helper-api-error": ["@webassemblyjs/helper-api-error@1.13.2", "", {}, "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ=="], - - "@webassemblyjs/helper-buffer": ["@webassemblyjs/helper-buffer@1.14.1", "", {}, "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA=="], - - "@webassemblyjs/helper-numbers": ["@webassemblyjs/helper-numbers@1.13.2", "", { "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA=="], - - "@webassemblyjs/helper-wasm-bytecode": ["@webassemblyjs/helper-wasm-bytecode@1.13.2", "", {}, "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA=="], - - "@webassemblyjs/helper-wasm-section": ["@webassemblyjs/helper-wasm-section@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/wasm-gen": "1.14.1" } }, "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw=="], - - "@webassemblyjs/ieee754": ["@webassemblyjs/ieee754@1.13.2", "", { "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw=="], - - "@webassemblyjs/leb128": ["@webassemblyjs/leb128@1.13.2", "", { "dependencies": { "@xtuc/long": "4.2.2" } }, "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw=="], - - "@webassemblyjs/utf8": ["@webassemblyjs/utf8@1.13.2", "", {}, "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ=="], - - "@webassemblyjs/wasm-edit": ["@webassemblyjs/wasm-edit@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/helper-wasm-section": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-opt": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1", "@webassemblyjs/wast-printer": "1.14.1" } }, "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ=="], - - "@webassemblyjs/wasm-gen": ["@webassemblyjs/wasm-gen@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg=="], - - "@webassemblyjs/wasm-opt": ["@webassemblyjs/wasm-opt@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1" } }, "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw=="], - - "@webassemblyjs/wasm-parser": ["@webassemblyjs/wasm-parser@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ=="], - - "@webassemblyjs/wast-printer": ["@webassemblyjs/wast-printer@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw=="], - - "@xtuc/ieee754": ["@xtuc/ieee754@1.2.0", "", {}, "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="], - - "@xtuc/long": ["@xtuc/long@4.2.2", "", {}, "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="], - - "@yarnpkg/lockfile": ["@yarnpkg/lockfile@1.1.0", "", {}, "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ=="], - - "abbrev": ["abbrev@3.0.0", "", {}, "sha512-+/kfrslGQ7TNV2ecmQwMJj/B65g5KVq1/L3SGVZ3tCYGqlzFuFCGBZJtMP99wH3NpEUyAjn0zPdPUg0D+DwrOA=="], - - "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], - - "acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], - - "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], - - "adjust-sourcemap-loader": ["adjust-sourcemap-loader@4.0.0", "", { "dependencies": { "loader-utils": "^2.0.0", "regex-parser": "^2.2.11" } }, "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A=="], - - "agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="], - - "ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], - - "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], - - "ajv-keywords": ["ajv-keywords@5.1.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3" }, "peerDependencies": { "ajv": "^8.8.2" } }, "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw=="], - - "angular-eslint": ["angular-eslint@19.7.0", "", { "dependencies": { "@angular-devkit/core": ">= 19.0.0 < 20.0.0", "@angular-devkit/schematics": ">= 19.0.0 < 20.0.0", "@angular-eslint/builder": "19.7.0", "@angular-eslint/eslint-plugin": "19.7.0", "@angular-eslint/eslint-plugin-template": "19.7.0", "@angular-eslint/schematics": "19.7.0", "@angular-eslint/template-parser": "19.7.0", "@typescript-eslint/types": "^8.0.0", "@typescript-eslint/utils": "^8.0.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": "*", "typescript-eslint": "^8.0.0" } }, "sha512-ujlc8CR40RYEWUctpVEg41ZCtmKnWeJH0mzORhzf0NVZb6FLhoNhmDPr1byw4Bcxzl0DAoNgKBhJymt6FNL6Rw=="], - - "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], - - "ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="], - - "ansi-html-community": ["ansi-html-community@0.0.8", "", { "bin": { "ansi-html": "bin/ansi-html" } }, "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw=="], - - "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], - - "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - - "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], - - "array-flatten": ["array-flatten@1.1.1", "", {}, "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="], - - "autoprefixer": ["autoprefixer@10.4.20", "", { "dependencies": { "browserslist": "^4.23.3", "caniuse-lite": "^1.0.30001646", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.0.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g=="], - - "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], - - "babel-loader": ["babel-loader@9.2.1", "", { "dependencies": { "find-cache-dir": "^4.0.0", "schema-utils": "^4.0.0" }, "peerDependencies": { "@babel/core": "^7.12.0", "webpack": ">=5" } }, "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA=="], - - "babel-plugin-polyfill-corejs2": ["babel-plugin-polyfill-corejs2@0.4.13", "", { "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.6.4", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g=="], - - "babel-plugin-polyfill-corejs3": ["babel-plugin-polyfill-corejs3@0.11.1", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.3", "core-js-compat": "^3.40.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ=="], - - "babel-plugin-polyfill-regenerator": ["babel-plugin-polyfill-regenerator@0.6.4", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.4" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw=="], - - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - - "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], - - "base64id": ["base64id@2.0.0", "", {}, "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="], - - "batch": ["batch@0.6.1", "", {}, "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw=="], - - "beasties": ["beasties@0.2.0", "", { "dependencies": { "css-select": "^5.1.0", "css-what": "^6.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "htmlparser2": "^9.1.0", "picocolors": "^1.1.1", "postcss": "^8.4.49", "postcss-media-query-parser": "^0.2.3" } }, "sha512-Ljqskqx/tbZagIglYoJIMzH5zgssyp+in9+9sAyh15N22AornBeIDnb8EZ6Rk+6ShfMxd92uO3gfpT0NtZbpow=="], - - "big.js": ["big.js@5.2.2", "", {}, "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="], - - "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], - - "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], - - "body-parser": ["body-parser@1.20.3", "", { "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" } }, "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g=="], - - "bonjour-service": ["bonjour-service@1.3.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" } }, "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA=="], - - "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], - - "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], - - "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], - - "browserslist": ["browserslist@4.24.4", "", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A=="], - - "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], - - "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], - - "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], - - "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], - - "cacache": ["cacache@19.0.1", "", { "dependencies": { "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^7.0.2", "ssri": "^12.0.0", "tar": "^7.4.3", "unique-filename": "^4.0.0" } }, "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ=="], - - "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], - - "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], - - "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - - "caniuse-lite": ["caniuse-lite@1.0.30001709", "", {}, "sha512-NgL3vUTnDrPCZ3zTahp4fsugQ4dc7EKTSzwQDPEel6DMoMnfH2jhry9n2Zm8onbSR+f/QtKHFOA+iAQu4kbtWA=="], - - "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "chardet": ["chardet@0.7.0", "", {}, "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="], - - "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], - - "chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], - - "chrome-trace-event": ["chrome-trace-event@1.0.4", "", {}, "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ=="], - - "cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="], - - "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], - - "cli-truncate": ["cli-truncate@4.0.0", "", { "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" } }, "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA=="], - - "cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="], - - "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], - - "clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="], - - "clone-deep": ["clone-deep@4.0.1", "", { "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", "shallow-clone": "^3.0.0" } }, "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ=="], - - "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], - - "commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], - - "common-path-prefix": ["common-path-prefix@3.0.0", "", {}, "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w=="], - - "compressible": ["compressible@2.0.18", "", { "dependencies": { "mime-db": ">= 1.43.0 < 2" } }, "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg=="], - - "compression": ["compression@1.8.0", "", { "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", "on-headers": "~1.0.2", "safe-buffer": "5.2.1", "vary": "~1.1.2" } }, "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA=="], - - "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], - - "connect": ["connect@3.7.0", "", { "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.2", "parseurl": "~1.3.3", "utils-merge": "1.0.1" } }, "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ=="], - - "connect-history-api-fallback": ["connect-history-api-fallback@2.0.0", "", {}, "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA=="], - - "content-disposition": ["content-disposition@0.5.4", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ=="], - - "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], - - "convert-source-map": ["convert-source-map@1.9.0", "", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="], - - "cookie": ["cookie@0.7.1", "", {}, "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w=="], - - "cookie-signature": ["cookie-signature@1.0.6", "", {}, "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="], - - "copy-anything": ["copy-anything@2.0.6", "", { "dependencies": { "is-what": "^3.14.1" } }, "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw=="], - - "copy-webpack-plugin": ["copy-webpack-plugin@12.0.2", "", { "dependencies": { "fast-glob": "^3.3.2", "glob-parent": "^6.0.1", "globby": "^14.0.0", "normalize-path": "^3.0.0", "schema-utils": "^4.2.0", "serialize-javascript": "^6.0.2" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-SNwdBeHyII+rWvee/bTnAYyO8vfVdcSTud4EIb6jcZ8inLeWucJE0DnxXQBjlQ5zlteuuvooGQy3LIyGxhvlOA=="], - - "core-js-compat": ["core-js-compat@3.41.0", "", { "dependencies": { "browserslist": "^4.24.4" } }, "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A=="], - - "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], - - "cors": ["cors@2.8.5", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="], - - "cosmiconfig": ["cosmiconfig@9.0.0", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg=="], - - "countup.js": ["countup.js@2.8.0", "", {}, "sha512-f7xEhX0awl4NOElHulrl4XRfKoNH3rB+qfNSZZyjSZhaAoUk6elvhH+MNxMmlmuUJ2/QNTWPSA7U4mNtIAKljQ=="], - - "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], - - "css-loader": ["css-loader@7.1.2", "", { "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.4.33", "postcss-modules-extract-imports": "^3.1.0", "postcss-modules-local-by-default": "^4.0.5", "postcss-modules-scope": "^3.2.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", "semver": "^7.5.4" }, "peerDependencies": { "@rspack/core": "0.x || 1.x", "webpack": "^5.27.0" }, "optionalPeers": ["@rspack/core", "webpack"] }, "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA=="], - - "css-select": ["css-select@5.1.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg=="], - - "css-what": ["css-what@6.1.0", "", {}, "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="], - - "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], - - "custom-event": ["custom-event@1.0.1", "", {}, "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg=="], - - "date-format": ["date-format@4.0.14", "", {}, "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg=="], - - "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], - - "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], - - "default-browser": ["default-browser@5.2.1", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg=="], - - "default-browser-id": ["default-browser-id@5.0.0", "", {}, "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA=="], - - "defaults": ["defaults@1.0.4", "", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="], - - "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="], - - "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], - - "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="], - - "detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], - - "detect-node": ["detect-node@2.1.0", "", {}, "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="], - - "di": ["di@0.0.1", "", {}, "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA=="], - - "dns-packet": ["dns-packet@5.6.1", "", { "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" } }, "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw=="], - - "dom-serialize": ["dom-serialize@2.2.1", "", { "dependencies": { "custom-event": "~1.0.0", "ent": "~2.2.0", "extend": "^3.0.0", "void-elements": "^2.0.0" } }, "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ=="], - - "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], - - "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], - - "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], - - "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], - - "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], - - "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], - - "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], - - "electron-to-chromium": ["electron-to-chromium@1.5.130", "", {}, "sha512-Ou2u7L9j2XLZbhqzyX0jWDj6gA8D3jIfVzt4rikLf3cGBa0VdReuFimBKS9tQJA4+XpeCxj1NoWlfBXzbMa9IA=="], - - "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "emojis-list": ["emojis-list@3.0.0", "", {}, "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="], - - "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], - - "encoding": ["encoding@0.1.13", "", { "dependencies": { "iconv-lite": "^0.6.2" } }, "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="], - - "engine.io": ["engine.io@6.6.4", "", { "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", "ws": "~8.17.1" } }, "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g=="], - - "engine.io-parser": ["engine.io-parser@5.2.3", "", {}, "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q=="], - - "enhanced-resolve": ["enhanced-resolve@5.18.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg=="], - - "ent": ["ent@2.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "punycode": "^1.4.1", "safe-regex-test": "^1.1.0" } }, "sha512-kKvD1tO6BM+oK9HzCPpUdRb4vKFQY/FPTFmurMvh6LlN68VMrdj77w8yp51/kDbpkFOS9J8w5W6zIzgM2H8/hw=="], - - "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], - - "env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], - - "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="], - - "err-code": ["err-code@2.0.3", "", {}, "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="], - - "errno": ["errno@0.1.8", "", { "dependencies": { "prr": "~1.0.1" }, "bin": { "errno": "cli.js" } }, "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A=="], - - "error-ex": ["error-ex@1.3.2", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="], - - "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], - - "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], - - "es-module-lexer": ["es-module-lexer@1.6.0", "", {}, "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ=="], - - "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], - - "esbuild": ["esbuild@0.25.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.1", "@esbuild/android-arm": "0.25.1", "@esbuild/android-arm64": "0.25.1", "@esbuild/android-x64": "0.25.1", "@esbuild/darwin-arm64": "0.25.1", "@esbuild/darwin-x64": "0.25.1", "@esbuild/freebsd-arm64": "0.25.1", "@esbuild/freebsd-x64": "0.25.1", "@esbuild/linux-arm": "0.25.1", "@esbuild/linux-arm64": "0.25.1", "@esbuild/linux-ia32": "0.25.1", "@esbuild/linux-loong64": "0.25.1", "@esbuild/linux-mips64el": "0.25.1", "@esbuild/linux-ppc64": "0.25.1", "@esbuild/linux-riscv64": "0.25.1", "@esbuild/linux-s390x": "0.25.1", "@esbuild/linux-x64": "0.25.1", "@esbuild/netbsd-arm64": "0.25.1", "@esbuild/netbsd-x64": "0.25.1", "@esbuild/openbsd-arm64": "0.25.1", "@esbuild/openbsd-x64": "0.25.1", "@esbuild/sunos-x64": "0.25.1", "@esbuild/win32-arm64": "0.25.1", "@esbuild/win32-ia32": "0.25.1", "@esbuild/win32-x64": "0.25.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ=="], - - "esbuild-wasm": ["esbuild-wasm@0.25.1", "", { "bin": { "esbuild": "bin/esbuild" } }, "sha512-dZxPeDHcDIQ6ilml/NzYxnPbNkoVsHSFH3JGLSobttc5qYYgExMo8lh2XcB+w+AfiqykVDGK5PWanGB0gWaAWw=="], - - "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], - - "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], - - "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - - "eslint": ["eslint@9.25.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.13.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.25.1", "@eslint/plugin-kit": "^0.2.8", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ=="], - - "eslint-scope": ["eslint-scope@8.3.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ=="], - - "eslint-visitor-keys": ["eslint-visitor-keys@4.2.0", "", {}, "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw=="], - - "espree": ["espree@10.3.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.0" } }, "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg=="], - - "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], - - "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], - - "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], - - "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], - - "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], - - "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], - - "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], - - "exponential-backoff": ["exponential-backoff@3.1.2", "", {}, "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA=="], - - "express": ["express@4.21.2", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.19.0", "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA=="], - - "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], - - "external-editor": ["external-editor@3.1.0", "", { "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" } }, "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew=="], - - "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], - - "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], - - "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], - - "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], - - "fast-uri": ["fast-uri@3.0.6", "", {}, "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw=="], - - "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], - - "faye-websocket": ["faye-websocket@0.11.4", "", { "dependencies": { "websocket-driver": ">=0.5.1" } }, "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g=="], - - "fdir": ["fdir@6.4.3", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw=="], - - "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], - - "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], - - "finalhandler": ["finalhandler@1.1.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" } }, "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA=="], - - "find-cache-dir": ["find-cache-dir@4.0.0", "", { "dependencies": { "common-path-prefix": "^3.0.0", "pkg-dir": "^7.0.0" } }, "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg=="], - - "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], - - "flat": ["flat@5.0.2", "", { "bin": { "flat": "cli.js" } }, "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ=="], - - "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], - - "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], - - "follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="], - - "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], - - "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], - - "fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="], - - "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], - - "fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], - - "fs-minipass": ["fs-minipass@3.0.3", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw=="], - - "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], - - "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - - "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - - "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], - - "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], - - "get-east-asian-width": ["get-east-asian-width@1.3.0", "", {}, "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ=="], - - "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], - - "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], - - "glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - - "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], - - "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], - - "globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], - - "globby": ["globby@14.1.0", "", { "dependencies": { "@sindresorhus/merge-streams": "^2.1.0", "fast-glob": "^3.3.3", "ignore": "^7.0.3", "path-type": "^6.0.0", "slash": "^5.1.0", "unicorn-magic": "^0.3.0" } }, "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA=="], - - "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], - - "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], - - "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], - - "gsap": ["gsap@3.12.7", "", {}, "sha512-V4GsyVamhmKefvcAKaoy0h6si0xX7ogwBoBSs2CTJwt7luW0oZzC0LhdkyuKV8PJAXr7Yaj8pMjCKD4GJ+eEMg=="], - - "handle-thing": ["handle-thing@2.0.1", "", {}, "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg=="], - - "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], - - "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], - - "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], - - "hosted-git-info": ["hosted-git-info@8.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-sYKnA7eGln5ov8T8gnYlkSOxFJvywzEx9BueN6xo/GKO8PGiI6uK6xx+DIGe45T3bdVjLAQDQW1aicT8z8JwQg=="], - - "hpack.js": ["hpack.js@2.1.6", "", { "dependencies": { "inherits": "^2.0.1", "obuf": "^1.0.0", "readable-stream": "^2.0.1", "wbuf": "^1.1.0" } }, "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ=="], - - "html-escaper": ["html-escaper@2.0.2", "", {}, "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="], - - "htmlparser2": ["htmlparser2@9.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.1.0", "entities": "^4.5.0" } }, "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ=="], - - "http-cache-semantics": ["http-cache-semantics@4.1.1", "", {}, "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="], - - "http-deceiver": ["http-deceiver@1.2.7", "", {}, "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw=="], - - "http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], - - "http-parser-js": ["http-parser-js@0.5.9", "", {}, "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw=="], - - "http-proxy": ["http-proxy@1.18.1", "", { "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" } }, "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ=="], - - "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="], - - "http-proxy-middleware": ["http-proxy-middleware@3.0.3", "", { "dependencies": { "@types/http-proxy": "^1.17.15", "debug": "^4.3.6", "http-proxy": "^1.18.1", "is-glob": "^4.0.3", "is-plain-object": "^5.0.0", "micromatch": "^4.0.8" } }, "sha512-usY0HG5nyDUwtqpiZdETNbmKtw3QQ1jwYFZ9wi5iHzX2BcILwQKtYDJPo7XHTsu5Z0B2Hj3W9NNnbd+AjFWjqg=="], - - "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], - - "hyperdyperid": ["hyperdyperid@1.2.0", "", {}, "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A=="], - - "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], - - "icss-utils": ["icss-utils@5.1.0", "", { "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA=="], - - "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], - - "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], - - "ignore-walk": ["ignore-walk@7.0.0", "", { "dependencies": { "minimatch": "^9.0.0" } }, "sha512-T4gbf83A4NH95zvhVYZc+qWocBBGlpzUXLPGurJggw/WIOwicfXJChLDP/iBZnN5WqROSu5Bm3hhle4z8a8YGQ=="], - - "image-size": ["image-size@0.5.5", "", { "bin": { "image-size": "bin/image-size.js" } }, "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ=="], - - "immutable": ["immutable@5.1.1", "", {}, "sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg=="], - - "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], - - "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], - - "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], - - "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], - - "ini": ["ini@5.0.0", "", {}, "sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw=="], - - "ip-address": ["ip-address@9.0.5", "", { "dependencies": { "jsbn": "1.1.0", "sprintf-js": "^1.1.3" } }, "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g=="], - - "ipaddr.js": ["ipaddr.js@2.2.0", "", {}, "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA=="], - - "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], - - "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], - - "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], - - "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], - - "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], - - "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - - "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], - - "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="], - - "is-interactive": ["is-interactive@1.0.0", "", {}, "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="], - - "is-network-error": ["is-network-error@1.1.0", "", {}, "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g=="], - - "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], - - "is-plain-obj": ["is-plain-obj@3.0.0", "", {}, "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA=="], - - "is-plain-object": ["is-plain-object@5.0.0", "", {}, "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="], - - "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="], - - "is-unicode-supported": ["is-unicode-supported@0.1.0", "", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="], - - "is-what": ["is-what@3.14.1", "", {}, "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA=="], - - "is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="], - - "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], - - "isbinaryfile": ["isbinaryfile@4.0.10", "", {}, "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw=="], - - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - - "isobject": ["isobject@3.0.1", "", {}, "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="], - - "istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="], - - "istanbul-lib-instrument": ["istanbul-lib-instrument@6.0.3", "", { "dependencies": { "@babel/core": "^7.23.9", "@babel/parser": "^7.23.9", "@istanbuljs/schema": "^0.1.3", "istanbul-lib-coverage": "^3.2.0", "semver": "^7.5.4" } }, "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q=="], - - "istanbul-lib-report": ["istanbul-lib-report@3.0.1", "", { "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", "supports-color": "^7.1.0" } }, "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw=="], - - "istanbul-lib-source-maps": ["istanbul-lib-source-maps@4.0.1", "", { "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" } }, "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw=="], - - "istanbul-reports": ["istanbul-reports@3.1.7", "", { "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g=="], - - "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], - - "jasmine-core": ["jasmine-core@5.7.1", "", {}, "sha512-QnurrtpKsPoixxG2R3d1xP0St/2kcX5oTZyDyQJMY+Vzi/HUlu1kGm+2V8Tz+9lV991leB1l0xcsyz40s9xOOw=="], - - "jest-worker": ["jest-worker@27.5.1", "", { "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg=="], - - "jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], - - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - - "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], - - "jsbn": ["jsbn@1.1.0", "", {}, "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="], - - "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], - - "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], - - "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], - - "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - - "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], - - "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], - - "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], - - "jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], - - "jsonparse": ["jsonparse@1.3.1", "", {}, "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg=="], - - "karma": ["karma@6.4.4", "", { "dependencies": { "@colors/colors": "1.5.0", "body-parser": "^1.19.0", "braces": "^3.0.2", "chokidar": "^3.5.1", "connect": "^3.7.0", "di": "^0.0.1", "dom-serialize": "^2.2.1", "glob": "^7.1.7", "graceful-fs": "^4.2.6", "http-proxy": "^1.18.1", "isbinaryfile": "^4.0.8", "lodash": "^4.17.21", "log4js": "^6.4.1", "mime": "^2.5.2", "minimatch": "^3.0.4", "mkdirp": "^0.5.5", "qjobs": "^1.2.0", "range-parser": "^1.2.1", "rimraf": "^3.0.2", "socket.io": "^4.7.2", "source-map": "^0.6.1", "tmp": "^0.2.1", "ua-parser-js": "^0.7.30", "yargs": "^16.1.1" }, "bin": { "karma": "bin/karma" } }, "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w=="], - - "karma-chrome-launcher": ["karma-chrome-launcher@3.2.0", "", { "dependencies": { "which": "^1.2.1" } }, "sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q=="], - - "karma-coverage": ["karma-coverage@2.2.1", "", { "dependencies": { "istanbul-lib-coverage": "^3.2.0", "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.1", "istanbul-reports": "^3.0.5", "minimatch": "^3.0.4" } }, "sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A=="], - - "karma-jasmine": ["karma-jasmine@5.1.0", "", { "dependencies": { "jasmine-core": "^4.1.0" }, "peerDependencies": { "karma": "^6.0.0" } }, "sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ=="], - - "karma-jasmine-html-reporter": ["karma-jasmine-html-reporter@2.1.0", "", { "peerDependencies": { "jasmine-core": "^4.0.0 || ^5.0.0", "karma": "^6.0.0", "karma-jasmine": "^5.0.0" } }, "sha512-sPQE1+nlsn6Hwb5t+HHwyy0A1FNCVKuL1192b+XNauMYWThz2kweiBVW1DqloRpVvZIJkIoHVB7XRpK78n1xbQ=="], - - "karma-source-map-support": ["karma-source-map-support@1.4.0", "", { "dependencies": { "source-map-support": "^0.5.5" } }, "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A=="], - - "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], - - "kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="], - - "launch-editor": ["launch-editor@2.10.0", "", { "dependencies": { "picocolors": "^1.0.0", "shell-quote": "^1.8.1" } }, "sha512-D7dBRJo/qcGX9xlvt/6wUYzQxjh5G1RvZPgPv8vi4KRU99DVQL/oW7tnVOCCTm2HGeo3C5HvGE5Yrh6UBoZ0vA=="], - - "less": ["less@4.2.2", "", { "dependencies": { "copy-anything": "^2.0.1", "parse-node-version": "^1.0.1", "tslib": "^2.3.0" }, "optionalDependencies": { "errno": "^0.1.1", "graceful-fs": "^4.1.2", "image-size": "~0.5.0", "make-dir": "^2.1.0", "mime": "^1.4.1", "needle": "^3.1.0", "source-map": "~0.6.0" }, "bin": { "lessc": "bin/lessc" } }, "sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg=="], - - "less-loader": ["less-loader@12.2.0", "", { "peerDependencies": { "@rspack/core": "0.x || 1.x", "less": "^3.5.0 || ^4.0.0", "webpack": "^5.0.0" }, "optionalPeers": ["@rspack/core", "webpack"] }, "sha512-MYUxjSQSBUQmowc0l5nPieOYwMzGPUaTzB6inNW/bdPEG9zOL3eAAD1Qw5ZxSPk7we5dMojHwNODYMV1hq4EVg=="], - - "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], - - "license-webpack-plugin": ["license-webpack-plugin@4.0.2", "", { "dependencies": { "webpack-sources": "^3.0.0" } }, "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw=="], - - "lightningcss": ["lightningcss@1.29.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.29.2", "lightningcss-darwin-x64": "1.29.2", "lightningcss-freebsd-x64": "1.29.2", "lightningcss-linux-arm-gnueabihf": "1.29.2", "lightningcss-linux-arm64-gnu": "1.29.2", "lightningcss-linux-arm64-musl": "1.29.2", "lightningcss-linux-x64-gnu": "1.29.2", "lightningcss-linux-x64-musl": "1.29.2", "lightningcss-win32-arm64-msvc": "1.29.2", "lightningcss-win32-x64-msvc": "1.29.2" } }, "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA=="], - - "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.29.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA=="], - - "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.29.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w=="], - - "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.29.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg=="], - - "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.29.2", "", { "os": "linux", "cpu": "arm" }, "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg=="], - - "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.29.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ=="], - - "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.29.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ=="], - - "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.29.2", "", { "os": "linux", "cpu": "x64" }, "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg=="], - - "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.29.2", "", { "os": "linux", "cpu": "x64" }, "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w=="], - - "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.29.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw=="], - - "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.29.2", "", { "os": "win32", "cpu": "x64" }, "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA=="], - - "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], - - "listr2": ["listr2@8.2.5", "", { "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ=="], - - "lmdb": ["lmdb@3.2.6", "", { "dependencies": { "msgpackr": "^1.11.2", "node-addon-api": "^6.1.0", "node-gyp-build-optional-packages": "5.2.2", "ordered-binary": "^1.5.3", "weak-lru-cache": "^1.2.2" }, "optionalDependencies": { "@lmdb/lmdb-darwin-arm64": "3.2.6", "@lmdb/lmdb-darwin-x64": "3.2.6", "@lmdb/lmdb-linux-arm": "3.2.6", "@lmdb/lmdb-linux-arm64": "3.2.6", "@lmdb/lmdb-linux-x64": "3.2.6", "@lmdb/lmdb-win32-x64": "3.2.6" }, "bin": { "download-lmdb-prebuilds": "bin/download-prebuilds.js" } }, "sha512-SuHqzPl7mYStna8WRotY8XX/EUZBjjv3QyKIByeCLFfC9uXT/OIHByEcA07PzbMfQAM0KYJtLgtpMRlIe5dErQ=="], - - "loader-runner": ["loader-runner@4.3.0", "", {}, "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg=="], - - "loader-utils": ["loader-utils@3.3.1", "", {}, "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg=="], - - "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], - - "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], - - "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="], - - "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], - - "log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="], - - "log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="], - - "log4js": ["log4js@6.9.1", "", { "dependencies": { "date-format": "^4.0.14", "debug": "^4.3.4", "flatted": "^3.2.7", "rfdc": "^1.3.0", "streamroller": "^3.1.5" } }, "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g=="], - - "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], - - "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], - - "make-dir": ["make-dir@2.1.0", "", { "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" } }, "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA=="], - - "make-fetch-happen": ["make-fetch-happen@14.0.3", "", { "dependencies": { "@npmcli/agent": "^3.0.0", "cacache": "^19.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^5.0.0", "promise-retry": "^2.0.1", "ssri": "^12.0.0" } }, "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ=="], - - "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], - - "media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], - - "memfs": ["memfs@4.17.0", "", { "dependencies": { "@jsonjoy.com/json-pack": "^1.0.3", "@jsonjoy.com/util": "^1.3.0", "tree-dump": "^1.0.1", "tslib": "^2.0.0" } }, "sha512-4eirfZ7thblFmqFjywlTmuWVSvccHAJbn1r8qQLzmTO11qcqpohOjmY2mFce6x7x7WtskzRqApPD0hv+Oa74jg=="], - - "merge-descriptors": ["merge-descriptors@1.0.3", "", {}, "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ=="], - - "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], - - "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], - - "methods": ["methods@1.1.2", "", {}, "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="], - - "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], - - "mime": ["mime@2.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="], - - "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - - "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - - "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], - - "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], - - "mini-css-extract-plugin": ["mini-css-extract-plugin@2.9.2", "", { "dependencies": { "schema-utils": "^4.0.0", "tapable": "^2.2.1" }, "peerDependencies": { "webpack": "^5.0.0" } }, "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w=="], - - "minimalistic-assert": ["minimalistic-assert@1.0.1", "", {}, "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="], - - "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - - "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], - - "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], - - "minipass-collect": ["minipass-collect@2.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw=="], - - "minipass-fetch": ["minipass-fetch@4.0.1", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^3.0.1" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ=="], - - "minipass-flush": ["minipass-flush@1.0.5", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw=="], - - "minipass-pipeline": ["minipass-pipeline@1.2.4", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A=="], - - "minipass-sized": ["minipass-sized@1.0.3", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g=="], - - "minizlib": ["minizlib@3.0.2", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="], - - "mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="], - - "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], - - "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - - "msgpackr": ["msgpackr@1.11.2", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g=="], - - "msgpackr-extract": ["msgpackr-extract@3.0.3", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA=="], - - "multicast-dns": ["multicast-dns@7.2.5", "", { "dependencies": { "dns-packet": "^5.2.2", "thunky": "^1.0.2" }, "bin": { "multicast-dns": "cli.js" } }, "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg=="], - - "mute-stream": ["mute-stream@1.0.0", "", {}, "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA=="], - - "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - - "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], - - "needle": ["needle@3.3.1", "", { "dependencies": { "iconv-lite": "^0.6.3", "sax": "^1.2.4" }, "bin": { "needle": "bin/needle" } }, "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q=="], - - "negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="], - - "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], - - "node-addon-api": ["node-addon-api@6.1.0", "", {}, "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="], - - "node-forge": ["node-forge@1.3.1", "", {}, "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA=="], - - "node-gyp": ["node-gyp@11.2.0", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "graceful-fs": "^4.2.6", "make-fetch-happen": "^14.0.3", "nopt": "^8.0.0", "proc-log": "^5.0.0", "semver": "^7.3.5", "tar": "^7.4.3", "tinyglobby": "^0.2.12", "which": "^5.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-T0S1zqskVUSxcsSTkAsLc7xCycrRYmtDHadDinzocrThjyQCn5kMlEBSj6H4qDbgsIOSLmmlRIeb0lZXj+UArA=="], - - "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="], - - "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], - - "nopt": ["nopt@8.1.0", "", { "dependencies": { "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A=="], - - "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], - - "normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="], - - "npm-bundled": ["npm-bundled@4.0.0", "", { "dependencies": { "npm-normalize-package-bin": "^4.0.0" } }, "sha512-IxaQZDMsqfQ2Lz37VvyyEtKLe8FsRZuysmedy/N06TU1RyVppYKXrO4xIhR0F+7ubIBox6Q7nir6fQI3ej39iA=="], - - "npm-install-checks": ["npm-install-checks@7.1.1", "", { "dependencies": { "semver": "^7.1.1" } }, "sha512-u6DCwbow5ynAX5BdiHQ9qvexme4U3qHW3MWe5NqH+NeBm0LbiH6zvGjNNew1fY+AZZUtVHbOPF3j7mJxbUzpXg=="], - - "npm-normalize-package-bin": ["npm-normalize-package-bin@4.0.0", "", {}, "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w=="], - - "npm-package-arg": ["npm-package-arg@12.0.2", "", { "dependencies": { "hosted-git-info": "^8.0.0", "proc-log": "^5.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^6.0.0" } }, "sha512-f1NpFjNI9O4VbKMOlA5QoBq/vSQPORHcTZ2feJpFkTHJ9eQkdlmZEKSjcAhxTGInC7RlEyScT9ui67NaOsjFWA=="], - - "npm-packlist": ["npm-packlist@9.0.0", "", { "dependencies": { "ignore-walk": "^7.0.0" } }, "sha512-8qSayfmHJQTx3nJWYbbUmflpyarbLMBc6LCAjYsiGtXxDB68HaZpb8re6zeaLGxZzDuMdhsg70jryJe+RrItVQ=="], - - "npm-pick-manifest": ["npm-pick-manifest@10.0.0", "", { "dependencies": { "npm-install-checks": "^7.1.0", "npm-normalize-package-bin": "^4.0.0", "npm-package-arg": "^12.0.0", "semver": "^7.3.5" } }, "sha512-r4fFa4FqYY8xaM7fHecQ9Z2nE9hgNfJR+EmoKv0+chvzWkBcORX3r0FpTByP+CbOVJDladMXnPQGVN8PBLGuTQ=="], - - "npm-registry-fetch": ["npm-registry-fetch@18.0.2", "", { "dependencies": { "@npmcli/redact": "^3.0.0", "jsonparse": "^1.3.1", "make-fetch-happen": "^14.0.0", "minipass": "^7.0.2", "minipass-fetch": "^4.0.0", "minizlib": "^3.0.1", "npm-package-arg": "^12.0.0", "proc-log": "^5.0.0" } }, "sha512-LeVMZBBVy+oQb5R6FDV9OlJCcWDU+al10oKpe+nsvcHnG24Z3uM3SvJYKfGJlfGjVU8v9liejCrUR/M5HO5NEQ=="], - - "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], - - "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], - - "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], - - "obuf": ["obuf@1.1.2", "", {}, "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg=="], - - "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], - - "on-headers": ["on-headers@1.0.2", "", {}, "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="], - - "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], - - "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], - - "open": ["open@10.1.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "is-wsl": "^3.1.0" } }, "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw=="], - - "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], - - "ora": ["ora@5.4.1", "", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="], - - "ordered-binary": ["ordered-binary@1.5.3", "", {}, "sha512-oGFr3T+pYdTGJ+YFEILMpS3es+GiIbs9h/XQrclBXUtd44ey7XwfsMzM31f64I1SQOawDoDr/D823kNCADI8TA=="], - - "os-tmpdir": ["os-tmpdir@1.0.2", "", {}, "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="], - - "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], - - "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], - - "p-map": ["p-map@7.0.3", "", {}, "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA=="], - - "p-retry": ["p-retry@6.2.1", "", { "dependencies": { "@types/retry": "0.12.2", "is-network-error": "^1.0.0", "retry": "^0.13.1" } }, "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ=="], - - "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], - - "pacote": ["pacote@20.0.0", "", { "dependencies": { "@npmcli/git": "^6.0.0", "@npmcli/installed-package-contents": "^3.0.0", "@npmcli/package-json": "^6.0.0", "@npmcli/promise-spawn": "^8.0.0", "@npmcli/run-script": "^9.0.0", "cacache": "^19.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", "npm-package-arg": "^12.0.0", "npm-packlist": "^9.0.0", "npm-pick-manifest": "^10.0.0", "npm-registry-fetch": "^18.0.0", "proc-log": "^5.0.0", "promise-retry": "^2.0.1", "sigstore": "^3.0.0", "ssri": "^12.0.0", "tar": "^6.1.11" }, "bin": { "pacote": "bin/index.js" } }, "sha512-pRjC5UFwZCgx9kUFDVM9YEahv4guZ1nSLqwmWiLUnDbGsjs+U5w7z6Uc8HNR1a6x8qnu5y9xtGE6D1uAuYz+0A=="], - - "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], - - "parse-json": ["parse-json@5.2.0", "", { "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" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], - - "parse-node-version": ["parse-node-version@1.0.1", "", {}, "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA=="], - - "parse5": ["parse5@7.2.1", "", { "dependencies": { "entities": "^4.5.0" } }, "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ=="], - - "parse5-html-rewriting-stream": ["parse5-html-rewriting-stream@7.0.0", "", { "dependencies": { "entities": "^4.3.0", "parse5": "^7.0.0", "parse5-sax-parser": "^7.0.0" } }, "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg=="], - - "parse5-sax-parser": ["parse5-sax-parser@7.0.0", "", { "dependencies": { "parse5": "^7.0.0" } }, "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg=="], - - "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], - - "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], - - "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], - - "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], - - "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], - - "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - - "path-to-regexp": ["path-to-regexp@0.1.12", "", {}, "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="], - - "path-type": ["path-type@6.0.0", "", {}, "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ=="], - - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - - "picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], - - "pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="], - - "piscina": ["piscina@4.8.0", "", { "optionalDependencies": { "@napi-rs/nice": "^1.0.1" } }, "sha512-EZJb+ZxDrQf3dihsUL7p42pjNyrNIFJCrRHPMgxu/svsj+P3xS3fuEWp7k2+rfsavfl1N0G29b1HGs7J0m8rZA=="], - - "pkg-dir": ["pkg-dir@7.0.0", "", { "dependencies": { "find-up": "^6.3.0" } }, "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA=="], - - "postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], - - "postcss-loader": ["postcss-loader@8.1.1", "", { "dependencies": { "cosmiconfig": "^9.0.0", "jiti": "^1.20.0", "semver": "^7.5.4" }, "peerDependencies": { "@rspack/core": "0.x || 1.x", "postcss": "^7.0.0 || ^8.0.1", "webpack": "^5.0.0" }, "optionalPeers": ["@rspack/core", "webpack"] }, "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ=="], - - "postcss-media-query-parser": ["postcss-media-query-parser@0.2.3", "", {}, "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig=="], - - "postcss-modules-extract-imports": ["postcss-modules-extract-imports@3.1.0", "", { "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q=="], - - "postcss-modules-local-by-default": ["postcss-modules-local-by-default@4.2.0", "", { "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.1.0" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw=="], - - "postcss-modules-scope": ["postcss-modules-scope@3.2.1", "", { "dependencies": { "postcss-selector-parser": "^7.0.0" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA=="], - - "postcss-modules-values": ["postcss-modules-values@4.0.0", "", { "dependencies": { "icss-utils": "^5.0.0" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ=="], - - "postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="], - - "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], - - "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], - - "prettier": ["prettier@3.5.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw=="], - - "proc-log": ["proc-log@5.0.0", "", {}, "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ=="], - - "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], - - "promise-retry": ["promise-retry@2.0.1", "", { "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g=="], - - "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], - - "prr": ["prr@1.0.1", "", {}, "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw=="], - - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - - "qjobs": ["qjobs@1.2.0", "", {}, "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg=="], - - "qs": ["qs@6.13.0", "", { "dependencies": { "side-channel": "^1.0.6" } }, "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg=="], - - "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], - - "randombytes": ["randombytes@2.1.0", "", { "dependencies": { "safe-buffer": "^5.1.0" } }, "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ=="], - - "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], - - "raw-body": ["raw-body@2.5.2", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA=="], - - "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], - - "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], - - "reflect-metadata": ["reflect-metadata@0.2.2", "", {}, "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="], - - "regenerate": ["regenerate@1.4.2", "", {}, "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="], - - "regenerate-unicode-properties": ["regenerate-unicode-properties@10.2.0", "", { "dependencies": { "regenerate": "^1.4.2" } }, "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA=="], - - "regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="], - - "regenerator-transform": ["regenerator-transform@0.15.2", "", { "dependencies": { "@babel/runtime": "^7.8.4" } }, "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg=="], - - "regex-parser": ["regex-parser@2.3.1", "", {}, "sha512-yXLRqatcCuKtVHsWrNg0JL3l1zGfdXeEvDa0bdu4tCDQw0RpMDZsqbkyRTUnKMR0tXF627V2oEWjBEaEdqTwtQ=="], - - "regexpu-core": ["regexpu-core@6.2.0", "", { "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.0", "regjsgen": "^0.8.0", "regjsparser": "^0.12.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" } }, "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA=="], - - "regjsgen": ["regjsgen@0.8.0", "", {}, "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q=="], - - "regjsparser": ["regjsparser@0.12.0", "", { "dependencies": { "jsesc": "~3.0.2" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ=="], - - "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], - - "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], - - "requires-port": ["requires-port@1.0.0", "", {}, "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="], - - "resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="], - - "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], - - "resolve-url-loader": ["resolve-url-loader@5.0.0", "", { "dependencies": { "adjust-sourcemap-loader": "^4.0.0", "convert-source-map": "^1.7.0", "loader-utils": "^2.0.0", "postcss": "^8.2.14", "source-map": "0.6.1" } }, "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg=="], - - "restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="], - - "retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], - - "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], - - "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], - - "rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], - - "rollup": ["rollup@4.34.8", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.34.8", "@rollup/rollup-android-arm64": "4.34.8", "@rollup/rollup-darwin-arm64": "4.34.8", "@rollup/rollup-darwin-x64": "4.34.8", "@rollup/rollup-freebsd-arm64": "4.34.8", "@rollup/rollup-freebsd-x64": "4.34.8", "@rollup/rollup-linux-arm-gnueabihf": "4.34.8", "@rollup/rollup-linux-arm-musleabihf": "4.34.8", "@rollup/rollup-linux-arm64-gnu": "4.34.8", "@rollup/rollup-linux-arm64-musl": "4.34.8", "@rollup/rollup-linux-loongarch64-gnu": "4.34.8", "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8", "@rollup/rollup-linux-riscv64-gnu": "4.34.8", "@rollup/rollup-linux-s390x-gnu": "4.34.8", "@rollup/rollup-linux-x64-gnu": "4.34.8", "@rollup/rollup-linux-x64-musl": "4.34.8", "@rollup/rollup-win32-arm64-msvc": "4.34.8", "@rollup/rollup-win32-ia32-msvc": "4.34.8", "@rollup/rollup-win32-x64-msvc": "4.34.8", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ=="], - - "run-applescript": ["run-applescript@7.0.0", "", {}, "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A=="], - - "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], - - "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="], - - "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], - - "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="], - - "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], - - "sass": ["sass@1.85.0", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-3ToiC1xZ1Y8aU7+CkgCI/tqyuPXEmYGJXO7H4uqp0xkLXUqp88rQQ4j1HmP37xSJLbCJPaIiv+cT1y+grssrww=="], - - "sass-loader": ["sass-loader@16.0.5", "", { "dependencies": { "neo-async": "^2.6.2" }, "peerDependencies": { "@rspack/core": "0.x || 1.x", "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", "sass": "^1.3.0", "sass-embedded": "*", "webpack": "^5.0.0" }, "optionalPeers": ["@rspack/core", "node-sass", "sass", "sass-embedded", "webpack"] }, "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw=="], - - "sax": ["sax@1.4.1", "", {}, "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="], - - "schema-utils": ["schema-utils@4.3.0", "", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g=="], - - "select-hose": ["select-hose@2.0.0", "", {}, "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg=="], - - "selfsigned": ["selfsigned@2.4.1", "", { "dependencies": { "@types/node-forge": "^1.3.0", "node-forge": "^1" } }, "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q=="], - - "semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], - - "send": ["send@0.19.0", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "2.4.1", "range-parser": "~1.2.1", "statuses": "2.0.1" } }, "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw=="], - - "serialize-javascript": ["serialize-javascript@6.0.2", "", { "dependencies": { "randombytes": "^2.1.0" } }, "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g=="], - - "serve-index": ["serve-index@1.9.1", "", { "dependencies": { "accepts": "~1.3.4", "batch": "0.6.1", "debug": "2.6.9", "escape-html": "~1.0.3", "http-errors": "~1.6.2", "mime-types": "~2.1.17", "parseurl": "~1.3.2" } }, "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw=="], - - "serve-static": ["serve-static@1.16.2", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.19.0" } }, "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw=="], - - "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], - - "shallow-clone": ["shallow-clone@3.0.1", "", { "dependencies": { "kind-of": "^6.0.2" } }, "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA=="], - - "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], - - "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], - - "shell-quote": ["shell-quote@1.8.2", "", {}, "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA=="], - - "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], - - "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], - - "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], - - "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], - - "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - - "sigstore": ["sigstore@3.1.0", "", { "dependencies": { "@sigstore/bundle": "^3.1.0", "@sigstore/core": "^2.0.0", "@sigstore/protobuf-specs": "^0.4.0", "@sigstore/sign": "^3.1.0", "@sigstore/tuf": "^3.1.0", "@sigstore/verify": "^2.1.0" } }, "sha512-ZpzWAFHIFqyFE56dXqgX/DkDRZdz+rRcjoIk/RQU4IX0wiCv1l8S7ZrXDHcCc+uaf+6o7w3h2l3g6GYG5TKN9Q=="], - - "slash": ["slash@5.1.0", "", {}, "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="], - - "slice-ansi": ["slice-ansi@5.0.0", "", { "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" } }, "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ=="], - - "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="], - - "socket.io": ["socket.io@4.8.1", "", { "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" } }, "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg=="], - - "socket.io-adapter": ["socket.io-adapter@2.5.5", "", { "dependencies": { "debug": "~4.3.4", "ws": "~8.17.1" } }, "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg=="], - - "socket.io-parser": ["socket.io-parser@4.2.4", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" } }, "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew=="], - - "sockjs": ["sockjs@0.3.24", "", { "dependencies": { "faye-websocket": "^0.11.3", "uuid": "^8.3.2", "websocket-driver": "^0.7.4" } }, "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ=="], - - "socks": ["socks@2.8.4", "", { "dependencies": { "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" } }, "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ=="], - - "socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="], - - "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], - - "source-map-loader": ["source-map-loader@5.0.0", "", { "dependencies": { "iconv-lite": "^0.6.3", "source-map-js": "^1.0.2" }, "peerDependencies": { "webpack": "^5.72.1" } }, "sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA=="], - - "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], - - "spdx-correct": ["spdx-correct@3.2.0", "", { "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA=="], - - "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="], - - "spdx-expression-parse": ["spdx-expression-parse@3.0.1", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q=="], - - "spdx-license-ids": ["spdx-license-ids@3.0.21", "", {}, "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg=="], - - "spdy": ["spdy@4.0.2", "", { "dependencies": { "debug": "^4.1.0", "handle-thing": "^2.0.0", "http-deceiver": "^1.2.7", "select-hose": "^2.0.0", "spdy-transport": "^3.0.0" } }, "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA=="], - - "spdy-transport": ["spdy-transport@3.0.0", "", { "dependencies": { "debug": "^4.1.0", "detect-node": "^2.0.4", "hpack.js": "^2.1.6", "obuf": "^1.1.2", "readable-stream": "^3.0.6", "wbuf": "^1.7.3" } }, "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw=="], - - "sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="], - - "ssri": ["ssri@12.0.0", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ=="], - - "statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], - - "streamroller": ["streamroller@3.1.5", "", { "dependencies": { "date-format": "^4.0.14", "debug": "^4.3.4", "fs-extra": "^8.1.0" } }, "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw=="], - - "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], - - "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], - - "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - - "symbol-observable": ["symbol-observable@4.0.0", "", {}, "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ=="], - - "tailwindcss": ["tailwindcss@4.1.1", "", {}, "sha512-QNbdmeS979Efzim2g/bEvfuh+fTcIdp1y7gA+sb6OYSW74rt7Cr7M78AKdf6HqWT3d5AiTb7SwTT3sLQxr4/qw=="], - - "tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="], - - "tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], - - "terser": ["terser@5.39.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw=="], - - "terser-webpack-plugin": ["terser-webpack-plugin@5.3.14", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw=="], - - "thingies": ["thingies@1.21.0", "", { "peerDependencies": { "tslib": "^2" } }, "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g=="], - - "thunky": ["thunky@1.1.0", "", {}, "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="], - - "tinyglobby": ["tinyglobby@0.2.12", "", { "dependencies": { "fdir": "^6.4.3", "picomatch": "^4.0.2" } }, "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww=="], - - "tmp": ["tmp@0.2.3", "", {}, "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w=="], - - "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], - - "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], - - "tree-dump": ["tree-dump@1.0.2", "", { "peerDependencies": { "tslib": "2" } }, "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ=="], - - "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], - - "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], - - "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - - "tuf-js": ["tuf-js@3.0.1", "", { "dependencies": { "@tufjs/models": "3.0.1", "debug": "^4.3.6", "make-fetch-happen": "^14.0.1" } }, "sha512-+68OP1ZzSF84rTckf3FA95vJ1Zlx/uaXyiiKyPd1pA4rZNkpEvDAKmsu1xUSmbF/chCRYgZ6UZkDwC7PmzmAyA=="], - - "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], - - "type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], - - "type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], - - "typed-assert": ["typed-assert@1.0.9", "", {}, "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg=="], - - "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], - - "typescript-eslint": ["typescript-eslint@8.33.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.33.1", "@typescript-eslint/parser": "8.33.1", "@typescript-eslint/utils": "8.33.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-AgRnV4sKkWOiZ0Kjbnf5ytTJXMUZQ0qhSVdQtDNYLPLnjsATEYhaO94GlRQwi4t4gO8FfjM6NnikHeKjUm8D7A=="], - - "ua-parser-js": ["ua-parser-js@0.7.40", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ=="], - - "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], - - "unicode-canonical-property-names-ecmascript": ["unicode-canonical-property-names-ecmascript@2.0.1", "", {}, "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg=="], - - "unicode-match-property-ecmascript": ["unicode-match-property-ecmascript@2.0.0", "", { "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" } }, "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q=="], - - "unicode-match-property-value-ecmascript": ["unicode-match-property-value-ecmascript@2.2.0", "", {}, "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg=="], - - "unicode-property-aliases-ecmascript": ["unicode-property-aliases-ecmascript@2.1.0", "", {}, "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w=="], - - "unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="], - - "unique-filename": ["unique-filename@4.0.0", "", { "dependencies": { "unique-slug": "^5.0.0" } }, "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ=="], - - "unique-slug": ["unique-slug@5.0.0", "", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg=="], - - "universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], - - "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], - - "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], - - "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], - - "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], - - "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], - - "uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], - - "validate-npm-package-license": ["validate-npm-package-license@3.0.4", "", { "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew=="], - - "validate-npm-package-name": ["validate-npm-package-name@6.0.0", "", {}, "sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg=="], - - "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], - - "vite": ["vite@6.2.4", "", { "dependencies": { "esbuild": "^0.25.0", "postcss": "^8.5.3", "rollup": "^4.30.1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw=="], - - "void-elements": ["void-elements@2.0.1", "", {}, "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung=="], - - "watchpack": ["watchpack@2.4.2", "", { "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw=="], - - "wbuf": ["wbuf@1.7.3", "", { "dependencies": { "minimalistic-assert": "^1.0.0" } }, "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA=="], - - "wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="], - - "weak-lru-cache": ["weak-lru-cache@1.2.2", "", {}, "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw=="], - - "webpack": ["webpack@5.98.0", "", { "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.14.0", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^4.3.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { "webpack": "bin/webpack.js" } }, "sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA=="], - - "webpack-dev-middleware": ["webpack-dev-middleware@7.4.2", "", { "dependencies": { "colorette": "^2.0.10", "memfs": "^4.6.0", "mime-types": "^2.1.31", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" }, "peerDependencies": { "webpack": "^5.0.0" }, "optionalPeers": ["webpack"] }, "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA=="], - - "webpack-dev-server": ["webpack-dev-server@5.2.0", "", { "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", "@types/express": "^4.17.21", "@types/serve-index": "^1.9.4", "@types/serve-static": "^1.15.5", "@types/sockjs": "^0.3.36", "@types/ws": "^8.5.10", "ansi-html-community": "^0.0.8", "bonjour-service": "^1.2.1", "chokidar": "^3.6.0", "colorette": "^2.0.10", "compression": "^1.7.4", "connect-history-api-fallback": "^2.0.0", "express": "^4.21.2", "graceful-fs": "^4.2.6", "http-proxy-middleware": "^2.0.7", "ipaddr.js": "^2.1.0", "launch-editor": "^2.6.1", "open": "^10.0.3", "p-retry": "^6.2.0", "schema-utils": "^4.2.0", "selfsigned": "^2.4.1", "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", "webpack-dev-middleware": "^7.4.2", "ws": "^8.18.0" }, "peerDependencies": { "webpack": "^5.0.0" }, "optionalPeers": ["webpack"], "bin": { "webpack-dev-server": "bin/webpack-dev-server.js" } }, "sha512-90SqqYXA2SK36KcT6o1bvwvZfJFcmoamqeJY7+boioffX9g9C0wjjJRGUrQIuh43pb0ttX7+ssavmj/WN2RHtA=="], - - "webpack-merge": ["webpack-merge@6.0.1", "", { "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", "wildcard": "^2.0.1" } }, "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg=="], - - "webpack-sources": ["webpack-sources@3.2.3", "", {}, "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w=="], - - "webpack-subresource-integrity": ["webpack-subresource-integrity@5.1.0", "", { "dependencies": { "typed-assert": "^1.0.8" }, "peerDependencies": { "html-webpack-plugin": ">= 5.0.0-beta.1 < 6", "webpack": "^5.12.0" }, "optionalPeers": ["html-webpack-plugin"] }, "sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q=="], - - "websocket-driver": ["websocket-driver@0.7.4", "", { "dependencies": { "http-parser-js": ">=0.5.1", "safe-buffer": ">=5.1.0", "websocket-extensions": ">=0.1.1" } }, "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg=="], - - "websocket-extensions": ["websocket-extensions@0.1.4", "", {}, "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="], - - "which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="], - - "wildcard": ["wildcard@2.0.1", "", {}, "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ=="], - - "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], - - "wrap-ansi": ["wrap-ansi@9.0.0", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q=="], - - "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - - "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - - "ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="], - - "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], - - "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - - "yargs": ["yargs@17.7.2", "", { "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" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - - "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], - - "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], - - "yoctocolors-cjs": ["yoctocolors-cjs@2.1.2", "", {}, "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA=="], - - "zone.js": ["zone.js@0.15.0", "", {}, "sha512-9oxn0IIjbCZkJ67L+LkhYWRyAy7axphb3VgE2MBDlOqnmHMPWGYMxJxBYFueFq/JGY2GMwS0rU+UCLunEmy5UA=="], - - "@angular-devkit/architect/rxjs": ["rxjs@7.8.1", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg=="], - - "@angular-devkit/build-angular/postcss": ["postcss@8.5.2", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA=="], - - "@angular-devkit/build-angular/rxjs": ["rxjs@7.8.1", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg=="], - - "@angular-devkit/build-webpack/rxjs": ["rxjs@7.8.1", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg=="], - - "@angular-devkit/core/rxjs": ["rxjs@7.8.1", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg=="], - - "@angular-devkit/core/source-map": ["source-map@0.7.4", "", {}, "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="], - - "@angular-devkit/schematics/rxjs": ["rxjs@7.8.1", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg=="], - - "@angular-eslint/schematics/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - - "@angular-eslint/schematics/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], - - "@angular/compiler-cli/@babel/core": ["@babel/core@7.26.9", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.9", "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-module-transforms": "^7.26.0", "@babel/helpers": "^7.26.9", "@babel/parser": "^7.26.9", "@babel/template": "^7.26.9", "@babel/traverse": "^7.26.9", "@babel/types": "^7.26.9", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw=="], - - "@babel/core/convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], - - "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@babel/helper-create-regexp-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@babel/plugin-transform-classes/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], - - "@babel/plugin-transform-runtime/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@babel/preset-env/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@babel/traverse/@babel/generator": ["@babel/generator@7.27.0", "", { "dependencies": { "@babel/parser": "^7.27.0", "@babel/types": "^7.27.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw=="], - - "@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], - - "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "@eslint/eslintrc/ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], - - "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], - - "@inquirer/checkbox/@inquirer/type": ["@inquirer/type@3.0.5", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg=="], - - "@inquirer/confirm/@inquirer/type": ["@inquirer/type@3.0.5", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg=="], - - "@inquirer/core/@inquirer/type": ["@inquirer/type@3.0.5", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg=="], - - "@inquirer/core/mute-stream": ["mute-stream@2.0.0", "", {}, "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA=="], - - "@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], - - "@inquirer/editor/@inquirer/type": ["@inquirer/type@3.0.5", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg=="], - - "@inquirer/expand/@inquirer/type": ["@inquirer/type@3.0.5", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg=="], - - "@inquirer/input/@inquirer/type": ["@inquirer/type@3.0.5", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg=="], - - "@inquirer/number/@inquirer/type": ["@inquirer/type@3.0.5", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg=="], - - "@inquirer/password/@inquirer/type": ["@inquirer/type@3.0.5", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg=="], - - "@inquirer/rawlist/@inquirer/type": ["@inquirer/type@3.0.5", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg=="], - - "@inquirer/search/@inquirer/type": ["@inquirer/type@3.0.5", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg=="], - - "@inquirer/select/@inquirer/type": ["@inquirer/type@3.0.5", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg=="], - - "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], - - "@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], - - "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], - - "@npmcli/agent/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - - "@npmcli/git/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - - "@npmcli/git/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], - - "@npmcli/package-json/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], - - "@npmcli/package-json/json-parse-even-better-errors": ["json-parse-even-better-errors@4.0.0", "", {}, "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA=="], - - "@npmcli/promise-spawn/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], - - "@npmcli/run-script/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], - - "@parcel/watcher/node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], - - "@tailwindcss/node/jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], - - "@tufjs/models/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "@types/express/@types/express-serve-static-core": ["@types/express-serve-static-core@4.19.6", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.33.1", "", { "dependencies": { "@typescript-eslint/types": "8.33.1", "@typescript-eslint/visitor-keys": "8.33.1" } }, "sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils": ["@typescript-eslint/utils@8.33.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.33.1", "@typescript-eslint/types": "8.33.1", "@typescript-eslint/typescript-estree": "8.33.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ=="], - - "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - - "@typescript-eslint/parser/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.33.1", "", { "dependencies": { "@typescript-eslint/types": "8.33.1", "@typescript-eslint/visitor-keys": "8.33.1" } }, "sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA=="], - - "@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.33.1", "", {}, "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg=="], - - "@typescript-eslint/parser/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.33.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.33.1", "@typescript-eslint/tsconfig-utils": "8.33.1", "@typescript-eslint/types": "8.33.1", "@typescript-eslint/visitor-keys": "8.33.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA=="], - - "@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.33.0", "", { "dependencies": { "@typescript-eslint/types": "8.33.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ=="], - - "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.33.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.33.1", "@typescript-eslint/tsconfig-utils": "8.33.1", "@typescript-eslint/types": "8.33.1", "@typescript-eslint/visitor-keys": "8.33.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA=="], - - "@typescript-eslint/type-utils/@typescript-eslint/utils": ["@typescript-eslint/utils@8.33.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.33.1", "@typescript-eslint/types": "8.33.1", "@typescript-eslint/typescript-estree": "8.33.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ=="], - - "@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.33.0", "", { "dependencies": { "@typescript-eslint/types": "8.33.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ=="], - - "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], - - "@typescript-eslint/utils/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="], - - "@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.33.1", "", {}, "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg=="], - - "accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], - - "adjust-sourcemap-loader/loader-utils": ["loader-utils@2.0.4", "", { "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", "json5": "^2.1.2" } }, "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw=="], - - "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - - "babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "body-parser/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], - - "cacache/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], - - "cacache/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - - "cacache/tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="], - - "cli-truncate/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], - - "cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - - "clone-deep/is-plain-object": ["is-plain-object@2.0.4", "", { "dependencies": { "isobject": "^3.0.1" } }, "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og=="], - - "compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "connect/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], - - "engine.io/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], - - "engine.io/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], - - "engine.io/ws": ["ws@8.17.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ=="], - - "ent/punycode": ["punycode@1.4.1", "", {}, "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="], - - "eslint/ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], - - "express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "express/finalhandler": ["finalhandler@1.3.1", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", "statuses": "2.0.1", "unpipe": "~1.0.0" } }, "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ=="], - - "external-editor/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], - - "external-editor/tmp": ["tmp@0.0.33", "", { "dependencies": { "os-tmpdir": "~1.0.2" } }, "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw=="], - - "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - - "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "finalhandler/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], - - "finalhandler/on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="], - - "finalhandler/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="], - - "globby/ignore": ["ignore@7.0.3", "", {}, "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA=="], - - "hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - - "hpack.js/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], - - "http-proxy/eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], - - "ignore-walk/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "istanbul-lib-report/make-dir": ["make-dir@4.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw=="], - - "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - - "karma/chokidar": ["chokidar@3.6.0", "", { "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" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], - - "karma/yargs": ["yargs@16.2.0", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="], - - "karma-coverage/istanbul-lib-instrument": ["istanbul-lib-instrument@5.2.1", "", { "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" } }, "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg=="], - - "karma-jasmine/jasmine-core": ["jasmine-core@4.6.1", "", {}, "sha512-VYz/BjjmC3klLJlLwA4Kw8ytk0zDSmbbDLNs794VnWmkcCB7I9aAL/D48VNQtmITyPvea2C3jdUMfc3kAoy0PQ=="], - - "less/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], - - "lightningcss/detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], - - "log-update/ansi-escapes": ["ansi-escapes@7.0.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw=="], - - "log-update/cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], - - "log-update/slice-ansi": ["slice-ansi@7.1.0", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg=="], - - "log-update/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], - - "lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], - - "make-dir/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], - - "make-fetch-happen/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], - - "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - - "minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - - "minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - - "minipass-sized/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - - "node-gyp/tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="], - - "node-gyp/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], - - "node-gyp-build-optional-packages/detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], - - "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - - "pkg-dir/find-up": ["find-up@6.3.0", "", { "dependencies": { "locate-path": "^7.1.0", "path-exists": "^5.0.0" } }, "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw=="], - - "promise-retry/retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], - - "proxy-addr/ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], - - "raw-body/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], - - "regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], - - "resolve-url-loader/loader-utils": ["loader-utils@2.0.4", "", { "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", "json5": "^2.1.2" } }, "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw=="], - - "restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - - "rollup/@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], - - "schema-utils/ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="], - - "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], - - "send/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], - - "serve-index/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "serve-index/http-errors": ["http-errors@1.6.3", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", "statuses": ">= 1.4.0 < 2" } }, "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A=="], - - "slice-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], - - "slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@4.0.0", "", {}, "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ=="], - - "socket.io/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], - - "socket.io-adapter/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], - - "socket.io-adapter/ws": ["ws@8.17.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ=="], - - "socket.io-parser/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], - - "tar/fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="], - - "tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], - - "tar/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], - - "tar/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], - - "typescript-eslint/@typescript-eslint/utils": ["@typescript-eslint/utils@8.33.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.33.1", "@typescript-eslint/types": "8.33.1", "@typescript-eslint/typescript-estree": "8.33.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ=="], - - "webpack/eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="], - - "webpack-dev-server/chokidar": ["chokidar@3.6.0", "", { "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" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], - - "webpack-dev-server/http-proxy-middleware": ["http-proxy-middleware@2.0.7", "", { "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", "is-glob": "^4.0.1", "is-plain-obj": "^3.0.0", "micromatch": "^4.0.2" }, "peerDependencies": { "@types/express": "^4.17.13" }, "optionalPeers": ["@types/express"] }, "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA=="], - - "wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], - - "wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], - - "wrap-ansi/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], - - "@angular/compiler-cli/@babel/core/convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], - - "@angular/compiler-cli/@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@eslint/eslintrc/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - - "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], - - "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], - - "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], - - "@npmcli/git/which/isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="], - - "@npmcli/package-json/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "@npmcli/promise-spawn/which/isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="], - - "@npmcli/run-script/which/isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="], - - "@tufjs/models/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.33.1", "", {}, "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.33.1", "", {}, "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.33.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.33.1", "@typescript-eslint/tsconfig-utils": "8.33.1", "@typescript-eslint/types": "8.33.1", "@typescript-eslint/visitor-keys": "8.33.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA=="], - - "@typescript-eslint/parser/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.33.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.33.1", "@typescript-eslint/types": "^8.33.1", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw=="], - - "@typescript-eslint/parser/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.33.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g=="], - - "@typescript-eslint/parser/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "@typescript-eslint/parser/@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], - - "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.33.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.33.1", "@typescript-eslint/types": "^8.33.1", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw=="], - - "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.33.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g=="], - - "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@8.33.1", "", {}, "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg=="], - - "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], - - "@typescript-eslint/type-utils/@typescript-eslint/utils/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="], - - "@typescript-eslint/type-utils/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.33.1", "", { "dependencies": { "@typescript-eslint/types": "8.33.1", "@typescript-eslint/visitor-keys": "8.33.1" } }, "sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA=="], - - "@typescript-eslint/type-utils/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.33.1", "", {}, "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg=="], - - "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "@typescript-eslint/utils/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "cacache/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "cacache/tar/chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], - - "cacache/tar/mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="], - - "cacache/tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], - - "cli-truncate/string-width/emoji-regex": ["emoji-regex@10.4.0", "", {}, "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="], - - "cli-truncate/string-width/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], - - "compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "connect/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "eslint/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - - "express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "hpack.js/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], - - "hpack.js/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], - - "ignore-walk/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "karma-coverage/istanbul-lib-instrument/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "karma/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - - "karma/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], - - "karma/yargs/cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], - - "karma/yargs/yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], - - "log-update/cli-cursor/restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], - - "log-update/slice-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], - - "log-update/slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.0.0", "", { "dependencies": { "get-east-asian-width": "^1.0.0" } }, "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA=="], - - "log-update/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], - - "node-gyp/tar/chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], - - "node-gyp/tar/mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="], - - "node-gyp/tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], - - "node-gyp/which/isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="], - - "pkg-dir/find-up/locate-path": ["locate-path@7.2.0", "", { "dependencies": { "p-locate": "^6.0.0" } }, "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA=="], - - "pkg-dir/find-up/path-exists": ["path-exists@5.0.0", "", {}, "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ=="], - - "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "serve-index/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "serve-index/http-errors/depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="], - - "serve-index/http-errors/inherits": ["inherits@2.0.3", "", {}, "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="], - - "serve-index/http-errors/setprototypeof": ["setprototypeof@1.1.0", "", {}, "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="], - - "serve-index/http-errors/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="], - - "tar/fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - - "tar/minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - - "typescript-eslint/@typescript-eslint/utils/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="], - - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.33.1", "", { "dependencies": { "@typescript-eslint/types": "8.33.1", "@typescript-eslint/visitor-keys": "8.33.1" } }, "sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA=="], - - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.33.1", "", {}, "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg=="], - - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.33.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.33.1", "@typescript-eslint/tsconfig-utils": "8.33.1", "@typescript-eslint/types": "8.33.1", "@typescript-eslint/visitor-keys": "8.33.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA=="], - - "webpack-dev-server/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - - "webpack-dev-server/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], - - "webpack/eslint-scope/estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], - - "wrap-ansi/string-width/emoji-regex": ["emoji-regex@10.4.0", "", {}, "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="], - - "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], - - "@npmcli/package-json/glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.33.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.33.1", "@typescript-eslint/types": "^8.33.1", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.33.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], - - "@typescript-eslint/parser/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "@typescript-eslint/type-utils/@typescript-eslint/utils/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "cli-truncate/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], - - "karma/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - - "karma/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - - "log-update/cli-cursor/restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], - - "pkg-dir/find-up/locate-path/p-locate": ["p-locate@6.0.0", "", { "dependencies": { "p-limit": "^4.0.0" } }, "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw=="], - - "typescript-eslint/@typescript-eslint/utils/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.33.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.33.1", "@typescript-eslint/types": "^8.33.1", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw=="], - - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.33.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g=="], - - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], - - "webpack-dev-server/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@4.0.0", "", { "dependencies": { "yocto-queue": "^1.0.0" } }, "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ=="], - - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "pkg-dir/find-up/locate-path/p-locate/p-limit/yocto-queue": ["yocto-queue@1.2.1", "", {}, "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg=="], - } -} diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js deleted file mode 100644 index 99a007a..0000000 --- a/frontend/eslint.config.js +++ /dev/null @@ -1,43 +0,0 @@ -// @ts-check -const eslint = require("@eslint/js"); -const tseslint = require("typescript-eslint"); -const angular = require("angular-eslint"); - -module.exports = tseslint.config( - { - files: ["**/*.ts"], - extends: [ - eslint.configs.recommended, - ...tseslint.configs.recommended, - ...tseslint.configs.stylistic, - ...angular.configs.tsRecommended, - ], - processor: angular.processInlineTemplates, - rules: { - "@angular-eslint/directive-selector": [ - "error", - { - type: "attribute", - prefix: "app", - style: "camelCase", - }, - ], - "@angular-eslint/component-selector": [ - "error", - { - type: "element", - prefix: "app", - style: "kebab-case", - }, - ], - }, - }, - { - files: ["**/*.html"], - extends: [ - ...angular.configs.templateRecommended, - ...angular.configs.templateAccessibility, - ], - rules: {}, - } -); diff --git a/frontend/package.json b/frontend/package.json deleted file mode 100644 index fd5c806..0000000 --- a/frontend/package.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "trustworthy-casino", - "version": "0.0.0", - "scripts": { - "ng": "bunx @angular/cli", - "start": "bunx @angular/cli serve --proxy-config src/proxy.conf.json", - "build": "bunx @angular/cli build", - "watch": "bunx @angular/cli build --watch --configuration development", - "test": "bunx @angular/cli test", - "format": "prettier --write \"src/**/*.{ts,html,css,scss}\"", - "format:check": "prettier --check \"src/**/*.{ts,html,css,scss}\"", - "lint": "bunx @angular/cli lint", - "oxlint": "bunx oxlint --deny-warnings" - }, - "private": true, - "dependencies": { - "@angular/animations": "^19.0.0", - "@angular/cdk": "~19.2.0", - "@angular/common": "^19.0.0", - "@angular/compiler": "^19.2.4", - "@angular/core": "^19.0.0", - "@angular/forms": "^19.0.0", - "@angular/platform-browser": "^19.0.0", - "@angular/platform-browser-dynamic": "^19.0.0", - "@angular/router": "^19.0.0", - "@fortawesome/angular-fontawesome": "^1.0.0", - "@fortawesome/fontawesome-svg-core": "^6.7.2", - "@fortawesome/free-brands-svg-icons": "^6.7.2", - "@fortawesome/free-solid-svg-icons": "^6.7.2", - "@stripe/stripe-js": "^7.0.0", - "@tailwindcss/postcss": "^4.0.3", - "ajv": "8.17.1", - "ajv-formats": "3.0.1", - "countup.js": "^2.8.0", - "gsap": "^3.12.7", - "postcss": "^8.5.1", - "rxjs": "~7.8.2", - "tailwindcss": "^4.0.3", - "tslib": "^2.3.0" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^19.0.0", - "@angular/cli": "^19.2.5", - "@angular/compiler-cli": "^19.0.0", - "@types/jasmine": "~5.1.0", - "angular-eslint": "19.7.0", - "eslint": "^9.25.1", - "jasmine-core": "~5.7.0", - "karma": "~6.4.0", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.1.0", - "karma-jasmine-html-reporter": "~2.1.0", - "prettier": "^3.4.2", - "typescript": "~5.8.0", - "typescript-eslint": "8.33.1" - } -} diff --git a/frontend/public/blackjack.webp b/frontend/public/blackjack.webp deleted file mode 100644 index e47c246..0000000 Binary files a/frontend/public/blackjack.webp and /dev/null differ diff --git a/frontend/public/coinflip.png b/frontend/public/coinflip.png deleted file mode 100644 index 0f39ca8..0000000 Binary files a/frontend/public/coinflip.png and /dev/null differ diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico deleted file mode 100644 index 0a22de4..0000000 Binary files a/frontend/public/favicon.ico and /dev/null differ diff --git a/frontend/public/images/1-box.png b/frontend/public/images/1-box.png deleted file mode 100644 index b343dbd..0000000 Binary files a/frontend/public/images/1-box.png and /dev/null differ diff --git a/frontend/public/images/2-box.png b/frontend/public/images/2-box.png deleted file mode 100644 index 0ec4438..0000000 Binary files a/frontend/public/images/2-box.png and /dev/null differ diff --git a/frontend/public/images/3-box.png b/frontend/public/images/3-box.png deleted file mode 100644 index 87a8401..0000000 Binary files a/frontend/public/images/3-box.png and /dev/null differ diff --git a/frontend/public/liars-dice.webp b/frontend/public/liars-dice.webp deleted file mode 100644 index 0e1a05c..0000000 Binary files a/frontend/public/liars-dice.webp and /dev/null differ diff --git a/frontend/public/lootbox.webp b/frontend/public/lootbox.webp deleted file mode 100644 index 0750897..0000000 Binary files a/frontend/public/lootbox.webp and /dev/null differ diff --git a/frontend/public/plinko.webp b/frontend/public/plinko.webp deleted file mode 100644 index ada7958..0000000 Binary files a/frontend/public/plinko.webp and /dev/null differ diff --git a/frontend/public/silent-check-sso.html b/frontend/public/silent-check-sso.html deleted file mode 100644 index 9de338b..0000000 --- a/frontend/public/silent-check-sso.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/frontend/public/slots.webp b/frontend/public/slots.webp deleted file mode 100644 index 12a8d8e..0000000 Binary files a/frontend/public/slots.webp and /dev/null differ diff --git a/frontend/public/sounds/bet.mp3 b/frontend/public/sounds/bet.mp3 deleted file mode 100644 index b3b7ca3..0000000 Binary files a/frontend/public/sounds/bet.mp3 and /dev/null differ diff --git a/frontend/public/sounds/coinflip.mp3 b/frontend/public/sounds/coinflip.mp3 deleted file mode 100644 index f8708ea..0000000 Binary files a/frontend/public/sounds/coinflip.mp3 and /dev/null differ diff --git a/frontend/public/sounds/drag.mp3 b/frontend/public/sounds/drag.mp3 deleted file mode 100644 index cc7a53d..0000000 Binary files a/frontend/public/sounds/drag.mp3 and /dev/null differ diff --git a/frontend/public/sounds/win.mp3 b/frontend/public/sounds/win.mp3 deleted file mode 100644 index 09441ef..0000000 Binary files a/frontend/public/sounds/win.mp3 and /dev/null differ diff --git a/frontend/src/app/app.component.css b/frontend/src/app/app.component.css deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/app/app.component.html b/frontend/src/app/app.component.html deleted file mode 100644 index e07b16d..0000000 --- a/frontend/src/app/app.component.html +++ /dev/null @@ -1,42 +0,0 @@ -
-
- - -
- - - - @if (showLogin() || showRegister() || showRecoverPassword()) { - - - } -
diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts deleted file mode 100644 index 7499296..0000000 --- a/frontend/src/app/app.component.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Component, HostListener, inject, signal } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; -import { NavbarComponent } from '@shared/components/navbar/navbar.component'; -import { FooterComponent } from '@shared/components/footer/footer.component'; -import { LoginComponent } from './feature/auth/login/login.component'; -import { RegisterComponent } from './feature/auth/register/register.component'; -import RecoverPasswordComponent from './feature/auth/recover-password/recover-password.component'; -import { PlaySoundDirective } from '@shared/directives/play-sound.directive'; -import { SoundInitializerService } from '@shared/services/sound-initializer.service'; - -@Component({ - selector: 'app-root', - standalone: true, - imports: [ - RouterOutlet, - NavbarComponent, - FooterComponent, - LoginComponent, - RegisterComponent, - RecoverPasswordComponent, - ], - templateUrl: './app.component.html', - hostDirectives: [PlaySoundDirective], -}) -export class AppComponent { - private soundInitializer = inject(SoundInitializerService); - - showLogin = signal(false); - showRegister = signal(false); - showRecoverPassword = signal(false); - - constructor() { - this.soundInitializer.initialize(); - } - - @HostListener('document:keydown.escape') - handleEscapeKey() { - this.hideAuthForms(); - } - - showLoginForm() { - this.showLogin.set(true); - this.showRegister.set(false); - this.showRecoverPassword.set(false); - document.body.style.overflow = 'hidden'; - } - - showRegisterForm() { - this.showRegister.set(true); - this.showLogin.set(false); - this.showRecoverPassword.set(false); - document.body.style.overflow = 'hidden'; - } - - showRecoverPasswordForm() { - this.showRecoverPassword.set(true); - this.showLogin.set(false); - this.showRegister.set(false); - document.body.style.overflow = 'hidden'; - } - - hideAuthForms() { - this.showLogin.set(false); - this.showRegister.set(false); - this.showRecoverPassword.set(false); - document.body.style.overflow = 'auto'; - } - - stopPropagation(event: MouseEvent) { - event.stopPropagation(); - } -} diff --git a/frontend/src/app/app.config.ts b/frontend/src/app/app.config.ts deleted file mode 100644 index 679c5e4..0000000 --- a/frontend/src/app/app.config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ApplicationConfig, provideExperimentalZonelessChangeDetection } from '@angular/core'; -import { provideRouter } from '@angular/router'; -import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; - -import { routes } from './app.routes'; -import { provideHttpClient, withInterceptors } from '@angular/common/http'; -import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; -import { httpInterceptor } from '@shared/interceptor/http.interceptor'; - -export const appConfig: ApplicationConfig = { - providers: [ - provideRouter(routes), - FontAwesomeModule, - provideHttpClient(withInterceptors([httpInterceptor])), - provideExperimentalZonelessChangeDetection(), - provideAnimationsAsync(), - ], -}; diff --git a/frontend/src/app/app.routes.ts b/frontend/src/app/app.routes.ts deleted file mode 100644 index 88f4fe1..0000000 --- a/frontend/src/app/app.routes.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Routes } from '@angular/router'; -import { LandingComponent } from './feature/landing/landing.component'; -import { authGuard } from './auth.guard'; - -export const routes: Routes = [ - { - path: '', - component: LandingComponent, - }, - { - path: 'home', - loadComponent: () => import('./feature/home/home.component'), - canActivate: [authGuard], - }, - { - path: 'verify', - loadComponent: () => import('./feature/auth/verify-email/verify-email.component'), - }, - { - path: 'recover-password', - loadComponent: () => import('./feature/auth/recover-password/recover-password.component'), - }, - { - path: 'reset-password', - loadComponent: () => import('./feature/auth/recover-password/recover-password.component'), - }, - { - path: 'oauth2/callback', - children: [ - { - path: 'github', - loadComponent: () => import('./feature/auth/oauth2/oauth2-callback.component'), - data: { provider: 'github' }, - }, - { - path: 'google', - loadComponent: () => import('./feature/auth/oauth2/oauth2-callback.component'), - data: { provider: 'google' }, - }, - ], - }, - { - path: 'game', - children: [ - { - path: 'blackjack', - loadComponent: () => import('./feature/game/blackjack/blackjack.component'), - canActivate: [authGuard], - }, - { - path: 'coinflip', - loadComponent: () => import('./feature/game/coinflip/coinflip.component'), - canActivate: [authGuard], - }, - { - path: 'slots', - loadComponent: () => import('./feature/game/slots/slots.component'), - canActivate: [authGuard], - }, - { - path: 'lootboxes', - loadComponent: () => - import('./feature/lootboxes/lootbox-selection/lootbox-selection.component'), - canActivate: [authGuard], - children: [ - { - path: 'open/:id', - loadComponent: () => - import('./feature/lootboxes/lootbox-opening/lootbox-opening.component'), - canActivate: [authGuard], - }, - ], - }, - { - path: 'dice', - loadComponent: () => import('./feature/game/dice/dice.component'), - canActivate: [authGuard], - }, - ], - }, -]; diff --git a/frontend/src/app/auth.guard.ts b/frontend/src/app/auth.guard.ts deleted file mode 100644 index ffb2526..0000000 --- a/frontend/src/app/auth.guard.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { CanActivateFn, Router } from '@angular/router'; -import { inject } from '@angular/core'; -import { AuthService } from '@service/auth.service'; - -export const authGuard: CanActivateFn = async () => { - const authService = inject(AuthService); - const router = inject(Router); - - if (authService.isLoggedIn()) { - return true; - } - - router.navigate(['']); - - return false; -}; diff --git a/frontend/src/app/feature/auth/login/login.component.html b/frontend/src/app/feature/auth/login/login.component.html deleted file mode 100644 index 044742c..0000000 --- a/frontend/src/app/feature/auth/login/login.component.html +++ /dev/null @@ -1,160 +0,0 @@ -
- -
diff --git a/frontend/src/app/feature/auth/login/login.component.ts b/frontend/src/app/feature/auth/login/login.component.ts deleted file mode 100644 index 09c1cdf..0000000 --- a/frontend/src/app/feature/auth/login/login.component.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { Component, EventEmitter, Output, signal } from '@angular/core'; -import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; -import { Router } from '@angular/router'; -import { LoginRequest } from '../../../model/auth/LoginRequest'; -import { AuthService } from '@service/auth.service'; -import { CommonModule } from '@angular/common'; -import { environment } from '@environments/environment'; - -@Component({ - selector: 'app-login', - standalone: true, - imports: [CommonModule, ReactiveFormsModule], - templateUrl: './login.component.html', -}) -export class LoginComponent { - loginForm: FormGroup; - errorMessage = signal(''); - isLoading = signal(false); - @Output() switchForm = new EventEmitter(); - @Output() closeDialog = new EventEmitter(); - @Output() forgotPassword = new EventEmitter(); - - constructor( - private fb: FormBuilder, - private authService: AuthService, - private router: Router - ) { - this.loginForm = this.fb.group({ - usernameOrEmail: ['', [Validators.required]], - password: ['', [Validators.required]], - }); - } - - get form() { - return this.loginForm.controls; - } - - switchToRegister(): void { - this.switchForm.emit(); - } - - onSubmit(): void { - if (this.loginForm.invalid) { - return; - } - - this.isLoading.set(true); - this.errorMessage.set(''); - - const loginRequest: LoginRequest = { - usernameOrEmail: this.form['usernameOrEmail'].value, - password: this.form['password'].value, - }; - - this.authService.login(loginRequest).subscribe({ - next: () => { - this.closeDialog.emit(); - this.router.navigate(['/home']); - }, - error: (err) => { - this.isLoading.set(false); - this.errorMessage.set( - err.error?.message || 'Failed to login. Please check your credentials.' - ); - }, - }); - } - - loginWithGithub(): void { - this.isLoading.set(true); - window.location.href = `${environment.apiUrl}/oauth2/github/authorize`; - } - - loginWithGoogle(): void { - this.isLoading.set(true); - window.location.href = `${environment.apiUrl}/oauth2/google/authorize`; - } - - switchToForgotPassword() { - this.forgotPassword.emit(); - } -} diff --git a/frontend/src/app/feature/auth/oauth2/oauth2-callback.component.ts b/frontend/src/app/feature/auth/oauth2/oauth2-callback.component.ts deleted file mode 100644 index 9c4bcf3..0000000 --- a/frontend/src/app/feature/auth/oauth2/oauth2-callback.component.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Component, computed, inject, OnInit, Signal } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { ActivatedRoute, Router } from '@angular/router'; -import { Oauth2Service } from './oauth2.service'; - -@Component({ - selector: 'app-oauth2-callback', - standalone: true, - imports: [CommonModule], - template: ` -
-
-

Authentifizierung...

-
-

{{ error() }}

-
-
- `, -}) -export default class OAuth2CallbackComponent implements OnInit { - error: Signal = computed(() => this.oauthService.error()); - - private route: ActivatedRoute = inject(ActivatedRoute); - private router: Router = inject(Router); - private oauthService: Oauth2Service = inject(Oauth2Service); - - ngOnInit(): void { - this.route.queryParams.subscribe((params) => { - const code = params['code']; - const provider = this.route.snapshot.data['provider'] || 'github'; - - if (code) { - this.oauthService.oauth(provider, code); - } else { - this.oauthService.error.set( - 'Authentifizierung fehlgeschlagen. Bitte versuchen Sie es erneut.' - ); - - setTimeout(() => { - this.router.navigate(['/']); - }, 3000); - } - }); - } -} diff --git a/frontend/src/app/feature/auth/oauth2/oauth2.service.ts b/frontend/src/app/feature/auth/oauth2/oauth2.service.ts deleted file mode 100644 index 79ad6d9..0000000 --- a/frontend/src/app/feature/auth/oauth2/oauth2.service.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { inject, Injectable, signal } from '@angular/core'; -import { Router } from '@angular/router'; -import { AuthService } from '@service/auth.service'; - -@Injectable({ - providedIn: 'root', -}) -export class Oauth2Service { - private router: Router = inject(Router); - private authService: AuthService = inject(AuthService); - private _error = signal(''); - - oauth(provider: string, code: string) { - const oauth$ = - provider === 'github' ? this.authService.githubAuth(code) : this.authService.googleAuth(code); - - oauth$.subscribe({ - next: () => { - this.router.navigate(['/home']); - }, - error: (err) => { - this._error.set( - err.error?.message || 'Authentifizierung fehlgeschlagen. Bitte versuchen Sie es erneut.' - ); - - setTimeout(() => { - this.router.navigate(['/']); - }, 3000); - }, - }); - } - - public get error() { - return this._error; - } -} diff --git a/frontend/src/app/feature/auth/recover-password/recover-password.component.html b/frontend/src/app/feature/auth/recover-password/recover-password.component.html deleted file mode 100644 index d89ce27..0000000 --- a/frontend/src/app/feature/auth/recover-password/recover-password.component.html +++ /dev/null @@ -1,170 +0,0 @@ - diff --git a/frontend/src/app/feature/auth/recover-password/recover-password.component.ts b/frontend/src/app/feature/auth/recover-password/recover-password.component.ts deleted file mode 100644 index 89f5d96..0000000 --- a/frontend/src/app/feature/auth/recover-password/recover-password.component.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { Component, EventEmitter, Output, signal, OnInit } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; -import { ActivatedRoute, Router, RouterModule } from '@angular/router'; -import { AuthService } from '@service/auth.service'; - -@Component({ - selector: 'app-recover-password', - standalone: true, - imports: [CommonModule, ReactiveFormsModule, RouterModule], - templateUrl: './recover-password.component.html', -}) -export default class RecoverPasswordComponent implements OnInit { - emailForm: FormGroup; - resetPasswordForm: FormGroup; - errorMessage = signal(''); - successMessage = signal(''); - isLoading = signal(false); - token = ''; - isResetMode = signal(false); - - @Output() closeDialog = new EventEmitter(); - @Output() switchToLogin = new EventEmitter(); - - constructor( - private fb: FormBuilder, - private authService: AuthService, - private router: Router, - private route: ActivatedRoute - ) { - this.emailForm = this.fb.group({ - email: ['', [Validators.required, Validators.email]], - }); - - this.resetPasswordForm = this.fb.group( - { - password: ['', [Validators.required, Validators.minLength(8)]], - confirmPassword: ['', [Validators.required]], - }, - { - validators: this.passwordMatchValidator, - } - ); - } - - ngOnInit(): void { - // Check if we're in reset mode via URL parameters - // This is still needed for direct access via URLs with token - this.route.queryParamMap.subscribe((params) => { - const token = params.get('token'); - if (token) { - this.token = token; - this.isResetMode.set(true); - } - }); - } - - passwordMatchValidator(form: FormGroup) { - const password = form.get('password')?.value; - const confirmPassword = form.get('confirmPassword')?.value; - return password === confirmPassword ? null : { passwordMismatch: true }; - } - - get emailFormControls() { - return this.emailForm.controls; - } - - get resetFormControls() { - return this.resetPasswordForm.controls; - } - - onSubmitEmail(): void { - if (this.emailForm.invalid) { - return; - } - - this.isLoading.set(true); - this.errorMessage.set(''); - this.successMessage.set(''); - - const email = this.emailFormControls['email'].value; - - this.authService.recoverPassword(email).subscribe({ - next: () => { - this.isLoading.set(false); - this.successMessage.set( - 'Wenn ein Konto mit dieser E-Mail existiert, wird eine E-Mail mit weiteren Anweisungen gesendet.' - ); - this.emailForm.reset(); - setTimeout(() => { - this.closeDialog.emit(); - this.switchToLogin.emit(); - }, 2000); - }, - error: (err) => { - this.isLoading.set(false); - this.errorMessage.set( - err.error?.message || 'Ein Fehler ist aufgetreten. Bitte versuche es später erneut.' - ); - }, - }); - } - - onSubmitReset(): void { - if (this.resetPasswordForm.invalid) { - return; - } - - this.isLoading.set(true); - this.errorMessage.set(''); - this.successMessage.set(''); - - const password = this.resetFormControls['password'].value; - - this.authService.resetPassword(this.token, password).subscribe({ - next: () => { - this.isLoading.set(false); - this.successMessage.set( - 'Dein Passwort wurde erfolgreich zurückgesetzt. Du kannst dich jetzt anmelden.' - ); - setTimeout(() => { - this.closeDialog.emit(); - this.switchToLogin.emit(); - }, 3000); - }, - error: (err) => { - this.isLoading.set(false); - this.errorMessage.set( - err.error?.message || 'Ein Fehler ist aufgetreten. Bitte versuche es später erneut.' - ); - }, - }); - } - - goBackToLogin(): void { - this.switchToLogin.emit(); - } -} diff --git a/frontend/src/app/feature/auth/register/register.component.html b/frontend/src/app/feature/auth/register/register.component.html deleted file mode 100644 index cf342b0..0000000 --- a/frontend/src/app/feature/auth/register/register.component.html +++ /dev/null @@ -1,140 +0,0 @@ -
- -
diff --git a/frontend/src/app/feature/auth/register/register.component.ts b/frontend/src/app/feature/auth/register/register.component.ts deleted file mode 100644 index 8ad38bb..0000000 --- a/frontend/src/app/feature/auth/register/register.component.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Component, EventEmitter, Output, signal } from '@angular/core'; -import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; -import { RegisterRequest } from '../../../model/auth/RegisterRequest'; -import { AuthService } from '@service/auth.service'; -import { CommonModule } from '@angular/common'; -import { HttpErrorResponse } from '@angular/common/http'; - -@Component({ - selector: 'app-register', - standalone: true, - imports: [CommonModule, ReactiveFormsModule], - templateUrl: './register.component.html', -}) -export class RegisterComponent { - registerForm: FormGroup; - errorMessage = signal(''); - isLoading = signal(false); - fieldErrors = signal>({}); - @Output() switchForm = new EventEmitter(); - @Output() closeDialog = new EventEmitter(); - - constructor( - private fb: FormBuilder, - private authService: AuthService - ) { - this.registerForm = this.fb.group({ - email: ['', [Validators.required, Validators.email]], - username: ['', [Validators.required, Validators.minLength(3)]], - password: ['', [Validators.required, Validators.minLength(6)]], - }); - } - - get form() { - return this.registerForm.controls; - } - - switchToLogin(): void { - this.switchForm.emit(); - } - - onSubmit(): void { - if (this.registerForm.invalid) { - return; - } - - this.isLoading.set(true); - this.errorMessage.set(''); - this.fieldErrors.set({}); - - const registerRequest: RegisterRequest = { - email: this.form['email'].value, - username: this.form['username'].value, - password: this.form['password'].value, - }; - - this.authService.register(registerRequest).subscribe({ - next: () => { - this.isLoading.set(false); - this.closeDialog.emit(); - this.switchToLogin(); - }, - error: (err: HttpErrorResponse) => { - this.isLoading.set(false); - - if (err.status === 409) { - const message = err.error?.message; - switch (message) { - case 'Email is already in use': - this.fieldErrors.update((errors) => ({ - ...errors, - email: 'Diese E-Mail-Adresse wird bereits verwendet.', - })); - break; - case 'Username is already taken': - this.fieldErrors.update((errors) => ({ - ...errors, - username: 'Dieser Benutzername ist bereits vergeben.', - })); - break; - } - } else { - this.errorMessage.set(err.error?.message || 'Failed to register. Please try again.'); - } - }, - }); - } -} diff --git a/frontend/src/app/feature/auth/verify-email/verify-email.component.html b/frontend/src/app/feature/auth/verify-email/verify-email.component.html deleted file mode 100644 index d7bc11c..0000000 --- a/frontend/src/app/feature/auth/verify-email/verify-email.component.html +++ /dev/null @@ -1 +0,0 @@ -

Verifying...

diff --git a/frontend/src/app/feature/auth/verify-email/verify-email.component.ts b/frontend/src/app/feature/auth/verify-email/verify-email.component.ts deleted file mode 100644 index 54f4c2f..0000000 --- a/frontend/src/app/feature/auth/verify-email/verify-email.component.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Component, inject, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { AuthService } from '@service/auth.service'; - -@Component({ - selector: 'app-verify-email', - imports: [], - templateUrl: './verify-email.component.html', -}) -export default class VerifyEmailComponent implements OnInit { - route: ActivatedRoute = inject(ActivatedRoute); - router: Router = inject(Router); - authService: AuthService = inject(AuthService); - - ngOnInit(): void { - const token = this.route.snapshot.queryParamMap.get('email-token'); - - if (!token) { - this.router.navigate(['/']); - console.log('no token'); - return; - } - - this.authService.verifyEmail(token).subscribe(() => { - this.router.navigate(['/'], { - queryParams: { login: true }, - }); - }); - } -} diff --git a/frontend/src/app/feature/deposit/deposit.component.html b/frontend/src/app/feature/deposit/deposit.component.html deleted file mode 100644 index e8e4dfb..0000000 --- a/frontend/src/app/feature/deposit/deposit.component.html +++ /dev/null @@ -1,25 +0,0 @@ -@if (isOpen) { - -} diff --git a/frontend/src/app/feature/deposit/deposit.component.ts b/frontend/src/app/feature/deposit/deposit.component.ts deleted file mode 100644 index 8768bbe..0000000 --- a/frontend/src/app/feature/deposit/deposit.component.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { - AfterViewInit, - ChangeDetectionStrategy, - ChangeDetectorRef, - Component, - ElementRef, - EventEmitter, - inject, - Input, - OnChanges, - OnDestroy, - OnInit, - Output, - SimpleChanges, - ViewChild, -} from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; -import { loadStripe, Stripe } from '@stripe/stripe-js'; -import { debounceTime } from 'rxjs'; -import { CommonModule } from '@angular/common'; -import gsap from 'gsap'; -import { DepositService } from '@service/deposit.service'; -import { environment } from '@environments/environment'; -import { ModalAnimationService } from '@shared/services/modal-animation.service'; - -@Component({ - selector: 'app-deposit', - standalone: true, - imports: [ReactiveFormsModule, CommonModule], - templateUrl: './deposit.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class DepositComponent implements OnInit, AfterViewInit, OnDestroy, OnChanges { - @Input() isOpen = false; - @Output() closeModalEmitter = new EventEmitter(); - @ViewChild('modalBg') modalBg!: ElementRef; - @ViewChild('modalCard') modalCard!: ElementRef; - protected form!: FormGroup; - protected errorMsg = ''; - private stripe: Stripe | null = null; - private service: DepositService = inject(DepositService); - private modalAnimationService: ModalAnimationService = inject(ModalAnimationService); - private cdr: ChangeDetectorRef = inject(ChangeDetectorRef); - - async ngOnInit() { - this.form = new FormGroup({ - amount: new FormControl(50, [Validators.min(50)]), - }); - - this.form.controls['amount'].valueChanges.pipe(debounceTime(1000)).subscribe((value) => { - if (value < 50) { - this.errorMsg = 'Minimum Einzahlungsbetrag ist 50€'; - } - }); - - this.stripe = await loadStripe(environment.STRIPE_KEY); - } - - ngAfterViewInit() { - if (this.isOpen) { - this.openModal(); - } - } - - ngOnChanges(changes: SimpleChanges) { - if (changes['isOpen']) { - this.cdr.detectChanges(); - setTimeout(() => { - if (this.modalBg?.nativeElement && this.modalCard?.nativeElement) { - if (changes['isOpen'].currentValue) { - this.openModal(); - } else { - this.closeModal(); - } - } - }, 0); - } - } - - ngOnDestroy() { - gsap.killTweensOf([this.modalBg?.nativeElement, this.modalCard?.nativeElement]); - } - - private openModal() { - if (this.modalBg?.nativeElement && this.modalCard?.nativeElement) { - this.modalAnimationService.openModal( - this.modalCard.nativeElement, - this.modalBg.nativeElement - ); - } - } - - submit() { - if (!this.stripe) { - this.errorMsg = 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.'; - return; - } - if (!this.form.valid) { - this.errorMsg = 'Bitte geben Sie einen gültigen Betrag ein.'; - return; - } - - this.service.handleDeposit(this.form.value.amount as number).subscribe(({ sessionId }) => { - this.stripe?.redirectToCheckout({ sessionId }); - }); - } - - public closeModal() { - if (this.modalBg?.nativeElement && this.modalCard?.nativeElement) { - this.modalAnimationService.closeModal( - this.modalCard.nativeElement, - this.modalBg.nativeElement, - () => this.closeModalEmitter.emit() - ); - } - } -} diff --git a/frontend/src/app/feature/game/blackjack/blackjack.component.html b/frontend/src/app/feature/game/blackjack/blackjack.component.html deleted file mode 100644 index 55ad5b1..0000000 --- a/frontend/src/app/feature/game/blackjack/blackjack.component.html +++ /dev/null @@ -1,44 +0,0 @@ -
-
-
- - - - @if (gameInProgress()) { - - } -
- -
- -
-
-
- - - - diff --git a/frontend/src/app/feature/game/blackjack/blackjack.component.ts b/frontend/src/app/feature/game/blackjack/blackjack.component.ts deleted file mode 100644 index e4b19b5..0000000 --- a/frontend/src/app/feature/game/blackjack/blackjack.component.ts +++ /dev/null @@ -1,242 +0,0 @@ -import { ChangeDetectionStrategy, Component, inject, OnInit, signal } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { Router } from '@angular/router'; -import { DealerHandComponent } from './components/dealer-hand/dealer-hand.component'; -import { PlayerHandComponent } from './components/player-hand/player-hand.component'; -import { GameControlsComponent } from './components/game-controls/game-controls.component'; -import { GameInfoComponent } from './components/game-info/game-info.component'; -import { BlackjackGame, Card } from '@blackjack/models/blackjack.model'; -import { BlackjackService } from '@blackjack/services/blackjack.service'; -import { HttpErrorResponse } from '@angular/common/http'; -import { GameResultComponent } from '@blackjack/components/game-result/game-result.component'; -import { GameState } from '@blackjack/enum/gameState'; -import { UserService } from '@service/user.service'; -import { timer } from 'rxjs'; -import { DebtDialogComponent } from '@shared/components/debt-dialog/debt-dialog.component'; -import { AuthService } from '@service/auth.service'; -import { AudioService } from '@shared/services/audio.service'; - -@Component({ - selector: 'app-blackjack', - standalone: true, - imports: [ - CommonModule, - DealerHandComponent, - PlayerHandComponent, - GameControlsComponent, - GameInfoComponent, - GameResultComponent, - DebtDialogComponent, - ], - templateUrl: './blackjack.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export default class BlackjackComponent implements OnInit { - private router = inject(Router); - private userService = inject(UserService); - private authService = inject(AuthService); - private blackjackService = inject(BlackjackService); - private audioService = inject(AudioService); - - dealerCards = signal([]); - playerCards = signal([]); - currentBet = signal(0); - balance = signal(0); - currentGameId = signal(undefined); - gameInProgress = signal(false); - gameState = signal(GameState.IN_PROGRESS); - showGameResult = signal(false); - - isActionInProgress = signal(false); - - showDebtDialog = signal(false); - debtAmount = signal(0); - - ngOnInit(): void { - // Subscribe to user updates for real-time balance changes - this.authService.userSubject.subscribe((user) => { - if (user) { - this.balance.set(user.balance); - } - }); - } - - private updateGameState(game: BlackjackGame) { - console.log('Game state update:', game); - this.currentGameId.set(game.id); - this.currentBet.set(game.bet); - this.gameInProgress.set(game.state === GameState.IN_PROGRESS); - this.gameState.set(game.state as GameState); - - const isGameOver = game.state !== GameState.IN_PROGRESS; - - this.dealerCards.set( - game.dealerCards.map((card, index) => ({ - ...card, - hidden: !isGameOver && index === 1 && game.state === GameState.IN_PROGRESS, - })) - ); - - this.playerCards.set( - game.playerCards.map((card) => ({ - ...card, - hidden: false, - })) - ); - - if (isGameOver) { - console.log('Game is over, state:', game.state); - this.userService.refreshCurrentUser(); - - // Get the latest balance before showing the result dialog - timer(1000).subscribe(() => { - // Show the result dialog after refreshing user data - timer(500).subscribe(() => { - this.showGameResult.set(true); - if (game.state === GameState.PLAYER_WON || game.state === GameState.PLAYER_BLACKJACK) { - this.audioService.playWinSound(); - } - console.log('Game result dialog shown after delay'); - }); - }); - } - } - - onNewGame(bet: number): void { - this.isActionInProgress.set(true); - this.audioService.playBetSound(); - - this.blackjackService.startGame(bet).subscribe({ - next: (game) => { - this.updateGameState(game); - this.userService.refreshCurrentUser(); - this.isActionInProgress.set(false); - }, - error: (error) => { - console.error('Failed to start game:', error); - this.isActionInProgress.set(false); - }, - }); - } - - onHit(): void { - if (!this.currentGameId() || this.isActionInProgress()) return; - - this.isActionInProgress.set(true); - this.audioService.playBetSound(); - - this.blackjackService.hit(this.currentGameId()!).subscribe({ - next: (game) => { - this.updateGameState(game); - if (game.state !== 'IN_PROGRESS') { - this.userService.refreshCurrentUser(); - } - this.isActionInProgress.set(false); - }, - error: (error) => { - console.error('Failed to hit:', error); - this.handleGameError(error); - this.isActionInProgress.set(false); - }, - }); - } - - onStand(): void { - if (!this.currentGameId() || this.isActionInProgress()) return; - - if (this.gameState() !== GameState.IN_PROGRESS) { - console.log('Cannot stand: game is not in progress'); - return; - } - - this.isActionInProgress.set(true); - this.audioService.playBetSound(); - - this.blackjackService.stand(this.currentGameId()!).subscribe({ - next: (game) => { - this.updateGameState(game); - this.userService.refreshCurrentUser(); - this.isActionInProgress.set(false); - }, - error: (error) => { - console.error('Failed to stand:', error); - this.handleGameError(error); - this.isActionInProgress.set(false); - }, - }); - } - - onDoubleDown(): void { - if (!this.currentGameId() || this.isActionInProgress()) return; - - if (this.gameState() !== GameState.IN_PROGRESS || this.playerCards().length !== 2) { - console.log('Cannot double down: game is not in progress or more than 2 cards'); - return; - } - - this.isActionInProgress.set(true); - this.audioService.playBetSound(); - - this.blackjackService.doubleDown(this.currentGameId()!).subscribe({ - next: (game) => { - this.updateGameState(game); - - // Wait a bit to ensure the backend has finished processing - timer(1000).subscribe(() => { - const user = this.authService.currentUserValue; - if (user && user.balance < 0) { - this.debtAmount.set(Math.abs(user.balance)); - this.showDebtDialog.set(true); - } - }); - - this.isActionInProgress.set(false); - }, - error: (error) => { - console.error('Failed to double down:', error); - this.handleGameError(error); - this.isActionInProgress.set(false); - }, - }); - } - - onCloseGameResult(): void { - console.log('Closing game result dialog'); - this.showGameResult.set(false); - } - - onCloseDebtDialog(): void { - this.showDebtDialog.set(false); - } - - private handleGameError(error: HttpErrorResponse): void { - if (error instanceof HttpErrorResponse) { - if (error.status === 400 && error.error?.error === 'Invalid state') { - this.gameInProgress.set(false); - this.userService.refreshCurrentUser(); - } else if (error.status === 500) { - console.log('Server error occurred. The game may have been updated in another session.'); - this.gameInProgress.set(false); - this.userService.refreshCurrentUser(); - if (this.currentGameId()) { - this.refreshGameState(this.currentGameId()!); - } - } - } - } - - private refreshGameState(gameId: number): void { - this.blackjackService.getGame(gameId).subscribe({ - next: (game) => { - this.updateGameState(game); - }, - error: (err) => { - console.error('Failed to refresh game state:', err); - }, - }); - } - - leaveGame(): void { - this.router.navigate(['/home']); - } -} diff --git a/frontend/src/app/feature/game/blackjack/components/animated-number/animated-number.component.ts b/frontend/src/app/feature/game/blackjack/components/animated-number/animated-number.component.ts deleted file mode 100644 index 6e61c0e..0000000 --- a/frontend/src/app/feature/game/blackjack/components/animated-number/animated-number.component.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { - AfterViewInit, - ChangeDetectionStrategy, - Component, - ElementRef, - Input, - OnChanges, - SimpleChanges, - ViewChild, -} from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { CountUp } from 'countup.js'; - -@Component({ - selector: 'app-animated-number', - standalone: true, - imports: [CommonModule], - template: ` {{ formattedValue }} `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class AnimatedNumberComponent implements OnChanges, AfterViewInit { - @Input() value = 0; - @Input() duration = 1; - @Input() ease = 'power1.out'; - - @ViewChild('numberElement') numberElement!: ElementRef; - - private countUp: CountUp | null = null; - private previousValue = 0; - formattedValue = '0,00 €'; - - ngAfterViewInit(): void { - this.initializeCountUp(); - if (this.countUp && this.value !== 0) { - this.countUp.start(() => { - this.previousValue = this.value; - }); - } - } - - ngOnChanges(changes: SimpleChanges): void { - if (changes['value']) { - if (this.countUp) { - const endVal = this.value; - - this.countUp.update(endVal); - this.previousValue = endVal; - } else { - this.formattedValue = new Intl.NumberFormat('de-DE', { - style: 'currency', - currency: 'EUR', - minimumFractionDigits: 2, - maximumFractionDigits: 2, - }).format(this.value); - } - } - } - - private initializeCountUp(): void { - if (this.numberElement) { - this.countUp = new CountUp(this.numberElement.nativeElement, this.value, { - startVal: this.previousValue, - duration: this.duration, - easingFn: (t, b, c, d) => { - if (this.ease === 'power1.out') { - return c * (1 - Math.pow(1 - t / d, 1)) + b; - } - return c * (t / d) + b; - }, - formattingFn: (value) => { - const formatted = new Intl.NumberFormat('de-DE', { - style: 'currency', - currency: 'EUR', - minimumFractionDigits: 2, - maximumFractionDigits: 2, - }).format(value); - this.formattedValue = formatted; - return formatted; - }, - }); - } - } -} diff --git a/frontend/src/app/feature/game/blackjack/components/dealer-hand/dealer-hand.component.ts b/frontend/src/app/feature/game/blackjack/components/dealer-hand/dealer-hand.component.ts deleted file mode 100644 index 3674d63..0000000 --- a/frontend/src/app/feature/game/blackjack/components/dealer-hand/dealer-hand.component.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { Card } from '@blackjack/models/blackjack.model'; -import { PlayingCardComponent } from '../playing-card/playing-card.component'; -import { GameControlsService } from '@blackjack/services/game-controls.service'; - -@Component({ - selector: 'app-dealer-hand', - standalone: true, - imports: [CommonModule, PlayingCardComponent], - template: ` -
-
-

Dealer's Karten

-
-
Punkte:
-
- {{ gameControlsService.calculateHandValue(cards) }} -
-
-
-
-
- @if (cards.length > 0) { - @for (card of cardsWithState; track card.id) { - - } - } @else { -
- Warte auf Spielstart... -
- } -
-
-
- `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class DealerHandComponent implements OnChanges { - @Input() cards: Card[] = []; - cardsWithState: (Card & { isNew: boolean; id: string })[] = []; - - private lastCardCount = 0; - - constructor(protected gameControlsService: GameControlsService) {} - - ngOnChanges(changes: SimpleChanges): void { - if (changes['cards']) { - this.updateCardsWithState(); - } - } - - private updateCardsWithState(): void { - const newCards = this.cards.length > this.lastCardCount; - - this.cardsWithState = this.cards.map((card, index) => { - const isNew = newCards && index >= this.lastCardCount; - - return { - ...card, - isNew, - id: `${card.suit}-${card.rank}-${index}`, - }; - }); - - this.lastCardCount = this.cards.length; - } -} diff --git a/frontend/src/app/feature/game/blackjack/components/game-controls/game-controls.component.ts b/frontend/src/app/feature/game/blackjack/components/game-controls/game-controls.component.ts deleted file mode 100644 index 9799b08..0000000 --- a/frontend/src/app/feature/game/blackjack/components/game-controls/game-controls.component.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { GameState } from '@blackjack/enum/gameState'; -import { Card } from '@blackjack/models/blackjack.model'; -import { GameControlsService } from '@blackjack/services/game-controls.service'; - -@Component({ - selector: 'app-game-controls', - standalone: true, - imports: [CommonModule], - template: ` -
-
-
-
- Deine Punkte: {{ gameControlsService.calculateHandValue(playerCards) }} -
-
- Status: - {{ - gameControlsService.getStatusText(gameState) - }} -
-
-
-
- - - - -
-
- `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class GameControlsComponent { - @Input() playerCards: Card[] = []; - @Input() gameState: GameState = GameState.IN_PROGRESS; - @Input() isActionInProgress = false; - - @Output() hit = new EventEmitter(); - @Output() stand = new EventEmitter(); - @Output() doubleDown = new EventEmitter(); - @Output() leave = new EventEmitter(); - - protected readonly GameState = GameState; - - constructor(protected gameControlsService: GameControlsService) {} - - get canDoubleDown(): boolean { - return ( - this.gameState === GameState.IN_PROGRESS && - this.playerCards.length === 2 && - !this.isActionInProgress - ); - } -} diff --git a/frontend/src/app/feature/game/blackjack/components/game-info/game-info.component.ts b/frontend/src/app/feature/game/blackjack/components/game-info/game-info.component.ts deleted file mode 100644 index 644fb22..0000000 --- a/frontend/src/app/feature/game/blackjack/components/game-info/game-info.component.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { - ChangeDetectionStrategy, - Component, - EventEmitter, - Input, - OnChanges, - Output, - signal, - SimpleChanges, -} from '@angular/core'; -import { CommonModule, CurrencyPipe } from '@angular/common'; -import { FormGroup, ReactiveFormsModule } from '@angular/forms'; -import { BettingService } from '@blackjack/services/betting.service'; -import { AnimatedNumberComponent } from '../animated-number/animated-number.component'; - -@Component({ - selector: 'app-game-info', - standalone: true, - imports: [CommonModule, CurrencyPipe, ReactiveFormsModule, AnimatedNumberComponent], - template: ` -
-

Spiel Informationen

-
-
- Aktuelle Wette: - - - -
- - @if (!gameInProgress) { -
- - - - -
- } - -
-
- - - @if (betForm.get('bet')?.errors?.['required'] && betForm.get('bet')?.touched) { - Bitte geben Sie einen Einsatz ein - } - @if (betForm.get('bet')?.errors?.['min'] && betForm.get('bet')?.touched) { - Mindestens 1€ setzen - } - @if (betForm.get('bet')?.errors?.['max'] && betForm.get('bet')?.touched) { - Nicht genügend Guthaben - } -
- -
-
-
- `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class GameInfoComponent implements OnChanges { - @Input() set balance(value: number) { - this._balance.set(value); - } - get balance() { - return this._balance(); - } - private _balance = signal(0); - - @Input() currentBet = 0; - @Input() gameInProgress = false; - @Input() isActionInProgress = false; - @Output() newGame = new EventEmitter(); - - betForm: FormGroup; - - constructor(private bettingService: BettingService) { - this.betForm = this.bettingService.createBetForm(); - } - - ngOnChanges(changes: SimpleChanges): void { - if (changes['balance']) { - this.bettingService.updateBetFormValidators(this.betForm, this.balance); - } - } - - setBetAmount(percentage: number) { - const betAmount = this.bettingService.calculateBetAmount(this.balance, percentage); - if (this.bettingService.isValidBet(betAmount, this.balance)) { - this.betForm.patchValue({ bet: betAmount }); - } - } - - onSubmit() { - if (this.betForm.valid) { - const betAmount = parseFloat(this.betForm.value.bet); - if (this.bettingService.isValidBet(betAmount, this.balance)) { - this.newGame.emit(betAmount); - this.betForm.reset(); - } - } - } -} diff --git a/frontend/src/app/feature/game/blackjack/components/game-result/game-result.component.ts b/frontend/src/app/feature/game/blackjack/components/game-result/game-result.component.ts deleted file mode 100644 index 1aab1a4..0000000 --- a/frontend/src/app/feature/game/blackjack/components/game-result/game-result.component.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { animate, style, transition, trigger } from '@angular/animations'; -import { GameState } from '../../enum/gameState'; -import { AnimatedNumberComponent } from '../animated-number/animated-number.component'; - -@Component({ - selector: 'app-game-result', - standalone: true, - imports: [CommonModule, AnimatedNumberComponent], - template: ` - - `, - changeDetection: ChangeDetectionStrategy.OnPush, - animations: [ - trigger('fadeInOut', [ - transition(':enter', [ - style({ opacity: 0 }), - animate('150ms ease-out', style({ opacity: 1 })), - ]), - transition(':leave', [animate('150ms ease-in', style({ opacity: 0 }))]), - ]), - trigger('cardAnimation', [ - transition(':enter', [ - style({ opacity: 0, transform: 'scale(0.95)' }), - animate('200ms ease-out', style({ opacity: 1, transform: 'scale(1)' })), - ]), - ]), - ], -}) -export class GameResultComponent { - @Input() gameState: GameState = GameState.IN_PROGRESS; - @Input() amount = 0; - @Input() balance = 0; - @Input() set show(value: boolean) { - console.log('GameResultComponent show input changed:', value, 'gameState:', this.gameState); - this.visible = value; - } - - @Output() gameResultClosed = new EventEmitter(); - - visible = false; - - get isWin(): boolean { - return this.gameState === GameState.PLAYER_WON || this.gameState === GameState.PLAYER_BLACKJACK; - } - - get isLoss(): boolean { - return this.gameState === GameState.PLAYER_LOST; - } - - get isDraw(): boolean { - return this.gameState === GameState.DRAW; - } - - getResultTitle(): string { - if (this.gameState === GameState.PLAYER_BLACKJACK) return 'Blackjack!'; - if (this.isWin) return 'Gewonnen!'; - if (this.isLoss) return 'Verloren!'; - if (this.isDraw) return 'Unentschieden!'; - return ''; - } - - getResultMessage(): string { - if (this.gameState === GameState.PLAYER_BLACKJACK) - return 'Glückwunsch! Du hast mit einem Blackjack gewonnen!'; - if (this.isWin) return 'Glückwunsch! Du hast diese Runde gewonnen.'; - if (this.isLoss) return 'Schade! Du hast diese Runde verloren.'; - if (this.isDraw) return 'Diese Runde endet unentschieden. Dein Einsatz wurde zurückgegeben.'; - return ''; - } - - getResultClass(): string { - if (this.gameState === GameState.PLAYER_BLACKJACK) return 'text-emerald font-bold'; - if (this.isWin) return 'text-emerald'; - if (this.isLoss) return 'text-accent-red'; - if (this.isDraw) return 'text-yellow-400'; - return ''; - } - - closeDialog(): void { - this.visible = false; - this.gameResultClosed.emit(); - console.log('Dialog closed by user'); - } -} diff --git a/frontend/src/app/feature/game/blackjack/components/player-hand/player-hand.component.ts b/frontend/src/app/feature/game/blackjack/components/player-hand/player-hand.component.ts deleted file mode 100644 index bca976c..0000000 --- a/frontend/src/app/feature/game/blackjack/components/player-hand/player-hand.component.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { PlayingCardComponent } from '../playing-card/playing-card.component'; -import { Card } from '@blackjack/models/blackjack.model'; -import { GameControlsService } from '@blackjack/services/game-controls.service'; - -@Component({ - selector: 'app-player-hand', - standalone: true, - imports: [CommonModule, PlayingCardComponent], - template: ` -
-
-

Deine Karten

-
-
Punkte:
-
- {{ gameControlsService.calculateHandValue(cards) }} -
-
-
-
-
- @if (cards.length > 0) { - @for (card of cardsWithState; track card.id) { - - } - } @else { -
- Platziere eine Wette um zu spielen... -
- } -
-
-
- `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class PlayerHandComponent implements OnChanges { - @Input() cards: Card[] = []; - cardsWithState: (Card & { isNew: boolean; id: string })[] = []; - - private lastCardCount = 0; - - constructor(protected gameControlsService: GameControlsService) {} - - ngOnChanges(changes: SimpleChanges): void { - if (changes['cards']) { - this.updateCardsWithState(); - } - } - - private updateCardsWithState(): void { - const newCards = this.cards.length > this.lastCardCount; - - this.cardsWithState = this.cards.map((card, index) => { - const isNew = newCards && index >= this.lastCardCount; - - return { - ...card, - isNew, - id: `${card.suit}-${card.rank}-${index}`, - }; - }); - - this.lastCardCount = this.cards.length; - } -} diff --git a/frontend/src/app/feature/game/blackjack/components/playing-card/playing-card.component.ts b/frontend/src/app/feature/game/blackjack/components/playing-card/playing-card.component.ts deleted file mode 100644 index 0fbbb5a..0000000 --- a/frontend/src/app/feature/game/blackjack/components/playing-card/playing-card.component.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { - AfterViewInit, - ChangeDetectionStrategy, - Component, - ElementRef, - Input, - OnChanges, - SimpleChanges, -} from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { gsap } from 'gsap'; -import { Suit, suitSymbols } from '@blackjack/models/blackjack.model'; - -@Component({ - selector: 'app-playing-card', - standalone: true, - imports: [CommonModule], - template: ` -
- @if (!hidden) { - {{ - getDisplayRank(rank) - }} - } - @if (!hidden) { - {{ getSuitSymbol(suit) }} - } - @if (!hidden) { - {{ getDisplayRank(rank) }} - } -
- `, - styles: [ - ` - .card-element { - transform-style: preserve-3d; - backface-visibility: hidden; - } - `, - ], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class PlayingCardComponent implements AfterViewInit, OnChanges { - @Input({ required: true }) rank!: string; - @Input({ required: true }) suit!: Suit; - @Input({ required: true }) hidden!: boolean; - @Input() isNew = false; - - constructor(private elementRef: ElementRef) {} - - get isRedSuit(): boolean { - return this.suit === 'HEARTS' || this.suit === 'DIAMONDS'; - } - - ngAfterViewInit(): void { - if (this.isNew) { - this.animateNewCard(); - } - } - - ngOnChanges(changes: SimpleChanges): void { - if (changes['hidden'] && !changes['hidden'].firstChange) { - this.animateCardFlip(); - } - } - - private animateNewCard(): void { - const cardElement = this.elementRef.nativeElement.querySelector('.card-element'); - gsap.fromTo( - cardElement, - { - y: -100, - opacity: 0, - rotation: -10, - scale: 0.7, - }, - { - y: 0, - opacity: 1, - rotation: 0, - scale: 1, - duration: 0.5, - ease: 'power2.out', - } - ); - } - - private animateCardFlip(): void { - const cardElement = this.elementRef.nativeElement.querySelector('.card-element'); - gsap.to(cardElement, { - rotationY: 180, - duration: 0.3, - onComplete: () => { - gsap.set(cardElement, { rotationY: 0 }); - }, - }); - } - - protected getSuitSymbol(suit: Suit): string { - return suitSymbols[suit]; - } - - protected getDisplayRank(rank: string): string { - const rankMap: Record = { - TWO: '2', - THREE: '3', - FOUR: '4', - FIVE: '5', - SIX: '6', - SEVEN: '7', - EIGHT: '8', - NINE: '9', - TEN: '10', - JACK: 'J', - QUEEN: 'Q', - KING: 'K', - ACE: 'A', - }; - return rankMap[rank] || rank; - } -} diff --git a/frontend/src/app/feature/game/blackjack/enum/gameState.ts b/frontend/src/app/feature/game/blackjack/enum/gameState.ts deleted file mode 100644 index 977e16d..0000000 --- a/frontend/src/app/feature/game/blackjack/enum/gameState.ts +++ /dev/null @@ -1,7 +0,0 @@ -export enum GameState { - PLAYER_WON = 'PLAYER_WON', - IN_PROGRESS = 'IN_PROGRESS', - PLAYER_LOST = 'PLAYER_LOST', - DRAW = 'DRAW', - PLAYER_BLACKJACK = 'PLAYER_BLACKJACK', -} diff --git a/frontend/src/app/feature/game/blackjack/models/blackjack.model.ts b/frontend/src/app/feature/game/blackjack/models/blackjack.model.ts deleted file mode 100644 index 55f2ee1..0000000 --- a/frontend/src/app/feature/game/blackjack/models/blackjack.model.ts +++ /dev/null @@ -1,23 +0,0 @@ -export type Suit = 'HEARTS' | 'DIAMONDS' | 'CLUBS' | 'SPADES'; - -export interface Card { - suit: Suit; - rank: string; - hidden: boolean; -} - -export interface BlackjackGame { - id: number; - state: string; - bet: number; - playerCards: Card[]; - dealerCards: Card[]; - userId: number; -} - -export const suitSymbols: Record = { - HEARTS: '♥', - DIAMONDS: '♦', - CLUBS: '♣', - SPADES: '♠', -}; diff --git a/frontend/src/app/feature/game/blackjack/models/card.model.ts b/frontend/src/app/feature/game/blackjack/models/card.model.ts deleted file mode 100644 index 79b5ad1..0000000 --- a/frontend/src/app/feature/game/blackjack/models/card.model.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface Card { - value: string; - suit: string; - hidden: boolean; -} diff --git a/frontend/src/app/feature/game/blackjack/services/betting.service.ts b/frontend/src/app/feature/game/blackjack/services/betting.service.ts deleted file mode 100644 index 347f19b..0000000 --- a/frontend/src/app/feature/game/blackjack/services/betting.service.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Injectable } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; - -@Injectable({ - providedIn: 'root', -}) -export class BettingService { - constructor(private fb: FormBuilder) {} - - createBetForm(): FormGroup { - return this.fb.group({ - bet: ['', [Validators.required, Validators.min(1)]], - }); - } - - updateBetFormValidators(form: FormGroup, balance: number): void { - form.reset(); - form - .get('bet') - ?.setValidators([Validators.required, Validators.min(1), Validators.max(balance)]); - form.get('bet')?.updateValueAndValidity(); - } - - calculateBetAmount(balance: number, percentage: number): number { - return Math.floor(balance * percentage * 100) / 100; - } - - isValidBet(betAmount: number, balance: number): boolean { - return betAmount >= 1 && betAmount <= balance; - } -} diff --git a/frontend/src/app/feature/game/blackjack/services/blackjack.service.ts b/frontend/src/app/feature/game/blackjack/services/blackjack.service.ts deleted file mode 100644 index 5e43dc7..0000000 --- a/frontend/src/app/feature/game/blackjack/services/blackjack.service.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { inject, Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { catchError, Observable } from 'rxjs'; -import { BlackjackGame } from '@blackjack/models/blackjack.model'; - -@Injectable({ - providedIn: 'root', -}) -export class BlackjackService { - private http = inject(HttpClient); - - startGame(bet: number): Observable { - return this.http - .post('/backend/blackjack/start', { betAmount: bet }, { responseType: 'json' }) - .pipe( - catchError((error) => { - console.error('Start game error:', error); - throw error; - }) - ); - } - - hit(gameId: number): Observable { - return this.http - .post(`/backend/blackjack/${gameId}/hit`, {}, { responseType: 'json' }) - .pipe( - catchError((error) => { - console.error('Hit error:', error); - throw error; - }) - ); - } - - stand(gameId: number): Observable { - return this.http - .post(`/backend/blackjack/${gameId}/stand`, {}, { responseType: 'json' }) - .pipe( - catchError((error) => { - console.error('Stand error:', error); - throw error; - }) - ); - } - - doubleDown(gameId: number): Observable { - return this.http - .post(`/backend/blackjack/${gameId}/doubleDown`, {}, { responseType: 'json' }) - .pipe( - catchError((error) => { - console.error('Double Down error:', error); - throw error; - }) - ); - } - - getGame(gameId: number): Observable { - return this.http - .get(`/backend/blackjack/${gameId}`, { responseType: 'json' }) - .pipe( - catchError((error) => { - console.error('Get game error:', error); - throw error; - }) - ); - } -} diff --git a/frontend/src/app/feature/game/blackjack/services/game-controls.service.ts b/frontend/src/app/feature/game/blackjack/services/game-controls.service.ts deleted file mode 100644 index fd055c8..0000000 --- a/frontend/src/app/feature/game/blackjack/services/game-controls.service.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Card } from '../models/blackjack.model'; -import { GameState } from '../enum/gameState'; - -@Injectable({ - providedIn: 'root', -}) -export class GameControlsService { - calculateHandValue(cards: Card[]): number { - let sum = 0; - let aceCount = 0; - - const rankValues: Record = { - TWO: 2, - THREE: 3, - FOUR: 4, - FIVE: 5, - SIX: 6, - SEVEN: 7, - EIGHT: 8, - NINE: 9, - TEN: 10, - JACK: 10, - QUEEN: 10, - KING: 10, - ACE: 11, - }; - - for (const card of cards) { - if (!card.hidden) { - const value = rankValues[card.rank] || 0; - sum += value; - if (card.rank === 'ACE') { - aceCount++; - } - } - } - - while (sum > 21 && aceCount > 0) { - sum -= 10; - aceCount--; - } - - return sum; - } - - getStatusText(state: GameState): string { - switch (state) { - case GameState.IN_PROGRESS: - return 'Spiel läuft'; - case GameState.PLAYER_WON: - return 'Gewonnen!'; - case GameState.PLAYER_LOST: - return 'Verloren!'; - case GameState.DRAW: - return 'Unentschieden!'; - default: - return state; - } - } - - getStatusClass(state: GameState): string { - switch (state) { - case GameState.PLAYER_WON: - return 'text-emerald'; - case GameState.PLAYER_LOST: - return 'text-accent-red'; - case GameState.DRAW: - return 'text-yellow-400'; - default: - return 'text-white'; - } - } -} diff --git a/frontend/src/app/feature/game/coinflip/coinflip.component.css b/frontend/src/app/feature/game/coinflip/coinflip.component.css deleted file mode 100644 index 06c9671..0000000 --- a/frontend/src/app/feature/game/coinflip/coinflip.component.css +++ /dev/null @@ -1,117 +0,0 @@ -/* Custom CSS for 3D Transformations and Coin Flip */ -@keyframes flipToHeads { - 0% { - transform: rotateY(0); - } - 100% { - transform: rotateY(1800deg); /* End with heads facing up (even number of Y rotations) */ - } -} - -@keyframes flipToTails { - 0% { - transform: rotateY(0); - } - 100% { - transform: rotateY(1980deg); /* End with tails facing up (odd number of Y rotations) */ - } -} - -.coin-container { - width: 180px; - height: 180px; - perspective: 1000px; - margin: 20px auto; -} - -.coin { - width: 100%; - height: 100%; - position: relative; - transform-style: preserve-3d; - transition: transform 0.01s; - transform: rotateY(0deg); - box-shadow: 0 0 30px rgba(0, 0, 0, 0.4); -} - -.coin-side { - width: 100%; - height: 100%; - position: absolute; - backface-visibility: hidden; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-weight: bold; - font-size: 24px; - box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.2); - border: 8px solid rgba(255, 255, 255, 0.2); -} - -.front { - background: linear-gradient(45deg, #ffd700, #ffb700); - color: #333; - z-index: 2; - transform: rotateY(0); -} - -.back { - background: linear-gradient(45deg, #5a5a5a, #333333); - color: white; - z-index: 1; - transform: rotateY(180deg); -} - -/* We apply transform directly to the SVG element in HTML */ - -/* Text for both sides */ -.coin-text { - /* Ensure text is readable */ - user-select: none; - pointer-events: none; -} - -/* Animation classes */ -.coin.animate-to-heads { - animation: flipToHeads 1s ease-in-out forwards; -} - -.coin.animate-to-tails { - animation: flipToTails 1s ease-in-out forwards; -} - -/* Make the buttons more responsive */ -button:not([disabled]) { - cursor: pointer; - transition: all 0.2s ease; -} - -button:not([disabled]):hover { - transform: translateY(-2px); - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); -} - -button:not([disabled]):active { - transform: translateY(1px); -} - -/* Animation for results */ -@keyframes popIn { - 0% { - transform: scale(0.8); - opacity: 0; - } - 70% { - transform: scale(1.1); - opacity: 1; - } - 100% { - transform: scale(1); - opacity: 1; - } -} - -.result-text { - animation: popIn 0.5s ease-out forwards; -} diff --git a/frontend/src/app/feature/game/coinflip/coinflip.component.html b/frontend/src/app/feature/game/coinflip/coinflip.component.html deleted file mode 100644 index 8dd6be8..0000000 --- a/frontend/src/app/feature/game/coinflip/coinflip.component.html +++ /dev/null @@ -1,141 +0,0 @@ -
-
-
- - @if (gameResult()) { -
-

- {{ gameResult()?.isWin ? 'Du hast gewonnen!' : 'Du hast verloren' }} -

-

- Münze zeigt: - {{ gameResult()?.coinSide === 'HEAD' ? 'KOPF' : 'ZAHL' }} -

- @if (gameResult()?.isWin) { -

- +{{ gameResult()?.payout | currency: 'EUR' }} -

- } -
- } - - - @if (errorMessage()) { -
-

{{ errorMessage() }}

-
- } - - -
-
- -
-
KOPF
-
- - -
- - ZAHL -
-
-
- - -
- - -
-
- - -
-
-

Spielinformationen

-
- -
- Aktueller Einsatz: - - € - -
- - -
- Dein Guthaben: - - {{ balance() | currency: 'EUR' }} - -
- - - @if (!gameInProgress()) { -
- - - - -
- } - - -
-
- - Darf Guthaben nicht überschreiten -
- -
- - -
-

Spielregeln

-
    -
  • • Wähle deinen Einsatzbetrag
  • -
  • • Wähle Kopf oder Zahl
  • -
  • • Gewinne das Doppelte deines Einsatzes bei richtiger Wahl
  • -
-
-
-
-
-
-
diff --git a/frontend/src/app/feature/game/coinflip/coinflip.component.ts b/frontend/src/app/feature/game/coinflip/coinflip.component.ts deleted file mode 100644 index 112a300..0000000 --- a/frontend/src/app/feature/game/coinflip/coinflip.component.ts +++ /dev/null @@ -1,250 +0,0 @@ -import { NgClass, NgIf, CurrencyPipe, CommonModule } from '@angular/common'; -import { HttpClient } from '@angular/common/http'; -import { FormsModule } from '@angular/forms'; -import { - ChangeDetectionStrategy, - Component, - ElementRef, - inject, - OnInit, - signal, - ViewChild, -} from '@angular/core'; -import { AnimatedNumberComponent } from '@blackjack/components/animated-number/animated-number.component'; -import { catchError, finalize } from 'rxjs/operators'; -import { of } from 'rxjs'; -import { AuthService } from '@service/auth.service'; -import { AudioService } from '@shared/services/audio.service'; -import { CoinflipGame, CoinflipRequest } from './models/coinflip.model'; - -@Component({ - selector: 'app-coinflip', - standalone: true, - imports: [AnimatedNumberComponent, CurrencyPipe, FormsModule, CommonModule, NgIf, NgClass], - templateUrl: './coinflip.component.html', - styleUrl: './coinflip.component.css', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export default class CoinflipComponent implements OnInit { - currentBet = signal(10); - balance = signal(0); - gameInProgress = signal(false); - isActionInProgress = signal(false); - gameResult = signal(null); - betInputValue = signal(10); - errorMessage = signal(''); - isInvalidBet = signal(false); - - @ViewChild('coinElement') coinElement?: ElementRef; - - audioService = inject(AudioService); - authService = inject(AuthService); - private http = inject(HttpClient); - - private coinflipSound?: HTMLAudioElement; - - ngOnInit(): void { - // Abonniere Benutzerupdates für Echtzeitaktualisierungen des Guthabens - this.authService.userSubject.subscribe((user) => { - if (user) { - this.balance.set(user.balance); - } - }); - - // Initialisiere Münzwurf-Sound - this.coinflipSound = new Audio('/sounds/coinflip.mp3'); - } - - setBetAmount(percentage: number) { - const newBet = Math.floor(this.balance() * percentage); - this.betInputValue.set(newBet > 0 ? newBet : 1); - this.currentBet.set(this.betInputValue()); - } - - updateBet(event: Event) { - const inputElement = event.target as HTMLInputElement; - let value = Number(inputElement.value); - - // Setze ungültigen Einsatz-Status zurück - this.isInvalidBet.set(false); - - // Erzwinge Mindesteinsatz von 1 - if (value <= 0) { - value = 1; - } - - // Begrenze Einsatz auf verfügbares Guthaben und zeige Feedback - if (value > this.balance()) { - value = this.balance(); - // Visuelles Feedback anzeigen - this.isInvalidBet.set(true); - // Zeige den Fehler kurz an - setTimeout(() => this.isInvalidBet.set(false), 800); - // Aktualisiere das Eingabefeld direkt, um dem Benutzer den maximalen Wert anzuzeigen - inputElement.value = String(value); - } - - // Aktualisiere Signale - this.betInputValue.set(value); - this.currentBet.set(value); - } - - betHeads() { - this.placeBet('HEAD'); - } - - betTails() { - this.placeBet('TAILS'); - } - - private placeBet(side: 'HEAD' | 'TAILS') { - if (this.gameInProgress() || this.isActionInProgress()) return; - - // Setze vorheriges Ergebnis zurück - this.gameResult.set(null); - this.errorMessage.set(''); - - // Setze Spielstatus - this.gameInProgress.set(true); - this.isActionInProgress.set(true); - - // Spiele Einsatz-Sound - this.audioService.playBetSound(); - - // Erstelle Einsatz-Anfrage - const request: CoinflipRequest = { - betAmount: this.currentBet(), - coinSide: side, - }; - - // API aufrufen - this.http - .post('/backend/coinflip', request) - .pipe( - catchError((error) => { - console.error('Fehler beim Spielen von Coinflip:', error); - - if (error.status === 400 && error.error.message.includes('insufficient')) { - this.errorMessage.set('Unzureichendes Guthaben'); - } else { - this.errorMessage.set('Ein Fehler ist aufgetreten. Bitte versuche es erneut.'); - } - - this.gameInProgress.set(false); - return of(null); - }), - finalize(() => { - this.isActionInProgress.set(false); - }) - ) - .subscribe((result) => { - if (!result) return; - - console.log('API-Antwort:', result); - - // Behebe mögliche Inkonsistenzen bei der Eigenschaftenbenennung vom Backend - const fixedResult: CoinflipGame = { - isWin: result.isWin ?? result.win, - payout: result.payout, - coinSide: result.coinSide, - }; - - console.log('Korrigiertes Ergebnis:', fixedResult); - - // Spiele Münzwurf-Animation und -Sound - this.playCoinFlipAnimation(fixedResult.coinSide); - - // Setze Ergebnis nach Abschluss der Animation - setTimeout(() => { - this.gameResult.set(fixedResult); - - // Aktualisiere Guthaben mit neuem Wert vom Auth-Service - this.authService.loadCurrentUser(); - - // Spiele Gewinn-Sound, wenn der Spieler gewonnen hat - if (fixedResult.isWin) { - this.audioService.playWinSound(); - } - - // Setze Spielstatus nach Anzeigen des Ergebnisses zurück - setTimeout(() => { - this.gameInProgress.set(false); - }, 1500); - }, 1100); // Kurz nach Ende der Animation - }); - } - - private playCoinFlipAnimation(result: 'HEAD' | 'TAILS') { - if (!this.coinElement) return; - - const coinEl = this.coinElement.nativeElement; - - // Setze bestehende Animationen zurück - coinEl.classList.remove('animate-to-heads', 'animate-to-tails'); - - // Setze alle Inline-Styles von vorherigen Animationen zurück - coinEl.style.transform = ''; - - // Erzwinge Reflow, um Animation neu zu starten - void coinEl.offsetWidth; - - // Spiele Münzwurf-Sound - if (this.coinflipSound) { - this.coinflipSound.currentTime = 0; - this.coinflipSound - .play() - .catch((err) => console.error('Fehler beim Abspielen des Sounds:', err)); - } - - // Füge passende Animationsklasse basierend auf dem Ergebnis hinzu - if (result === 'HEAD') { - coinEl.classList.add('animate-to-heads'); - } else { - coinEl.classList.add('animate-to-tails'); - } - - console.log(`Animation angewendet für Ergebnis: ${result}`); - } - - /** - * Validiert Eingabe während der Benutzer tippt, um ungültige Werte zu verhindern - */ - validateBetInput(event: KeyboardEvent) { - // Erlaube Navigationstasten (Pfeile, Entf, Rücktaste, Tab) - const navigationKeys = ['ArrowLeft', 'ArrowRight', 'Delete', 'Backspace', 'Tab']; - if (navigationKeys.includes(event.key)) { - return; - } - - // Erlaube nur Zahlen - if (!/^\d$/.test(event.key)) { - event.preventDefault(); - return; - } - - // Ermittle den Wert, der nach dem Tastendruck entstehen würde - const input = event.target as HTMLInputElement; - const currentValue = input.value; - const cursorPosition = input.selectionStart || 0; - const newValue = - currentValue.substring(0, cursorPosition) + - event.key + - currentValue.substring(input.selectionEnd || cursorPosition); - const numValue = Number(newValue); - - // Verhindere Werte, die größer als das Guthaben sind - if (numValue > this.balance()) { - event.preventDefault(); - } - } - - // Der Paste-Handler wurde der Einfachheit halber entfernt, da die updateBet-Methode - // jeden Wert behandelt, der in das Eingabefeld gelangt - - getResultClass() { - if (!this.gameResult()) return ''; - const result = this.gameResult(); - const isWinner = result?.isWin || result?.win; - return isWinner ? 'text-emerald-500' : 'text-accent-red'; - } -} diff --git a/frontend/src/app/feature/game/coinflip/models/coinflip.model.ts b/frontend/src/app/feature/game/coinflip/models/coinflip.model.ts deleted file mode 100644 index f87a3f9..0000000 --- a/frontend/src/app/feature/game/coinflip/models/coinflip.model.ts +++ /dev/null @@ -1,11 +0,0 @@ -export interface CoinflipGame { - isWin?: boolean; - win?: boolean; - payout: number; - coinSide: 'HEAD' | 'TAILS'; -} - -export interface CoinflipRequest { - betAmount: number; - coinSide: 'HEAD' | 'TAILS'; -} diff --git a/frontend/src/app/feature/game/dice/dice.component.html b/frontend/src/app/feature/game/dice/dice.component.html deleted file mode 100644 index 6cf5d12..0000000 --- a/frontend/src/app/feature/game/dice/dice.component.html +++ /dev/null @@ -1,305 +0,0 @@ -
-

Dice

-
-
-
-
-
-
-

- Zielwert: - {{ - diceForm.get('targetValue')?.value | number: '1.0-2' - }} -

-
- -
-
- 0 - 25 - 50 - 75 - 100 -
- - - -
-
- - - -
-
- {{ potentialWin() | currency: 'EUR' : 'symbol' : '1.2-2' }} -
- - - {{ diceForm.get('rollOver')?.value ? '>' : '<' }} - -
- - - - @if (rolledValue() !== null) { -
-
-
- } -
- -
- @for (i of [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]; track i) { -
- } -
-
- - @if ( - hasError('targetValue', 'required') || - hasError('targetValue', 'min') || - hasError('targetValue', 'max') - ) { -
- @if (hasError('targetValue', 'required')) { - Zielwert ist erforderlich - } - @if (hasError('targetValue', 'min')) { - Zielwert muss mindestens 1 sein - } - @if (hasError('targetValue', 'max')) { - Zielwert darf höchstens 99 sein - } -
- } -
- -
- - -
-
-
- - @if (rolledValue() !== null) { -
-
- @if (win()) { - - - -

- Du hast gewonnen! Auszahlung: {{ payout() | currency: 'EUR' : 'symbol' : '1.2-2' }} -

- } @else { - - - -

Du hast verloren.

- } -
-
- } -
- -
-
-

Spielinformationen

-
-
- Möglicher Gewinn: - {{ - potentialWin() | currency: 'EUR' : 'symbol' : '1.2-2' - }} -
- -
- Gewinnchance: - {{ winChance() | number: '1.0-2' }}% -
- -
- - - - -
- -
-
- -
- - @if (hasError('betAmount', 'required')) { - Einsatz ist erforderlich - } - @if (hasError('betAmount', 'min')) { - Einsatz muss mindestens 0.01 sein - } -
- - - -
-

Spielanleitung

-
    -
  • • Setze deinen Einsatz und Zielwert
  • -
  • • Wähle "Über Zielwert" oder "Unter Zielwert"
  • -
  • • Gewinne, wenn der Würfel zu deinen Gunsten fällt
  • -
  • • Höheres Risiko = höhere Belohnung
  • -
-
-
-
-
-
-
diff --git a/frontend/src/app/feature/game/dice/dice.component.ts b/frontend/src/app/feature/game/dice/dice.component.ts deleted file mode 100644 index aaca5c5..0000000 --- a/frontend/src/app/feature/game/dice/dice.component.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { Component, inject, OnInit, signal } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { - FormBuilder, - FormControl, - FormGroup, - ReactiveFormsModule, - Validators, -} from '@angular/forms'; -import { DiceService } from './dice.service'; -import { DiceDto, DiceResult } from './dice.model'; -import { tap } from 'rxjs/operators'; -import { UserService } from '@service/user.service'; -import { PlaySoundDirective } from '@shared/directives/play-sound.directive'; -import { DragSoundDirective } from '@shared/directives/drag-sound.directive'; -import { AudioService } from '@shared/services/audio.service'; - -type DiceFormGroup = FormGroup<{ - betAmount: FormControl; - rollOver: FormControl; - targetValue: FormControl; -}>; - -@Component({ - selector: 'app-dice', - standalone: true, - imports: [CommonModule, ReactiveFormsModule, PlaySoundDirective, DragSoundDirective], - templateUrl: './dice.component.html', -}) -export default class DiceComponent implements OnInit { - private readonly formBuilder = inject(FormBuilder); - private readonly diceService = inject(DiceService); - private readonly userService = inject(UserService); - private readonly audioService = inject(AudioService); - - rolledValue = signal(null); - win = signal(null); - payout = signal(null); - winChance = signal(0); - potentialWin = signal(0); - - readonly diceForm: DiceFormGroup = this.createDiceForm(); - - private readonly MAX_DICE_VALUE = 100; - - ngOnInit(): void { - this.diceForm.valueChanges - .pipe(tap(() => this.calculateWinChanceAndPotentialWin())) - .subscribe(); - - this.calculateWinChanceAndPotentialWin(); - } - - createDiceForm(): DiceFormGroup { - return this.formBuilder.group({ - betAmount: new FormControl(1, { - validators: [Validators.required, Validators.min(1)], - nonNullable: true, - }), - rollOver: new FormControl(true, { - validators: [Validators.required], - nonNullable: true, - }), - targetValue: new FormControl(50, { - validators: [Validators.required, Validators.min(1), Validators.max(99)], - nonNullable: true, - }), - }); - } - - toggleRollMode(): void { - const currentMode = this.diceForm.get('rollOver')?.value ?? true; - this.diceForm.get('rollOver')?.setValue(!currentMode); - } - - calculateWinChanceAndPotentialWin(): void { - const formValues = this.diceForm.value; - const target = formValues.targetValue ?? 0; - const bet = formValues.betAmount ?? 0; - const isOver = formValues.rollOver ?? true; - - const calculatedWinChance = isOver ? this.MAX_DICE_VALUE - target : target - 1; - - this.winChance.set(Math.max(0, calculatedWinChance)); - - let multiplier = 0; - if (calculatedWinChance > 0) { - multiplier = (this.MAX_DICE_VALUE - 1) / calculatedWinChance; - } - - this.potentialWin.set(bet * multiplier); - } - - roll(): void { - if (this.diceForm.invalid) { - this.diceForm.markAllAsTouched(); - return; - } - - const diceDto: DiceDto = this.diceForm.getRawValue() as DiceDto; - - this.rolledValue.set(null); - this.win.set(null); - this.payout.set(null); - - this.diceService.rollDice(diceDto).subscribe({ - next: (result: DiceResult) => { - this.rolledValue.set(result.rolledValue); - this.win.set(result.win); - this.payout.set(result.payout); - - if (result.win) { - this.audioService.playWinSound(); - } - - this.userService.refreshCurrentUser(); - }, - error: (error) => { - console.error('Dice roll failed:', error); - }, - }); - } - - setBetAmount(percentage: number): void { - const user = this.userService['authService'].currentUserValue; - if (!user) return; - - const balance = user.balance || 0; - - const newBet = Math.max(1, Math.floor(balance * percentage * 100) / 100); - - this.diceForm.get('betAmount')?.setValue(newBet); - this.calculateWinChanceAndPotentialWin(); - } - - getTrackGradient(): string { - const targetValue = this.diceForm.get('targetValue')?.value ?? 50; - const isRollOver = this.diceForm.get('rollOver')?.value ?? true; - - if (isRollOver) { - return `linear-gradient(to right, var(--color-accent-red) ${targetValue}%, var(--color-emerald) ${targetValue}%)`; - } else { - return `linear-gradient(to right, var(--color-accent-red) ${targetValue}%, var(--color-emerald) ${targetValue}%)`; - } - } - - hasError(controlName: string, errorName: string): boolean { - const control = this.diceForm.get(controlName); - return control !== null && control.touched && control.hasError(errorName); - } -} diff --git a/frontend/src/app/feature/game/dice/dice.model.ts b/frontend/src/app/feature/game/dice/dice.model.ts deleted file mode 100644 index 93a1133..0000000 --- a/frontend/src/app/feature/game/dice/dice.model.ts +++ /dev/null @@ -1,11 +0,0 @@ -export interface DiceDto { - betAmount: number; - rollOver: boolean; - targetValue: number; -} - -export interface DiceResult { - win: boolean; - payout: number; - rolledValue: number; -} diff --git a/frontend/src/app/feature/game/dice/dice.service.ts b/frontend/src/app/feature/game/dice/dice.service.ts deleted file mode 100644 index a071495..0000000 --- a/frontend/src/app/feature/game/dice/dice.service.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { Observable } from 'rxjs'; -import { DiceDto, DiceResult } from './dice.model'; -import { environment } from '@environments/environment'; - -@Injectable({ - providedIn: 'root', -}) -export class DiceService { - private apiUrl = `${environment.apiUrl}/dice`; - - constructor(private http: HttpClient) {} - - rollDice(diceDto: DiceDto): Observable { - return this.http.post(this.apiUrl, diceDto); - } -} diff --git a/frontend/src/app/feature/game/slots/slots.component.css b/frontend/src/app/feature/game/slots/slots.component.css deleted file mode 100644 index c1fa452..0000000 --- a/frontend/src/app/feature/game/slots/slots.component.css +++ /dev/null @@ -1,16 +0,0 @@ -/* Symbol colors */ -.symbol-BAR { - color: var(--color-accent-yellow); -} -.symbol-SEVEN { - color: var(--color-accent-red); -} -.symbol-BELL { - color: var(--color-accent-purple); -} -.symbol-CHERRY { - color: #ec4899; -} -.symbol-LEMON { - color: #a3e635; -} diff --git a/frontend/src/app/feature/game/slots/slots.component.html b/frontend/src/app/feature/game/slots/slots.component.html deleted file mode 100644 index b7ddcf6..0000000 --- a/frontend/src/app/feature/game/slots/slots.component.html +++ /dev/null @@ -1,173 +0,0 @@ -
-

Spielautomaten

- -
-
-
-
-
-
-

Slot Machine

- - +{{ slotResult().amount | currency: 'EUR' }} - -
- -
- - {{ - slotResult().status === 'win' - ? 'Gewonnen!' - : slotResult().status === 'lose' - ? 'Verloren' - : 'Bereit' - }} - -
-
-
- -
-
-
- @for (row of slotResult().resultMatrix; track $index) { - @for (cell of row; track $index) { -
- {{ - cell - }} -
- } - } -
-
- -
-
- - -
- - -
-
-
-
- -
-
-

Spiel Informationen

-
-
- Kontostand: - - - -
-
- Einsatz: - - - -
- -
- - - - -
- -

Auszahlungen:

- - @if (slotInfo(); as info) { -
    - @for (item of info | keyvalue; track item.key) { -
  • -
    - {{ item.key }} -
    - {{ item.value }}x -
  • - } -
- } @else { -
-
-
- } - -
-

Spielregeln:

-
    -
  • • Gewinne mit 3 gleichen Symbolen
  • -
  • • Höhere Symbole = höhere Gewinne
  • -
-
-
-
-
-
-
diff --git a/frontend/src/app/feature/game/slots/slots.component.ts b/frontend/src/app/feature/game/slots/slots.component.ts deleted file mode 100644 index b297875..0000000 --- a/frontend/src/app/feature/game/slots/slots.component.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { - ChangeDetectionStrategy, - Component, - inject, - OnDestroy, - OnInit, - signal, -} from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { CommonModule, CurrencyPipe, KeyValuePipe, NgClass } from '@angular/common'; -import { FormsModule } from '@angular/forms'; -import { UserService } from '@service/user.service'; -import { Subscription } from 'rxjs'; -import { AnimatedNumberComponent } from '@blackjack/components/animated-number/animated-number.component'; -import { AuthService } from '@service/auth.service'; - -interface SlotResult { - status: 'win' | 'lose' | 'blank' | 'start'; - amount: number; - resultMatrix: string[][]; -} - -@Component({ - selector: 'app-slots', - standalone: true, - imports: [ - CommonModule, - KeyValuePipe, - NgClass, - FormsModule, - CurrencyPipe, - AnimatedNumberComponent, - ], - templateUrl: './slots.component.html', - styleUrl: './slots.component.css', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export default class SlotsComponent implements OnInit, OnDestroy { - private httpClient: HttpClient = inject(HttpClient); - private userService = inject(UserService); - private authService = inject(AuthService); - private userSubscription: Subscription | undefined; - private winSound: HTMLAudioElement; - - slotInfo = signal | null>(null); - slotResult = signal({ - status: 'start', - amount: 0, - resultMatrix: [ - ['BAR', 'BAR', 'BAR'], - ['SEVEN', 'SEVEN', 'SEVEN'], - ['BELL', 'BELL', 'BELL'], - ], - }); - - balance = signal(0); - betAmount = signal(1); - isSpinning = false; - - constructor() { - this.winSound = new Audio('/sounds/win.mp3'); - } - - ngOnInit(): void { - this.httpClient.get>('/backend/slots/info').subscribe((data) => { - this.slotInfo.set(data); - }); - - this.userSubscription = this.authService.userSubject.subscribe((user) => { - this.balance.set(user?.balance ?? 0); - }); - - this.userService.refreshCurrentUser(); - } - - ngOnDestroy(): void { - if (this.userSubscription) { - this.userSubscription.unsubscribe(); - } - } - - getSymbolClass(symbol: string): string { - return `symbol-${symbol}`; - } - - hasEnoughBalance(): boolean { - return this.balance() >= this.betAmount(); - } - - setBetAmount(percentage: number): void { - const calculatedBet = Math.floor(this.balance() * percentage * 100) / 100; - const minimumBet = 0.01; - - const newBet = Math.max(minimumBet, Math.min(calculatedBet, this.balance())); - - this.betAmount.set(newBet); - } - - spin(): void { - if (!this.hasEnoughBalance()) { - return; - } - - this.isSpinning = true; - const betAmount = this.betAmount(); - - this.userService.updateLocalBalance(-betAmount); - - const payload = { - betAmount: betAmount, - }; - - this.httpClient.post('/backend/slots/spin', payload).subscribe({ - next: (result) => { - setTimeout(() => { - this.slotResult.set(result); - - if (result.status === 'win') { - this.winSound.play(); - this.userService.updateLocalBalance(result.amount); - } - - this.userService.refreshCurrentUser(); - - this.isSpinning = false; - }, 100); - }, - error: (err) => { - console.error('Error spinning slot machine:', err); - this.userService.updateLocalBalance(betAmount); - this.userService.refreshCurrentUser(); - this.isSpinning = false; - }, - }); - } -} diff --git a/frontend/src/app/feature/home/home.component.html b/frontend/src/app/feature/home/home.component.html deleted file mode 100644 index fae788a..0000000 --- a/frontend/src/app/feature/home/home.component.html +++ /dev/null @@ -1,95 +0,0 @@ -
-
-
-
- -
-
-
-

Alle Spiele

-
- - -
-
- -
-
-
-
- -
-
-

{{ game.name }}

- -
-
-
-
-
-
-
- -
-
-

Konto

-
- - - - -
-
- - - -
-

Letzte Transaktionen

-
-
-
-

{{ transaction.status }}

-

- {{ transaction.createdAt | date: 'd.m.Y H:m' }} -

-
- - {{ transaction.amount | currency: 'EUR' }} - -
-
-
-
-
-
diff --git a/frontend/src/app/feature/home/home.component.ts b/frontend/src/app/feature/home/home.component.ts deleted file mode 100644 index 1fad4cb..0000000 --- a/frontend/src/app/feature/home/home.component.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core'; -import { AsyncPipe, CurrencyPipe, DatePipe, NgFor } from '@angular/common'; -import { DepositComponent } from '../deposit/deposit.component'; -import { ActivatedRoute, Router } from '@angular/router'; -import { ConfirmationComponent } from '@shared/components/confirmation/confirmation.component'; -import { Game } from 'app/model/Game'; -import { Observable } from 'rxjs'; -import { TransactionService } from '@service/transaction.service'; -import format from 'ajv/dist/vocabularies/format'; -import { TransactionHistoryComponent } from '../transaction-history/transaction-history.component'; -import { TransactionData } from '../../model/TransactionData'; - -@Component({ - selector: 'app-homepage', - standalone: true, - imports: [ - CurrencyPipe, - NgFor, - DepositComponent, - ConfirmationComponent, - AsyncPipe, - DatePipe, - TransactionHistoryComponent, - ], - templateUrl: './home.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export default class HomeComponent implements OnInit { - isDepositModalOpen = false; - isDepositSuccessful = false; - isTransactionModalOpen = false; - - constructor( - public route: ActivatedRoute, - public router: Router - ) {} - - ngOnInit() { - this.isDepositSuccessful = this.route.snapshot.queryParams['success'] == 'true'; - - this.router.navigate([], { queryParams: {} }); - - if (this.isDepositSuccessful) { - this.openDepositConfirmationModal(); - } - } - - featuredGames: Game[] = [ - { - id: '1', - name: 'Coinflip', - image: '/coinflip.png', - route: '/game/coinflip', - }, - { - id: '2', - name: 'Blackjack', - image: '/blackjack.webp', - route: '/game/blackjack', - }, - { - id: '3', - name: 'Slots', - image: '/slots.webp', - route: '/game/slots', - }, - { - id: '4', - name: 'Plinko', - image: '/plinko.webp', - route: '/game/plinko', - }, - { - id: '5', - name: 'Dice', - image: '/liars-dice.webp', - route: '/game/dice', - }, - { - id: '6', - name: 'Lootboxen', - image: '/lootbox.webp', - route: '/game/lootboxes', - }, - ]; - - allGames: Game[] = [...this.featuredGames]; - - recentTransactionData: Observable = - inject(TransactionService).getUsersTransactions(5); - - openDepositModal() { - this.isDepositModalOpen = true; - } - - closeDepositModal() { - this.isDepositModalOpen = false; - } - - openDepositConfirmationModal() { - this.isDepositSuccessful = true; - } - - openTransactionModal() { - this.isTransactionModalOpen = true; - } - - closeDepositConfirmationModal() { - this.isDepositSuccessful = false; - } - - closeTransactionModal() { - this.isTransactionModalOpen = false; - } - - navigateToGame(route: string) { - this.router.navigate([route]); - } - - protected readonly format = format; -} diff --git a/frontend/src/app/feature/landing/landing.component.html b/frontend/src/app/feature/landing/landing.component.html deleted file mode 100644 index 4cc9c52..0000000 --- a/frontend/src/app/feature/landing/landing.component.html +++ /dev/null @@ -1,218 +0,0 @@ -
-
-
-
-

- Willkommensbonus -

-
von bis zu €100
-

Fangen Sie an, zu gewinnen!

- -
- @if (authService.isLoggedIn()) { - - Spiele - - } @else { - - - } -
-
- -
-

Beliebte Spiele

-
-
-
-
-
-
-

Slots

-

Klassische Spielautomaten

- Jetzt Spielen -
-
-
-
-

Plinko

-

Spannendes Geschicklichkeitsspiel

- Jetzt Spielen -
-
- -
- -
-
-
-

Poker

-

Texas Hold'em & mehr

- Jetzt Spielen -
-
-
-
-

Dice

-

Würfelspiel

- Jetzt Spielen -
-
- -
-
-
- - - - -
- -
-
-
- -
-
-
50 Mio.€+
-
Ausgezahlt
-
- -
-
10 Mio.+
-
Spiele
-
- -
-
24/7
-
Support *
-
-
-
-
- - @if (showLogin() || showRegister() || showRecoverPassword()) { - - - } -
diff --git a/frontend/src/app/feature/landing/landing.component.ts b/frontend/src/app/feature/landing/landing.component.ts deleted file mode 100644 index d354fa4..0000000 --- a/frontend/src/app/feature/landing/landing.component.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { - ChangeDetectionStrategy, - Component, - inject, - OnDestroy, - OnInit, - signal, -} from '@angular/core'; -import { NgFor } from '@angular/common'; -import { ActivatedRoute, RouterLink } from '@angular/router'; -import { AuthService } from '@service/auth.service'; -import { LoginComponent } from '../auth/login/login.component'; -import { RegisterComponent } from '../auth/register/register.component'; -import '../auth/recover-password/recover-password.component'; -import RecoverPasswordComponent from '../auth/recover-password/recover-password.component'; - -@Component({ - selector: 'app-landing-page', - standalone: true, - imports: [NgFor, RouterLink, LoginComponent, RegisterComponent, RecoverPasswordComponent], - templateUrl: './landing.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class LandingComponent implements OnInit, OnDestroy { - currentSlide = 0; - private autoplayInterval: ReturnType | undefined; - authService: AuthService = inject(AuthService); - route: ActivatedRoute = inject(ActivatedRoute); - showLogin = signal(false); - showRegister = signal(false); - showRecoverPassword = signal(false); - - ngOnInit() { - this.startAutoplay(); - document.body.style.overflow = 'auto'; - if (this.route.snapshot.queryParamMap.get('login') === 'true') { - this.showLoginForm(); - } - } - - ngOnDestroy() { - this.stopAutoplay(); - document.body.style.overflow = 'auto'; - } - - showLoginForm() { - this.showLogin.set(true); - this.showRegister.set(false); - this.showRecoverPassword.set(false); - document.body.style.overflow = 'hidden'; - } - - showRegisterForm() { - this.showRegister.set(true); - this.showLogin.set(false); - this.showRecoverPassword.set(false); - document.body.style.overflow = 'hidden'; - } - - showRecoverPasswordForm() { - this.showRecoverPassword.set(true); - this.showLogin.set(false); - this.showRegister.set(false); - document.body.style.overflow = 'hidden'; - } - - hideAuthForms() { - this.showLogin.set(false); - this.showRegister.set(false); - this.showRecoverPassword.set(false); - document.body.style.overflow = 'auto'; - } - - prevSlide() { - this.currentSlide = this.currentSlide === 0 ? 1 : 0; - this.resetAutoplay(); - } - - nextSlide() { - this.currentSlide = this.currentSlide === 1 ? 0 : 1; - this.resetAutoplay(); - } - - goToSlide(index: number) { - this.currentSlide = index; - this.resetAutoplay(); - } - - private startAutoplay() { - this.autoplayInterval = setInterval(() => { - this.nextSlide(); - }, 5000); - } - - private stopAutoplay() { - if (this.autoplayInterval) { - clearInterval(this.autoplayInterval); - } - } - - private resetAutoplay() { - this.stopAutoplay(); - this.startAutoplay(); - } -} diff --git a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.css b/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.css deleted file mode 100644 index 4e5f67f..0000000 --- a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.css +++ /dev/null @@ -1,322 +0,0 @@ -body { - background: linear-gradient(to bottom, #181c2a, #232c43); -} - -/* Color classes */ -.text-yellow-400 { - color: #facc15; -} -.text-purple-400 { - color: #a78bfa; -} -.text-blue-400 { - color: #60a5fa; -} - -.border-yellow-400 { - border-color: #facc15; -} -.border-purple-400 { - border-color: #a78bfa; -} -.border-blue-400 { - border-color: #60a5fa; -} - -/* Loader animation */ -.loader { - border: 4px solid rgba(255, 255, 255, 0.3); - border-radius: 50%; - border-top: 4px solid #fff; - width: 40px; - height: 40px; - animation: spin 1s linear infinite; -} - -@keyframes spin { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } -} - -/* Open button styling */ -.open-btn { - background: linear-gradient(90deg, #4338ca 0%, #8b5cf6 100%); - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3); - transition: all 0.2s ease; -} -.open-btn:hover { - background: linear-gradient(90deg, #4f46e5 0%, #a78bfa 100%); - transform: translateY(-2px); - box-shadow: 0 6px 8px rgba(0, 0, 0, 0.3); -} - -/* CSGO-style case opening display */ -.case-container { - position: relative; - width: 100%; - background: rgba(26, 31, 48, 0.6); - border-radius: 8px; - box-shadow: 0 0 20px rgba(0, 0, 0, 0.3); - overflow: hidden; - margin-bottom: 20px; - display: flex; - justify-content: center; -} - -.case-indicator { - position: absolute; - top: 50%; - left: 50%; /* Back to center - we'll adjust the animation instead */ - transform: translate(-50%, -50%); /* Center precisely */ - width: 6px; - height: 100%; - background: #facc15; - box-shadow: - 0 0 10px #facc15, - 0 0 15px rgba(255, 255, 255, 0.5); - z-index: 3; - animation: indicator-pulse 1.5s ease-in-out 10s infinite alternate; -} - -@keyframes indicator-pulse { - 0% { - opacity: 0.6; - box-shadow: - 0 0 10px #facc15, - 0 0 15px rgba(255, 255, 255, 0.3); - } - 100% { - opacity: 1; - box-shadow: - 0 0 15px #facc15, - 0 0 20px rgba(255, 255, 255, 0.7); - } -} - -.case-items-container { - position: relative; - z-index: 1; - padding: 10px 5px; - margin: 0 auto; - width: 100%; - height: 150px; /* Fixed height for the horizontal row */ - overflow: hidden; /* Hide scrollbar */ - display: flex; - justify-content: center; /* Center the items container */ - align-items: center; -} - -.case-items { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - gap: 8px; - padding: 5px 0; - height: 100%; - width: 100%; - animation: slide-in 10s cubic-bezier(0.33, 0.9, 0.3, 1) forwards; - transform: translateX(4500px); - position: relative; -} - -@keyframes slide-in { - 0% { - transform: translateX(4500px); - } - 100% { - transform: translateX(-37.5px); - } -} - -.case-item { - transition: all 0.2s ease; - padding: 2px; - animation: item-flash 0.3s ease-out forwards; - animation-play-state: paused; - width: 69px; - flex-shrink: 0; -} - -@keyframes item-flash { - 0% { - filter: brightness(1); - } - 50% { - filter: brightness(1.8); - } - 100% { - filter: brightness(1.2); - } -} - -.case-item-inner { - background: #232c43; - border: 2px solid #2d3748; - border-radius: 8px; - padding: 10px 5px; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100%; -} - -.case-item-won { - z-index: 2; - animation: highlight-winner 1s ease-out 10s forwards; -} - -.winning-prize { - border: 2px solid transparent; - transition: all 0.5s ease; -} - -.winning-prize.highlight { - border-color: #fff !important; - box-shadow: 0 0 8px rgba(255, 255, 255, 0.6) !important; -} - -/* Specific ID for the winning item to ensure it's visible */ -#winning-item { - z-index: 5; /* Higher than indicator */ -} - -@keyframes highlight-winner { - 0% { - transform: scale(1); - filter: brightness(1); - } - 10% { - transform: scale(1.1); - filter: brightness(1.5); - } - 20% { - transform: scale(1.05); - filter: brightness(1.3); - } - 30% { - transform: scale(1.1); - filter: brightness(1.5); - } - 40% { - transform: scale(1.05); - filter: brightness(1.3); - } - 50% { - transform: scale(1.1); - filter: brightness(1.5); - } - 60% { - transform: scale(1.05); - filter: brightness(1.3); - } - 70% { - transform: scale(1.1); - filter: brightness(1.5); - } - 80% { - transform: scale(1.05); - filter: brightness(1.3); - } - 90% { - transform: scale(1.1); - filter: brightness(1.5); - } - 100% { - transform: scale(1.05); - filter: brightness(1.3); - } -} - -.amount { - font-size: 1rem; - font-weight: bold; - margin-bottom: 4px; -} - -.rarity { - font-size: 0.75rem; - opacity: 0.7; -} - -/* Prize animation */ -.prize-reel { - animation: slide-prizes 10s cubic-bezier(0.05, 0.82, 0.17, 1) forwards; -} - -@keyframes slide-prizes { - 0% { - transform: translateX(800px); - } - 85% { - transform: translateX(-120px); /* Small overshoot */ - } - 92% { - transform: translateX(-90px); /* Bounce back */ - } - 100% { - transform: translateX(-100px); /* Final position centered */ - } -} - -.animate-item-flash { - animation: item-flash 0.5s ease-out alternate infinite; -} - -.highlight { - animation: highlight-winner 1s ease-out forwards; -} - -/* Reward rarity classes */ -.text-common { - color: #ffffff; -} - -.text-uncommon { - color: #4ade80; -} - -.text-rare { - color: #60a5fa; -} - -.text-epic { - color: #a78bfa; -} - -.text-legendary { - color: #facc15; -} - -.text-mythic { - color: #f87171; -} - -.text-emerald { - color: #10b981; -} - -.text-accent-red { - color: #ef4444; -} - -.animation-fade { - opacity: 0; - transform: translateY(10px); - transition: - opacity 0.5s ease-out, - transform 0.5s ease-out; - transition-delay: 0.5s; - pointer-events: none; /* Prevent clicks when invisible */ -} - -.animation-fade.visible { - opacity: 1; - transform: translateY(0); - pointer-events: auto; /* Enable clicks when visible */ -} diff --git a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.html b/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.html deleted file mode 100644 index d4abab7..0000000 --- a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.html +++ /dev/null @@ -1,166 +0,0 @@ -
-

Lootbox Öffnen

- -
-
-
- -
- {{ error }} -
- -
-
-
-
- -
- {{ lootbox.price | currency: 'EUR' }} -
-
- -
-

{{ lootbox.name }}

- -
- -
- -
-
-
Öffne Lootbox...
-
- -
-
-

Dein Gewinn:

-
- {{ wonReward?.value | currency: 'EUR' }} -
-
- -
-
- -
-
-
-
-
- {{ reward.value | currency: 'EUR' }} -
-
- {{ reward.probability * 100 | number: '1.0-0' }}% -
-
-
-
-
-
- -
- - -
-
-
- -
-
-

Fairness garantiert - Alle Ergebnisse werden transparent berechnet.

-
-
-
-
- -
-
-

Mögliche Gewinne:

-
    -
  • - {{ - reward.value | currency: 'EUR' - }} - {{ reward.probability * 100 | number: '1.0-0' }}% -
  • -
- -
-

Gewinn-Details:

-
-
- Kosten: - {{ lootbox.price | currency: 'EUR' }} -
-
- Gewinn: - {{ wonReward.value | currency: 'EUR' }} -
-
- Profit: - - {{ wonReward.value - (lootbox.price || 0) | currency: 'EUR' }} - -
-
-
-
-
-
-
diff --git a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.ts b/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.ts deleted file mode 100644 index 3faf5be..0000000 --- a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.ts +++ /dev/null @@ -1,216 +0,0 @@ -import { ChangeDetectorRef, Component } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { ActivatedRoute, Router } from '@angular/router'; -import { LootboxService } from '../services/lootbox.service'; -import { LootBox, Reward } from 'app/model/LootBox'; -import { UserService } from '@service/user.service'; -import { User } from 'app/model/User'; -import { AuthService } from '@service/auth.service'; - -@Component({ - selector: 'app-lootbox-opening', - standalone: true, - imports: [CommonModule], - templateUrl: './lootbox-opening.component.html', - styleUrls: ['./lootbox-opening.component.css'], -}) -export default class LootboxOpeningComponent { - lootbox: LootBox | null = null; - isLoading = true; - error = ''; - isOpening = false; - isOpen = false; - wonReward: Reward | null = null; - prizeList: Reward[] = []; - animationCompleted = false; - currentUser: User | null = null; - private winSound: HTMLAudioElement; - - constructor( - private route: ActivatedRoute, - private router: Router, - private lootboxService: LootboxService, - private userService: UserService, - private authService: AuthService, - private cdr: ChangeDetectorRef - ) { - this.winSound = new Audio('/sounds/win.mp3'); - this.loadLootbox(); - this.authService.userSubject.subscribe((user) => { - this.currentUser = user; - this.cdr.detectChanges(); - }); - } - - private loadLootbox(): void { - const idParam = this.route.snapshot.paramMap.get('id'); - if (!idParam) { - this.error = 'Invalid lootbox ID'; - this.isLoading = false; - return; - } - - const lootboxId = parseInt(idParam, 10); - this.lootboxService.getAllLootBoxes().subscribe({ - next: (lootboxes) => { - this.lootbox = lootboxes.find((box) => box.id === lootboxId) || null; - this.isLoading = false; - this.cdr.detectChanges(); - }, - error: () => { - this.error = 'Failed to load lootbox data'; - this.isLoading = false; - this.cdr.detectChanges(); - }, - }); - } - - openLootbox(): void { - if (!this.lootbox || this.isOpening) return; - - // Check if user has enough balance - if (!this.hasEnoughBalance()) { - this.error = 'Nicht genug Guthaben, um diese Lootbox zu öffnen.'; - window.scrollTo(0, 0); - this.cdr.detectChanges(); - setTimeout(() => { - this.error = ''; - this.cdr.detectChanges(); - }, 5000); - return; - } - - this.resetState(true); - - if (this.lootbox.price) { - this.userService.updateLocalBalance(-this.lootbox.price); - } - - setTimeout(() => { - this.lootboxService.purchaseLootBox(this.lootbox!.id).subscribe({ - next: this.handleRewardSuccess.bind(this), - error: this.handleRewardError.bind(this), - }); - }, 100); - } - - private handleRewardSuccess(reward: Reward): void { - this.wonReward = reward; - this.generateCasePrizes(reward); - this.isOpening = false; - this.isOpen = true; - - this.cdr.detectChanges(); - } - - private handleRewardError(): void { - if (!this.lootbox) return; - - const rewards = this.lootbox.rewards; - const fallback = rewards[Math.floor(Math.random() * rewards.length)]; - - this.wonReward = fallback; - this.generateCasePrizes(fallback); - this.isOpening = false; - this.isOpen = true; - this.cdr.detectChanges(); - } - - private resetState(isOpening = false): void { - this.isOpening = isOpening; - this.isOpen = false; - this.wonReward = null; - this.prizeList = []; - this.animationCompleted = false; - this.cdr.detectChanges(); - } - - generateCasePrizes(wonReward: Reward): void { - if (!this.lootbox) return; - - const prizeCount = 120; - const winningPosition = Math.floor(prizeCount / 2); - const possibleRewards = this.lootbox.rewards; - const items: Reward[] = []; - - for (let i = 0; i < prizeCount; i++) { - if (i === winningPosition) { - items.push({ ...wonReward }); - } else { - items.push(this.getWeightedRandomReward(possibleRewards)); - } - } - - this.prizeList = items; - - setTimeout(() => { - this.animationCompleted = true; - - if (this.wonReward) { - this.winSound.play(); - this.userService.updateLocalBalance(this.wonReward.value); - } - - this.userService.refreshCurrentUser(); - this.cdr.detectChanges(); - }, 10000); - } - - getWeightedRandomReward(rewards: Reward[]): Reward { - const totalProbability = rewards.reduce((sum, reward) => sum + reward.probability, 0); - const randomValue = Math.random() * totalProbability; - let cumulativeProbability = 0; - - for (const reward of rewards) { - cumulativeProbability += reward.probability; - if (randomValue <= cumulativeProbability) { - return { ...reward }; - } - } - - return { ...rewards[0] }; - } - - openAgain(): void { - this.resetState(); - this.openLootbox(); - } - - getBoxImage(id: number): string { - return `/images/${id}-box.png`; - } - - goBack(): void { - this.router.navigate(['/game/lootboxes']); - } - - isWonReward(reward: Reward): boolean { - if (!this.wonReward || !this.prizeList.length) return false; - - const middleIndex = Math.floor(this.prizeList.length / 2); - return this.prizeList.indexOf(reward) === middleIndex; - } - - getRewardRarityClass(reward: Reward): string { - if (!reward) return 'text-common'; - - const probability = reward.probability; - - if (probability < 0.01) return 'text-mythic'; - if (probability < 0.05) return 'text-legendary'; - if (probability < 0.1) return 'text-epic'; - if (probability < 0.2) return 'text-rare'; - if (probability < 0.4) return 'text-uncommon'; - return 'text-common'; - } - - getRewardClass(): string { - if (!this.wonReward || !this.lootbox) return ''; - return this.wonReward.value > (this.lootbox.price || 0) ? 'text-emerald' : 'text-accent-red'; - } - - hasEnoughBalance(): boolean { - if (!this.currentUser || !this.lootbox) return false; - return this.currentUser.balance >= this.lootbox.price; - } -} diff --git a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.css b/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.css deleted file mode 100644 index 878220b..0000000 --- a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.css +++ /dev/null @@ -1,28 +0,0 @@ -.loader { - border: 4px solid rgba(255, 255, 255, 0.3); - border-radius: 50%; - border-top: 4px solid #fff; - width: 40px; - height: 40px; - animation: spin 1s linear infinite; -} - -@keyframes spin { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } -} - -.card { - transition: - transform 0.3s ease, - box-shadow 0.3s ease; -} - -.card:hover { - transform: translateY(-5px); - box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); -} diff --git a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.html b/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.html deleted file mode 100644 index 76fcc04..0000000 --- a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.html +++ /dev/null @@ -1,66 +0,0 @@ -
-

Lootboxen

- -
-
-
- -
- {{ error }} -
- -
-
-
- -
- {{ lootbox.price | currency: 'EUR' }} -
-
- -
-

{{ lootbox.name }}

- -
-

Mögliche Gewinne:

-
    -
  • - {{ - reward.value | currency: 'EUR' - }} - {{ formatProbability(reward.probability) }} -
  • -
-
- -
- -
-
- -
-
-

Fairness garantiert - Alle Ergebnisse werden transparent berechnet.

-
-
-
-
-
diff --git a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.ts b/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.ts deleted file mode 100644 index 373199b..0000000 --- a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { ChangeDetectorRef, Component, OnInit } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { LootboxService } from '../services/lootbox.service'; -import { LootBox } from 'app/model/LootBox'; -import { Router } from '@angular/router'; -import { timeout } from 'rxjs'; -import { User } from 'app/model/User'; -import { AuthService } from '@service/auth.service'; -import { UserService } from '@service/user.service'; - -@Component({ - selector: 'app-lootbox-selection', - standalone: true, - imports: [CommonModule], - templateUrl: './lootbox-selection.component.html', - styleUrls: ['./lootbox-selection.component.css'], -}) -export default class LootboxSelectionComponent implements OnInit { - lootboxes: LootBox[] = []; - isLoading = true; - error = ''; - currentUser: User | null = null; - - // Fallback data in case the API call fails - fallbackLootboxes: LootBox[] = [ - { - id: 1, - name: 'Basic LootBox', - price: 2.0, - rewards: [ - { - id: 1, - value: 0.5, - probability: 0.7, - }, - { - id: 5, - value: 5.0, - probability: 0.3, - }, - ], - }, - { - id: 2, - name: 'Premium LootBox', - price: 5.0, - rewards: [ - { - id: 4, - value: 2.0, - probability: 0.6, - }, - { - id: 5, - value: 5.0, - probability: 0.3, - }, - { - id: 6, - value: 15.0, - probability: 0.1, - }, - ], - }, - { - id: 3, - name: 'Legendäre LootBox', - price: 15.0, - rewards: [ - { - id: 4, - value: 2.0, - probability: 0.6, - }, - { - id: 5, - value: 5.0, - probability: 0.3, - }, - { - id: 6, - value: 15.0, - probability: 0.1, - }, - ], - }, - ]; - - constructor( - private lootboxService: LootboxService, - private router: Router, - private cdr: ChangeDetectorRef, - private authService: AuthService, - private userService: UserService - ) {} - - ngOnInit(): void { - this.loadLootboxes(); - this.authService.userSubject.subscribe((user) => { - this.currentUser = user; - this.cdr.detectChanges(); - }); - } - - loadLootboxes(): void { - this.isLoading = true; - this.lootboxService - .getAllLootBoxes() - .pipe(timeout(5000)) - .subscribe({ - next: (data) => { - console.log('Received lootboxes:', data); - this.lootboxes = data; - this.isLoading = false; - this.cdr.detectChanges(); - }, - error: (err) => { - this.error = 'Konnte keine Verbindung zum Backend herstellen. Zeige Demo-Daten.'; - this.lootboxes = this.fallbackLootboxes; - this.isLoading = false; - this.cdr.detectChanges(); - console.error('Failed to load lootboxes:', err); - }, - }); - } - - getBoxImage(id: number): string { - return `/images/${id}-box.png`; - } - - openLootbox(lootboxId: number): void { - const lootbox = this.lootboxes.find((box) => box.id === lootboxId); - - if (!lootbox) { - return; - } - - if (!this.currentUser || this.currentUser.balance < lootbox.price) { - this.error = 'Nicht genug Guthaben, um diese Lootbox zu öffnen.'; - // Scroll to top to see the error message - window.scrollTo(0, 0); - this.cdr.detectChanges(); - setTimeout(() => { - this.error = ''; - this.cdr.detectChanges(); - }, 5000); - return; - } - - this.router.navigate(['/game/lootboxes/open', lootboxId]); - } - - getRarityClass(probability: number): string { - if (probability <= 0.1) { - return 'text-yellow-400'; // Legendary - } else if (probability <= 0.3) { - return 'text-purple-400'; // Rare - } else { - return 'text-blue-400'; // Common - } - } - - formatProbability(probability: number): string { - return (probability * 100).toFixed(0) + '%'; - } - - hasEnoughBalance(price: number): boolean { - return !!this.currentUser && this.currentUser.balance >= price; - } -} diff --git a/frontend/src/app/feature/lootboxes/services/lootbox.service.ts b/frontend/src/app/feature/lootboxes/services/lootbox.service.ts deleted file mode 100644 index 1d1661a..0000000 --- a/frontend/src/app/feature/lootboxes/services/lootbox.service.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { inject, Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { catchError, Observable } from 'rxjs'; -import { LootBox, Reward } from 'app/model/LootBox'; - -@Injectable({ - providedIn: 'root', -}) -export class LootboxService { - private http = inject(HttpClient); - - getAllLootBoxes(): Observable { - return this.http.get('/backend/lootboxes', { responseType: 'json' }).pipe( - catchError((error) => { - console.error('Get lootboxes error:', error); - throw error; - }) - ); - } - - purchaseLootBox(lootBoxId: number): Observable { - return this.http - .post(`/backend/lootboxes/${lootBoxId}`, {}, { responseType: 'json' }) - .pipe( - catchError((error) => { - console.error('Purchase lootbox error:', error); - throw error; - }) - ); - } -} diff --git a/frontend/src/app/feature/transaction-history/transaction-history.component.css b/frontend/src/app/feature/transaction-history/transaction-history.component.css deleted file mode 100644 index c68e294..0000000 --- a/frontend/src/app/feature/transaction-history/transaction-history.component.css +++ /dev/null @@ -1,8 +0,0 @@ -button[disabled] { - cursor: not-allowed; - background-color: #077b58; - box-shadow: none; -} -button[disabled]:hover { - background-color: #077b58; -} diff --git a/frontend/src/app/feature/transaction-history/transaction-history.component.html b/frontend/src/app/feature/transaction-history/transaction-history.component.html deleted file mode 100644 index 974964c..0000000 --- a/frontend/src/app/feature/transaction-history/transaction-history.component.html +++ /dev/null @@ -1,60 +0,0 @@ - diff --git a/frontend/src/app/feature/transaction-history/transaction-history.component.ts b/frontend/src/app/feature/transaction-history/transaction-history.component.ts deleted file mode 100644 index 338ef4e..0000000 --- a/frontend/src/app/feature/transaction-history/transaction-history.component.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { - ChangeDetectionStrategy, - Component, - EventEmitter, - inject, - Input, - Output, -} from '@angular/core'; -import { TransactionService } from '@service/transaction.service'; -import { Observable } from 'rxjs'; -import { AsyncPipe, CurrencyPipe, DatePipe, NgIf } from '@angular/common'; -import { TransactionData } from '../../model/TransactionData'; - -const PER_PAGE = 5; - -@Component({ - standalone: true, - selector: 'app-transaction-history', - imports: [AsyncPipe, CurrencyPipe, DatePipe, NgIf], - templateUrl: './transaction-history.component.html', - styleUrl: './transaction-history.component.css', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class TransactionHistoryComponent { - @Input() - isOpen = false; - @Output() - closeEventEmitter = new EventEmitter(); - - protected offset = 0; - - private transactionService: TransactionService = inject(TransactionService); - transactionData$: Observable = this.loadTransactions(); - - closeDialog() { - this.isOpen = false; - this.closeEventEmitter.emit(); - } - - forward() { - this.offset++; - this.transactionData$ = this.loadTransactions(); - } - - back() { - this.offset--; - this.transactionData$ = this.loadTransactions(); - } - - loadTransactions() { - return this.transactionService.getUsersTransactions(PER_PAGE, this.offset * PER_PAGE); - } -} diff --git a/frontend/src/app/model/Game.ts b/frontend/src/app/model/Game.ts deleted file mode 100644 index 9adbf7a..0000000 --- a/frontend/src/app/model/Game.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface Game { - id: string; - name: string; - image: string; - route: string; -} diff --git a/frontend/src/app/model/LootBox.ts b/frontend/src/app/model/LootBox.ts deleted file mode 100644 index ebcf6e8..0000000 --- a/frontend/src/app/model/LootBox.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface Reward { - id: number; - value: number; - probability: number; -} - -export interface LootBox { - id: number; - name: string; - price: number; - rewards: Reward[]; -} diff --git a/frontend/src/app/model/Transaction.ts b/frontend/src/app/model/Transaction.ts deleted file mode 100644 index d3bccf1..0000000 --- a/frontend/src/app/model/Transaction.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface Transaction { - status: string; - amount: number; - createdAt: string; -} diff --git a/frontend/src/app/model/TransactionData.ts b/frontend/src/app/model/TransactionData.ts deleted file mode 100644 index 2da39bb..0000000 --- a/frontend/src/app/model/TransactionData.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Transaction } from './Transaction'; - -export interface TransactionData { - transactions: Transaction[]; - hasMore: boolean; -} diff --git a/frontend/src/app/model/User.ts b/frontend/src/app/model/User.ts deleted file mode 100644 index 3c983b8..0000000 --- a/frontend/src/app/model/User.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface User { - id: number; - email: string; - username: string; - balance: number; -} diff --git a/frontend/src/app/model/auth/AuthResponse.ts b/frontend/src/app/model/auth/AuthResponse.ts deleted file mode 100644 index 495d0cd..0000000 --- a/frontend/src/app/model/auth/AuthResponse.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface AuthResponse { - token: string; - tokenType: string; -} diff --git a/frontend/src/app/model/auth/LoginRequest.ts b/frontend/src/app/model/auth/LoginRequest.ts deleted file mode 100644 index 98c1b0e..0000000 --- a/frontend/src/app/model/auth/LoginRequest.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface LoginRequest { - usernameOrEmail: string; - password: string; -} diff --git a/frontend/src/app/model/auth/RegisterRequest.ts b/frontend/src/app/model/auth/RegisterRequest.ts deleted file mode 100644 index 2b07d41..0000000 --- a/frontend/src/app/model/auth/RegisterRequest.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface RegisterRequest { - email: string; - username: string; - password: string; -} diff --git a/frontend/src/app/service/auth.service.ts b/frontend/src/app/service/auth.service.ts deleted file mode 100644 index 61b3e7d..0000000 --- a/frontend/src/app/service/auth.service.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { BehaviorSubject, Observable, tap } from 'rxjs'; -import { Router, ActivatedRoute } from '@angular/router'; -import { LoginRequest } from '../model/auth/LoginRequest'; -import { RegisterRequest } from '../model/auth/RegisterRequest'; -import { AuthResponse } from '../model/auth/AuthResponse'; -import { User } from '../model/User'; -import { environment } from '@environments/environment'; - -const TOKEN_KEY = 'token'; -const USER_KEY = 'user'; - -@Injectable({ - providedIn: 'root', -}) -export class AuthService { - private authUrl = `${environment.apiUrl}/auth`; - private userUrl = `${environment.apiUrl}/users`; - private oauthUrl = `${environment.apiUrl}/oauth2`; - - userSubject: BehaviorSubject; - - constructor( - private http: HttpClient, - private router: Router, - private route: ActivatedRoute - ) { - this.userSubject = new BehaviorSubject(this.getUserFromStorage()); - - // Check for token in URL (OAuth callback) on initialization - this.route.queryParams.subscribe((params) => { - const token = params['token']; - if (token) { - this.handleOAuthCallback(token); - } - }); - - if (this.getToken()) { - this.loadCurrentUser(); - } - } - - private handleOAuthCallback(token: string): void { - this.setToken(token); - this.loadCurrentUser(); - // Clean up the URL by removing the token - this.router.navigate([], { - relativeTo: this.route, - queryParams: {}, - replaceUrl: true, - }); - } - - public get currentUserValue(): User | null { - return this.userSubject.value; - } - - login(loginRequest: LoginRequest): Observable { - return this.http.post(`${this.authUrl}/login`, loginRequest).pipe( - tap((response) => { - this.setToken(response.token); - this.loadCurrentUser(); - }) - ); - } - - register(registerRequest: RegisterRequest): Observable { - return this.http.post(`${this.authUrl}/register`, registerRequest); - } - - githubAuth(code: string): Observable { - return this.http.post(`${this.oauthUrl}/github/callback`, { code }).pipe( - tap((response) => { - console.log(response.token); - this.setToken(response.token); - this.loadCurrentUser(); - }) - ); - } - - googleAuth(code: string): Observable { - return this.http.post(`${this.oauthUrl}/google/callback`, { code }).pipe( - tap((response) => { - this.setToken(response.token); - this.loadCurrentUser(); - }) - ); - } - - logout(): void { - localStorage.removeItem(TOKEN_KEY); - localStorage.removeItem(USER_KEY); - this.userSubject.next(null); - this.router.navigate(['/']); - } - - isLoggedIn(): boolean { - return !!this.getToken(); - } - - getToken(): string | null { - return localStorage.getItem(TOKEN_KEY); - } - - public loadCurrentUser(): void { - this.http.get(`${this.userUrl}/me`).subscribe({ - next: (user) => { - this.setUser(user); - }, - error: () => { - this.logout(); - }, - }); - } - - public verifyEmail(token: string): Observable { - return this.http.post(`${this.authUrl}/verify?token=${token}`, null); - } - - public recoverPassword(email: string): Observable { - return this.http.post(`${this.authUrl}/recover-password?email=${email}`, null); - } - - public resetPassword(token: string, password: string): Observable { - return this.http.post(`${this.authUrl}/reset-password`, { token, password }); - } - - private setToken(token: string): void { - localStorage.setItem(TOKEN_KEY, token); - } - - private setUser(user: User): void { - localStorage.setItem(USER_KEY, JSON.stringify(user)); - this.userSubject.next(user); - } - - private getUserFromStorage(): User | null { - const user = localStorage.getItem(USER_KEY); - return user ? JSON.parse(user) : null; - } - - getUser(): User | null { - return this.currentUserValue; - } -} diff --git a/frontend/src/app/service/deposit.service.ts b/frontend/src/app/service/deposit.service.ts deleted file mode 100644 index 02c8ea1..0000000 --- a/frontend/src/app/service/deposit.service.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { inject, Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { Observable } from 'rxjs'; - -@Injectable({ - providedIn: 'root', -}) -export class DepositService { - private http: HttpClient = inject(HttpClient); - - handleDeposit(amount: number): Observable<{ sessionId: string }> { - return this.http.post<{ sessionId: string }>('/backend/deposit/checkout', { amount }); - } -} diff --git a/frontend/src/app/service/transaction.service.ts b/frontend/src/app/service/transaction.service.ts deleted file mode 100644 index 55aba0f..0000000 --- a/frontend/src/app/service/transaction.service.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { inject, Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { TransactionData } from '../model/TransactionData'; - -@Injectable({ - providedIn: 'root', -}) -export class TransactionService { - private http: HttpClient = inject(HttpClient); - - public getUsersTransactions(limit: number | null = null, offset: number | null = null) { - const baseUrl = new URL(`${window.location.origin}/backend/user/transactions`); - - if (limit !== null) { - baseUrl.searchParams.append('limit', limit.toString()); - } - - if (offset !== null) { - baseUrl.searchParams.append('offset', offset.toString()); - } - - return this.http.get(`${baseUrl}`); - } -} diff --git a/frontend/src/app/service/user.service.ts b/frontend/src/app/service/user.service.ts deleted file mode 100644 index e126fc4..0000000 --- a/frontend/src/app/service/user.service.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { inject, Injectable } from '@angular/core'; -import { AuthService } from '@service/auth.service'; -import { User } from '../model/User'; - -@Injectable({ - providedIn: 'root', -}) -export class UserService { - private authService = inject(AuthService); - - /** - * Updates the user's balance locally for immediate UI feedback - * This should be called before a server-side balance change is made - * The server update will be reflected when AuthService.loadCurrentUser() is called - */ - public updateLocalBalance(amount: number): void { - const currentUser = this.authService.currentUserValue; - if (currentUser) { - const updatedUser: User = { - ...currentUser, - balance: currentUser.balance + amount, - }; - this.authService.userSubject.next(updatedUser); - } - } - - /** - * Refreshes the current user's data from the server - */ - public refreshCurrentUser(): void { - this.authService.loadCurrentUser(); - } -} diff --git a/frontend/src/app/shared/components/confirmation/confirmation.component.html b/frontend/src/app/shared/components/confirmation/confirmation.component.html deleted file mode 100644 index 193ea9a..0000000 --- a/frontend/src/app/shared/components/confirmation/confirmation.component.html +++ /dev/null @@ -1,11 +0,0 @@ -@if (successful) { - -} diff --git a/frontend/src/app/shared/components/confirmation/confirmation.component.ts b/frontend/src/app/shared/components/confirmation/confirmation.component.ts deleted file mode 100644 index 9ce91ba..0000000 --- a/frontend/src/app/shared/components/confirmation/confirmation.component.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { - AfterViewInit, - Component, - ElementRef, - EventEmitter, - Input, - OnDestroy, - Output, - ViewChild, -} from '@angular/core'; -import { ModalAnimationService } from '@shared/services/modal-animation.service'; -import gsap from 'gsap'; - -@Component({ - selector: 'app-confirmation', - standalone: true, - imports: [], - templateUrl: './confirmation.component.html', -}) -export class ConfirmationComponent implements AfterViewInit, OnDestroy { - @Input() successful = true; - @Output() closeConfirmation = new EventEmitter(); - @ViewChild('modalBg') modalBg!: ElementRef; - @ViewChild('modalCard') modalCard!: ElementRef; - - constructor(private modalAnimationService: ModalAnimationService) {} - - ngAfterViewInit() { - if (this.successful) { - this.openModal(); - } - } - - ngOnDestroy() { - gsap.killTweensOf([this.modalBg?.nativeElement, this.modalCard?.nativeElement]); - } - - private openModal() { - this.modalAnimationService.openModal(this.modalCard.nativeElement, this.modalBg.nativeElement); - } - - public closeModal() { - this.modalAnimationService.closeModal( - this.modalCard.nativeElement, - this.modalBg.nativeElement, - () => this.closeConfirmation.emit() - ); - } -} diff --git a/frontend/src/app/shared/components/debt-dialog/debt-dialog.component.ts b/frontend/src/app/shared/components/debt-dialog/debt-dialog.component.ts deleted file mode 100644 index a97f431..0000000 --- a/frontend/src/app/shared/components/debt-dialog/debt-dialog.component.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { - ChangeDetectionStrategy, - Component, - EventEmitter, - Input, - OnDestroy, - OnInit, - Output, - signal, -} from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { animate, style, transition, trigger } from '@angular/animations'; -import { interval, Subscription, takeWhile } from 'rxjs'; -import { AnimatedNumberComponent } from '@blackjack/components/animated-number/animated-number.component'; - -@Component({ - selector: 'app-debt-dialog', - standalone: true, - imports: [CommonModule, AnimatedNumberComponent], - template: ` - - `, - changeDetection: ChangeDetectionStrategy.OnPush, - animations: [ - trigger('fadeInOut', [ - transition(':enter', [ - style({ opacity: 0 }), - animate('150ms ease-out', style({ opacity: 1 })), - ]), - transition(':leave', [animate('150ms ease-in', style({ opacity: 0 }))]), - ]), - trigger('cardAnimation', [ - transition(':enter', [ - style({ opacity: 0, transform: 'scale(0.95)' }), - animate('200ms ease-out', style({ opacity: 1, transform: 'scale(1)' })), - ]), - ]), - trigger('countdown', [ - transition('* => *', [ - style({ transform: 'scale(1.2)' }), - animate('100ms ease-out', style({ transform: 'scale(1)' })), - ]), - ]), - ], -}) -export class DebtDialogComponent implements OnInit, OnDestroy { - @Input() amount = 0; - @Input() set show(value: boolean) { - this.visible = value; - if (value) { - this.startTimer(); - } - } - - @Output() dialogClosed = new EventEmitter(); - - visible = false; - timeLeft = signal(30); - private timerSubscription: Subscription | undefined; - private warningSound = new Audio('assets/sounds/warning.mp3'); - - ngOnInit() { - if (this.visible) { - this.startTimer(); - } - } - - ngOnDestroy() { - this.stopTimer(); - } - - private startTimer() { - this.timeLeft.set(30); - this.timerSubscription = interval(1000) - .pipe(takeWhile(() => this.timeLeft() > 0)) - .subscribe(() => { - this.timeLeft.update((value) => value - 1); - if (this.timeLeft() <= 5) { - this.warningSound.play(); - } - if (this.timeLeft() === 0) { - setTimeout(() => this.closeDialog(), 5000); - } - }); - } - - private stopTimer() { - if (this.timerSubscription) { - this.timerSubscription.unsubscribe(); - } - } - - closeDialog(): void { - this.stopTimer(); - this.visible = false; - this.dialogClosed.emit(); - } -} diff --git a/frontend/src/app/shared/components/footer/footer.component.html b/frontend/src/app/shared/components/footer/footer.component.html deleted file mode 100644 index e886973..0000000 --- a/frontend/src/app/shared/components/footer/footer.component.html +++ /dev/null @@ -1,80 +0,0 @@ -
-
-
- - - -
- -
- - - - - - - -
-
-
- -
-
- -
-
-
-
diff --git a/frontend/src/app/shared/components/footer/footer.component.ts b/frontend/src/app/shared/components/footer/footer.component.ts deleted file mode 100644 index 2cb56e1..0000000 --- a/frontend/src/app/shared/components/footer/footer.component.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; -import { faCreditCard, faMoneyBillTransfer, faWallet } from '@fortawesome/free-solid-svg-icons'; -import { faApplePay, faGooglePay, faPaypal } from '@fortawesome/free-brands-svg-icons'; - -@Component({ - selector: 'app-footer', - standalone: true, - templateUrl: './footer.component.html', - imports: [FontAwesomeModule], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class FooterComponent { - currentYear: number = new Date().getFullYear(); - - faPaypal = faPaypal; - faCreditCard = faCreditCard; - faMoneyBillTransfer = faMoneyBillTransfer; - faWallet = faWallet; - faGooglePay = faGooglePay; - faApplePay = faApplePay; -} diff --git a/frontend/src/app/shared/components/navbar/navbar.component.html b/frontend/src/app/shared/components/navbar/navbar.component.html deleted file mode 100644 index 7e010fa..0000000 --- a/frontend/src/app/shared/components/navbar/navbar.component.html +++ /dev/null @@ -1,95 +0,0 @@ - diff --git a/frontend/src/app/shared/components/navbar/navbar.component.ts b/frontend/src/app/shared/components/navbar/navbar.component.ts deleted file mode 100644 index 7b8bb63..0000000 --- a/frontend/src/app/shared/components/navbar/navbar.component.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { - ChangeDetectionStrategy, - Component, - EventEmitter, - inject, - OnDestroy, - OnInit, - Output, - signal, -} from '@angular/core'; -import { RouterModule } from '@angular/router'; -import { AuthService } from '@service/auth.service'; -import { Subscription } from 'rxjs'; -import { AnimatedNumberComponent } from '@blackjack/components/animated-number/animated-number.component'; - -@Component({ - selector: 'app-navbar', - templateUrl: './navbar.component.html', - standalone: true, - imports: [RouterModule, AnimatedNumberComponent], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class NavbarComponent implements OnInit, OnDestroy { - isMenuOpen = false; - private authService: AuthService = inject(AuthService); - isLoggedIn = signal(this.authService.isLoggedIn()); - - private authSubscription!: Subscription; - public balance = signal(0); - - @Output() showLogin = new EventEmitter(); - @Output() showRegister = new EventEmitter(); - - ngOnInit() { - this.authSubscription = this.authService.userSubject.subscribe({ - next: (user) => { - this.balance.set(user?.balance ?? 0); - this.isLoggedIn.set(this.authService.isLoggedIn()); - }, - }); - } - - ngOnDestroy() { - this.authSubscription.unsubscribe(); - } - - logout() { - this.authService.logout(); - } - - toggleMenu() { - this.isMenuOpen = !this.isMenuOpen; - } -} diff --git a/frontend/src/app/shared/directives/drag-sound.directive.ts b/frontend/src/app/shared/directives/drag-sound.directive.ts deleted file mode 100644 index 332cacc..0000000 --- a/frontend/src/app/shared/directives/drag-sound.directive.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Directive, ElementRef, HostListener, inject, Input, OnInit } from '@angular/core'; -import { AudioService } from '../services/audio.service'; -import { AbstractControl } from '@angular/forms'; - -@Directive({ - selector: '[appDragSound]', - standalone: true, -}) -export class DragSoundDirective implements OnInit { - private audioService = inject(AudioService); - private elementRef = inject(ElementRef); - private lastValue: number | null = null; - - @Input('appDragSound') formControl: AbstractControl | null = null; - - ngOnInit() { - if (this.formControl) { - this.lastValue = this.formControl.value; - - this.formControl.valueChanges.subscribe((newValue) => { - if (this.lastValue !== newValue) { - this.playSound(); - this.lastValue = newValue; - } - }); - } - } - - private playSound() { - this.audioService.playDragStepSound(); - } - - @HostListener('input') - onInput() { - if (!this.formControl) { - this.playSound(); - } - } -} diff --git a/frontend/src/app/shared/directives/play-sound.directive.ts b/frontend/src/app/shared/directives/play-sound.directive.ts deleted file mode 100644 index f949f64..0000000 --- a/frontend/src/app/shared/directives/play-sound.directive.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Directive, HostListener, inject } from '@angular/core'; -import { AudioService } from '../services/audio.service'; - -@Directive({ - selector: '[appPlaySound]', - standalone: true, -}) -export class PlaySoundDirective { - private audioService = inject(AudioService); - - @HostListener('click') - onClick() { - this.audioService.playBetSound(); - } -} diff --git a/frontend/src/app/shared/interceptor/http.interceptor.ts b/frontend/src/app/shared/interceptor/http.interceptor.ts deleted file mode 100644 index 2ff7788..0000000 --- a/frontend/src/app/shared/interceptor/http.interceptor.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { HttpInterceptorFn } from '@angular/common/http'; - -const TOKEN_KEY = 'token'; - -export const httpInterceptor: HttpInterceptorFn = (req, next) => { - const token = localStorage.getItem(TOKEN_KEY); - - // Always add CORS headers - if (token) { - return next( - req.clone({ - setHeaders: { - Authorization: `Bearer ${token}`, - 'Referrer-Policy': 'no-referrer', - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', - 'Access-Control-Allow-Headers': '*', - }, - }) - ); - } else { - return next( - req.clone({ - setHeaders: { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', - 'Access-Control-Allow-Headers': '*', - }, - }) - ); - } -}; diff --git a/frontend/src/app/shared/services/audio.service.ts b/frontend/src/app/shared/services/audio.service.ts deleted file mode 100644 index 53850c0..0000000 --- a/frontend/src/app/shared/services/audio.service.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Injectable } from '@angular/core'; - -@Injectable({ - providedIn: 'root', -}) -export class AudioService { - private audioCache = new Map(); - - private getAudio(soundName: string): HTMLAudioElement { - if (this.audioCache.has(soundName)) { - return this.audioCache.get(soundName)!; - } - - const audio = new Audio(`/sounds/${soundName}`); - this.audioCache.set(soundName, audio); - return audio; - } - - playBetSound(): void { - const audio = this.getAudio('bet.mp3'); - audio.currentTime = 0; - audio.play().catch((error) => console.error('Error playing bet sound:', error)); - } - - playWinSound(): void { - const audio = this.getAudio('win.mp3'); - audio.currentTime = 0; - audio.play().catch((error) => console.error('Error playing win sound:', error)); - } - - getDragSound(): HTMLAudioElement { - return this.getAudio('drag.mp3'); - } - - playDragStepSound(): void { - const audio = this.getAudio('drag.mp3'); - audio.currentTime = 0; - audio.volume = 0.5; - audio.play().catch((error) => console.error('Error playing drag step sound:', error)); - } -} diff --git a/frontend/src/app/shared/services/modal-animation.service.ts b/frontend/src/app/shared/services/modal-animation.service.ts deleted file mode 100644 index f54c2bc..0000000 --- a/frontend/src/app/shared/services/modal-animation.service.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Injectable } from '@angular/core'; -import gsap from 'gsap'; - -@Injectable({ - providedIn: 'root', -}) -export class ModalAnimationService { - private readonly defaultDuration = 0.3; - private readonly defaultEase = 'power2.out'; - - openModal(modalElement: HTMLElement, overlayElement: HTMLElement) { - gsap.set(overlayElement, { opacity: 0, display: 'block' }); - gsap.set(modalElement, { - opacity: 0, - scale: 0.95, - y: 20, - display: 'block', - }); - - gsap.to(overlayElement, { - opacity: 1, - duration: this.defaultDuration, - ease: this.defaultEase, - }); - - gsap.to(modalElement, { - opacity: 1, - scale: 1, - y: 0, - duration: this.defaultDuration, - ease: this.defaultEase, - }); - } - - closeModal(modalElement: HTMLElement, overlayElement: HTMLElement, onComplete?: () => void) { - gsap.to([overlayElement, modalElement], { - opacity: 0, - duration: this.defaultDuration, - ease: this.defaultEase, - onComplete: () => { - gsap.set([overlayElement, modalElement], { display: 'none' }); - onComplete?.(); - }, - }); - - gsap.to(modalElement, { - scale: 0.95, - y: 20, - duration: this.defaultDuration, - ease: this.defaultEase, - }); - } -} diff --git a/frontend/src/app/shared/services/sound-initializer.service.ts b/frontend/src/app/shared/services/sound-initializer.service.ts deleted file mode 100644 index 47d09e0..0000000 --- a/frontend/src/app/shared/services/sound-initializer.service.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Injectable, Renderer2, RendererFactory2 } from '@angular/core'; - -@Injectable({ - providedIn: 'root', -}) -export class SoundInitializerService { - private renderer: Renderer2; - private observer: MutationObserver; - - constructor(rendererFactory: RendererFactory2) { - this.renderer = rendererFactory.createRenderer(null, null); - - this.observer = new MutationObserver((mutations) => { - mutations.forEach((mutation) => { - mutation.addedNodes.forEach((node) => { - if (node instanceof HTMLElement) { - this.processElement(node); - } - }); - }); - }); - } - - initialize() { - document.querySelectorAll('button, a').forEach((element) => { - if (!element.hasAttribute('appPlaySound')) { - this.renderer.setAttribute(element, 'appPlaySound', ''); - } - }); - - this.observer.observe(document.body, { - childList: true, - subtree: true, - }); - } - - private processElement(element: HTMLElement) { - if ( - (element.tagName === 'BUTTON' || element.tagName === 'A') && - !element.hasAttribute('appPlaySound') - ) { - this.renderer.setAttribute(element, 'appPlaySound', ''); - } - - element.querySelectorAll('button, a').forEach((child) => { - if (!child.hasAttribute('appPlaySound')) { - this.renderer.setAttribute(child, 'appPlaySound', ''); - } - }); - } -} diff --git a/frontend/src/environments/environment.ts b/frontend/src/environments/environment.ts deleted file mode 100644 index c7df73a..0000000 --- a/frontend/src/environments/environment.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const environment = { - STRIPE_KEY: - 'pk_test_51QrePYIvCfqz7ANgMizBorPpVjJ8S6gcaL4yvcMQnVaKyReqcQ6jqaQEF7aDZbDu8rNVsTZrw8ABek4ToxQX7KZe00jpGh8naG', - apiUrl: window.location.origin + '/backend', -}; diff --git a/frontend/src/favicon.ico b/frontend/src/favicon.ico deleted file mode 100644 index 0a22de4..0000000 Binary files a/frontend/src/favicon.ico and /dev/null differ diff --git a/frontend/src/index.html b/frontend/src/index.html deleted file mode 100644 index 1c92a1e..0000000 --- a/frontend/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Trustworthy Casino - - - - - - - - diff --git a/frontend/src/main.ts b/frontend/src/main.ts deleted file mode 100644 index 17447a5..0000000 --- a/frontend/src/main.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err)); diff --git a/frontend/src/proxy.conf.json b/frontend/src/proxy.conf.json deleted file mode 100644 index c9839a6..0000000 --- a/frontend/src/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/backend": { - "target": "http://localhost:8080/", - "secure": false, - "logLevel": "debug", - "pathRewrite": { - "^/backend": "" - }, - "changeOrigin": true - } -} diff --git a/frontend/src/styles.css b/frontend/src/styles.css deleted file mode 100644 index 57a0f6a..0000000 --- a/frontend/src/styles.css +++ /dev/null @@ -1,191 +0,0 @@ -@import 'tailwindcss'; - -@theme { - --color-deep-blue: #0a1219; - --color-deep-blue-light: #121e27; - --color-deep-blue-contrast: #1a2835; - - --color-emerald: #10b981; - --color-emerald-dark: #059669; - --color-emerald-light: #34d399; - - --color-text-primary: #ffffff; - --color-text-secondary: #94a3b8; - --color-text-tertiary: #64748b; - - --color-accent-yellow: #fbbf24; - --color-accent-red: #ef4444; - --color-accent-purple: #8b5cf6; -} - -body { - @apply bg-deep-blue text-text-primary h-full; -} - -button, -a { - @apply cursor-pointer active:scale-95 text-text-primary transition-all duration-200; -} - -.card { - @apply bg-deep-blue-contrast rounded-lg overflow-hidden shadow-lg hover:shadow-xl transition-shadow duration-300; -} - -.button-primary { - @apply bg-emerald hover:bg-emerald-dark text-text-primary transition-all duration-300 active:scale-95 rounded; -} - -.button-secondary { - @apply bg-deep-blue-light hover:bg-deep-blue-contrast w-full py-2 rounded my-2; -} - -.game-card-content { - @apply p-4; -} - -.nav-button { - @apply hidden lg:block absolute top-1/2 -translate-y-1/2 bg-deep-blue-contrast hover:bg-deep-blue-contrast/90 text-text-primary p-3 rounded-full opacity-0 group-hover:opacity-100 transition-all duration-300 shadow-lg hover:scale-110; -} - -.slider-container { - @apply flex transition-transform duration-500 ease-out; -} - -.slider-grid { - @apply min-w-full grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4; -} - -.welcome-bonus { - @apply text-4xl sm:text-5xl lg:text-7xl font-extrabold text-emerald-light mb-3 sm:mb-4; -} - -.bonus-description { - @apply text-text-secondary text-base sm:text-lg mb-6 sm:mb-8; -} - -.section-heading { - @apply font-bold text-text-primary; -} - -.game-heading-sm { - @apply font-bold text-text-primary text-sm mb-2; -} - -.game-heading-xl { - @apply font-bold text-text-primary text-xl mb-2; -} - -.game-text { - @apply text-text-secondary text-sm mb-4; -} - -.stat-container { - @apply bg-deep-blue-contrast rounded-lg shadow-lg p-4 sm:p-6 text-center; -} - -.stat-number { - @apply text-xl sm:text-2xl font-bold text-emerald; -} - -.stat-text { - @apply text-text-secondary text-sm; -} - -.nav-brand { - @apply flex items-center text-text-primary text-xl font-semibold; -} - -.nav-link { - @apply px-3 py-2 rounded-md font-normal text-sm text-text-secondary hover:text-text-primary hover:bg-deep-blue-contrast transition-all duration-200; -} - -.nav-toggle { - @apply text-text-secondary hover:text-text-primary transition-colors duration-200; -} - -.nav-mobile-menu { - @apply p-2 pt-2 mb-4 space-y-1 bg-deep-blue-contrast rounded-b-lg; -} - -.nav-mobile-link { - @apply block px-3 py-2 rounded-md text-sm text-text-secondary hover:text-text-primary hover:bg-deep-blue-light transition-all duration-200; -} - -.footer-section { - @apply col-span-2 md:col-span-1; -} - -.footer-heading { - @apply text-text-primary text-sm font-semibold mb-4; -} - -.footer-link { - @apply text-text-secondary hover:text-text-primary text-sm transition-all duration-200; -} - -.footer-payment-method { - @apply bg-deep-blue rounded p-3 flex items-center justify-center space-x-2 hover:bg-deep-blue/50 transition-all duration-200; -} - -.footer-payment-icon { - @apply text-text-secondary text-lg; -} - -.footer-payment-text { - @apply text-text-secondary text-xs whitespace-nowrap; -} - -.footer-copyright { - @apply text-text-secondary text-sm; -} - -.footer-disclaimer { - @apply text-xs; -} - -.modal-bg { - @apply fixed inset-0 bg-black/80 backdrop-blur-sm z-50 focus:outline-none focus:ring-2 focus:ring-emerald-light; -} - -.modal-card { - @apply bg-deep-blue-contrast overflow-hidden hover:shadow-xl transition-shadow duration-300 p-6 rounded-xl shadow-2xl z-50 min-w-[300px] max-w-[400px] w-full mx-auto border border-deep-blue-light/20 fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2; -} - -.modal-heading { - @apply text-2xl font-bold text-text-primary mb-4; -} - -.modal-card input { - @apply w-full px-4 py-2.5 bg-deep-blue-light/50 text-white rounded-lg my-1 border border-deep-blue-light/30 focus:border-emerald/50 focus:ring-1 focus:ring-emerald/50 outline-none transition-all duration-200; -} - -.modal-card label { - @apply text-text-secondary text-sm font-medium mb-1 block; -} - -.modal-card button { - @apply transition-all duration-200; -} - -.modal-card .button-primary { - @apply bg-emerald hover:bg-emerald-dark text-text-primary transition-all duration-300 active:scale-95 shadow-lg shadow-emerald/20; -} - -.modal-card .button-secondary { - @apply bg-deep-blue-light/50 hover:bg-deep-blue-light w-full py-2.5 my-2 border border-deep-blue-light/30 hover:border-deep-blue-light/50; -} - -button, -a { - -webkit-tap-highlight-color: transparent; -} - -button[appPlaySound], -a[appPlaySound] { - cursor: pointer; -} - -button:not([appPlaySound]), -a:not([appPlaySound]) { - --add-sound-directive: true; -} diff --git a/frontend/tsconfig.app.json b/frontend/tsconfig.app.json deleted file mode 100644 index 3775b37..0000000 --- a/frontend/tsconfig.app.json +++ /dev/null @@ -1,15 +0,0 @@ -/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ -/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/app", - "types": [] - }, - "files": [ - "src/main.ts" - ], - "include": [ - "src/**/*.d.ts" - ] -} diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json deleted file mode 100644 index faf0f24..0000000 --- a/frontend/tsconfig.json +++ /dev/null @@ -1,40 +0,0 @@ -/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ -/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ -{ - "compileOnSave": false, - "compilerOptions": { - "baseUrl": "./src", - "paths": { - "@service/*": ["app/service/*"], - "@environments/*": ["environments/*"], - "@shared/*": ["app/shared/*"], - "@blackjack/*": ["app/feature/game/blackjack/*"] - }, - "outDir": "./dist/out-tsc", - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "skipLibCheck": true, - "isolatedModules": true, - "esModuleInterop": true, - "sourceMap": true, - "declaration": false, - "experimentalDecorators": true, - "moduleResolution": "bundler", - "importHelpers": true, - "target": "ES2022", - "module": "ES2022", - "lib": [ - "ES2022", - "dom" - ] - }, - "angularCompilerOptions": { - "enableI18nLegacyMessageIdFormat": false, - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } -} diff --git a/frontend/tsconfig.spec.json b/frontend/tsconfig.spec.json deleted file mode 100644 index 5fb748d..0000000 --- a/frontend/tsconfig.spec.json +++ /dev/null @@ -1,15 +0,0 @@ -/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ -/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/spec", - "types": [ - "jasmine" - ] - }, - "include": [ - "src/**/*.spec.ts", - "src/**/*.d.ts" - ] -} diff --git a/justfile b/justfile deleted file mode 100644 index 4fc777c..0000000 --- a/justfile +++ /dev/null @@ -1,27 +0,0 @@ -# Info -info: - just --list - -# Starts the project in development mode -start: - command -v concurrently &> /dev/null || bun add -g concurrently - command -v watchexec &> /dev/null || brew install watchexec - docker compose up -d - conc -n "frontend,backend" "cd frontend && bun run start" "cd backend/ && watchexec -r -e java ./gradlew :bootRun" - -# Builds both the backend and frontend docker images (obv) -build: - just build-fe - just build-be - -# Builds the backend docker image -build-be: - docker buildx build -f backend/.docker/Dockerfile -t git.kjan.de/szut/casino-backend:latest backend - -# Builds the frontend docker image -build-fe: - docker buildx build -f frontend/.docker/Dockerfile -t git.kjan.de/szut/casino-frontend:latest frontend - -# Formats the code duh -format: - cd frontend && bunx prettier --write "src/**/*.{ts,html,css,scss}" diff --git a/release.config.cjs b/release.config.cjs deleted file mode 100644 index dffea8d..0000000 --- a/release.config.cjs +++ /dev/null @@ -1,64 +0,0 @@ -module.exports = { - branches: ["main"], - plugins: [ - [ - "@semantic-release/commit-analyzer", - { - preset: "angular", - releaseRules: [ - { type: "feat", release: "minor" }, - { type: "fix", release: "patch" }, - { type: "perf", release: "patch" }, - { type: "docs", release: "patch" }, - { type: "style", release: "patch" }, - { type: "refactor", release: "patch" }, - { type: "test", release: "patch" }, - { type: "chore", release: "patch" }, - { type: "ci", release: "patch" }, - { type: "build", release: "patch" }, - { type: "revert", release: "patch" }, - ], - }, - ], - [ - "@semantic-release/release-notes-generator", - { - preset: "conventionalcommits", - presetConfig: { - types: [ - { type: "feat", section: "Features", hidden: false }, - { type: "fix", section: "Bug Fixes", hidden: false }, - { - type: "perf", - section: "Performance Improvements", - hidden: false, - }, - { type: "docs", section: "Documentation", hidden: false }, - { type: "style", section: "Code Style", hidden: false }, - { type: "refactor", section: "Code Refactoring", hidden: false }, - { type: "test", section: "Tests", hidden: false }, - { type: "chore", section: "Chores", hidden: false }, - { type: "ci", section: "Continuous Integration", hidden: false }, - { type: "build", section: "Build System", hidden: false }, - { type: "revert", section: "Reverts", hidden: false }, - ], - }, - parserOpts: { - noteKeywords: ["BREAKING CHANGE", "BREAKING CHANGES", "BREAKING"], - }, - }, - ], - [ - "@semantic-release/changelog", - { - changelogFile: "CHANGELOG.md", - }, - ], - [ - "@saithodev/semantic-release-gitea", - { - giteaUrl: "https://git.kjan.de", - }, - ], - ], -}; diff --git a/renovate.json b/renovate.json deleted file mode 100644 index c183f9d..0000000 --- a/renovate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "local>Renovate/renovate-config" - ] -}