From dfd01aafaee223c6aeb6bbfed6808058bb142c2d Mon Sep 17 00:00:00 2001 From: eXhumer Date: Fri, 4 Oct 2024 15:31:51 -0600 Subject: [PATCH] refactor: use new decky API * modernize main.py * use settings API instead of backend * fix frontend for new decky API * use decky/cli to make plugin Signed-off-by: eXhumer --- .devcontainer/Dockerfile | 2 - .devcontainer/devcontainer.json | 8 - .github/workflows/build-backend.yml | 19 - .../workflows/build-plugin-snapshot-zip.yml | 34 - .github/workflows/dev-build.yml | 46 + .gitignore | 26 +- .vscode/config.sh | 12 - .vscode/defsettings.json | 7 - .vscode/launch.json | 29 - .vscode/tasks.json | 148 -- Dockerfile | 26 - backend/Cargo.lock | 2 +- backend/Cargo.toml | 8 +- backend/build-docker-image.sh | 4 - backend/build-docker.sh | 15 - backend/build.sh | 18 +- backend/entrypoint.sh | 2 +- backend/run-docker-image.sh | 3 - backend/src/main.rs | 35 +- backend/src/settings.rs | 31 +- decky.pyi | 184 +++ main.py | 72 +- package.json | 30 +- package.sh | 16 - plugin.json | 1 + pnpm-lock.yaml | 1283 +++++++++++++---- release.sh | 41 - rollup.config.js | 37 +- scripts/build_docker_image.sh | 4 - scripts/reload_frontend.js | 34 - scripts/remote_debug.sh | 23 - settings.pyi | 9 + src/backend.ts | 27 +- src/index.tsx | 42 +- src/notifications.ts | 6 +- tsconfig.json | 1 + 36 files changed, 1355 insertions(+), 930 deletions(-) delete mode 100644 .devcontainer/Dockerfile delete mode 100644 .devcontainer/devcontainer.json delete mode 100644 .github/workflows/build-backend.yml delete mode 100644 .github/workflows/build-plugin-snapshot-zip.yml create mode 100644 .github/workflows/dev-build.yml delete mode 100755 .vscode/config.sh delete mode 100644 .vscode/defsettings.json delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/tasks.json delete mode 100644 Dockerfile delete mode 100755 backend/build-docker-image.sh delete mode 100755 backend/build-docker.sh delete mode 100755 backend/run-docker-image.sh create mode 100644 decky.pyi delete mode 100755 package.sh delete mode 100755 release.sh delete mode 100755 scripts/build_docker_image.sh delete mode 100755 scripts/reload_frontend.js delete mode 100755 scripts/remote_debug.sh create mode 100644 settings.pyi diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index a2e1ad9..0000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM mcr.microsoft.com/devcontainers/universal:2 -RUN apt-get update && apt-get -y install libudev-dev \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index eedf63f..0000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "build": { - "dockerfile": "Dockerfile" - }, - "features": { - "ghcr.io/devcontainers/features/rust:1": {} - } -} \ No newline at end of file diff --git a/.github/workflows/build-backend.yml b/.github/workflows/build-backend.yml deleted file mode 100644 index cb53d2a..0000000 --- a/.github/workflows/build-backend.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Build Backend - -on: - push: - branches: main - pull_request: - branches: main - # workflow_dispatch: -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3.2.0 - - name: Build docker image - run: ./backend/build-docker-image.sh - shell: bash - - name: Run docker image - run: ./backend/run-docker-image.sh \ No newline at end of file diff --git a/.github/workflows/build-plugin-snapshot-zip.yml b/.github/workflows/build-plugin-snapshot-zip.yml deleted file mode 100644 index 4e60cc4..0000000 --- a/.github/workflows/build-plugin-snapshot-zip.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Build Plugin snapshot ZIP -on: - pull_request: - branches: main -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3.2.0 - - name: Install NodeJS - uses: actions/setup-node@v3 - with: - node-version: 18 - - uses: pnpm/action-setup@v2 - name: Install pnpm - id: pnpm-install - with: - version: 7 - run_install: false - - run: npm install shx -g - - run: npm install rollup -g - - name: Install libudev-dev and libusb-dev - run: sudo apt-get install -y libusb-1.0-0-dev libudev-dev - - name: Build release zip - run: ./release.sh - shell: bash - env: - PR_NUMBER: ${{ github.event.number }} - - name: Archive zip - uses: actions/upload-artifact@v3 - with: - name: controller-tools - path: controller-tools-*.zip \ No newline at end of file diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml new file mode 100644 index 0000000..44056b0 --- /dev/null +++ b/.github/workflows/dev-build.yml @@ -0,0 +1,46 @@ +name: dev-build +run-name: Build plugin for development +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + build-plugin: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup latest Node.js + uses: actions/setup-node@v4 + with: + node-version: latest + + - name: Setup PNPM@9 + uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Build frontend from source + run: | + pnpm i + pnpm run build + + - name: Download Decky Plugin CLI + run: | + mkdir $(pwd)/cli + curl -L -o $(pwd)/cli/decky "https://github.com/SteamDeckHomebrew/cli/releases/latest/download/decky-linux-x86_64" + chmod +x $(pwd)/cli/decky + + - name: Build plugin + run: | + $(pwd)/cli/decky plugin build $(pwd) + unzip "out/Controller Tools.zip" -d "out/Controller Tools" + + - name: Upload plugin + uses: actions/upload-artifact@v4 + with: + name: Controller Tools + path: out/Controller Tools/* diff --git a/.gitignore b/.gitignore index 33736b1..c259f62 100644 --- a/.gitignore +++ b/.gitignore @@ -15,24 +15,8 @@ lib-cov *.gz *.swp -pids -logs -results -tmp - -# Coverage reports -coverage - -# API keys and secrets -.env - # Dependency directory node_modules -bower_components - -# Editors -.idea -*.iml # OS metadata .DS_Store @@ -41,13 +25,13 @@ Thumbs.db # Ignore built ts files dist/ -__pycache__/ - -/.yalc -yalc.lock - .vscode/settings.json # Ignore output folder backend/out + +.pnpm-store/ +cli/ +deck.json +out/ diff --git a/.vscode/config.sh b/.vscode/config.sh deleted file mode 100755 index b45c794..0000000 --- a/.vscode/config.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )"; -# printf "${SCRIPT_DIR}\n" -# printf "$(dirname $0)\n" -if ! [[ -e "${SCRIPT_DIR}/settings.json" ]]; then - printf '.vscode/settings.json does not exist. Creating it with default settings. Exiting afterwards. Run your task again.\n\n' - cp "${SCRIPT_DIR}/defsettings.json" "${SCRIPT_DIR}/settings.json" - exit 1 -else - printf '.vscode/settings.json does exist. Congrats.\n' - printf 'Make sure to change settings.json to match your deck.\n' -fi \ No newline at end of file diff --git a/.vscode/defsettings.json b/.vscode/defsettings.json deleted file mode 100644 index 7360735..0000000 --- a/.vscode/defsettings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "deckip" : "0.0.0.0", - "deckport" : "22", - "deckpass" : "ssap", - "deckkey" : "-i ${env:HOME}/.ssh/id_rsa", - "deckdir" : "/home/deck" -} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 0839d72..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "configurations": [ - { - "type": "lldb", - "request": "custom", - "name": "Remote executable 'controller-tools'", - "preLaunchTask": "rust: remote SteamDeck debug setup", - "targetCreateCommands": [ - "target create ${workspaceFolder}/backend/target/x86_64-unknown-linux-gnu/debug/controller-tools" - ], - "processCreateCommands": [ - "gdb-remote steamdeck:17777", - "process handle SIGPIPE -n true -p true -s false" - ] - }, - { - "name": "Launch (lldb)", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/a.out", - "args": [], - "stopAtEntry": false, - "cwd": "${workspaceFolder}", - "environment": [], - "externalConsole": false, - "miDebuggerPath": "/usr/bin/lldb" - } - ] -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 5eeda5d..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "rust: remote SteamDeck debug setup", - "type": "shell", - "command": "${workspaceFolder}/scripts/remote_debug.sh", - "args": [ - "${workspaceFolder}", - "steamdeck", - "17777" - ], - "group": "none", - "dependsOn": [ - "rust: cross build SteamDeck" - ] - }, - { - "label": "rust: cross build SteamDeck", - "type": "shell", - "command": "cross build --manifest-path backend/Cargo.toml", - "problemMatcher": [ - "$rustc" - ], - "group": "build" - }, - { - "label": "checkforsettings", - "type": "shell", - "group": "none", - "detail": "Check that settings.json has been created", - "command": "bash -c ${workspaceFolder}/.vscode/config.sh", - "problemMatcher": [] - }, - { - "label": "pnpmsetup", - "type": "shell", - "group": "build", - "detail": "Setup pnpm", - "command": "pnpm i", - "problemMatcher": [] - }, - { - "label": "updatefrontendlib", - "type": "shell", - "group": "build", - "detail": "Update deck-frontend-lib", - "command": "pnpm update decky-frontend-lib --latest", - "problemMatcher": [] - }, - { - "label": "buildfrontend", - "type": "npm", - "group": "build", - "detail": "rollup -c", - "script": "build", - "path": "", - "problemMatcher": [] - }, - { - "label": "buildbackend", - "type": "shell", - "group": "build", - "detail": "Build Rust backend", - "command": "cross build --manifest-path backend/Cargo.toml", - "problemMatcher": [] - }, - { - "label": "buildall", - "group": "build", - "detail": "Build decky-plugin-template", - "dependsOrder": "sequence", - "dependsOn": [ - "pnpmsetup", - "buildfrontend", - "buildbackend" - ], - "problemMatcher": [] - }, - { - "label": "createfolders", - "detail": "Create plugins folder in expected directory", - "type": "shell", - "group": "none", - "dependsOn": [ - "checkforsettings" - ], - "command": "ssh deck@${config:deckip} -p ${config:deckport} ${config:deckkey} 'mkdir -p ${config:deckdir}/homebrew/pluginloader && mkdir -p ${config:deckdir}/homebrew/plugins'", - "problemMatcher": [] - }, - { - "label": "deploy frontend", - "detail": "Deploy plugin frontend to deck", - "type": "shell", - "group": "none", - "dependsOn": [ - "buildfrontend" - ], - "command": "rsync -azp --delete --rsh='ssh -p ${config:deckport} ${config:deckkey}' dist deck@${config:deckip}:${config:deckdir}/homebrew/plugins/ControllerTools && DECKIP=${config:deckip} node scripts/reload_frontend.js", - "problemMatcher": [] - }, - { - "label": "deploy", - "detail": "Deploy dev plugin to deck", - "type": "shell", - "group": "none", - "command": "rsync -azp --delete --rsh='ssh -p ${config:deckport} ${config:deckkey}' build/ deck@${config:deckip}:${config:deckdir}/homebrew/plugins/ControllerTools", - "problemMatcher": [] - }, - { - "label": "chmodfolders", - "detail": "chmods folders to prevent perms issues", - "type": "shell", - "group": "none", - "command": "ssh deck@${config:deckip} -p ${config:deckport} ${config:deckkey} 'echo '${config:deckpass}' | sudo -S chmod -R ug+rw ${config:deckdir}/homebrew/'", - "problemMatcher": [] - }, - { - "label": "deployall", - "dependsOrder": "sequence", - "group": "none", - "dependsOn": [ - "deploy", - "chmodfolders" - ], - "problemMatcher": [] - }, - { - "label": "restartdecky", - "detail": "restart decky plugin_loader service", - "type": "shell", - "group": "none", - "command": "ssh deck@${config:deckip} -p ${config:deckport} ${config:deckkey} 'echo '${config:deckpass}' | sudo -S systemctl restart plugin_loader'", - "problemMatcher": [] - }, - { - "label": "allinone", - "detail": "Build and deploy", - "dependsOrder": "sequence", - "group": "test", - "dependsOn": [ - "buildall", - "deployall" - ], - "problemMatcher": [] - } - ] -} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index bca7c4e..0000000 --- a/Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -FROM ubuntu:22.04 AS builder - -RUN apt-get update && \ - apt-get install -y build-essential git curl npm zip pkg-config libudev-dev jq - -# Version supported by the Decky CI -RUN npm install -g pnpm@6.0.0 - -# Install Rust using rustup -RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - -# Configure environment for Rust -ENV PATH="/root/.cargo/bin:${PATH}" - -WORKDIR /app - -COPY . . - -RUN pnpm install --force - -RUN ./release.sh - -FROM scratch AS binaries - -COPY --from=builder /app/pnpm-lock.yaml / -COPY --from=builder /app/*.zip / \ No newline at end of file diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 2c7b619..42f815d 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -175,7 +175,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "controller-tools" -version = "1.2.2" +version = "2.0.0" dependencies = [ "anyhow", "axum", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index a72c631..3416c7f 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "controller-tools" -version = "1.2.2" +version = "2.0.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -18,8 +18,10 @@ bincode = "1.3.3" serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" anyhow = "1.0.82" -udev = "0.8.0" # logging log = "0.4.21" -simplelog = "0.12.2" \ No newline at end of file +simplelog = "0.12.2" + +[target.x86_64-unknown-linux-gnu.dependencies] +udev = "0.8.0" diff --git a/backend/build-docker-image.sh b/backend/build-docker-image.sh deleted file mode 100755 index 2d06f56..0000000 --- a/backend/build-docker-image.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -# build docker container locally (for testing) - -docker build -f $PWD/backend/Dockerfile -t controller-tools-backend . \ No newline at end of file diff --git a/backend/build-docker.sh b/backend/build-docker.sh deleted file mode 100755 index f9145a5..0000000 --- a/backend/build-docker.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -echo "--- Rust version info ---" -rustup --version -rustc --version -cargo --version - -echo "--- Building plugin backend ---" -cargo build --release -mkdir -p out -cp target/release/controller-tools out/backend - -echo " --- Cleaning up ---" -# remove root-owned target folder -cargo clean \ No newline at end of file diff --git a/backend/build.sh b/backend/build.sh index 2ff75b4..4e4b337 100755 --- a/backend/build.sh +++ b/backend/build.sh @@ -1,11 +1,15 @@ #!/bin/bash -mkdir -p ../bin +echo "--- Rust version info ---" +rustup --version +rustc --version +cargo --version -# Debug -cross build -cp ./target/x86_64-unknown-linux-gnu/debug/controller-tools ../bin/backend +echo "--- Building plugin backend ---" +cargo build --release +mkdir -p out +cp target/release/controller-tools out/backend -# Release -#TARGET_CC=x86_64-unknown-linux-gnu-gcc cargo build --release --target x86_64-unknown-linux-gnu -#cp ./target/x86_64-unknown-linux-gnu/release/backend ../bin/backend +echo " --- Cleaning up ---" +# remove root-owned target folder +cargo clean diff --git a/backend/entrypoint.sh b/backend/entrypoint.sh index c58e6a2..3a8a6eb 100755 --- a/backend/entrypoint.sh +++ b/backend/entrypoint.sh @@ -5,4 +5,4 @@ echo "Container's IP address: `awk 'END{print $1}' /etc/hosts`" cd /backend -./build-docker.sh \ No newline at end of file +./build.sh diff --git a/backend/run-docker-image.sh b/backend/run-docker-image.sh deleted file mode 100755 index 8c1b77f..0000000 --- a/backend/run-docker-image.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run -i --entrypoint /backend/entrypoint.sh -v $PWD/backend:/backend controller-tools-backend \ No newline at end of file diff --git a/backend/src/main.rs b/backend/src/main.rs index 56e9f8a..e72feab 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -6,7 +6,6 @@ mod ws; use std::{fs::File, net::SocketAddr, sync::Arc}; use axum::{ - extract::State, http::{HeaderValue, Method, StatusCode}, response::{IntoResponse, Response}, routing::get, @@ -14,7 +13,6 @@ use axum::{ }; use controller::Controller; use log::info; -use settings::Settings; use simplelog::{ ColorChoice, CombinedLogger, Config, LevelFilter, TermLogger, TerminalMode, WriteLogger, }; @@ -31,11 +29,19 @@ pub struct AppState { #[tokio::main] async fn main() { - let settings_location = match tokio::fs::metadata("/home/deck/homebrew/settings").await { - Ok(_) => "/home/deck/homebrew/settings/controller-tools.json", - Err(_) => "/tmp/controller-tools.json", + let args: Vec = std::env::args().collect(); + + if args.len() != 3 { + panic!("Error: Expected 2 arguments, but got {}", args.len() - 1); + } + + let settings_directory = args[1].clone(); + + let settings_location = match tokio::fs::metadata(&settings_directory).await { + Ok(_) => format!("{}/settings.json", &settings_directory), + Err(_) => String::from("/tmp/controller-tools.json"), }; - let settings_service = SettingsService::new(settings_location).await.unwrap(); + let settings_service = SettingsService::new(&settings_location).await.unwrap(); let level_filter = match settings_service.get_settings().await.debug { true => LevelFilter::Debug, @@ -51,7 +57,7 @@ async fn main() { WriteLogger::new( level_filter, Config::default(), - File::create("/tmp/controller-tools.log").unwrap(), + File::create(args[2].clone()).unwrap(), ), ]) .unwrap(); @@ -60,7 +66,6 @@ async fn main() { let app = Router::new() .route("/controllers", get(controllers_json)) - .route("/settings", get(get_settings).post(post_settings)) .route("/ws", get(ws::ws_handler)) .with_state(app_state) .layer( @@ -71,7 +76,6 @@ async fn main() { ); let addr = SocketAddr::from(([127, 0, 0, 1], PORT)); - info!("Using settings file: {}", settings_location); info!("Logging level: {:?}", level_filter); info!("Listening on {}", addr); @@ -79,19 +83,6 @@ async fn main() { axum::serve(listener, app).await.unwrap(); } -async fn get_settings(State(state): State>) -> Result, AppError> { - let settings = state.settings_service.get_settings().await; - Ok(Json(settings)) -} - -async fn post_settings( - State(state): State>, - Json(settings): Json, -) -> Result, AppError> { - let settings = state.settings_service.set_settings(settings).await?; - Ok(Json(settings)) -} - async fn controllers_json() -> Result>, AppError> { // Spawn a tokio blocking task because `get_controllers()` is a blocking API let controllers = tokio::task::spawn_blocking(api::controllers).await??; diff --git a/backend/src/settings.rs b/backend/src/settings.rs index 6082431..5194f26 100644 --- a/backend/src/settings.rs +++ b/backend/src/settings.rs @@ -1,10 +1,10 @@ use anyhow::Result; use log::error; -use serde::{Deserialize, Serialize}; +use serde::Deserialize; use std::sync::Mutex; use tokio::fs::File; -#[derive(Serialize, Deserialize, Clone)] +#[derive(Deserialize, Clone)] pub struct Settings { pub notifications: bool, pub debug: bool, @@ -34,37 +34,25 @@ impl Default for Settings { pub struct SettingsService { settings: Mutex, - file_path: String, -} - -async fn write_settings(file_path: &str, settings: &Settings) -> Result<()> { - let file = File::create(file_path).await?; - serde_json::to_writer(file.into_std().await, settings)?; - Ok(()) } impl SettingsService { - pub async fn new(file_path: &str) -> Result { + pub async fn new(file_path: &String) -> Result { let file = File::open(file_path).await; let settings = if let Ok(file) = file { match serde_json::from_reader(file.into_std().await) { Ok(settings) => settings, Err(err) => { error!("Resetting config file due to parse failure: {}", err); - let settings = Settings::default(); - write_settings(file_path, &settings).await?; - settings + Settings::default() } } } else { - let settings = Settings::default(); - write_settings(file_path, &settings).await?; - settings + Settings::default() }; Ok(Self { settings: Mutex::new(settings), - file_path: file_path.to_string(), }) } @@ -78,13 +66,6 @@ impl SettingsService { }; settings.clone() } - - pub async fn set_settings(&self, settings: Settings) -> Result { - write_settings(&self.file_path, &settings).await?; - let mut current_settings = self.settings.lock().unwrap(); - *current_settings = settings; - Ok(current_settings.clone()) - } } #[cfg(test)] @@ -106,8 +87,6 @@ mod test { let mut settings = settings_service.get_settings().await; assert_eq!(settings.notifications, true); settings.notifications = false; - settings_service.set_settings(settings).await?; - assert!(!settings_service.get_settings().await.notifications); // Read it again let settings_service = SettingsService::new(&file_path).await?; diff --git a/decky.pyi b/decky.pyi new file mode 100644 index 0000000..a72c74c --- /dev/null +++ b/decky.pyi @@ -0,0 +1,184 @@ +""" +This module exposes various constants and helpers useful for decky plugins. + +* Plugin's settings and configurations should be stored under `DECKY_PLUGIN_SETTINGS_DIR`. +* Plugin's runtime data should be stored under `DECKY_PLUGIN_RUNTIME_DIR`. +* Plugin's persistent log files should be stored under `DECKY_PLUGIN_LOG_DIR`. + +Avoid writing outside of `DECKY_HOME`, storing under the suggested paths is strongly recommended. + +Some basic migration helpers are available: `migrate_any`, `migrate_settings`, `migrate_runtime`, `migrate_logs`. + +A logging facility `logger` is available which writes to the recommended location. +""" + +__version__ = '1.0.0' + +import logging + +from typing import Any + +""" +Constants +""" + +HOME: str +""" +The home directory of the effective user running the process. +Environment variable: `HOME`. +If `root` was specified in the plugin's flags it will be `/root` otherwise the user whose home decky resides in. +e.g.: `/home/deck` +""" + +USER: str +""" +The effective username running the process. +Environment variable: `USER`. +It would be `root` if `root` was specified in the plugin's flags otherwise the user whose home decky resides in. +e.g.: `deck` +""" + +DECKY_VERSION: str +""" +The version of the decky loader. +Environment variable: `DECKY_VERSION`. +e.g.: `v2.5.0-pre1` +""" + +DECKY_USER: str +""" +The user whose home decky resides in. +Environment variable: `DECKY_USER`. +e.g.: `deck` +""" + +DECKY_USER_HOME: str +""" +The home of the user where decky resides in. +Environment variable: `DECKY_USER_HOME`. +e.g.: `/home/deck` +""" + +DECKY_HOME: str +""" +The root of the decky folder. +Environment variable: `DECKY_HOME`. +e.g.: `/home/deck/homebrew` +""" + +DECKY_PLUGIN_SETTINGS_DIR: str +""" +The recommended path in which to store configuration files (created automatically). +Environment variable: `DECKY_PLUGIN_SETTINGS_DIR`. +e.g.: `/home/deck/homebrew/settings/decky-plugin-template` +""" + +DECKY_PLUGIN_RUNTIME_DIR: str +""" +The recommended path in which to store runtime data (created automatically). +Environment variable: `DECKY_PLUGIN_RUNTIME_DIR`. +e.g.: `/home/deck/homebrew/data/decky-plugin-template` +""" + +DECKY_PLUGIN_LOG_DIR: str +""" +The recommended path in which to store persistent logs (created automatically). +Environment variable: `DECKY_PLUGIN_LOG_DIR`. +e.g.: `/home/deck/homebrew/logs/decky-plugin-template` +""" + +DECKY_PLUGIN_DIR: str +""" +The root of the plugin's directory. +Environment variable: `DECKY_PLUGIN_DIR`. +e.g.: `/home/deck/homebrew/plugins/decky-plugin-template` +""" + +DECKY_PLUGIN_NAME: str +""" +The name of the plugin as specified in the 'plugin.json'. +Environment variable: `DECKY_PLUGIN_NAME`. +e.g.: `Example Plugin` +""" + +DECKY_PLUGIN_VERSION: str +""" +The version of the plugin as specified in the 'package.json'. +Environment variable: `DECKY_PLUGIN_VERSION`. +e.g.: `0.0.1` +""" + +DECKY_PLUGIN_AUTHOR: str +""" +The author of the plugin as specified in the 'plugin.json'. +Environment variable: `DECKY_PLUGIN_AUTHOR`. +e.g.: `John Doe` +""" + +DECKY_PLUGIN_LOG: str +""" +The path to the plugin's main logfile. +Environment variable: `DECKY_PLUGIN_LOG`. +e.g.: `/home/deck/homebrew/logs/decky-plugin-template/plugin.log` +""" + +""" +Migration helpers +""" + + +def migrate_any(target_dir: str, *files_or_directories: str) -> dict[str, str]: + """ + Migrate files and directories to a new location and remove old locations. + Specified files will be migrated to `target_dir`. + Specified directories will have their contents recursively migrated to `target_dir`. + + Returns the mapping of old -> new location. + """ + + +def migrate_settings(*files_or_directories: str) -> dict[str, str]: + """ + Migrate files and directories relating to plugin settings to the recommended location and remove old locations. + Specified files will be migrated to `DECKY_PLUGIN_SETTINGS_DIR`. + Specified directories will have their contents recursively migrated to `DECKY_PLUGIN_SETTINGS_DIR`. + + Returns the mapping of old -> new location. + """ + + +def migrate_runtime(*files_or_directories: str) -> dict[str, str]: + """ + Migrate files and directories relating to plugin runtime data to the recommended location and remove old locations + Specified files will be migrated to `DECKY_PLUGIN_RUNTIME_DIR`. + Specified directories will have their contents recursively migrated to `DECKY_PLUGIN_RUNTIME_DIR`. + + Returns the mapping of old -> new location. + """ + + +def migrate_logs(*files_or_directories: str) -> dict[str, str]: + """ + Migrate files and directories relating to plugin logs to the recommended location and remove old locations. + Specified files will be migrated to `DECKY_PLUGIN_LOG_DIR`. + Specified directories will have their contents recursively migrated to `DECKY_PLUGIN_LOG_DIR`. + + Returns the mapping of old -> new location. + """ + + +""" +Logging +""" + +logger: logging.Logger +"""The main plugin logger writing to `DECKY_PLUGIN_LOG`.""" + +""" +Event handling +""" +# TODO better docstring im lazy +async def emit(event: str, *args: Any) -> None: + """ + Send an event to the frontend. + """ \ No newline at end of file diff --git a/main.py b/main.py index db140f6..50992b5 100644 --- a/main.py +++ b/main.py @@ -1,30 +1,58 @@ -import pathlib -import subprocess import asyncio -import os - -HOME_DIR = str(pathlib.Path(os.getcwd()).parent.parent.resolve()) -PARENT_DIR = str(pathlib.Path(__file__).parent.resolve()) - -LOG_LOCATION = "/tmp/controller-tools.py.log" - +import asyncio.subprocess import logging +import typing -logging.basicConfig( - filename = LOG_LOCATION, - format = '%(asctime)s %(levelname)s %(message)s', - filemode = 'w', - force = True) +import decky # type: ignore +import settings # type: ignore -logger = logging.getLogger() +HOME_DIR = decky.DECKY_HOME +PARENT_DIR = decky.DECKY_PLUGIN_DIR + +logger = decky.logger logger.setLevel(logging.DEBUG) logging.info(f"ControllerTools main.py https://github.com/alphamercury/ControllerTools") +logger.info("[backend] Settings path: {}".format(decky.DECKY_PLUGIN_SETTINGS_DIR)) +settings = settings.SettingsManager(name="settings", settings_directory=decky.DECKY_PLUGIN_SETTINGS_DIR) +settings.read() + class Plugin: - backend_proc = None - # Asyncio-compatible long-running code, executed in a task when the plugin is loaded - async def _main(self): - # startup with my_env - self.backend_proc = subprocess.Popen([PARENT_DIR + "/bin/backend"]) - while True: - await asyncio.sleep(1) \ No newline at end of file + BACKEND_PROC: typing.Optional[asyncio.subprocess.Process] = None + + @classmethod + async def _main(cls): + cls.BACKEND_PROC = await asyncio.subprocess.create_subprocess_exec( + PARENT_DIR + "/bin/backend", + f"{decky.DECKY_PLUGIN_SETTINGS_DIR}/settings.json", + decky.DECKY_PLUGIN_LOG, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + ) + + @classmethod + async def _unload(cls): + if cls.BACKEND_PROC is not None: + cls.BACKEND_PROC.terminate() + await cls.BACKEND_PROC.wait() + cls.BACKEND_PROC = None + + @classmethod + async def settings_read(cls): + logger.info("[backend] Reading settings") + return settings.read() + + @classmethod + async def settings_commit(cls): + logger.info("[backend] Saving settings") + return settings.commit() + + @classmethod + async def settings_getSetting(cls, key: str, defaults: typing.Any): + logger.info("[backend] Get {}".format(key)) + return settings.getSetting(key, defaults) + + @classmethod + async def settings_setSetting(cls, key: str, value: typing.Any): + logger.info("[backend] Set {}: {}".format(key, value)) + return settings.setSetting(key, value) diff --git a/package.json b/package.json index 49ebc55..773946e 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { - "name": "ControllerTools", - "version": "1.2.2", + "name": "controller-tools", + "version": "2.0.0", "description": "The missing game controller menu. Displays the current battery % and charging status", "type": "module", "scripts": { - "build": "shx rm -rf dist && rollup -c", + "build": "rollup -c", "watch": "rollup -c -w", "test": "echo \"Error: no test specified\" && exit 1" }, @@ -41,22 +41,18 @@ }, "homepage": "https://github.com/jfernandez/ControllerTools#readme", "devDependencies": { - "@rollup/plugin-commonjs": "^21.1.0", - "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^13.3.0", - "@rollup/plugin-replace": "^4.0.0", - "@rollup/plugin-typescript": "^8.3.3", - "@types/react": "16.14.0", - "@types/webpack": "^5.28.0", - "rollup": "^2.77.1", - "rollup-plugin-import-assets": "^1.1.1", - "shx": "^0.3.4", - "tslib": "^2.4.0", - "typescript": "^4.7.4" + "@decky/rollup": "^1.0.1", + "@decky/ui": "^4.7.4", + "@types/react": "18.3.3", + "@types/react-dom": "18.3.0", + "@types/webpack": "^5.28.5", + "rollup": "^4.24.0", + "typescript": "^5.6.2" }, "dependencies": { - "decky-frontend-lib": "^3.25.0", - "react-icons": "^4.4.0" + "@decky/api": "^1.1.2", + "react-icons": "^5.3.0", + "tslib": "^2.7.0" }, "pnpm": { "peerDependencyRules": { diff --git a/package.sh b/package.sh deleted file mode 100755 index c0b8ffc..0000000 --- a/package.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -rm -rf build -mkdir -p build/bin - -pnpm run build -cp -r dist build/ - -cargo build --manifest-path backend/Cargo.toml -cp ./backend/target/debug/controller-tools build/bin/backend - -cp package.json build/package.json -cp plugin.json build/plugin.json -cp main.py build/main.py -cp README.md build/README.md -cp LICENSE build/LICENSE \ No newline at end of file diff --git a/plugin.json b/plugin.json index 72e7901..4a62f81 100644 --- a/plugin.json +++ b/plugin.json @@ -4,6 +4,7 @@ "flags": [ "debug" ], + "api_version": 1, "publish": { "tags": [ "controller", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 07c6921..c95461e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,58 +8,59 @@ importers: .: dependencies: - decky-frontend-lib: - specifier: ^3.25.0 - version: 3.25.0 + '@decky/api': + specifier: ^1.1.2 + version: 1.1.2 react-icons: - specifier: ^4.4.0 - version: 4.12.0(react@18.3.1) + specifier: ^5.3.0 + version: 5.3.0(react@18.3.1) + tslib: + specifier: ^2.7.0 + version: 2.7.0 devDependencies: - '@rollup/plugin-commonjs': - specifier: ^21.1.0 - version: 21.1.0(rollup@2.79.1) - '@rollup/plugin-json': - specifier: ^4.1.0 - version: 4.1.0(rollup@2.79.1) - '@rollup/plugin-node-resolve': - specifier: ^13.3.0 - version: 13.3.0(rollup@2.79.1) - '@rollup/plugin-replace': - specifier: ^4.0.0 - version: 4.0.0(rollup@2.79.1) - '@rollup/plugin-typescript': - specifier: ^8.3.3 - version: 8.5.0(rollup@2.79.1)(tslib@2.6.2)(typescript@4.9.5) + '@decky/rollup': + specifier: ^1.0.1 + version: 1.0.1 + '@decky/ui': + specifier: ^4.7.4 + version: 4.7.4 '@types/react': - specifier: 16.14.0 - version: 16.14.0 + specifier: 18.3.3 + version: 18.3.3 + '@types/react-dom': + specifier: 18.3.0 + version: 18.3.0 '@types/webpack': - specifier: ^5.28.0 + specifier: ^5.28.5 version: 5.28.5 rollup: - specifier: ^2.77.1 - version: 2.79.1 - rollup-plugin-import-assets: - specifier: ^1.1.1 - version: 1.1.1(rollup@2.79.1) - shx: - specifier: ^0.3.4 - version: 0.3.4 - tslib: - specifier: ^2.4.0 - version: 2.6.2 + specifier: ^4.24.0 + version: 4.24.0 typescript: - specifier: ^4.7.4 - version: 4.9.5 + specifier: ^5.6.2 + version: 5.6.2 packages: + '@decky/api@1.1.2': + resolution: {integrity: sha512-lTMqRpHOrGTCyH2c1jJvkmWhOq2dcnX5/ioHbfCVmyQOBik1OM1BnzF1uROsnNDC5GkRvl3J/ATqYp6vhYpRqw==} + + '@decky/rollup@1.0.1': + resolution: {integrity: sha512-dx1VJwD7ul14PA/aZvOwAfY/GujHzqZJ+MFb4OIUVi63/z4KWMSuZrK6QWo0S4LrNW3RzB3ua6LT0WcJaNY9gw==} + + '@decky/ui@4.7.4': + resolution: {integrity: sha512-ziCP3akLJVYG5FFoS0ao9MYEYJ09g44FP4xMmOUFe8SFRjC9BqBvbJBF0+OUOKgp2C7SJ0rNPSIFm4RwCUvoug==} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} - '@jridgewell/resolve-uri@3.1.0': - resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} '@jridgewell/set-array@1.2.1': @@ -69,77 +70,192 @@ packages: '@jridgewell/source-map@0.3.6': resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} - '@jridgewell/sourcemap-codec@1.4.15': - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@rollup/plugin-commonjs@21.1.0': - resolution: {integrity: sha512-6ZtHx3VHIp2ReNNDxHjuUml6ur+WcQ28N1yHgCQwsbNkQg2suhxGMDQGJOn/KuDxKtd1xuZP5xSTwBA4GQ8hbA==} - engines: {node: '>= 8.0.0'} + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@rollup/plugin-commonjs@26.0.3': + resolution: {integrity: sha512-2BJcolt43MY+y5Tz47djHkodCC3c1VKVrBDKpVqHKpQ9z9S158kCCqB8NF6/gzxLdNlYW9abB3Ibh+kOWLp8KQ==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} peerDependencies: - rollup: ^2.38.3 + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true - '@rollup/plugin-json@4.1.0': - resolution: {integrity: sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==} + '@rollup/plugin-json@6.1.0': + resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} + engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^1.20.0 || ^2.0.0 + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true - '@rollup/plugin-node-resolve@13.3.0': - resolution: {integrity: sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw==} - engines: {node: '>= 10.0.0'} + '@rollup/plugin-node-resolve@15.3.0': + resolution: {integrity: sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==} + engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^2.42.0 + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true - '@rollup/plugin-replace@4.0.0': - resolution: {integrity: sha512-+rumQFiaNac9y64OHtkHGmdjm7us9bo1PlbgQfdihQtuNxzjpaB064HbRnewUOggLQxVCCyINfStkgmBeQpv1g==} + '@rollup/plugin-replace@5.0.7': + resolution: {integrity: sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ==} + engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^1.20.0 || ^2.0.0 + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true - '@rollup/plugin-typescript@8.5.0': - resolution: {integrity: sha512-wMv1/scv0m/rXx21wD2IsBbJFba8wGF3ErJIr6IKRfRj49S85Lszbxb4DCo8iILpluTjk2GAAu9CoZt4G3ppgQ==} - engines: {node: '>=8.0.0'} + '@rollup/plugin-typescript@11.1.6': + resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==} + engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^2.14.0 + rollup: ^2.14.0||^3.0.0||^4.0.0 tslib: '*' typescript: '>=3.7.0' peerDependenciesMeta: + rollup: + optional: true tslib: optional: true - '@rollup/pluginutils@3.1.0': - resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} - engines: {node: '>= 8.0.0'} + '@rollup/pluginutils@5.1.2': + resolution: {integrity: sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==} + engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^1.20.0||^2.0.0 + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.24.0': + resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.24.0': + resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.24.0': + resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.24.0': + resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.24.0': + resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.24.0': + resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.24.0': + resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==} + cpu: [arm64] + os: [linux] - '@types/eslint-scope@3.7.4': - resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==} + '@rollup/rollup-linux-arm64-musl@4.24.0': + resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==} + cpu: [arm64] + os: [linux] - '@types/eslint@8.4.5': - resolution: {integrity: sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': + resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==} + cpu: [ppc64] + os: [linux] - '@types/estree@0.0.39': - resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} + '@rollup/rollup-linux-riscv64-gnu@4.24.0': + resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==} + cpu: [riscv64] + os: [linux] - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@rollup/rollup-linux-s390x-gnu@4.24.0': + resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==} + cpu: [s390x] + os: [linux] - '@types/json-schema@7.0.11': - resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} + '@rollup/rollup-linux-x64-gnu@4.24.0': + resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==} + cpu: [x64] + os: [linux] - '@types/node@18.6.1': - resolution: {integrity: sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg==} + '@rollup/rollup-linux-x64-musl@4.24.0': + resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==} + cpu: [x64] + os: [linux] - '@types/prop-types@15.7.5': - resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} + '@rollup/rollup-win32-arm64-msvc@4.24.0': + resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==} + cpu: [arm64] + os: [win32] - '@types/react@16.14.0': - resolution: {integrity: sha512-jJjHo1uOe+NENRIBvF46tJimUvPnmbQ41Ax0pEm7pRvhPg+wuj8VMOHHiMvaGmZRzRrCtm7KnL5OOE/6kHPK8w==} + '@rollup/rollup-win32-ia32-msvc@4.24.0': + resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==} + cpu: [ia32] + os: [win32] - '@types/resolve@1.17.1': - resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} + '@rollup/rollup-win32-x64-msvc@4.24.0': + resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==} + cpu: [x64] + os: [win32] + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/glob@7.2.0': + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/minimatch@5.1.2': + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + + '@types/node@22.7.4': + resolution: {integrity: sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==} + + '@types/prop-types@15.7.13': + resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} + + '@types/react-dom@18.3.0': + resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} + + '@types/react@18.3.3': + resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} + + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} '@types/webpack@5.28.5': resolution: {integrity: sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==} @@ -195,16 +311,20 @@ packages: '@xtuc/long@4.2.2': resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - acorn-import-assertions@1.9.0: - resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} + acorn-import-attributes@1.9.5: + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} peerDependencies: acorn: ^8 - acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} engines: {node: '>=0.4.0'} hasBin: true + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + ajv-keywords@3.5.2: resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} peerDependencies: @@ -213,30 +333,64 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - browserslist@4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.24.0: + resolution: {integrity: sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + caniuse-lite@1.0.30001667: + resolution: {integrity: sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==} + + chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} + engines: {node: '>=6.0'} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} - caniuse-lite@1.0.30001609: - resolution: {integrity: sha512-JFPQs34lHKx1B5t1EpQpWH4c+29zIyn/haGsbpfq3suuV9v56enjFt23zqijxGTMwy1p/4H2tjnQMY+p1WoAyA==} + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} - chrome-trace-event@1.0.3: - resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} - engines: {node: '>=6.0'} + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -247,28 +401,46 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - csstype@3.1.0: - resolution: {integrity: sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==} + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} - decky-frontend-lib@3.25.0: - resolution: {integrity: sha512-2lBoHS2AIRmuluq/bGdHBz+uyToQE7k3K/vDq1MQbDZ4eC+8CGDuh2T8yZOj3D0yjGP2MdikNNAWPA9Z5l2qDg==} + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - deepmerge@4.2.2: - resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - electron-to-chromium@1.4.736: - resolution: {integrity: sha512-Rer6wc3ynLelKNM4lOCg7/zPQj8tPOCB2hzD32PX9wd3hgRRi9MxEbmkFCokzcEhRVMiOVLjnL9ig9cefJ+6+Q==} + del@5.1.0: + resolution: {integrity: sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==} + engines: {node: '>=8'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} - enhanced-resolve@5.16.0: - resolution: {integrity: sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==} + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + electron-to-chromium@1.5.32: + resolution: {integrity: sha512-M+7ph0VGBQqqpTT2YrabjNKSQ2fEl9PVx6AK3N558gDH9NO8O6XN9SXXFWRo9u9PbEg/bWq+tjXQr+eXmxubCw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + enhanced-resolve@5.17.1: + resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} engines: {node: '>=10.13.0'} - es-module-lexer@1.5.0: - resolution: {integrity: sha512-pqrTKmwEIgafsYZAGw9kszYzmagcE/n4dbgwGWLEXg7J4QFJVQRBld8j3Q3GNez79jzxZshq0bcT962QHOghjw==} + es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} - escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} eslint-scope@5.1.1: @@ -290,12 +462,12 @@ packages: estree-walker@0.6.1: resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} - estree-walker@1.0.1: - resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} - estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -303,25 +475,53 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + globby@10.0.2: + resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} + engines: {node: '>=8'} graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -330,33 +530,72 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - interpret@1.4.0: - resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} - engines: {node: '>= 0.10'} + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} - is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} - is-core-module@2.9.0: - resolution: {integrity: sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==} + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-path-cwd@2.2.0: + resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} + engines: {node: '>=6'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + is-reference@1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + is-reference@3.0.2: + resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} + + is-what@5.0.2: + resolution: {integrity: sha512-vI7Ui0qzNQ2ClDZd0bC7uqRk3T1imbX5cZODmVlqqdqiwmSIUX3CNSiRgFjFMJ987sVCMSa7xZeEDtpJduPg4A==} + engines: {node: '>=18'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jest-worker@27.5.1: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} @@ -378,12 +617,27 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - magic-string@0.25.9: - resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + magic-string@0.30.11: + resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + + merge-anything@6.0.2: + resolution: {integrity: sha512-U8x6DL/YVudOcf82B6hd8GFg+6gF6hEHYwzqdo67GrH6vnDZ5YBq6BYX3hHWyCnG3CcqJDB1a9tj9fzMI3RL9Q==} + engines: {node: '>=18'} merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -395,41 +649,68 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimist@1.2.6: - resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + p-map@3.0.0: + resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} + engines: {node: '>=8'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - punycode@2.1.1: - resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - react-icons@4.12.0: - resolution: {integrity: sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==} + react-icons@5.3.0: + resolution: {integrity: sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==} peerDependencies: react: '*' @@ -437,14 +718,30 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} - rechoir@0.6.2: - resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} - engines: {node: '>= 0.10'} + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true - resolve@1.22.1: - resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true + rollup-plugin-delete@2.1.0: + resolution: {integrity: sha512-TEbqJd7giLvzQDTu4jSPufwhTJs/iYVN2LfR/YIYkqjC/oZ0/h9Q0AeljifIhzBzJYZtHQTWKEbMms5fbh54pw==} + engines: {node: '>=10'} + peerDependencies: + rollup: '*' + + rollup-plugin-external-globals@0.11.0: + resolution: {integrity: sha512-LR+sH2WkgWMPxsA5o5rT7uW7BeWXSeygLe60QQi9qoN/ufaCuHDaVOIbndIkqDPnZt/wZugJh5DCzkZFdSWlLQ==} + peerDependencies: + rollup: ^2.25.0 || ^3.3.0 || ^4.1.4 + rollup-plugin-import-assets@1.1.1: resolution: {integrity: sha512-u5zJwOjguTf2N+wETq2weNKGvNkuVc1UX/fPgg215p5xPvGOaI6/BTc024E9brvFjSQTfIYqgvwogQdipknu1g==} peerDependencies: @@ -453,11 +750,14 @@ packages: rollup-pluginutils@2.8.2: resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} - rollup@2.79.1: - resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} - engines: {node: '>=10.0.0'} + rollup@4.24.0: + resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -468,15 +768,21 @@ packages: serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} - shelljs@0.8.5: - resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} - engines: {node: '>=4'} - hasBin: true + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} - shx@0.3.4: - resolution: {integrity: sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==} - engines: {node: '>=6'} - hasBin: true + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -485,9 +791,21 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - sourcemap-codec@1.4.8: - resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} - deprecated: Please use @jridgewell/sourcemap-codec instead + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} supports-color@8.1.1: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} @@ -517,21 +835,28 @@ packages: uglify-js: optional: true - terser@5.30.3: - resolution: {integrity: sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA==} + terser@5.34.1: + resolution: {integrity: sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==} engines: {node: '>=10'} hasBin: true - tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} - typescript@4.9.5: - resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} - engines: {node: '>=4.2.0'} + typescript@5.6.2: + resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} + engines: {node: '>=14.17'} hasBin: true - update-browserslist-db@1.0.13: - resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + update-browserslist-db@1.1.1: + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -542,16 +867,16 @@ packages: url-join@4.0.1: resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} - watchpack@2.4.1: - resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} + watchpack@2.4.2: + resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} engines: {node: '>=10.13.0'} webpack-sources@3.2.3: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} - webpack@5.91.0: - resolution: {integrity: sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==} + webpack@5.95.0: + resolution: {integrity: sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -560,18 +885,59 @@ packages: webpack-cli: optional: true + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} snapshots: + '@decky/api@1.1.2': {} + + '@decky/rollup@1.0.1': + dependencies: + '@rollup/plugin-commonjs': 26.0.3(rollup@4.24.0) + '@rollup/plugin-json': 6.1.0(rollup@4.24.0) + '@rollup/plugin-node-resolve': 15.3.0(rollup@4.24.0) + '@rollup/plugin-replace': 5.0.7(rollup@4.24.0) + '@rollup/plugin-typescript': 11.1.6(rollup@4.24.0)(tslib@2.7.0)(typescript@5.6.2) + merge-anything: 6.0.2 + rollup: 4.24.0 + rollup-plugin-delete: 2.1.0(rollup@4.24.0) + rollup-plugin-external-globals: 0.11.0(rollup@4.24.0) + rollup-plugin-import-assets: 1.1.1(rollup@4.24.0) + tslib: 2.7.0 + typescript: 5.6.2 + + '@decky/ui@4.7.4': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 - '@jridgewell/resolve-uri@3.1.0': {} + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/set-array@1.2.1': {} @@ -580,95 +946,160 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@jridgewell/sourcemap-codec@1.4.15': {} + '@jridgewell/sourcemap-codec@1.5.0': {} '@jridgewell/trace-mapping@0.3.25': dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 - '@rollup/plugin-commonjs@21.1.0(rollup@2.79.1)': + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@rollup/plugin-commonjs@26.0.3(rollup@4.24.0)': dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) + '@rollup/pluginutils': 5.1.2(rollup@4.24.0) commondir: 1.0.1 estree-walker: 2.0.2 - glob: 7.2.3 + glob: 10.4.5 is-reference: 1.2.1 - magic-string: 0.25.9 - resolve: 1.22.1 - rollup: 2.79.1 + magic-string: 0.30.11 + optionalDependencies: + rollup: 4.24.0 - '@rollup/plugin-json@4.1.0(rollup@2.79.1)': + '@rollup/plugin-json@6.1.0(rollup@4.24.0)': dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) - rollup: 2.79.1 + '@rollup/pluginutils': 5.1.2(rollup@4.24.0) + optionalDependencies: + rollup: 4.24.0 - '@rollup/plugin-node-resolve@13.3.0(rollup@2.79.1)': + '@rollup/plugin-node-resolve@15.3.0(rollup@4.24.0)': dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) - '@types/resolve': 1.17.1 - deepmerge: 4.2.2 - is-builtin-module: 3.2.1 + '@rollup/pluginutils': 5.1.2(rollup@4.24.0) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 is-module: 1.0.0 - resolve: 1.22.1 - rollup: 2.79.1 + resolve: 1.22.8 + optionalDependencies: + rollup: 4.24.0 - '@rollup/plugin-replace@4.0.0(rollup@2.79.1)': + '@rollup/plugin-replace@5.0.7(rollup@4.24.0)': dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) - magic-string: 0.25.9 - rollup: 2.79.1 + '@rollup/pluginutils': 5.1.2(rollup@4.24.0) + magic-string: 0.30.11 + optionalDependencies: + rollup: 4.24.0 - '@rollup/plugin-typescript@8.5.0(rollup@2.79.1)(tslib@2.6.2)(typescript@4.9.5)': + '@rollup/plugin-typescript@11.1.6(rollup@4.24.0)(tslib@2.7.0)(typescript@5.6.2)': dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) - resolve: 1.22.1 - rollup: 2.79.1 - typescript: 4.9.5 + '@rollup/pluginutils': 5.1.2(rollup@4.24.0) + resolve: 1.22.8 + typescript: 5.6.2 optionalDependencies: - tslib: 2.6.2 + rollup: 4.24.0 + tslib: 2.7.0 - '@rollup/pluginutils@3.1.0(rollup@2.79.1)': + '@rollup/pluginutils@5.1.2(rollup@4.24.0)': dependencies: - '@types/estree': 0.0.39 - estree-walker: 1.0.1 + '@types/estree': 1.0.6 + estree-walker: 2.0.2 picomatch: 2.3.1 - rollup: 2.79.1 + optionalDependencies: + rollup: 4.24.0 - '@types/eslint-scope@3.7.4': - dependencies: - '@types/eslint': 8.4.5 - '@types/estree': 1.0.5 + '@rollup/rollup-android-arm-eabi@4.24.0': + optional: true - '@types/eslint@8.4.5': - dependencies: - '@types/estree': 1.0.5 - '@types/json-schema': 7.0.11 + '@rollup/rollup-android-arm64@4.24.0': + optional: true - '@types/estree@0.0.39': {} + '@rollup/rollup-darwin-arm64@4.24.0': + optional: true - '@types/estree@1.0.5': {} + '@rollup/rollup-darwin-x64@4.24.0': + optional: true - '@types/json-schema@7.0.11': {} + '@rollup/rollup-linux-arm-gnueabihf@4.24.0': + optional: true - '@types/node@18.6.1': {} + '@rollup/rollup-linux-arm-musleabihf@4.24.0': + optional: true - '@types/prop-types@15.7.5': {} + '@rollup/rollup-linux-arm64-gnu@4.24.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.24.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.24.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.24.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.24.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.24.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.24.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.24.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.24.0': + optional: true - '@types/react@16.14.0': + '@types/estree@1.0.6': {} + + '@types/glob@7.2.0': + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 22.7.4 + + '@types/json-schema@7.0.15': {} + + '@types/minimatch@5.1.2': {} + + '@types/node@22.7.4': dependencies: - '@types/prop-types': 15.7.5 - csstype: 3.1.0 + undici-types: 6.19.8 - '@types/resolve@1.17.1': + '@types/prop-types@15.7.13': {} + + '@types/react-dom@18.3.0': + dependencies: + '@types/react': 18.3.3 + + '@types/react@18.3.3': dependencies: - '@types/node': 18.6.1 + '@types/prop-types': 15.7.13 + csstype: 3.1.3 + + '@types/resolve@1.20.2': {} '@types/webpack@5.28.5': dependencies: - '@types/node': 18.6.1 + '@types/node': 22.7.4 tapable: 2.2.1 - webpack: 5.91.0 + webpack: 5.95.0 transitivePeerDependencies: - '@swc/core' - esbuild @@ -755,11 +1186,16 @@ snapshots: '@xtuc/long@4.2.2': {} - acorn-import-assertions@1.9.0(acorn@8.11.3): + acorn-import-attributes@1.9.5(acorn@8.12.1): dependencies: - acorn: 8.11.3 + acorn: 8.12.1 - acorn@8.11.3: {} + acorn@8.12.1: {} + + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 ajv-keywords@3.5.2(ajv@6.12.6): dependencies: @@ -772,6 +1208,18 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + array-union@2.1.0: {} + balanced-match@1.0.2: {} brace-expansion@1.1.11: @@ -779,20 +1227,34 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 - browserslist@4.23.0: + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.24.0: dependencies: - caniuse-lite: 1.0.30001609 - electron-to-chromium: 1.4.736 - node-releases: 2.0.14 - update-browserslist-db: 1.0.13(browserslist@4.23.0) + caniuse-lite: 1.0.30001667 + electron-to-chromium: 1.5.32 + node-releases: 2.0.18 + update-browserslist-db: 1.1.1(browserslist@4.24.0) buffer-from@1.1.2: {} - builtin-modules@3.3.0: {} + caniuse-lite@1.0.30001667: {} + + chrome-trace-event@1.0.4: {} + + clean-stack@2.2.0: {} - caniuse-lite@1.0.30001609: {} + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 - chrome-trace-event@1.0.3: {} + color-name@1.1.4: {} commander@2.20.3: {} @@ -800,22 +1262,47 @@ snapshots: concat-map@0.0.1: {} - csstype@3.1.0: {} + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 - decky-frontend-lib@3.25.0: {} + csstype@3.1.3: {} - deepmerge@4.2.2: {} + deepmerge@4.3.1: {} - electron-to-chromium@1.4.736: {} + del@5.1.0: + dependencies: + globby: 10.0.2 + graceful-fs: 4.2.11 + is-glob: 4.0.3 + is-path-cwd: 2.2.0 + is-path-inside: 3.0.3 + p-map: 3.0.0 + rimraf: 3.0.2 + slash: 3.0.0 - enhanced-resolve@5.16.0: + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + eastasianwidth@0.2.0: {} + + electron-to-chromium@1.5.32: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + enhanced-resolve@5.17.1: dependencies: graceful-fs: 4.2.11 tapable: 2.2.1 - es-module-lexer@1.5.0: {} + es-module-lexer@1.5.4: {} - escalade@3.1.1: {} + escalade@3.2.0: {} eslint-scope@5.1.1: dependencies: @@ -832,25 +1319,61 @@ snapshots: estree-walker@0.6.1: {} - estree-walker@1.0.1: {} - estree-walker@2.0.2: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.6 + events@3.3.0: {} fast-deep-equal@3.1.3: {} + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + fast-json-stable-stringify@2.1.0: {} + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + fs.realpath@1.0.0: {} - fsevents@2.3.2: + fsevents@2.3.3: optional: true - function-bind@1.1.1: {} + function-bind@1.1.2: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 glob-to-regexp@0.4.1: {} + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -860,13 +1383,28 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 + globby@10.0.2: + dependencies: + '@types/glob': 7.2.0 + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + glob: 7.2.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + graceful-fs@4.2.11: {} has-flag@4.0.0: {} - has@1.0.3: + hasown@2.0.2: dependencies: - function-bind: 1.1.1 + function-bind: 1.1.2 + + ignore@5.3.2: {} + + indent-string@4.0.0: {} inflight@1.0.6: dependencies: @@ -875,25 +1413,47 @@ snapshots: inherits@2.0.4: {} - interpret@1.4.0: {} - - is-builtin-module@3.2.1: + is-core-module@2.15.1: dependencies: - builtin-modules: 3.3.0 + hasown: 2.0.2 + + is-extglob@2.1.1: {} - is-core-module@2.9.0: + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: dependencies: - has: 1.0.3 + is-extglob: 2.1.1 is-module@1.0.0: {} + is-number@7.0.0: {} + + is-path-cwd@2.2.0: {} + + is-path-inside@3.0.3: {} + is-reference@1.2.1: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 + + is-reference@3.0.2: + dependencies: + '@types/estree': 1.0.6 + + is-what@5.0.2: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 jest-worker@27.5.1: dependencies: - '@types/node': 18.6.1 + '@types/node': 22.7.4 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -909,12 +1469,25 @@ snapshots: dependencies: js-tokens: 4.0.0 - magic-string@0.25.9: + lru-cache@10.4.3: {} + + magic-string@0.30.11: dependencies: - sourcemap-codec: 1.4.8 + '@jridgewell/sourcemap-codec': 1.5.0 + + merge-anything@6.0.2: + dependencies: + is-what: 5.0.2 merge-stream@2.0.0: {} + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + mime-db@1.52.0: {} mime-types@2.1.35: @@ -925,31 +1498,52 @@ snapshots: dependencies: brace-expansion: 1.1.11 - minimist@1.2.6: {} + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minipass@7.1.2: {} neo-async@2.6.2: {} - node-releases@2.0.14: {} + node-releases@2.0.18: {} once@1.4.0: dependencies: wrappy: 1.0.2 + p-map@3.0.0: + dependencies: + aggregate-error: 3.1.0 + + package-json-from-dist@1.0.1: {} + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} + path-parse@1.0.7: {} - picocolors@1.0.0: {} + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-type@4.0.0: {} + + picocolors@1.1.0: {} picomatch@2.3.1: {} - punycode@2.1.1: {} + punycode@2.3.1: {} + + queue-microtask@1.2.3: {} randombytes@2.1.0: dependencies: safe-buffer: 5.2.1 - react-icons@4.12.0(react@18.3.1): + react-icons@5.3.0(react@18.3.1): dependencies: react: 18.3.1 @@ -957,19 +1551,34 @@ snapshots: dependencies: loose-envify: 1.4.0 - rechoir@0.6.2: + resolve@1.22.8: dependencies: - resolve: 1.22.1 - - resolve@1.22.1: - dependencies: - is-core-module: 2.9.0 + is-core-module: 2.15.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - rollup-plugin-import-assets@1.1.1(rollup@2.79.1): + reusify@1.0.4: {} + + rimraf@3.0.2: dependencies: - rollup: 2.79.1 + glob: 7.2.3 + + rollup-plugin-delete@2.1.0(rollup@4.24.0): + dependencies: + del: 5.1.0 + rollup: 4.24.0 + + rollup-plugin-external-globals@0.11.0(rollup@4.24.0): + dependencies: + '@rollup/pluginutils': 5.1.2(rollup@4.24.0) + estree-walker: 3.0.3 + is-reference: 3.0.2 + magic-string: 0.30.11 + rollup: 4.24.0 + + rollup-plugin-import-assets@1.1.1(rollup@4.24.0): + dependencies: + rollup: 4.24.0 rollup-pluginutils: 2.8.2 url-join: 4.0.1 @@ -977,15 +1586,37 @@ snapshots: dependencies: estree-walker: 0.6.1 - rollup@2.79.1: + rollup@4.24.0: + dependencies: + '@types/estree': 1.0.6 optionalDependencies: - fsevents: 2.3.2 + '@rollup/rollup-android-arm-eabi': 4.24.0 + '@rollup/rollup-android-arm64': 4.24.0 + '@rollup/rollup-darwin-arm64': 4.24.0 + '@rollup/rollup-darwin-x64': 4.24.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.24.0 + '@rollup/rollup-linux-arm-musleabihf': 4.24.0 + '@rollup/rollup-linux-arm64-gnu': 4.24.0 + '@rollup/rollup-linux-arm64-musl': 4.24.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.24.0 + '@rollup/rollup-linux-riscv64-gnu': 4.24.0 + '@rollup/rollup-linux-s390x-gnu': 4.24.0 + '@rollup/rollup-linux-x64-gnu': 4.24.0 + '@rollup/rollup-linux-x64-musl': 4.24.0 + '@rollup/rollup-win32-arm64-msvc': 4.24.0 + '@rollup/rollup-win32-ia32-msvc': 4.24.0 + '@rollup/rollup-win32-x64-msvc': 4.24.0 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 safe-buffer@5.2.1: {} schema-utils@3.3.0: dependencies: - '@types/json-schema': 7.0.11 + '@types/json-schema': 7.0.15 ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) @@ -993,16 +1624,15 @@ snapshots: dependencies: randombytes: 2.1.0 - shelljs@0.8.5: + shebang-command@2.0.0: dependencies: - glob: 7.2.3 - interpret: 1.4.0 - rechoir: 0.6.2 + shebang-regex: 3.0.0 - shx@0.3.4: - dependencies: - minimist: 1.2.6 - shelljs: 0.8.5 + shebang-regex@3.0.0: {} + + signal-exit@4.1.0: {} + + slash@3.0.0: {} source-map-support@0.5.21: dependencies: @@ -1011,7 +1641,25 @@ snapshots: source-map@0.6.1: {} - sourcemap-codec@1.4.8: {} + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 supports-color@8.1.1: dependencies: @@ -1021,58 +1669,63 @@ snapshots: tapable@2.2.1: {} - terser-webpack-plugin@5.3.10(webpack@5.91.0): + terser-webpack-plugin@5.3.10(webpack@5.95.0): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 - terser: 5.30.3 - webpack: 5.91.0 + terser: 5.34.1 + webpack: 5.95.0 - terser@5.30.3: + terser@5.34.1: dependencies: '@jridgewell/source-map': 0.3.6 - acorn: 8.11.3 + acorn: 8.12.1 commander: 2.20.3 source-map-support: 0.5.21 - tslib@2.6.2: {} + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tslib@2.7.0: {} + + typescript@5.6.2: {} - typescript@4.9.5: {} + undici-types@6.19.8: {} - update-browserslist-db@1.0.13(browserslist@4.23.0): + update-browserslist-db@1.1.1(browserslist@4.24.0): dependencies: - browserslist: 4.23.0 - escalade: 3.1.1 - picocolors: 1.0.0 + browserslist: 4.24.0 + escalade: 3.2.0 + picocolors: 1.1.0 uri-js@4.4.1: dependencies: - punycode: 2.1.1 + punycode: 2.3.1 url-join@4.0.1: {} - watchpack@2.4.1: + watchpack@2.4.2: dependencies: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 webpack-sources@3.2.3: {} - webpack@5.91.0: + webpack@5.95.0: dependencies: - '@types/eslint-scope': 3.7.4 - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 '@webassemblyjs/ast': 1.12.1 '@webassemblyjs/wasm-edit': 1.12.1 '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.11.3 - acorn-import-assertions: 1.9.0(acorn@8.11.3) - browserslist: 4.23.0 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.16.0 - es-module-lexer: 1.5.0 + acorn: 8.12.1 + acorn-import-attributes: 1.9.5(acorn@8.12.1) + browserslist: 4.24.0 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.17.1 + es-module-lexer: 1.5.4 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -1083,12 +1736,28 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(webpack@5.91.0) - watchpack: 2.4.1 + terser-webpack-plugin: 5.3.10(webpack@5.95.0) + watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' - esbuild - uglify-js + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + wrappy@1.0.2: {} diff --git a/release.sh b/release.sh deleted file mode 100755 index 7fda7aa..0000000 --- a/release.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -set -e - -rm -rf build -mkdir -p build/bin - -pnpm install - -pnpm run build -cp -r dist build/ - -VERSION=$(cat package.json| jq -r '.version') -SHA=$(git rev-parse --short HEAD) -if [ -n "$PR_NUMBER" ]; then - echo "Build release for PR $PR_NUMBER" - VERSION="$VERSION-beta+$PR_NUMBER.sha.$SHA" - sed -i -e 's/^version = .*/version = "'$VERSION'"/' ./backend/Cargo.toml - sed -i -e 's/"version": .*/\"version\": "'$VERSION'",/' package.json - cat ./backend/Cargo.toml - cat package.json -else - echo "Building release" -fi - -cargo build --release --manifest-path backend/Cargo.toml -cp ./backend/target/release/controller-tools build/bin/backend - -cp package.json build/package.json -cp plugin.json build/plugin.json -cp main.py build/main.py -cp README.md build/README.md -cp LICENSE build/LICENSE - -mv build ControllerTools -rm -f controller-tools-*.zip -zip -r controller-tools-$VERSION.zip ControllerTools/* -mv ControllerTools build - -if [ -n "$PR_NUMBER" ]; then - git checkout -- backend/Cargo.toml package.json -fi \ No newline at end of file diff --git a/rollup.config.js b/rollup.config.js index 1ccf6a8..1633494 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,36 +1,5 @@ -import commonjs from '@rollup/plugin-commonjs'; -import json from '@rollup/plugin-json'; -import { nodeResolve } from '@rollup/plugin-node-resolve'; -import replace from '@rollup/plugin-replace'; -import typescript from '@rollup/plugin-typescript'; -import { defineConfig } from 'rollup'; -import importAssets from 'rollup-plugin-import-assets'; +import deckyPlugin from "@decky/rollup"; -export default defineConfig({ - input: './src/index.tsx', - plugins: [ - commonjs(), - nodeResolve(), - typescript(), - json(), - replace({ - preventAssignment: false, - 'process.env.NODE_ENV': JSON.stringify('production'), - }), - importAssets({ - publicPath: `http://127.0.0.1:1337/plugins/Controller Tools/` - }) - ], - context: 'window', - external: ['react', 'react-dom', 'decky-frontend-lib'], - output: { - file: 'dist/index.js', - globals: { - react: 'SP_REACT', - 'react-dom': 'SP_REACTDOM', - 'decky-frontend-lib': 'DFL' - }, - format: 'iife', - exports: 'default', - }, +export default deckyPlugin({ + // Add your extra Rollup options here }); diff --git a/scripts/build_docker_image.sh b/scripts/build_docker_image.sh deleted file mode 100755 index 2d06f56..0000000 --- a/scripts/build_docker_image.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -# build docker container locally (for testing) - -docker build -f $PWD/backend/Dockerfile -t controller-tools-backend . \ No newline at end of file diff --git a/scripts/reload_frontend.js b/scripts/reload_frontend.js deleted file mode 100755 index 2192ec1..0000000 --- a/scripts/reload_frontend.js +++ /dev/null @@ -1,34 +0,0 @@ -// Thanks for Sky Leite: https://discord.com/channels/960281551428522045/960284327445418044/1057401742591021077 -const plugin = require("../plugin.json"); -const CDP = require('chrome-remote-interface'); - -const options = { - host: process.env.DECKIP, - port: 8081, -}; - -async function main() { - let client; - try { - // connect to endpoint - client = await CDP({ - ...options, - target: (targets) => targets.find((target) => target.title == "Steam"), - }); - - // extract domains - const { Network, Page, Runtime } = client; - - await Runtime.evaluate({ expression: `console.log("Reloading ${plugin.name} from an unbelievably stupid dev script")` }); - await Runtime.evaluate({ expression: `importDeckyPlugin("${plugin.name}")` }); - console.log("Frontend reloaded"); - } catch (err) { - console.error(err); - } finally { - if (client) { - await client.close(); - } - } -} - -main(); \ No newline at end of file diff --git a/scripts/remote_debug.sh b/scripts/remote_debug.sh deleted file mode 100755 index f27119d..0000000 --- a/scripts/remote_debug.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -VSCODE_WS="$1" -SSH_REMOTE="$2" -GDBPORT="$3" - -APP="controller-tools" -TARGET_ARCH="x86_64-unknown-linux-gnu" -BUILD_BIN_FILE="${VSCODE_WS}/backend/target/${TARGET_ARCH}/debug/${APP}" -TARGET_USER="deck" -TARGET_BIN_FILE="/home/deck/homebrew/${APP}" -TARGET_CWD="/home/deck" - -ssh "${TARGET_USER}@${SSH_REMOTE}" "killall gdbserver ${APP}" - -if ! rsync -avz "${BUILD_BIN_FILE}" "${TARGET_USER}@${SSH_REMOTE}:${TARGET_BIN_FILE}"; then - # If rsync doesn't work, it may not be available on target. Fallback to trying SSH copy. - if ! scp "${BUILD_BIN_FILE}" "${TARGET_USER}@${SSH_REMOTE}:${TARGET_BIN_FILE}"; then - exit 2 - fi -fi - -ssh -f "${TARGET_USER}@${SSH_REMOTE}" "sh -c 'gdbserver *:${GDBPORT} ${TARGET_BIN_FILE}'" \ No newline at end of file diff --git a/settings.pyi b/settings.pyi new file mode 100644 index 0000000..b570fdd --- /dev/null +++ b/settings.pyi @@ -0,0 +1,9 @@ +import typing + + +class SettingsManager: + def __init__(self, name: str, settings_directory: str | None = None) -> None: ... + def read(self) -> typing.Any: ... + def commit(self) -> typing.Any: ... + def getSetting(self, key: str, defaults: typing.Any) -> typing.Any: ... + def setSetting(self, key: str, value: typing.Any) -> typing.Any: ... diff --git a/src/backend.ts b/src/backend.ts index c96905d..f58e4f4 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -1,27 +1,16 @@ -import { Controller, Settings } from "./types"; +import { callable } from "@decky/api"; +import { Controller } from "./types"; const PORT: number = 33220; const HOST: string = `http://localhost:${PORT}`; +export const getDebugSetting = async () => await callable<[string, boolean], boolean>("settings_getSetting")("debug", false); +export const getNotificationsSetting = async () => await callable<[string, boolean], boolean>("settings_getSetting")("notifications", true); +export const setDebugSetting = async (value: boolean) => await callable<[string, boolean], unknown>("settings_setSetting")("debug", value); +export const setNotificationsSetting = async (value: boolean) => await callable<[string, boolean], unknown>("settings_setSetting")("notifications", value); +export const settingsCommit = callable<[], unknown>("settings_commit"); + export async function getControllers(): Promise<[Controller]> { let res = await fetch(`${HOST}/controllers`); return await res.json(); } - -export async function getSettings(): Promise { - let res = await fetch(`${HOST}/settings`); - return await res.json(); -} - -export async function setSettings(settings: Settings): Promise { - // Post settings as JSON to server using fetch - let res = await fetch(`${HOST}/settings`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(settings), - }); - - return await res.json(); -} \ No newline at end of file diff --git a/src/index.tsx b/src/index.tsx index 44e474c..0d31422 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -5,17 +5,16 @@ import { joinClassNames, PanelSection, PanelSectionRow, - ServerAPI, staticClasses, ToggleField, -} from "decky-frontend-lib"; -import { useEffect, useState, VFC } from "react"; +} from "@decky/ui"; +import { useEffect, useState, FC } from "react"; import { BiBluetooth, BiUsb } from "react-icons/bi"; import { SiStadia } from "react-icons/si"; import { RiSwitchLine } from "react-icons/ri"; import { FaBatteryEmpty, FaBatteryFull, FaBatteryQuarter, FaBatteryHalf, FaBatteryThreeQuarters, FaPlaystation, FaXbox } from "react-icons/fa"; import { BsController, BsBatteryCharging } from "react-icons/bs"; -import { Controller, Settings } from "./types"; +import { Controller } from "./types"; import * as backend from "./backend"; import { IconContext } from "react-icons"; import { setupNotifications } from "./notifications"; @@ -59,8 +58,9 @@ async function delayPromise(value: T): Promise { }); } -const Content: VFC<{ serverAPI: ServerAPI }> = () => { - const [settings, setSettings] = useState({ notifications: true, debug: false }); +const Content: FC = () => { + const [debug, setDebug] = useState(false); + const [notifications, setNotifications] = useState(true); const [loading, setLoading] = useState(false); const [controllers, setControllers] = useState([]); const FieldWithSeparator = joinClassNames(gamepadDialogClasses.Field, gamepadDialogClasses.WithBottomSeparatorStandard); @@ -73,8 +73,10 @@ const Content: VFC<{ serverAPI: ServerAPI }> = () => { // For fetching settings on render useEffect(() => { - backend.getSettings() - .then((settings) => { setSettings(settings) }); + backend.getDebugSetting() + .then((debug) => { setDebug(debug) }); + backend.getNotificationsSetting() + .then((notifications) => { setNotifications(notifications) }); }, []); const refreshButton = ( @@ -100,24 +102,20 @@ const Content: VFC<{ serverAPI: ServerAPI }> = () => { { - let new_settings = settings; - new_settings.notifications = e; - await backend.setSettings(new_settings); - setSettings(new_settings); + await backend.setNotificationsSetting(e); + await backend.settingsCommit(); }} /> { - let new_settings = settings; - new_settings.debug = e; - await backend.setSettings(new_settings); - setSettings(new_settings); + await backend.setDebugSetting(e); + await backend.settingsCommit(); }} /> @@ -157,7 +155,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = () => { { (controller.capacity > 0 || controller.status !== "unknown") && -
+
{ // only show battery capacity for non-MS vendors unless capacity is > 0 and over BT // since we don't have the battery capacity yet for Xbox over USB @@ -179,14 +177,14 @@ const Content: VFC<{ serverAPI: ServerAPI }> = () => { ); }; -export default definePlugin((serverApi: ServerAPI) => { +export default definePlugin(() => { // Starts a self-healing websocket connection to the backend to listen for push notifications. // Must be called here to maintain the connection regardless of whether the plugin is open or not - setupNotifications(serverApi); + setupNotifications(); return { title:
Controller Tools
, - content: , + content: , icon: , }; }); diff --git a/src/notifications.ts b/src/notifications.ts index e4e2116..a0e4485 100644 --- a/src/notifications.ts +++ b/src/notifications.ts @@ -1,7 +1,7 @@ -import { ServerAPI, ToastData } from 'decky-frontend-lib'; +import { toaster, ToastData } from '@decky/api'; import { log, error } from './logger'; -export const setupNotifications = (serverAPI: ServerAPI): void => { +export const setupNotifications = (): void => { const handleMessage = (e: MessageEvent): void => { let toastData: ToastData = { title: "Controller Tools", @@ -9,7 +9,7 @@ export const setupNotifications = (serverAPI: ServerAPI): void => { showToast: true } - serverAPI.toaster.toast(toastData); + toaster.toast(toastData); } const setupWebsocket = (): void => { diff --git a/tsconfig.json b/tsconfig.json index c2bc719..7915130 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,7 @@ "target": "ES2020", "jsx": "react", "jsxFactory": "window.SP_REACT.createElement", + "jsxFragmentFactory": "window.SP_REACT.Fragment", "declaration": false, "moduleResolution": "node", "noUnusedLocals": true,