commit 644a6f980322645d210e11b206798ae090790412 Author: AzenKain Date: Tue Jul 8 14:54:41 2025 +0700 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..91af0b8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.task +bin +tests/ +server/ +proxy/ +temp/ +frontend/dist +frontend/node_modules +build/linux/appimage/build +build/windows/nsis/MicrosoftEdgeWebview2Setup.exe \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..14edd9f --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# 🚀 Firefly Launcher + +A lightweight and modern launcher for Anime game — designed to make launching, updating, and customizing your game easy and efficient. + +--- + +## ✨ Features + +- 🔄 Automatically update Firefly Go and proxy tools on launch +- 🎮 Launch the game with correct parameters and environment +- 🌐 Switch in-game language (EN, JP, CN, KR) via Language Tools +- 📦 Apply game patches using Hdiffz Tool (HDiffPatch-based) + +--- + +## 🧑‍💻 About the Developer + +Hi! I'm **Kain**, a developer passionate about building simple and powerful tools. +Firefly Launcher is built with: + +- ⚙️ **Go + Wails** for backend/frontend integration +- 🎨 **Tailwind CSS** + **DaisyUI** for a clean, responsive UI + +My goal is to create tools that are fast, efficient, and enjoyable to use. + +--- + +## 📦 Installation + +You can choose between: + +- ✅ **Portable** version (no install needed) +- 🛠️ **MSI Installer** (for full integration) + +--- + +## 🛠️ Common Development Commands (Wails v3) + +```bash +# Start the app in development mode (hot reload frontend) +wails3 dev + +# Build the application (production binary) +wails3 build + +# Package the app (NSIS) +wails3 package +``` +--- + +## 📄 License + +MIT License — feel free to use and contribute. + +--- + diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..68db0be --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,34 @@ +version: '3' + +includes: + common: ./build/Taskfile.yml + windows: ./build/windows/Taskfile.yml + darwin: ./build/darwin/Taskfile.yml + linux: ./build/linux/Taskfile.yml + +vars: + APP_NAME: "firefly-launcher" + BIN_DIR: "bin" + VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}' + +tasks: + build: + summary: Builds the application + cmds: + - task: "{{OS}}:build" + + package: + summary: Packages a production build of the application + cmds: + - task: "{{OS}}:package" + + run: + summary: Runs the application + cmds: + - task: "{{OS}}:run" + + dev: + summary: Runs the application in development mode + cmds: + - wails3 dev -config ./build/config.yml -port {{.VITE_PORT}} + diff --git a/assets/7zip/7za.dll b/assets/7zip/7za.dll new file mode 100644 index 0000000..f2485e3 Binary files /dev/null and b/assets/7zip/7za.dll differ diff --git a/assets/7zip/7za.exe b/assets/7zip/7za.exe new file mode 100644 index 0000000..b322bf8 Binary files /dev/null and b/assets/7zip/7za.exe differ diff --git a/assets/7zip/7zxa.dll b/assets/7zip/7zxa.dll new file mode 100644 index 0000000..3bd6303 Binary files /dev/null and b/assets/7zip/7zxa.dll differ diff --git a/assets/HDiffPatch/hdiffz.exe b/assets/HDiffPatch/hdiffz.exe new file mode 100644 index 0000000..38c092d Binary files /dev/null and b/assets/HDiffPatch/hdiffz.exe differ diff --git a/assets/HDiffPatch/hpatchz.exe b/assets/HDiffPatch/hpatchz.exe new file mode 100644 index 0000000..d3fe650 Binary files /dev/null and b/assets/HDiffPatch/hpatchz.exe differ diff --git a/build/Taskfile.yml b/build/Taskfile.yml new file mode 100644 index 0000000..3fe117b --- /dev/null +++ b/build/Taskfile.yml @@ -0,0 +1,78 @@ +version: '3' + +tasks: + go:mod:tidy: + summary: Runs `go mod tidy` + internal: true + cmds: + - go mod tidy + + install:frontend:deps: + summary: Install frontend dependencies + dir: frontend + sources: + - package.json + - package-lock.json + generates: + - node_modules/* + preconditions: + - sh: npm version + msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" + cmds: + - npm install + + build:frontend: + summary: Build the frontend project + dir: frontend + sources: + - "**/*" + generates: + - dist/* + deps: + - task: install:frontend:deps + - task: generate:bindings + cmds: + - npm run {{.BUILD_COMMAND}} -q + env: + PRODUCTION: '{{.PRODUCTION | default "false"}}' + vars: + BUILD_COMMAND: '{{if eq .PRODUCTION "true"}}build{{else}}build:dev{{end}}' + + + generate:bindings: + summary: Generates bindings for the frontend + deps: + - task: go:mod:tidy + sources: + - "**/*.go" + - go.mod + - go.sum + generates: + - "frontend/bindings/**/*" + cmds: + - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true + + generate:icons: + summary: Generates Windows `.ico` and Mac `.icns` files from an image + dir: build + sources: + - "appicon.png" + generates: + - "icons.icns" + - "icons.ico" + cmds: + - wails3 generate icons -input appicon.png -macfilename darwin/icons.icns -windowsfilename windows/icons.ico + + dev:frontend: + summary: Runs the frontend in development mode + dir: frontend + deps: + - task: install:frontend:deps + cmds: + - npm run dev -- --port {{.VITE_PORT}} --strictPort + + update:build-assets: + summary: Updates the build assets + dir: build + cmds: + - wails3 update build-assets -name "{{.APP_NAME}}" -binaryname "{{.APP_NAME}}" -config config.yml -dir . \ No newline at end of file diff --git a/build/appicon.png b/build/appicon.png new file mode 100644 index 0000000..0803fc3 Binary files /dev/null and b/build/appicon.png differ diff --git a/build/config.yml b/build/config.yml new file mode 100644 index 0000000..a6a194e --- /dev/null +++ b/build/config.yml @@ -0,0 +1,53 @@ +# This file contains the configuration for this project. +# When you update `info` or `fileAssociations`, run `wails3 task common:update:build-assets` to update the assets. +# Note that this will overwrite any changes you have made to the assets. +version: '3' + +# This information is used to generate the build assets. +info: + companyName: "Firefly Shelter" # The name of the company + productName: "Firefly Launcher" # The name of the application + productIdentifier: "com.fireflyshelter.fireflylauncher" # The unique product identifier + description: "Custom game launcher built for convenience and quick access" # The application description + copyright: "@ 2025, Firefly Shelter" # Copyright text + comments: "Custom game launcher built for convenience and quick access" # Comments + version: "0.1.0" # The application version + +# Dev mode configuration +dev_mode: + root_path: . + log_level: warn + debounce: 1000 + ignore: + dir: + - .git + - node_modules + - frontend + - bin + file: + - .DS_Store + - .gitignore + - .gitkeep + watched_extension: + - "*.go" + git_ignore: true + executes: + - cmd: wails3 task common:install:frontend:deps + type: once + - cmd: wails3 task common:dev:frontend + type: background + - cmd: go mod tidy + type: blocking + - cmd: wails3 task build + type: blocking + - cmd: wails3 task run + type: primary + +# File Associations +# More information at: https://v3alpha.wails.io/noit/done/yet +fileAssociations: + + +# Other data +other: + - name: My Other Data \ No newline at end of file diff --git a/build/darwin/Info.dev.plist b/build/darwin/Info.dev.plist new file mode 100644 index 0000000..8b9912e --- /dev/null +++ b/build/darwin/Info.dev.plist @@ -0,0 +1,32 @@ + + + + CFBundlePackageType + APPL + CFBundleName + Firefly Launcher + CFBundleExecutable + Firefly Launcher + CFBundleIdentifier + com.fireflyshelter.fireflylauncher + CFBundleVersion + 0.1.0 + CFBundleGetInfoString + Custom game launcher built for convenience and quick access + CFBundleShortVersionString + 0.1.0 + CFBundleIconFile + icons + LSMinimumSystemVersion + 10.13.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + @ 2025, Firefly Shelter + NSAppTransportSecurity + + NSAllowsLocalNetworking + + + + \ No newline at end of file diff --git a/build/darwin/Info.plist b/build/darwin/Info.plist new file mode 100644 index 0000000..cb37f04 --- /dev/null +++ b/build/darwin/Info.plist @@ -0,0 +1,27 @@ + + + + CFBundlePackageType + APPL + CFBundleName + Firefly Launcher + CFBundleExecutable + Firefly Launcher + CFBundleIdentifier + com.fireflyshelter.fireflylauncher + CFBundleVersion + 0.1.0 + CFBundleGetInfoString + Custom game launcher built for convenience and quick access + CFBundleShortVersionString + 0.1.0 + CFBundleIconFile + icons + LSMinimumSystemVersion + 10.13.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + @ 2025, Firefly Shelter + + \ No newline at end of file diff --git a/build/darwin/Taskfile.yml b/build/darwin/Taskfile.yml new file mode 100644 index 0000000..331ee6f --- /dev/null +++ b/build/darwin/Taskfile.yml @@ -0,0 +1,70 @@ +version: '3' + +includes: + common: ../Taskfile.yml + +tasks: + build: + summary: Creates a production build of the application + deps: + - task: common:go:mod:tidy + - task: common:build:frontend + - task: common:generate:icons + cmds: + - go build {{.BUILD_FLAGS}} -o {{.OUTPUT}} + vars: + BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' + DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' + OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' + env: + GOOS: darwin + CGO_ENABLED: 1 + GOARCH: '{{.ARCH | default ARCH}}' + CGO_CFLAGS: "-mmacosx-version-min=10.15" + CGO_LDFLAGS: "-mmacosx-version-min=10.15" + MACOSX_DEPLOYMENT_TARGET: "10.15" + PRODUCTION: '{{.PRODUCTION | default "false"}}' + + build:universal: + summary: Builds darwin universal binary (arm64 + amd64) + deps: + - task: build + vars: + ARCH: amd64 + OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" + - task: build + vars: + ARCH: arm64 + OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" + cmds: + - lipo -create -output "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" + - rm "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" + + package: + summary: Packages a production build of the application into a `.app` bundle + deps: + - task: build + vars: + PRODUCTION: "true" + cmds: + - task: create:app:bundle + + package:universal: + summary: Packages darwin universal binary (arm64 + amd64) + deps: + - task: build:universal + cmds: + - task: create:app:bundle + + + create:app:bundle: + summary: Creates an `.app` bundle + cmds: + - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/{MacOS,Resources} + - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources + - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS + - cp build/darwin/Info.plist {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents + + run: + cmds: + - '{{.BIN_DIR}}/{{.APP_NAME}}' diff --git a/build/darwin/icons.icns b/build/darwin/icons.icns new file mode 100644 index 0000000..290fdbc Binary files /dev/null and b/build/darwin/icons.icns differ diff --git a/build/linux/Taskfile.yml b/build/linux/Taskfile.yml new file mode 100644 index 0000000..e37d032 --- /dev/null +++ b/build/linux/Taskfile.yml @@ -0,0 +1,114 @@ +version: '3' + +includes: + common: ../Taskfile.yml + +tasks: + build: + summary: Builds the application for Linux + deps: + - task: common:go:mod:tidy + - task: common:build:frontend + - task: common:generate:icons + cmds: + - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}} + vars: + BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' + env: + GOOS: linux + CGO_ENABLED: 1 + GOARCH: '{{.ARCH | default ARCH}}' + PRODUCTION: '{{.PRODUCTION | default "false"}}' + + package: + summary: Packages a production build of the application for Linux + deps: + - task: build + vars: + PRODUCTION: "true" + cmds: + - task: create:appimage + - task: create:deb + - task: create:rpm + - task: create:aur + + create:appimage: + summary: Creates an AppImage + dir: build/linux/appimage + deps: + - task: build + vars: + PRODUCTION: "true" + - task: generate:dotdesktop + cmds: + - cp {{.APP_BINARY}} {{.APP_NAME}} + - cp ../../appicon.png appicon.png + - wails3 generate appimage -binary {{.APP_NAME}} -icon {{.ICON}} -desktopfile {{.DESKTOP_FILE}} -outputdir {{.OUTPUT_DIR}} -builddir {{.ROOT_DIR}}/build/linux/appimage/build + vars: + APP_NAME: '{{.APP_NAME}}' + APP_BINARY: '../../../bin/{{.APP_NAME}}' + ICON: '../../appicon.png' + DESKTOP_FILE: '../{{.APP_NAME}}.desktop' + OUTPUT_DIR: '../../../bin' + + create:deb: + summary: Creates a deb package + deps: + - task: build + vars: + PRODUCTION: "true" + cmds: + - task: generate:dotdesktop + - task: generate:deb + + create:rpm: + summary: Creates a rpm package + deps: + - task: build + vars: + PRODUCTION: "true" + cmds: + - task: generate:dotdesktop + - task: generate:rpm + + create:aur: + summary: Creates a arch linux packager package + deps: + - task: build + vars: + PRODUCTION: "true" + cmds: + - task: generate:dotdesktop + - task: generate:aur + + generate:deb: + summary: Creates a deb package + cmds: + - wails3 tool package -name {{.APP_NAME}} -format deb -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin + + generate:rpm: + summary: Creates a rpm package + cmds: + - wails3 tool package -name {{.APP_NAME}} -format rpm -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin + + generate:aur: + summary: Creates a arch linux packager package + cmds: + - wails3 tool package -name {{.APP_NAME}} -format archlinux -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin + + generate:dotdesktop: + summary: Generates a `.desktop` file + dir: build + cmds: + - mkdir -p {{.ROOT_DIR}}/build/linux/appimage + - wails3 generate .desktop -name "{{.APP_NAME}}" -exec "{{.EXEC}}" -icon "{{.ICON}}" -outputfile {{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop -categories "{{.CATEGORIES}}" + vars: + APP_NAME: '{{.APP_NAME}}' + EXEC: '{{.APP_NAME}}' + ICON: 'appicon' + CATEGORIES: 'Development;' + OUTPUTFILE: '{{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop' + + run: + cmds: + - '{{.BIN_DIR}}/{{.APP_NAME}}' diff --git a/build/linux/appimage/build.sh b/build/linux/appimage/build.sh new file mode 100644 index 0000000..fcba535 --- /dev/null +++ b/build/linux/appimage/build.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Copyright (c) 2018-Present Lea Anthony +# SPDX-License-Identifier: MIT + +# Fail script on any error +set -euxo pipefail + +# Define variables +APP_DIR="${APP_NAME}.AppDir" + +# Create AppDir structure +mkdir -p "${APP_DIR}/usr/bin" +cp -r "${APP_BINARY}" "${APP_DIR}/usr/bin/" +cp "${ICON_PATH}" "${APP_DIR}/" +cp "${DESKTOP_FILE}" "${APP_DIR}/" + +# Download linuxdeploy and make it executable +wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage +chmod +x linuxdeploy-x86_64.AppImage + +# Run linuxdeploy to bundle the application +./linuxdeploy-x86_64.AppImage --appdir "${APP_DIR}" --output appimage + +# Rename the generated AppImage +mv "${APP_NAME}*.AppImage" "${APP_NAME}.AppImage" + diff --git a/build/linux/nfpm/nfpm.yaml b/build/linux/nfpm/nfpm.yaml new file mode 100644 index 0000000..012c526 --- /dev/null +++ b/build/linux/nfpm/nfpm.yaml @@ -0,0 +1,50 @@ +# Feel free to remove those if you don't want/need to use them. +# Make sure to check the documentation at https://nfpm.goreleaser.com +# +# The lines below are called `modelines`. See `:help modeline` + +name: "Firefly Launcher" +arch: ${GOARCH} +platform: "linux" +version: "0.1.0" +section: "default" +priority: "extra" +maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}> +description: "Custom game launcher built for convenience and quick access" +vendor: "Firefly Shelter" +homepage: "https://wails.io" +license: "MIT" +release: "1" + +contents: + - src: "./bin/Firefly Launcher" + dst: "/usr/local/bin/Firefly Launcher" + - src: "./build/appicon.png" + dst: "/usr/share/icons/hicolor/128x128/apps/Firefly Launcher.png" + - src: "./build/linux/Firefly Launcher.desktop" + dst: "/usr/share/applications/Firefly Launcher.desktop" + +depends: + - gtk3 + - libwebkit2gtk + +# replaces: +# - foobar +# provides: +# - bar +# depends: +# - gtk3 +# - libwebkit2gtk +# recommends: +# - whatever +# suggests: +# - something-else +# conflicts: +# - not-foo +# - not-bar +# changelog: "changelog.yaml" +# scripts: +# preinstall: ./build/linux/nfpm/scripts/preinstall.sh +# postinstall: ./build/linux/nfpm/scripts/postinstall.sh +# preremove: ./build/linux/nfpm/scripts/preremove.sh +# postremove: ./build/linux/nfpm/scripts/postremove.sh diff --git a/build/linux/nfpm/scripts/postinstall.sh b/build/linux/nfpm/scripts/postinstall.sh new file mode 100644 index 0000000..a9bf588 --- /dev/null +++ b/build/linux/nfpm/scripts/postinstall.sh @@ -0,0 +1 @@ +#!/bin/bash diff --git a/build/linux/nfpm/scripts/postremove.sh b/build/linux/nfpm/scripts/postremove.sh new file mode 100644 index 0000000..a9bf588 --- /dev/null +++ b/build/linux/nfpm/scripts/postremove.sh @@ -0,0 +1 @@ +#!/bin/bash diff --git a/build/linux/nfpm/scripts/preinstall.sh b/build/linux/nfpm/scripts/preinstall.sh new file mode 100644 index 0000000..a9bf588 --- /dev/null +++ b/build/linux/nfpm/scripts/preinstall.sh @@ -0,0 +1 @@ +#!/bin/bash diff --git a/build/linux/nfpm/scripts/preremove.sh b/build/linux/nfpm/scripts/preremove.sh new file mode 100644 index 0000000..a9bf588 --- /dev/null +++ b/build/linux/nfpm/scripts/preremove.sh @@ -0,0 +1 @@ +#!/bin/bash diff --git a/build/windows/Taskfile.yml b/build/windows/Taskfile.yml new file mode 100644 index 0000000..d233f62 --- /dev/null +++ b/build/windows/Taskfile.yml @@ -0,0 +1,60 @@ +version: '3' + +includes: + common: ../Taskfile.yml + +tasks: + build: + summary: Builds the application for Windows + deps: + - task: common:go:mod:tidy + - task: common:build:frontend + vars: + PRODUCTION: '{{.PRODUCTION}}' + - task: common:generate:icons + cmds: + - task: generate:syso + - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}.exe + - cmd: powershell Remove-item *.syso + platforms: [windows] + - cmd: rm -f *.syso + platforms: [linux, darwin] + vars: + BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' + env: + GOOS: windows + CGO_ENABLED: 0 + GOARCH: '{{.ARCH | default ARCH}}' + PRODUCTION: '{{.PRODUCTION | default "false"}}' + + package: + summary: Packages a production build of the application into a `.exe` bundle + cmds: + - task: create:nsis:installer + + generate:syso: + summary: Generates Windows `.syso` file + dir: build + cmds: + - wails3 generate syso -arch {{.ARCH}} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_{{.ARCH}}.syso + vars: + ARCH: '{{.ARCH | default ARCH}}' + + create:nsis:installer: + summary: Creates an NSIS installer + dir: build/windows/nsis + deps: + - task: build + vars: + PRODUCTION: "true" + cmds: + # Create the Microsoft WebView2 bootstrapper if it doesn't exist + - wails3 generate webview2bootstrapper -dir "{{.ROOT_DIR}}\build\windows\nsis" + - makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}\{{.BIN_DIR}}\{{.APP_NAME}}.exe" project.nsi + vars: + ARCH: '{{.ARCH | default ARCH}}' + ARG_FLAG: '{{if eq .ARCH "amd64"}}AMD64{{else}}ARM64{{end}}' + + run: + cmds: + - '{{.BIN_DIR}}\\{{.APP_NAME}}.exe' \ No newline at end of file diff --git a/build/windows/icon.ico b/build/windows/icon.ico new file mode 100644 index 0000000..66651f3 Binary files /dev/null and b/build/windows/icon.ico differ diff --git a/build/windows/icons.ico b/build/windows/icons.ico new file mode 100644 index 0000000..5779397 Binary files /dev/null and b/build/windows/icons.ico differ diff --git a/build/windows/info.json b/build/windows/info.json new file mode 100644 index 0000000..c91ecd3 --- /dev/null +++ b/build/windows/info.json @@ -0,0 +1,15 @@ +{ + "fixed": { + "file_version": "0.1.0" + }, + "info": { + "0000": { + "ProductVersion": "0.1.0", + "CompanyName": "Firefly Shelter", + "FileDescription": "Custom game launcher built for convenience and quick access", + "LegalCopyright": "@ 2025, Firefly Shelter", + "ProductName": "Firefly Launcher", + "Comments": "Custom game launcher built for convenience and quick access" + } + } +} \ No newline at end of file diff --git a/build/windows/nsis/project.nsi b/build/windows/nsis/project.nsi new file mode 100644 index 0000000..2de6666 --- /dev/null +++ b/build/windows/nsis/project.nsi @@ -0,0 +1,112 @@ +Unicode true + +#### +## Please note: Template replacements don't work in this file. They are provided with default defines like +## mentioned underneath. +## If the keyword is not defined, "wails_tools.nsh" will populate them. +## If they are defined here, "wails_tools.nsh" will not touch them. This allows you to use this project.nsi manually +## from outside of Wails for debugging and development of the installer. +## +## For development first make a wails nsis build to populate the "wails_tools.nsh": +## > wails build --target windows/amd64 --nsis +## Then you can call makensis on this file with specifying the path to your binary: +## For a AMD64 only installer: +## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe +## For a ARM64 only installer: +## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe +## For a installer with both architectures: +## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe +#### +## The following information is taken from the wails_tools.nsh file, but they can be overwritten here. +#### +## !define INFO_PROJECTNAME "my-project" # Default "firefly-launcher" +## !define INFO_COMPANYNAME "My Company" # Default "FireflyShelter" +## !define INFO_PRODUCTNAME "My Product Name" # Default "Firefly Launcher" +## !define INFO_PRODUCTVERSION "1.0.0" # Default "0.1.0" +## !define INFO_COPYRIGHT "(c) Now, My Company" # Default "@ 2025, FireflyShelter" +### +## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" +## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" +#### +## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html +#### +## Include the wails tools +#### +!include "wails_tools.nsh" + +# The version information for this two must consist of 4 parts +VIProductVersion "${INFO_PRODUCTVERSION}.0" +VIFileVersion "${INFO_PRODUCTVERSION}.0" + +VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" +VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" +VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" +VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" +VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" +VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" + +# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware +ManifestDPIAware true + +!include "MUI.nsh" + +!define MUI_ICON "..\icon.ico" +!define MUI_UNICON "..\icon.ico" +# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 +!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps +!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. + +!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. +# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer +!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. +!insertmacro MUI_PAGE_INSTFILES # Installing page. +!insertmacro MUI_PAGE_FINISH # Finished installation page. + +!insertmacro MUI_UNPAGE_INSTFILES # Uninstalling page + +!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer + +## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 +#!uninstfinalize 'signtool --file "%1"' +#!finalize 'signtool --file "%1"' + +Name "${INFO_PRODUCTNAME}" +OutFile "..\..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. +InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). +ShowInstDetails show # This will always show the installation details. + +Function .onInit + !insertmacro wails.checkArchitecture +FunctionEnd + +Section + !insertmacro wails.setShellContext + + !insertmacro wails.webview2runtime + + SetOutPath $INSTDIR + + !insertmacro wails.files + + CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" + CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" + + !insertmacro wails.associateFiles + + !insertmacro wails.writeUninstaller +SectionEnd + +Section "uninstall" + !insertmacro wails.setShellContext + + RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath + + RMDir /r $INSTDIR + + Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" + Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" + + !insertmacro wails.unassociateFiles + + !insertmacro wails.deleteUninstaller +SectionEnd diff --git a/build/windows/nsis/wails_tools.nsh b/build/windows/nsis/wails_tools.nsh new file mode 100644 index 0000000..998022c --- /dev/null +++ b/build/windows/nsis/wails_tools.nsh @@ -0,0 +1,212 @@ +# DO NOT EDIT - Generated automatically by `wails build` + +!include "x64.nsh" +!include "WinVer.nsh" +!include "FileFunc.nsh" + +!ifndef INFO_PROJECTNAME + !define INFO_PROJECTNAME "firefly-launcher" +!endif +!ifndef INFO_COMPANYNAME + !define INFO_COMPANYNAME "Firefly Shelter" +!endif +!ifndef INFO_PRODUCTNAME + !define INFO_PRODUCTNAME "Firefly Launcher" +!endif +!ifndef INFO_PRODUCTVERSION + !define INFO_PRODUCTVERSION "0.1.0" +!endif +!ifndef INFO_COPYRIGHT + !define INFO_COPYRIGHT "@ 2025, Firefly Shelter" +!endif +!ifndef PRODUCT_EXECUTABLE + !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" +!endif +!ifndef UNINST_KEY_NAME + !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" +!endif +!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" + +!ifndef REQUEST_EXECUTION_LEVEL + !define REQUEST_EXECUTION_LEVEL "admin" +!endif + +RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" + +!ifdef ARG_WAILS_AMD64_BINARY + !define SUPPORTS_AMD64 +!endif + +!ifdef ARG_WAILS_ARM64_BINARY + !define SUPPORTS_ARM64 +!endif + +!ifdef SUPPORTS_AMD64 + !ifdef SUPPORTS_ARM64 + !define ARCH "amd64_arm64" + !else + !define ARCH "amd64" + !endif +!else + !ifdef SUPPORTS_ARM64 + !define ARCH "arm64" + !else + !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" + !endif +!endif + +!macro wails.checkArchitecture + !ifndef WAILS_WIN10_REQUIRED + !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." + !endif + + !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED + !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" + !endif + + ${If} ${AtLeastWin10} + !ifdef SUPPORTS_AMD64 + ${if} ${IsNativeAMD64} + Goto ok + ${EndIf} + !endif + + !ifdef SUPPORTS_ARM64 + ${if} ${IsNativeARM64} + Goto ok + ${EndIf} + !endif + + IfSilent silentArch notSilentArch + silentArch: + SetErrorLevel 65 + Abort + notSilentArch: + MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" + Quit + ${else} + IfSilent silentWin notSilentWin + silentWin: + SetErrorLevel 64 + Abort + notSilentWin: + MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" + Quit + ${EndIf} + + ok: +!macroend + +!macro wails.files + !ifdef SUPPORTS_AMD64 + ${if} ${IsNativeAMD64} + File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" + ${EndIf} + !endif + + !ifdef SUPPORTS_ARM64 + ${if} ${IsNativeARM64} + File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" + ${EndIf} + !endif +!macroend + +!macro wails.writeUninstaller + WriteUninstaller "$INSTDIR\uninstall.exe" + + SetRegView 64 + WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" + WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" + WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" + WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" + WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" + WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" + + ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 + IntFmt $0 "0x%08X" $0 + WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" +!macroend + +!macro wails.deleteUninstaller + Delete "$INSTDIR\uninstall.exe" + + SetRegView 64 + DeleteRegKey HKLM "${UNINST_KEY}" +!macroend + +!macro wails.setShellContext + ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" + SetShellVarContext all + ${else} + SetShellVarContext current + ${EndIf} +!macroend + +# Install webview2 by launching the bootstrapper +# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment +!macro wails.webview2runtime + !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT + !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" + !endif + + SetRegView 64 + # If the admin key exists and is not empty then webview2 is already installed + ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" + ${If} $0 != "" + Goto ok + ${EndIf} + + ${If} ${REQUEST_EXECUTION_LEVEL} == "user" + # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed + ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" + ${If} $0 != "" + Goto ok + ${EndIf} + ${EndIf} + + SetDetailsPrint both + DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" + SetDetailsPrint listonly + + InitPluginsDir + CreateDirectory "$pluginsdir\webview2bootstrapper" + SetOutPath "$pluginsdir\webview2bootstrapper" + File "MicrosoftEdgeWebview2Setup.exe" + ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' + + SetDetailsPrint both + ok: +!macroend + +# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b +!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND + ; Backup the previously associated file class + ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" + WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" + + WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" + + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` +!macroend + +!macro APP_UNASSOCIATE EXT FILECLASS + ; Backup the previously associated file class + ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` + WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" + + DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` +!macroend + +!macro wails.associateFiles + ; Create file associations + +!macroend + +!macro wails.unassociateFiles + ; Delete app associations + +!macroend \ No newline at end of file diff --git a/build/windows/wails.exe.manifest b/build/windows/wails.exe.manifest new file mode 100644 index 0000000..0bddb82 --- /dev/null +++ b/build/windows/wails.exe.manifest @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + true/pm + permonitorv2,permonitor + + + diff --git a/frontend/Inter Font License.txt b/frontend/Inter Font License.txt new file mode 100644 index 0000000..b525cbf --- /dev/null +++ b/frontend/Inter Font License.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/frontend/bindings/firefly-launcher/internal/fsservice.js b/frontend/bindings/firefly-launcher/internal/fsservice.js new file mode 100644 index 0000000..ccac2e6 --- /dev/null +++ b/frontend/bindings/firefly-launcher/internal/fsservice.js @@ -0,0 +1,78 @@ +// @ts-check +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore: Unused imports +import {Call as $Call, Create as $Create} from "@wailsio/runtime"; + +/** + * @param {string} path + * @returns {Promise & { cancel(): void }} + */ +export function DirExists(path) { + let $resultPromise = /** @type {any} */($Call.ByID(1291974398, path)); + return $resultPromise; +} + +/** + * @param {string} path + * @returns {Promise & { cancel(): void }} + */ +export function FileExists(path) { + let $resultPromise = /** @type {any} */($Call.ByID(3373618865, path)); + return $resultPromise; +} + +/** + * @param {string} archivePath + * @param {string} fileInside + * @returns {Promise<[boolean, string]> & { cancel(): void }} + */ +export function FileExistsInZip(archivePath, fileInside) { + let $resultPromise = /** @type {any} */($Call.ByID(1737012553, archivePath, fileInside)); + return $resultPromise; +} + +/** + * @param {string} path + * @returns {Promise<[boolean, string]> & { cancel(): void }} + */ +export function OpenFolder(path) { + let $resultPromise = /** @type {any} */($Call.ByID(2733319263, path)); + return $resultPromise; +} + +/** + * @returns {Promise & { cancel(): void }} + */ +export function PickFile() { + let $resultPromise = /** @type {any} */($Call.ByID(2181012076)); + return $resultPromise; +} + +/** + * @returns {Promise & { cancel(): void }} + */ +export function PickFolder() { + let $resultPromise = /** @type {any} */($Call.ByID(3906046322)); + return $resultPromise; +} + +/** + * @param {string} path + * @returns {Promise & { cancel(): void }} + */ +export function StartApp(path) { + let $resultPromise = /** @type {any} */($Call.ByID(3825990132, path)); + return $resultPromise; +} + +/** + * @param {string} path + * @returns {Promise & { cancel(): void }} + */ +export function StartWithConsole(path) { + let $resultPromise = /** @type {any} */($Call.ByID(2364569062, path)); + return $resultPromise; +} diff --git a/frontend/bindings/firefly-launcher/internal/gitservice.js b/frontend/bindings/firefly-launcher/internal/gitservice.js new file mode 100644 index 0000000..1bbe0ab --- /dev/null +++ b/frontend/bindings/firefly-launcher/internal/gitservice.js @@ -0,0 +1,59 @@ +// @ts-check +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore: Unused imports +import {Call as $Call, Create as $Create} from "@wailsio/runtime"; + +/** + * @param {string} version + * @returns {Promise<[boolean, string]> & { cancel(): void }} + */ +export function DownloadProxyProgress(version) { + let $resultPromise = /** @type {any} */($Call.ByID(1951249093, version)); + return $resultPromise; +} + +/** + * @param {string} version + * @returns {Promise<[boolean, string]> & { cancel(): void }} + */ +export function DownloadServerProgress(version) { + let $resultPromise = /** @type {any} */($Call.ByID(314135954, version)); + return $resultPromise; +} + +/** + * @param {string} oldVersion + * @returns {Promise<[boolean, string, string]> & { cancel(): void }} + */ +export function GetLatestProxyVersion(oldVersion) { + let $resultPromise = /** @type {any} */($Call.ByID(1462362449, oldVersion)); + return $resultPromise; +} + +/** + * @param {string} oldVersion + * @returns {Promise<[boolean, string, string]> & { cancel(): void }} + */ +export function GetLatestServerVersion(oldVersion) { + let $resultPromise = /** @type {any} */($Call.ByID(1447982978, oldVersion)); + return $resultPromise; +} + +/** + * @returns {Promise & { cancel(): void }} + */ +export function UnzipProxy() { + let $resultPromise = /** @type {any} */($Call.ByID(4071181044)); + return $resultPromise; +} + +/** + * @returns {Promise & { cancel(): void }} + */ +export function UnzipServer() { + let $resultPromise = /** @type {any} */($Call.ByID(4110296071)); + return $resultPromise; +} diff --git a/frontend/bindings/firefly-launcher/internal/hdiffzservice.js b/frontend/bindings/firefly-launcher/internal/hdiffzservice.js new file mode 100644 index 0000000..c57395d --- /dev/null +++ b/frontend/bindings/firefly-launcher/internal/hdiffzservice.js @@ -0,0 +1,54 @@ +// @ts-check +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore: Unused imports +import {Call as $Call, Create as $Create} from "@wailsio/runtime"; + +/** + * @param {string} gamePath + * @returns {Promise<[boolean, string]> & { cancel(): void }} + */ +export function CutData(gamePath) { + let $resultPromise = /** @type {any} */($Call.ByID(3671642725, gamePath)); + return $resultPromise; +} + +/** + * @param {string} gamePath + * @param {string} patchPath + * @returns {Promise<[boolean, string]> & { cancel(): void }} + */ +export function DataExtract(gamePath, patchPath) { + let $resultPromise = /** @type {any} */($Call.ByID(1843136452, gamePath, patchPath)); + return $resultPromise; +} + +/** + * @param {string} gamePath + * @returns {Promise<[boolean, string]> & { cancel(): void }} + */ +export function DeleteFiles(gamePath) { + let $resultPromise = /** @type {any} */($Call.ByID(989019003, gamePath)); + return $resultPromise; +} + +/** + * @param {string} gamePath + * @returns {Promise<[boolean, string]> & { cancel(): void }} + */ +export function PatchData(gamePath) { + let $resultPromise = /** @type {any} */($Call.ByID(3608591627, gamePath)); + return $resultPromise; +} + +/** + * @param {string} gamePath + * @param {string} patchPath + * @returns {Promise<[boolean, string]> & { cancel(): void }} + */ +export function VersionValidate(gamePath, patchPath) { + let $resultPromise = /** @type {any} */($Call.ByID(3916254383, gamePath, patchPath)); + return $resultPromise; +} diff --git a/frontend/bindings/firefly-launcher/internal/index.js b/frontend/bindings/firefly-launcher/internal/index.js new file mode 100644 index 0000000..91c053c --- /dev/null +++ b/frontend/bindings/firefly-launcher/internal/index.js @@ -0,0 +1,14 @@ +// @ts-check +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +import * as FSService from "./fsservice.js"; +import * as GitService from "./gitservice.js"; +import * as HdiffzService from "./hdiffzservice.js"; +import * as LanguageService from "./languageservice.js"; +export { + FSService, + GitService, + HdiffzService, + LanguageService +}; diff --git a/frontend/bindings/firefly-launcher/internal/languageservice.js b/frontend/bindings/firefly-launcher/internal/languageservice.js new file mode 100644 index 0000000..657a236 --- /dev/null +++ b/frontend/bindings/firefly-launcher/internal/languageservice.js @@ -0,0 +1,27 @@ +// @ts-check +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore: Unused imports +import {Call as $Call, Create as $Create} from "@wailsio/runtime"; + +/** + * @param {string} path + * @returns {Promise<[string, string]> & { cancel(): void }} + */ +export function GetLanguage(path) { + let $resultPromise = /** @type {any} */($Call.ByID(3450750492, path)); + return $resultPromise; +} + +/** + * @param {string} path + * @param {string} text + * @param {string} voice + * @returns {Promise & { cancel(): void }} + */ +export function SetLanguage(path, text, voice) { + let $resultPromise = /** @type {any} */($Call.ByID(2793672496, path, text, voice)); + return $resultPromise; +} diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..7faba62 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + Wails + React + TS + + +
+ + + diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000..578b738 --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,5459 @@ +{ + "name": "react-ts-latest", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "react-ts-latest", + "version": "0.0.0", + "dependencies": { + "@tailwindcss/vite": "^4.1.11", + "@tanstack/react-router": "^1.124.0", + "@tanstack/react-router-devtools": "^1.124.0", + "lucide-react": "^0.525.0", + "motion": "^12.23.0", + "path-browserify": "^1.0.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-toastify": "^11.0.5", + "tailwindcss": "^4.1.11", + "zustand": "^5.0.6" + }, + "devDependencies": { + "@tanstack/router-plugin": "^1.124.0", + "@types/node": "^24.0.10", + "@types/path-browserify": "^1.0.3", + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", + "@vitejs/plugin-react": "^4.2.1", + "@wailsio/runtime": "^3.0.0-alpha.66", + "daisyui": "^5.0.43", + "eslint": "^8.55.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "typescript": "^5.2.2", + "vite": "^5.0.8" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", + "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.6", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", + "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.0", + "@babel/types": "^7.28.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", + "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.27.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", + "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", + "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", + "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz", + "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", + "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", + "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.19", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.19.tgz", + "integrity": "sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz", + "integrity": "sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz", + "integrity": "sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz", + "integrity": "sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz", + "integrity": "sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz", + "integrity": "sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz", + "integrity": "sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz", + "integrity": "sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz", + "integrity": "sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz", + "integrity": "sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz", + "integrity": "sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz", + "integrity": "sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz", + "integrity": "sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz", + "integrity": "sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz", + "integrity": "sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz", + "integrity": "sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz", + "integrity": "sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz", + "integrity": "sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz", + "integrity": "sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz", + "integrity": "sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz", + "integrity": "sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz", + "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "enhanced-resolve": "^5.18.1", + "jiti": "^2.4.2", + "lightningcss": "1.30.1", + "magic-string": "^0.30.17", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.11" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz", + "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.4.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.11", + "@tailwindcss/oxide-darwin-arm64": "4.1.11", + "@tailwindcss/oxide-darwin-x64": "4.1.11", + "@tailwindcss/oxide-freebsd-x64": "4.1.11", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", + "@tailwindcss/oxide-linux-x64-musl": "4.1.11", + "@tailwindcss/oxide-wasm32-wasi": "4.1.11", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz", + "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz", + "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz", + "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz", + "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz", + "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz", + "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz", + "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz", + "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz", + "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz", + "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@emnapi/wasi-threads": "^1.0.2", + "@napi-rs/wasm-runtime": "^0.2.11", + "@tybys/wasm-util": "^0.9.0", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", + "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz", + "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.11.tgz", + "integrity": "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw==", + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.1.11", + "@tailwindcss/oxide": "4.1.11", + "tailwindcss": "4.1.11" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7" + } + }, + "node_modules/@tanstack/history": { + "version": "1.121.34", + "resolved": "https://registry.npmjs.org/@tanstack/history/-/history-1.121.34.tgz", + "integrity": "sha512-YL8dGi5ZU+xvtav2boRlw4zrRghkY6hvdcmHhA0RGSJ/CBgzv+cbADW9eYJLx74XMZvIQ1pp6VMbrpXnnM5gHA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-router": { + "version": "1.124.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.124.0.tgz", + "integrity": "sha512-jJxuLbPP/Cxirnft3CoiGWyH0aj94VTmLNcYauvjTGRNbUitK4udvGaHXVEP8bcifYvpko7ptsqqBlisaosugA==", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.121.34", + "@tanstack/react-store": "^0.7.0", + "@tanstack/router-core": "1.124.0", + "isbot": "^5.1.22", + "jsesc": "^3.1.0", + "tiny-invariant": "^1.3.3", + "tiny-warning": "^1.0.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=18.0.0 || >=19.0.0", + "react-dom": ">=18.0.0 || >=19.0.0" + } + }, + "node_modules/@tanstack/react-router-devtools": { + "version": "1.124.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-router-devtools/-/react-router-devtools-1.124.0.tgz", + "integrity": "sha512-CpOUUvtOYfLQEQS/ikGL9FQgEgYzBOKq9/2LqqFDXhZZgCVW18rBvR3LZeejkYSHAWlRphG33sdXCYVRM02sZQ==", + "license": "MIT", + "dependencies": { + "@tanstack/router-devtools-core": "^1.124.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-router": "^1.124.0", + "react": ">=18.0.0 || >=19.0.0", + "react-dom": ">=18.0.0 || >=19.0.0" + } + }, + "node_modules/@tanstack/react-store": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-store/-/react-store-0.7.1.tgz", + "integrity": "sha512-qUTEKdId6QPWGiWyKAPf/gkN29scEsz6EUSJ0C3HgLMgaqTAyBsQ2sMCfGVcqb+kkhEXAdjleCgH6LAPD6f2sA==", + "license": "MIT", + "dependencies": { + "@tanstack/store": "0.7.1", + "use-sync-external-store": "^1.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tanstack/router-core": { + "version": "1.124.0", + "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.124.0.tgz", + "integrity": "sha512-mU2KA2v+ZFWC3NIjY2y+pPCx1sZDXPsUkzPjPPZxRgonE11nIu9MB89WuukqYuPbxoSWeodKNXsLe4KksGFCKA==", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.121.34", + "@tanstack/store": "^0.7.0", + "cookie-es": "^1.2.2", + "jsesc": "^3.1.0", + "tiny-invariant": "^1.3.3", + "tiny-warning": "^1.0.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/router-devtools-core": { + "version": "1.124.0", + "resolved": "https://registry.npmjs.org/@tanstack/router-devtools-core/-/router-devtools-core-1.124.0.tgz", + "integrity": "sha512-F4xejY63XrQmQZ8q6IJmLHJGeow/5CzdCAWChYEHIFy9SWYiFMMvdGFpB8SReJuwld+eoHvvtp2qhUqNloqzRA==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.1", + "goober": "^2.1.16", + "solid-js": "^1.9.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/router-core": "^1.124.0", + "csstype": "^3.0.10", + "solid-js": ">=1.9.5", + "tiny-invariant": "^1.3.3" + }, + "peerDependenciesMeta": { + "csstype": { + "optional": true + } + } + }, + "node_modules/@tanstack/router-generator": { + "version": "1.124.0", + "resolved": "https://registry.npmjs.org/@tanstack/router-generator/-/router-generator-1.124.0.tgz", + "integrity": "sha512-fatjfBvgLh7i2xcLKO3QaM5egHAhMy57B7DfE44sYx1D7/xxLOubSEjSnVSLE3dWBrstZ3aqyuYYhw7NuoXB7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tanstack/router-core": "^1.124.0", + "@tanstack/router-utils": "1.121.21", + "@tanstack/virtual-file-routes": "^1.121.21", + "prettier": "^3.5.0", + "recast": "^0.23.11", + "source-map": "^0.7.4", + "tsx": "^4.19.2", + "zod": "^3.24.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/router-plugin": { + "version": "1.124.0", + "resolved": "https://registry.npmjs.org/@tanstack/router-plugin/-/router-plugin-1.124.0.tgz", + "integrity": "sha512-CqV3PCVoMrHw0HyTioIGHTTjaMRgfwbW4ax2Pule++smyetn+3KPLV6C3VWc0vdukZMQz13JvLORSSeM0B2cYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.7", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.27.7", + "@babel/types": "^7.27.7", + "@tanstack/router-core": "^1.124.0", + "@tanstack/router-generator": "1.124.0", + "@tanstack/router-utils": "1.121.21", + "@tanstack/virtual-file-routes": "^1.121.21", + "babel-dead-code-elimination": "^1.0.10", + "chokidar": "^3.6.0", + "unplugin": "^2.1.2", + "zod": "^3.24.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@rsbuild/core": ">=1.0.2", + "@tanstack/react-router": "^1.124.0", + "vite": ">=5.0.0 || >=6.0.0", + "vite-plugin-solid": "^2.11.2", + "webpack": ">=5.92.0" + }, + "peerDependenciesMeta": { + "@rsbuild/core": { + "optional": true + }, + "@tanstack/react-router": { + "optional": true + }, + "vite": { + "optional": true + }, + "vite-plugin-solid": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@tanstack/router-utils": { + "version": "1.121.21", + "resolved": "https://registry.npmjs.org/@tanstack/router-utils/-/router-utils-1.121.21.tgz", + "integrity": "sha512-u7ubq1xPBtNiU7Fm+EOWlVWdgFLzuKOa1thhqdscVn8R4dNMUd1VoOjZ6AKmLw201VaUhFtlX+u0pjzI6szX7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/parser": "^7.27.5", + "@babel/preset-typescript": "^7.27.1", + "ansis": "^4.1.0", + "diff": "^8.0.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/store": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@tanstack/store/-/store-0.7.1.tgz", + "integrity": "sha512-PjUQKXEXhLYj2X5/6c1Xn/0/qKY0IVFxTJweopRfF26xfjVyb14yALydJrHupDh3/d+1WKmfEgZPBVCmDkzzwg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/virtual-file-routes": { + "version": "1.121.21", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-file-routes/-/virtual-file-routes-1.121.21.tgz", + "integrity": "sha512-3nuYsTyaq6ZN7jRZ9z6Gj3GXZqBOqOT0yzd/WZ33ZFfv4yVNIvsa5Lw+M1j3sgyEAxKMqGu/FaNi7FCjr3yOdw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.0.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.10.tgz", + "integrity": "sha512-ENHwaH+JIRTDIEEbDK6QSQntAYGtbvdDXnMXnZaZ6k13Du1dPMmprkEHIL7ok2Wl2aZevetwTAb5S+7yIF+enA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.8.0" + } + }, + "node_modules/@types/path-browserify": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/path-browserify/-/path-browserify-1.0.3.tgz", + "integrity": "sha512-ZmHivEbNCBtAfcrFeBCiTjdIc2dey0l7oCGNGpSuRTy8jP6UVND7oUowlvDujBy8r2Hoa8bfFUOCiPWfmtkfxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.23", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", + "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/semver": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.6.0.tgz", + "integrity": "sha512-5Kgff+m8e2PB+9j51eGHEpn5kUzRKH2Ry0qGoe8ItJg7pqnkPrYPkDQZGgGmTa0EGarHrkjLvOdU3b1fzI8otQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.19", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" + } + }, + "node_modules/@wailsio/runtime": { + "version": "3.0.0-alpha.66", + "resolved": "https://registry.npmjs.org/@wailsio/runtime/-/runtime-3.0.0-alpha.66.tgz", + "integrity": "sha512-ENLu8rn1griL1gFHJqkq1i+BVxrrA0JPJHYneUJYuf/s54kjuQViW0RKDEe/WTDo56ABpfykrd/T8OYpPUyXUw==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.1.0.tgz", + "integrity": "sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/babel-dead-code-elimination": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/babel-dead-code-elimination/-/babel-dead-code-elimination-1.0.10.tgz", + "integrity": "sha512-DV5bdJZTzZ0zn0DC24v3jD7Mnidh6xhKa4GfKCbq3sfW8kaWhDdZjP3i81geA8T33tdYqWKw4D3fVv0CwEgKVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.7", + "@babel/parser": "^7.23.6", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001726", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", + "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie-es": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz", + "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/daisyui": { + "version": "5.0.43", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.0.43.tgz", + "integrity": "sha512-2pshHJ73vetSpsbAyaOncGnNYL0mwvgseS1EWy1I9Qpw8D11OuBoDNIWrPIME4UFcq2xuff3A9x+eXbuFR9fUQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/saadeghi/daisyui?sponsor=1" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz", + "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.179", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.179.tgz", + "integrity": "sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/enhanced-resolve": { + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", + "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.20", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", + "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/framer-motion": { + "version": "12.23.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.0.tgz", + "integrity": "sha512-xf6NxTGAyf7zR4r2KlnhFmsRfKIbjqeBupEDBAaEtVIBJX96sAon00kMlsKButSIRwPSHjbRrAPnYdJJ9kyhbA==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.22.0", + "motion-utils": "^12.19.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/goober": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.16.tgz", + "integrity": "sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==", + "license": "MIT", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "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.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isbot": { + "version": "5.1.28", + "resolved": "https://registry.npmjs.org/isbot/-/isbot-5.1.28.tgz", + "integrity": "sha512-qrOp4g3xj8YNse4biorv6O5ZShwsJM0trsoda4y7j/Su7ZtTTfVXFzbKkpgcSoDrHS8FcTuUwcU04YimZlZOxw==", + "license": "Unlicense", + "engines": { + "node": ">=18" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.525.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.525.0.tgz", + "integrity": "sha512-Tm1txJ2OkymCGkvwoHt33Y2JpN5xucVq1slHcgE6Lk0WjDfjgKWor5CdVER8U6DvcfMwh4M8XxmpTiyzfmfDYQ==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/motion": { + "version": "12.23.0", + "resolved": "https://registry.npmjs.org/motion/-/motion-12.23.0.tgz", + "integrity": "sha512-PPNwblArRH9GRC4F3KtOTiIaYd+mtp324vYq3HIL+ueseoAVqPRK5TPFTAQBcIprfVd0NWo3DLzZSiyWaYFXXQ==", + "license": "MIT", + "dependencies": { + "framer-motion": "^12.23.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/motion-dom": { + "version": "12.22.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.22.0.tgz", + "integrity": "sha512-ooH7+/BPw9gOsL9VtPhEJHE2m4ltnhMlcGMhEqA0YGNhKof7jdaszvsyThXI6LVIKshJUZ9/CP6HNqQhJfV7kw==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.19.0" + } + }, + "node_modules/motion-utils": { + "version": "12.19.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.19.0.tgz", + "integrity": "sha512-BuFTHINYmV07pdWs6lj6aI63vr2N4dg0vR+td0rtrdpWOhBzIkEklZyLcvKBoEtwSqx8Jg06vUB5RS0xDiUybw==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-toastify": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.5.tgz", + "integrity": "sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": "^18 || ^19", + "react-dom": "^18 || ^19" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recast": { + "version": "0.23.11", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", + "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/recast/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.1.tgz", + "integrity": "sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.44.1", + "@rollup/rollup-android-arm64": "4.44.1", + "@rollup/rollup-darwin-arm64": "4.44.1", + "@rollup/rollup-darwin-x64": "4.44.1", + "@rollup/rollup-freebsd-arm64": "4.44.1", + "@rollup/rollup-freebsd-x64": "4.44.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.44.1", + "@rollup/rollup-linux-arm-musleabihf": "4.44.1", + "@rollup/rollup-linux-arm64-gnu": "4.44.1", + "@rollup/rollup-linux-arm64-musl": "4.44.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.44.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.44.1", + "@rollup/rollup-linux-riscv64-gnu": "4.44.1", + "@rollup/rollup-linux-riscv64-musl": "4.44.1", + "@rollup/rollup-linux-s390x-gnu": "4.44.1", + "@rollup/rollup-linux-x64-gnu": "4.44.1", + "@rollup/rollup-linux-x64-musl": "4.44.1", + "@rollup/rollup-win32-arm64-msvc": "4.44.1", + "@rollup/rollup-win32-ia32-msvc": "4.44.1", + "@rollup/rollup-win32-x64-msvc": "4.44.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/seroval": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.3.2.tgz", + "integrity": "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/seroval-plugins": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.3.2.tgz", + "integrity": "sha512-0QvCV2lM3aj/U3YozDiVwx9zpH0q8A60CTWIv4Jszj/givcudPb48B+rkU5D51NJ0pTpweGMttHjboPa9/zoIQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "seroval": "^1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/solid-js": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.7.tgz", + "integrity": "sha512-/saTKi8iWEM233n5OSi1YHCCuh66ZIQ7aK2hsToPe4tqGm7qAejU1SwNuTPivbWAYq7SjuHVVYxxuZQNRbICiw==", + "license": "MIT", + "dependencies": { + "csstype": "^3.1.0", + "seroval": "~1.3.0", + "seroval-plugins": "~1.3.0" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tailwindcss": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz", + "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==", + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz", + "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/darwin-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-loong64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-s390x": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/sunos-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/esbuild": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/unplugin": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.5.tgz", + "integrity": "sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.1", + "picomatch": "^4.0.2", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/unplugin/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/vite": { + "version": "5.4.19", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", + "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.25.72", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.72.tgz", + "integrity": "sha512-Cl+fe4dNL4XumOBNBsr0lHfA80PQiZXHI4xEMTEr8gt6aGz92t3lBA32e71j9+JeF/VAYvdfBnuwJs+BMx/BrA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zustand": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.6.tgz", + "integrity": "sha512-ihAqNeUVhe0MAD+X8M5UzqyZ9k3FFZLBTtqo6JLPwV53cbRB/mJwBI0PxcIgqhBBHlEs8G45OTDTMq3gNcLq3A==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..46452ae --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,43 @@ +{ + "name": "react-ts-latest", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build:dev": "tsc && vite build --minify false --mode development", + "build": "tsc && vite build --mode production", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "@tailwindcss/vite": "^4.1.11", + "@tanstack/react-router": "^1.124.0", + "@tanstack/react-router-devtools": "^1.124.0", + "lucide-react": "^0.525.0", + "motion": "^12.23.0", + "path-browserify": "^1.0.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-toastify": "^11.0.5", + "tailwindcss": "^4.1.11", + "zustand": "^5.0.6" + }, + "devDependencies": { + "@tanstack/router-plugin": "^1.124.0", + "@types/node": "^24.0.10", + "@types/path-browserify": "^1.0.3", + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", + "@vitejs/plugin-react": "^4.2.1", + "@wailsio/runtime": "^3.0.0-alpha.66", + "daisyui": "^5.0.43", + "eslint": "^8.55.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "typescript": "^5.2.2", + "vite": "^5.0.8" + } +} diff --git a/frontend/public/Inter-Medium.ttf b/frontend/public/Inter-Medium.ttf new file mode 100644 index 0000000..a01f377 Binary files /dev/null and b/frontend/public/Inter-Medium.ttf differ diff --git a/frontend/public/bg.jpg b/frontend/public/bg.jpg new file mode 100644 index 0000000..309e5a5 Binary files /dev/null and b/frontend/public/bg.jpg differ diff --git a/frontend/runtime-debug.js b/frontend/runtime-debug.js new file mode 100644 index 0000000..f6ad3ee --- /dev/null +++ b/frontend/runtime-debug.js @@ -0,0 +1,1605 @@ +var __defProp = Object.defineProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; + +// desktop/@wailsio/runtime/src/index.js +var src_exports = {}; +__export(src_exports, { + Application: () => application_exports, + Browser: () => browser_exports, + Call: () => calls_exports, + Clipboard: () => clipboard_exports, + Create: () => create_exports, + Dialogs: () => dialogs_exports, + Events: () => events_exports, + Flags: () => flags_exports, + Screens: () => screens_exports, + System: () => system_exports, + WML: () => wml_exports, + Window: () => window_default +}); + +// desktop/@wailsio/runtime/src/wml.js +var wml_exports = {}; +__export(wml_exports, { + Enable: () => Enable, + Reload: () => Reload +}); + +// desktop/@wailsio/runtime/src/browser.js +var browser_exports = {}; +__export(browser_exports, { + OpenURL: () => OpenURL +}); + +// node_modules/nanoid/non-secure/index.js +var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"; +var nanoid = (size = 21) => { + let id = ""; + let i = size; + while (i--) { + id += urlAlphabet[Math.random() * 64 | 0]; + } + return id; +}; + +// desktop/@wailsio/runtime/src/runtime.js +var runtimeURL = window.location.origin + "/wails/runtime"; +var objectNames = { + Call: 0, + Clipboard: 1, + Application: 2, + Events: 3, + ContextMenu: 4, + Dialog: 5, + Window: 6, + Screens: 7, + System: 8, + Browser: 9, + CancelCall: 10 +}; +var clientId = nanoid(); +function newRuntimeCallerWithID(object, windowName) { + return function(method, args = null) { + return runtimeCallWithID(object, method, windowName, args); + }; +} +function runtimeCallWithID(objectID, method, windowName, args) { + let url = new URL(runtimeURL); + url.searchParams.append("object", objectID); + url.searchParams.append("method", method); + let fetchOptions = { + headers: {} + }; + if (windowName) { + fetchOptions.headers["x-wails-window-name"] = windowName; + } + if (args) { + url.searchParams.append("args", JSON.stringify(args)); + } + fetchOptions.headers["x-wails-client-id"] = clientId; + return new Promise((resolve, reject) => { + fetch(url, fetchOptions).then((response) => { + if (response.ok) { + if (response.headers.get("Content-Type") && response.headers.get("Content-Type").indexOf("application/json") !== -1) { + return response.json(); + } else { + return response.text(); + } + } + reject(Error(response.statusText)); + }).then((data) => resolve(data)).catch((error) => reject(error)); + }); +} + +// desktop/@wailsio/runtime/src/browser.js +var call = newRuntimeCallerWithID(objectNames.Browser, ""); +var BrowserOpenURL = 0; +function OpenURL(url) { + return call(BrowserOpenURL, { url }); +} + +// desktop/@wailsio/runtime/src/dialogs.js +var dialogs_exports = {}; +__export(dialogs_exports, { + Error: () => Error2, + Info: () => Info, + OpenFile: () => OpenFile, + Question: () => Question, + SaveFile: () => SaveFile, + Warning: () => Warning +}); +window._wails = window._wails || {}; +window._wails.dialogErrorCallback = dialogErrorCallback; +window._wails.dialogResultCallback = dialogResultCallback; +var DialogInfo = 0; +var DialogWarning = 1; +var DialogError = 2; +var DialogQuestion = 3; +var DialogOpenFile = 4; +var DialogSaveFile = 5; +var call2 = newRuntimeCallerWithID(objectNames.Dialog, ""); +var dialogResponses = /* @__PURE__ */ new Map(); +function generateID() { + let result; + do { + result = nanoid(); + } while (dialogResponses.has(result)); + return result; +} +function dialog(type, options = {}) { + const id = generateID(); + options["dialog-id"] = id; + return new Promise((resolve, reject) => { + dialogResponses.set(id, { resolve, reject }); + call2(type, options).catch((error) => { + reject(error); + dialogResponses.delete(id); + }); + }); +} +function dialogResultCallback(id, data, isJSON) { + let p = dialogResponses.get(id); + if (p) { + if (isJSON) { + p.resolve(JSON.parse(data)); + } else { + p.resolve(data); + } + dialogResponses.delete(id); + } +} +function dialogErrorCallback(id, message) { + let p = dialogResponses.get(id); + if (p) { + p.reject(message); + dialogResponses.delete(id); + } +} +var Info = (options) => dialog(DialogInfo, options); +var Warning = (options) => dialog(DialogWarning, options); +var Error2 = (options) => dialog(DialogError, options); +var Question = (options) => dialog(DialogQuestion, options); +var OpenFile = (options) => dialog(DialogOpenFile, options); +var SaveFile = (options) => dialog(DialogSaveFile, options); + +// desktop/@wailsio/runtime/src/events.js +var events_exports = {}; +__export(events_exports, { + Emit: () => Emit, + Off: () => Off, + OffAll: () => OffAll, + On: () => On, + OnMultiple: () => OnMultiple, + Once: () => Once, + Types: () => Types, + WailsEvent: () => WailsEvent, + setup: () => setup +}); + +// desktop/@wailsio/runtime/src/event_types.js +var EventTypes = { + Windows: { + SystemThemeChanged: "windows:SystemThemeChanged", + APMPowerStatusChange: "windows:APMPowerStatusChange", + APMSuspend: "windows:APMSuspend", + APMResumeAutomatic: "windows:APMResumeAutomatic", + APMResumeSuspend: "windows:APMResumeSuspend", + APMPowerSettingChange: "windows:APMPowerSettingChange", + ApplicationStarted: "windows:ApplicationStarted", + WebViewNavigationCompleted: "windows:WebViewNavigationCompleted", + WindowInactive: "windows:WindowInactive", + WindowActive: "windows:WindowActive", + WindowClickActive: "windows:WindowClickActive", + WindowMaximise: "windows:WindowMaximise", + WindowUnMaximise: "windows:WindowUnMaximise", + WindowFullscreen: "windows:WindowFullscreen", + WindowUnFullscreen: "windows:WindowUnFullscreen", + WindowRestore: "windows:WindowRestore", + WindowMinimise: "windows:WindowMinimise", + WindowUnMinimise: "windows:WindowUnMinimise", + WindowClose: "windows:WindowClose", + WindowSetFocus: "windows:WindowSetFocus", + WindowKillFocus: "windows:WindowKillFocus", + WindowDragDrop: "windows:WindowDragDrop", + WindowDragEnter: "windows:WindowDragEnter", + WindowDragLeave: "windows:WindowDragLeave", + WindowDragOver: "windows:WindowDragOver", + WindowDidMove: "windows:WindowDidMove", + WindowDidResize: "windows:WindowDidResize" + }, + Mac: { + ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive", + ApplicationDidChangeBackingProperties: "mac:ApplicationDidChangeBackingProperties", + ApplicationDidChangeEffectiveAppearance: "mac:ApplicationDidChangeEffectiveAppearance", + ApplicationDidChangeIcon: "mac:ApplicationDidChangeIcon", + ApplicationDidChangeOcclusionState: "mac:ApplicationDidChangeOcclusionState", + ApplicationDidChangeScreenParameters: "mac:ApplicationDidChangeScreenParameters", + ApplicationDidChangeStatusBarFrame: "mac:ApplicationDidChangeStatusBarFrame", + ApplicationDidChangeStatusBarOrientation: "mac:ApplicationDidChangeStatusBarOrientation", + ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching", + ApplicationDidHide: "mac:ApplicationDidHide", + ApplicationDidResignActiveNotification: "mac:ApplicationDidResignActiveNotification", + ApplicationDidUnhide: "mac:ApplicationDidUnhide", + ApplicationDidUpdate: "mac:ApplicationDidUpdate", + ApplicationWillBecomeActive: "mac:ApplicationWillBecomeActive", + ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching", + ApplicationWillHide: "mac:ApplicationWillHide", + ApplicationWillResignActive: "mac:ApplicationWillResignActive", + ApplicationWillTerminate: "mac:ApplicationWillTerminate", + ApplicationWillUnhide: "mac:ApplicationWillUnhide", + ApplicationWillUpdate: "mac:ApplicationWillUpdate", + ApplicationDidChangeTheme: "mac:ApplicationDidChangeTheme!", + ApplicationShouldHandleReopen: "mac:ApplicationShouldHandleReopen!", + WindowDidBecomeKey: "mac:WindowDidBecomeKey", + WindowDidBecomeMain: "mac:WindowDidBecomeMain", + WindowDidBeginSheet: "mac:WindowDidBeginSheet", + WindowDidChangeAlpha: "mac:WindowDidChangeAlpha", + WindowDidChangeBackingLocation: "mac:WindowDidChangeBackingLocation", + WindowDidChangeBackingProperties: "mac:WindowDidChangeBackingProperties", + WindowDidChangeCollectionBehavior: "mac:WindowDidChangeCollectionBehavior", + WindowDidChangeEffectiveAppearance: "mac:WindowDidChangeEffectiveAppearance", + WindowDidChangeOcclusionState: "mac:WindowDidChangeOcclusionState", + WindowDidChangeOrderingMode: "mac:WindowDidChangeOrderingMode", + WindowDidChangeScreen: "mac:WindowDidChangeScreen", + WindowDidChangeScreenParameters: "mac:WindowDidChangeScreenParameters", + WindowDidChangeScreenProfile: "mac:WindowDidChangeScreenProfile", + WindowDidChangeScreenSpace: "mac:WindowDidChangeScreenSpace", + WindowDidChangeScreenSpaceProperties: "mac:WindowDidChangeScreenSpaceProperties", + WindowDidChangeSharingType: "mac:WindowDidChangeSharingType", + WindowDidChangeSpace: "mac:WindowDidChangeSpace", + WindowDidChangeSpaceOrderingMode: "mac:WindowDidChangeSpaceOrderingMode", + WindowDidChangeTitle: "mac:WindowDidChangeTitle", + WindowDidChangeToolbar: "mac:WindowDidChangeToolbar", + WindowDidChangeVisibility: "mac:WindowDidChangeVisibility", + WindowDidDeminiaturize: "mac:WindowDidDeminiaturize", + WindowDidEndSheet: "mac:WindowDidEndSheet", + WindowDidEnterFullScreen: "mac:WindowDidEnterFullScreen", + WindowDidEnterVersionBrowser: "mac:WindowDidEnterVersionBrowser", + WindowDidExitFullScreen: "mac:WindowDidExitFullScreen", + WindowDidExitVersionBrowser: "mac:WindowDidExitVersionBrowser", + WindowDidExpose: "mac:WindowDidExpose", + WindowDidFocus: "mac:WindowDidFocus", + WindowDidMiniaturize: "mac:WindowDidMiniaturize", + WindowDidMove: "mac:WindowDidMove", + WindowDidOrderOffScreen: "mac:WindowDidOrderOffScreen", + WindowDidOrderOnScreen: "mac:WindowDidOrderOnScreen", + WindowDidResignKey: "mac:WindowDidResignKey", + WindowDidResignMain: "mac:WindowDidResignMain", + WindowDidResize: "mac:WindowDidResize", + WindowDidUpdate: "mac:WindowDidUpdate", + WindowDidUpdateAlpha: "mac:WindowDidUpdateAlpha", + WindowDidUpdateCollectionBehavior: "mac:WindowDidUpdateCollectionBehavior", + WindowDidUpdateCollectionProperties: "mac:WindowDidUpdateCollectionProperties", + WindowDidUpdateShadow: "mac:WindowDidUpdateShadow", + WindowDidUpdateTitle: "mac:WindowDidUpdateTitle", + WindowDidUpdateToolbar: "mac:WindowDidUpdateToolbar", + WindowDidUpdateVisibility: "mac:WindowDidUpdateVisibility", + WindowShouldClose: "mac:WindowShouldClose!", + WindowWillBecomeKey: "mac:WindowWillBecomeKey", + WindowWillBecomeMain: "mac:WindowWillBecomeMain", + WindowWillBeginSheet: "mac:WindowWillBeginSheet", + WindowWillChangeOrderingMode: "mac:WindowWillChangeOrderingMode", + WindowWillClose: "mac:WindowWillClose", + WindowWillDeminiaturize: "mac:WindowWillDeminiaturize", + WindowWillEnterFullScreen: "mac:WindowWillEnterFullScreen", + WindowWillEnterVersionBrowser: "mac:WindowWillEnterVersionBrowser", + WindowWillExitFullScreen: "mac:WindowWillExitFullScreen", + WindowWillExitVersionBrowser: "mac:WindowWillExitVersionBrowser", + WindowWillFocus: "mac:WindowWillFocus", + WindowWillMiniaturize: "mac:WindowWillMiniaturize", + WindowWillMove: "mac:WindowWillMove", + WindowWillOrderOffScreen: "mac:WindowWillOrderOffScreen", + WindowWillOrderOnScreen: "mac:WindowWillOrderOnScreen", + WindowWillResignMain: "mac:WindowWillResignMain", + WindowWillResize: "mac:WindowWillResize", + WindowWillUnfocus: "mac:WindowWillUnfocus", + WindowWillUpdate: "mac:WindowWillUpdate", + WindowWillUpdateAlpha: "mac:WindowWillUpdateAlpha", + WindowWillUpdateCollectionBehavior: "mac:WindowWillUpdateCollectionBehavior", + WindowWillUpdateCollectionProperties: "mac:WindowWillUpdateCollectionProperties", + WindowWillUpdateShadow: "mac:WindowWillUpdateShadow", + WindowWillUpdateTitle: "mac:WindowWillUpdateTitle", + WindowWillUpdateToolbar: "mac:WindowWillUpdateToolbar", + WindowWillUpdateVisibility: "mac:WindowWillUpdateVisibility", + WindowWillUseStandardFrame: "mac:WindowWillUseStandardFrame", + MenuWillOpen: "mac:MenuWillOpen", + MenuDidOpen: "mac:MenuDidOpen", + MenuDidClose: "mac:MenuDidClose", + MenuWillSendAction: "mac:MenuWillSendAction", + MenuDidSendAction: "mac:MenuDidSendAction", + MenuWillHighlightItem: "mac:MenuWillHighlightItem", + MenuDidHighlightItem: "mac:MenuDidHighlightItem", + MenuWillDisplayItem: "mac:MenuWillDisplayItem", + MenuDidDisplayItem: "mac:MenuDidDisplayItem", + MenuWillAddItem: "mac:MenuWillAddItem", + MenuDidAddItem: "mac:MenuDidAddItem", + MenuWillRemoveItem: "mac:MenuWillRemoveItem", + MenuDidRemoveItem: "mac:MenuDidRemoveItem", + MenuWillBeginTracking: "mac:MenuWillBeginTracking", + MenuDidBeginTracking: "mac:MenuDidBeginTracking", + MenuWillEndTracking: "mac:MenuWillEndTracking", + MenuDidEndTracking: "mac:MenuDidEndTracking", + MenuWillUpdate: "mac:MenuWillUpdate", + MenuDidUpdate: "mac:MenuDidUpdate", + MenuWillPopUp: "mac:MenuWillPopUp", + MenuDidPopUp: "mac:MenuDidPopUp", + MenuWillSendActionToItem: "mac:MenuWillSendActionToItem", + MenuDidSendActionToItem: "mac:MenuDidSendActionToItem", + WebViewDidStartProvisionalNavigation: "mac:WebViewDidStartProvisionalNavigation", + WebViewDidReceiveServerRedirectForProvisionalNavigation: "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation", + WebViewDidFinishNavigation: "mac:WebViewDidFinishNavigation", + WebViewDidCommitNavigation: "mac:WebViewDidCommitNavigation", + WindowFileDraggingEntered: "mac:WindowFileDraggingEntered", + WindowFileDraggingPerformed: "mac:WindowFileDraggingPerformed", + WindowFileDraggingExited: "mac:WindowFileDraggingExited" + }, + Linux: { + SystemThemeChanged: "linux:SystemThemeChanged", + WindowLoadChanged: "linux:WindowLoadChanged", + WindowDeleteEvent: "linux:WindowDeleteEvent", + WindowDidMove: "linux:WindowDidMove", + WindowDidResize: "linux:WindowDidResize", + WindowFocusIn: "linux:WindowFocusIn", + WindowFocusOut: "linux:WindowFocusOut", + ApplicationStartup: "linux:ApplicationStartup" + }, + Common: { + ApplicationStarted: "common:ApplicationStarted", + WindowMaximise: "common:WindowMaximise", + WindowUnMaximise: "common:WindowUnMaximise", + WindowFullscreen: "common:WindowFullscreen", + WindowUnFullscreen: "common:WindowUnFullscreen", + WindowRestore: "common:WindowRestore", + WindowMinimise: "common:WindowMinimise", + WindowUnMinimise: "common:WindowUnMinimise", + WindowClosing: "common:WindowClosing", + WindowZoom: "common:WindowZoom", + WindowZoomIn: "common:WindowZoomIn", + WindowZoomOut: "common:WindowZoomOut", + WindowZoomReset: "common:WindowZoomReset", + WindowFocus: "common:WindowFocus", + WindowLostFocus: "common:WindowLostFocus", + WindowShow: "common:WindowShow", + WindowHide: "common:WindowHide", + WindowDPIChanged: "common:WindowDPIChanged", + WindowFilesDropped: "common:WindowFilesDropped", + WindowRuntimeReady: "common:WindowRuntimeReady", + ThemeChanged: "common:ThemeChanged", + WindowDidMove: "common:WindowDidMove", + WindowDidResize: "common:WindowDidResize" + } +}; + +// desktop/@wailsio/runtime/src/events.js +var Types = EventTypes; +window._wails = window._wails || {}; +window._wails.dispatchWailsEvent = dispatchWailsEvent; +var call3 = newRuntimeCallerWithID(objectNames.Events, ""); +var EmitMethod = 0; +var eventListeners = /* @__PURE__ */ new Map(); +var Listener = class { + constructor(eventName, callback, maxCallbacks) { + this.eventName = eventName; + this.maxCallbacks = maxCallbacks || -1; + this.Callback = (data) => { + callback(data); + if (this.maxCallbacks === -1) return false; + this.maxCallbacks -= 1; + return this.maxCallbacks === 0; + }; + } +}; +var WailsEvent = class { + constructor(name, data = null) { + this.name = name; + this.data = data; + } +}; +function setup() { +} +function dispatchWailsEvent(event) { + let listeners = eventListeners.get(event.name); + if (listeners) { + let toRemove = listeners.filter((listener) => { + let remove = listener.Callback(event); + if (remove) return true; + }); + if (toRemove.length > 0) { + listeners = listeners.filter((l) => !toRemove.includes(l)); + if (listeners.length === 0) eventListeners.delete(event.name); + else eventListeners.set(event.name, listeners); + } + } +} +function OnMultiple(eventName, callback, maxCallbacks) { + let listeners = eventListeners.get(eventName) || []; + const thisListener = new Listener(eventName, callback, maxCallbacks); + listeners.push(thisListener); + eventListeners.set(eventName, listeners); + return () => listenerOff(thisListener); +} +function On(eventName, callback) { + return OnMultiple(eventName, callback, -1); +} +function Once(eventName, callback) { + return OnMultiple(eventName, callback, 1); +} +function listenerOff(listener) { + const eventName = listener.eventName; + let listeners = eventListeners.get(eventName).filter((l) => l !== listener); + if (listeners.length === 0) eventListeners.delete(eventName); + else eventListeners.set(eventName, listeners); +} +function Off(eventName, ...additionalEventNames) { + let eventsToRemove = [eventName, ...additionalEventNames]; + eventsToRemove.forEach((eventName2) => eventListeners.delete(eventName2)); +} +function OffAll() { + eventListeners.clear(); +} +function Emit(event) { + return call3(EmitMethod, event); +} + +// desktop/@wailsio/runtime/src/utils.js +function debugLog(message) { + console.log( + "%c wails3 %c " + message + " ", + "background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem", + "background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem" + ); +} +function canAbortListeners() { + if (!EventTarget || !AbortSignal || !AbortController) + return false; + let result = true; + const target = new EventTarget(); + const controller2 = new AbortController(); + target.addEventListener("test", () => { + result = false; + }, { signal: controller2.signal }); + controller2.abort(); + target.dispatchEvent(new CustomEvent("test")); + return result; +} +var isReady = false; +document.addEventListener("DOMContentLoaded", () => isReady = true); +function whenReady(callback) { + if (isReady || document.readyState === "complete") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +} + +// desktop/@wailsio/runtime/src/window.js +var PositionMethod = 0; +var CenterMethod = 1; +var CloseMethod = 2; +var DisableSizeConstraintsMethod = 3; +var EnableSizeConstraintsMethod = 4; +var FocusMethod = 5; +var ForceReloadMethod = 6; +var FullscreenMethod = 7; +var GetScreenMethod = 8; +var GetZoomMethod = 9; +var HeightMethod = 10; +var HideMethod = 11; +var IsFocusedMethod = 12; +var IsFullscreenMethod = 13; +var IsMaximisedMethod = 14; +var IsMinimisedMethod = 15; +var MaximiseMethod = 16; +var MinimiseMethod = 17; +var NameMethod = 18; +var OpenDevToolsMethod = 19; +var RelativePositionMethod = 20; +var ReloadMethod = 21; +var ResizableMethod = 22; +var RestoreMethod = 23; +var SetPositionMethod = 24; +var SetAlwaysOnTopMethod = 25; +var SetBackgroundColourMethod = 26; +var SetFramelessMethod = 27; +var SetFullscreenButtonEnabledMethod = 28; +var SetMaxSizeMethod = 29; +var SetMinSizeMethod = 30; +var SetRelativePositionMethod = 31; +var SetResizableMethod = 32; +var SetSizeMethod = 33; +var SetTitleMethod = 34; +var SetZoomMethod = 35; +var ShowMethod = 36; +var SizeMethod = 37; +var ToggleFullscreenMethod = 38; +var ToggleMaximiseMethod = 39; +var UnFullscreenMethod = 40; +var UnMaximiseMethod = 41; +var UnMinimiseMethod = 42; +var WidthMethod = 43; +var ZoomMethod = 44; +var ZoomInMethod = 45; +var ZoomOutMethod = 46; +var ZoomResetMethod = 47; +var caller = Symbol(); +var Window = class _Window { + /** + * Initialises a window object with the specified name. + * + * @private + * @param {string} name - The name of the target window. + */ + constructor(name = "") { + this[caller] = newRuntimeCallerWithID(objectNames.Window, name); + for (const method of Object.getOwnPropertyNames(_Window.prototype)) { + if (method !== "constructor" && typeof this[method] === "function") { + this[method] = this[method].bind(this); + } + } + } + /** + * Gets the specified window. + * + * @public + * @param {string} name - The name of the window to get. + * @return {Window} - The corresponding window object. + */ + Get(name) { + return new _Window(name); + } + /** + * Returns the absolute position of the window. + * + * @public + * @return {Promise} - The current absolute position of the window. + */ + Position() { + return this[caller](PositionMethod); + } + /** + * Centers the window on the screen. + * + * @public + * @return {Promise} + */ + Center() { + return this[caller](CenterMethod); + } + /** + * Closes the window. + * + * @public + * @return {Promise} + */ + Close() { + return this[caller](CloseMethod); + } + /** + * Disables min/max size constraints. + * + * @public + * @return {Promise} + */ + DisableSizeConstraints() { + return this[caller](DisableSizeConstraintsMethod); + } + /** + * Enables min/max size constraints. + * + * @public + * @return {Promise} + */ + EnableSizeConstraints() { + return this[caller](EnableSizeConstraintsMethod); + } + /** + * Focuses the window. + * + * @public + * @return {Promise} + */ + Focus() { + return this[caller](FocusMethod); + } + /** + * Forces the window to reload the page assets. + * + * @public + * @return {Promise} + */ + ForceReload() { + return this[caller](ForceReloadMethod); + } + /** + * Doc. + * + * @public + * @return {Promise} + */ + Fullscreen() { + return this[caller](FullscreenMethod); + } + /** + * Returns the screen that the window is on. + * + * @public + * @return {Promise} - The screen the window is currently on + */ + GetScreen() { + return this[caller](GetScreenMethod); + } + /** + * Returns the current zoom level of the window. + * + * @public + * @return {Promise} - The current zoom level + */ + GetZoom() { + return this[caller](GetZoomMethod); + } + /** + * Returns the height of the window. + * + * @public + * @return {Promise} - The current height of the window + */ + Height() { + return this[caller](HeightMethod); + } + /** + * Hides the window. + * + * @public + * @return {Promise} + */ + Hide() { + return this[caller](HideMethod); + } + /** + * Returns true if the window is focused. + * + * @public + * @return {Promise} - Whether the window is currently focused + */ + IsFocused() { + return this[caller](IsFocusedMethod); + } + /** + * Returns true if the window is fullscreen. + * + * @public + * @return {Promise} - Whether the window is currently fullscreen + */ + IsFullscreen() { + return this[caller](IsFullscreenMethod); + } + /** + * Returns true if the window is maximised. + * + * @public + * @return {Promise} - Whether the window is currently maximised + */ + IsMaximised() { + return this[caller](IsMaximisedMethod); + } + /** + * Returns true if the window is minimised. + * + * @public + * @return {Promise} - Whether the window is currently minimised + */ + IsMinimised() { + return this[caller](IsMinimisedMethod); + } + /** + * Maximises the window. + * + * @public + * @return {Promise} + */ + Maximise() { + return this[caller](MaximiseMethod); + } + /** + * Minimises the window. + * + * @public + * @return {Promise} + */ + Minimise() { + return this[caller](MinimiseMethod); + } + /** + * Returns the name of the window. + * + * @public + * @return {Promise} - The name of the window + */ + Name() { + return this[caller](NameMethod); + } + /** + * Opens the development tools pane. + * + * @public + * @return {Promise} + */ + OpenDevTools() { + return this[caller](OpenDevToolsMethod); + } + /** + * Returns the relative position of the window to the screen. + * + * @public + * @return {Promise} - The current relative position of the window + */ + RelativePosition() { + return this[caller](RelativePositionMethod); + } + /** + * Reloads the page assets. + * + * @public + * @return {Promise} + */ + Reload() { + return this[caller](ReloadMethod); + } + /** + * Returns true if the window is resizable. + * + * @public + * @return {Promise} - Whether the window is currently resizable + */ + Resizable() { + return this[caller](ResizableMethod); + } + /** + * Restores the window to its previous state if it was previously minimised, maximised or fullscreen. + * + * @public + * @return {Promise} + */ + Restore() { + return this[caller](RestoreMethod); + } + /** + * Sets the absolute position of the window. + * + * @public + * @param {number} x - The desired horizontal absolute position of the window + * @param {number} y - The desired vertical absolute position of the window + * @return {Promise} + */ + SetPosition(x, y) { + return this[caller](SetPositionMethod, { x, y }); + } + /** + * Sets the window to be always on top. + * + * @public + * @param {boolean} alwaysOnTop - Whether the window should stay on top + * @return {Promise} + */ + SetAlwaysOnTop(alwaysOnTop) { + return this[caller](SetAlwaysOnTopMethod, { alwaysOnTop }); + } + /** + * Sets the background colour of the window. + * + * @public + * @param {number} r - The desired red component of the window background + * @param {number} g - The desired green component of the window background + * @param {number} b - The desired blue component of the window background + * @param {number} a - The desired alpha component of the window background + * @return {Promise} + */ + SetBackgroundColour(r, g, b, a) { + return this[caller](SetBackgroundColourMethod, { r, g, b, a }); + } + /** + * Removes the window frame and title bar. + * + * @public + * @param {boolean} frameless - Whether the window should be frameless + * @return {Promise} + */ + SetFrameless(frameless) { + return this[caller](SetFramelessMethod, { frameless }); + } + /** + * Disables the system fullscreen button. + * + * @public + * @param {boolean} enabled - Whether the fullscreen button should be enabled + * @return {Promise} + */ + SetFullscreenButtonEnabled(enabled) { + return this[caller](SetFullscreenButtonEnabledMethod, { enabled }); + } + /** + * Sets the maximum size of the window. + * + * @public + * @param {number} width - The desired maximum width of the window + * @param {number} height - The desired maximum height of the window + * @return {Promise} + */ + SetMaxSize(width, height) { + return this[caller](SetMaxSizeMethod, { width, height }); + } + /** + * Sets the minimum size of the window. + * + * @public + * @param {number} width - The desired minimum width of the window + * @param {number} height - The desired minimum height of the window + * @return {Promise} + */ + SetMinSize(width, height) { + return this[caller](SetMinSizeMethod, { width, height }); + } + /** + * Sets the relative position of the window to the screen. + * + * @public + * @param {number} x - The desired horizontal relative position of the window + * @param {number} y - The desired vertical relative position of the window + * @return {Promise} + */ + SetRelativePosition(x, y) { + return this[caller](SetRelativePositionMethod, { x, y }); + } + /** + * Sets whether the window is resizable. + * + * @public + * @param {boolean} resizable - Whether the window should be resizable + * @return {Promise} + */ + SetResizable(resizable2) { + return this[caller](SetResizableMethod, { resizable: resizable2 }); + } + /** + * Sets the size of the window. + * + * @public + * @param {number} width - The desired width of the window + * @param {number} height - The desired height of the window + * @return {Promise} + */ + SetSize(width, height) { + return this[caller](SetSizeMethod, { width, height }); + } + /** + * Sets the title of the window. + * + * @public + * @param {string} title - The desired title of the window + * @return {Promise} + */ + SetTitle(title) { + return this[caller](SetTitleMethod, { title }); + } + /** + * Sets the zoom level of the window. + * + * @public + * @param {number} zoom - The desired zoom level + * @return {Promise} + */ + SetZoom(zoom) { + return this[caller](SetZoomMethod, { zoom }); + } + /** + * Shows the window. + * + * @public + * @return {Promise} + */ + Show() { + return this[caller](ShowMethod); + } + /** + * Returns the size of the window. + * + * @public + * @return {Promise} - The current size of the window + */ + Size() { + return this[caller](SizeMethod); + } + /** + * Toggles the window between fullscreen and normal. + * + * @public + * @return {Promise} + */ + ToggleFullscreen() { + return this[caller](ToggleFullscreenMethod); + } + /** + * Toggles the window between maximised and normal. + * + * @public + * @return {Promise} + */ + ToggleMaximise() { + return this[caller](ToggleMaximiseMethod); + } + /** + * Un-fullscreens the window. + * + * @public + * @return {Promise} + */ + UnFullscreen() { + return this[caller](UnFullscreenMethod); + } + /** + * Un-maximises the window. + * + * @public + * @return {Promise} + */ + UnMaximise() { + return this[caller](UnMaximiseMethod); + } + /** + * Un-minimises the window. + * + * @public + * @return {Promise} + */ + UnMinimise() { + return this[caller](UnMinimiseMethod); + } + /** + * Returns the width of the window. + * + * @public + * @return {Promise} - The current width of the window + */ + Width() { + return this[caller](WidthMethod); + } + /** + * Zooms the window. + * + * @public + * @return {Promise} + */ + Zoom() { + return this[caller](ZoomMethod); + } + /** + * Increases the zoom level of the webview content. + * + * @public + * @return {Promise} + */ + ZoomIn() { + return this[caller](ZoomInMethod); + } + /** + * Decreases the zoom level of the webview content. + * + * @public + * @return {Promise} + */ + ZoomOut() { + return this[caller](ZoomOutMethod); + } + /** + * Resets the zoom level of the webview content. + * + * @public + * @return {Promise} + */ + ZoomReset() { + return this[caller](ZoomResetMethod); + } +}; +var thisWindow = new Window(""); +var window_default = thisWindow; + +// desktop/@wailsio/runtime/src/wml.js +function sendEvent(eventName, data = null) { + Emit(new WailsEvent(eventName, data)); +} +function callWindowMethod(windowName, methodName) { + const targetWindow = window_default.Get(windowName); + const method = targetWindow[methodName]; + if (typeof method !== "function") { + console.error(`Window method '${methodName}' not found`); + return; + } + try { + method.call(targetWindow); + } catch (e) { + console.error(`Error calling window method '${methodName}': `, e); + } +} +function onWMLTriggered(ev) { + const element = ev.currentTarget; + function runEffect(choice = "Yes") { + if (choice !== "Yes") + return; + const eventType = element.getAttribute("wml-event"); + const targetWindow = element.getAttribute("wml-target-window") || ""; + const windowMethod = element.getAttribute("wml-window"); + const url = element.getAttribute("wml-openurl"); + if (eventType !== null) + sendEvent(eventType); + if (windowMethod !== null) + callWindowMethod(targetWindow, windowMethod); + if (url !== null) + void OpenURL(url); + } + const confirm = element.getAttribute("wml-confirm"); + if (confirm) { + Question({ + Title: "Confirm", + Message: confirm, + Detached: false, + Buttons: [ + { Label: "Yes" }, + { Label: "No", IsDefault: true } + ] + }).then(runEffect); + } else { + runEffect(); + } +} +var controller = Symbol(); +var AbortControllerRegistry = class { + constructor() { + this[controller] = new AbortController(); + } + /** + * Returns an options object for addEventListener that ties the listener + * to the AbortSignal from the current AbortController. + * + * @param {HTMLElement} element An HTML element + * @param {string[]} triggers The list of active WML trigger events for the specified elements + * @returns {AddEventListenerOptions} + */ + set(element, triggers) { + return { signal: this[controller].signal }; + } + /** + * Removes all registered event listeners. + * + * @returns {void} + */ + reset() { + this[controller].abort(); + this[controller] = new AbortController(); + } +}; +var triggerMap = Symbol(); +var elementCount = Symbol(); +var WeakMapRegistry = class { + constructor() { + this[triggerMap] = /* @__PURE__ */ new WeakMap(); + this[elementCount] = 0; + } + /** + * Sets the active triggers for the specified element. + * + * @param {HTMLElement} element An HTML element + * @param {string[]} triggers The list of active WML trigger events for the specified element + * @returns {AddEventListenerOptions} + */ + set(element, triggers) { + this[elementCount] += !this[triggerMap].has(element); + this[triggerMap].set(element, triggers); + return {}; + } + /** + * Removes all registered event listeners. + * + * @returns {void} + */ + reset() { + if (this[elementCount] <= 0) + return; + for (const element of document.body.querySelectorAll("*")) { + if (this[elementCount] <= 0) + break; + const triggers = this[triggerMap].get(element); + this[elementCount] -= typeof triggers !== "undefined"; + for (const trigger of triggers || []) + element.removeEventListener(trigger, onWMLTriggered); + } + this[triggerMap] = /* @__PURE__ */ new WeakMap(); + this[elementCount] = 0; + } +}; +var triggerRegistry = canAbortListeners() ? new AbortControllerRegistry() : new WeakMapRegistry(); +function addWMLListeners(element) { + const triggerRegExp = /\S+/g; + const triggerAttr = element.getAttribute("wml-trigger") || "click"; + const triggers = []; + let match; + while ((match = triggerRegExp.exec(triggerAttr)) !== null) + triggers.push(match[0]); + const options = triggerRegistry.set(element, triggers); + for (const trigger of triggers) + element.addEventListener(trigger, onWMLTriggered, options); +} +function Enable() { + whenReady(Reload); +} +function Reload() { + triggerRegistry.reset(); + document.body.querySelectorAll("[wml-event], [wml-window], [wml-openurl]").forEach(addWMLListeners); +} + +// desktop/compiled/main.js +window.wails = src_exports; +Enable(); +if (true) { + debugLog("Wails Runtime Loaded"); +} + +// desktop/@wailsio/runtime/src/system.js +var system_exports = {}; +__export(system_exports, { + Capabilities: () => Capabilities, + Environment: () => Environment, + IsAMD64: () => IsAMD64, + IsARM: () => IsARM, + IsARM64: () => IsARM64, + IsDarkMode: () => IsDarkMode, + IsDebug: () => IsDebug, + IsLinux: () => IsLinux, + IsMac: () => IsMac, + IsWindows: () => IsWindows, + invoke: () => invoke +}); +var call4 = newRuntimeCallerWithID(objectNames.System, ""); +var systemIsDarkMode = 0; +var environment = 1; +function invoke(msg) { + if (window.chrome) { + return window.chrome.webview.postMessage(msg); + } + return window.webkit.messageHandlers.external.postMessage(msg); +} +function IsDarkMode() { + return call4(systemIsDarkMode); +} +function Capabilities() { + let response = fetch("/wails/capabilities"); + return response.json(); +} +function Environment() { + return call4(environment); +} +function IsWindows() { + return window._wails.environment.OS === "windows"; +} +function IsLinux() { + return window._wails.environment.OS === "linux"; +} +function IsMac() { + return window._wails.environment.OS === "darwin"; +} +function IsAMD64() { + return window._wails.environment.Arch === "amd64"; +} +function IsARM() { + return window._wails.environment.Arch === "arm"; +} +function IsARM64() { + return window._wails.environment.Arch === "arm64"; +} +function IsDebug() { + return window._wails.environment.Debug === true; +} + +// desktop/@wailsio/runtime/src/contextmenu.js +window.addEventListener("contextmenu", contextMenuHandler); +var call5 = newRuntimeCallerWithID(objectNames.ContextMenu, ""); +var ContextMenuOpen = 0; +function openContextMenu(id, x, y, data) { + void call5(ContextMenuOpen, { id, x, y, data }); +} +function contextMenuHandler(event) { + let element = event.target; + let customContextMenu = window.getComputedStyle(element).getPropertyValue("--custom-contextmenu"); + customContextMenu = customContextMenu ? customContextMenu.trim() : ""; + if (customContextMenu) { + event.preventDefault(); + let customContextMenuData = window.getComputedStyle(element).getPropertyValue("--custom-contextmenu-data"); + openContextMenu(customContextMenu, event.clientX, event.clientY, customContextMenuData); + return; + } + processDefaultContextMenu(event); +} +function processDefaultContextMenu(event) { + if (IsDebug()) { + return; + } + const element = event.target; + const computedStyle = window.getComputedStyle(element); + const defaultContextMenuAction = computedStyle.getPropertyValue("--default-contextmenu").trim(); + switch (defaultContextMenuAction) { + case "show": + return; + case "hide": + event.preventDefault(); + return; + default: + if (element.isContentEditable) { + return; + } + const selection = window.getSelection(); + const hasSelection = selection.toString().length > 0; + if (hasSelection) { + for (let i = 0; i < selection.rangeCount; i++) { + const range = selection.getRangeAt(i); + const rects = range.getClientRects(); + for (let j = 0; j < rects.length; j++) { + const rect = rects[j]; + if (document.elementFromPoint(rect.left, rect.top) === element) { + return; + } + } + } + } + if (element.tagName === "INPUT" || element.tagName === "TEXTAREA") { + if (hasSelection || !element.readOnly && !element.disabled) { + return; + } + } + event.preventDefault(); + } +} + +// desktop/@wailsio/runtime/src/flags.js +var flags_exports = {}; +__export(flags_exports, { + GetFlag: () => GetFlag +}); +function GetFlag(keyString) { + try { + return window._wails.flags[keyString]; + } catch (e) { + throw new Error("Unable to retrieve flag '" + keyString + "': " + e); + } +} + +// desktop/@wailsio/runtime/src/drag.js +var shouldDrag = false; +var resizable = false; +var resizeEdge = null; +var defaultCursor = "auto"; +window._wails = window._wails || {}; +window._wails.setResizable = function(value) { + resizable = value; +}; +window._wails.endDrag = function() { + document.body.style.cursor = "default"; + shouldDrag = false; +}; +window.addEventListener("mousedown", onMouseDown); +window.addEventListener("mousemove", onMouseMove); +window.addEventListener("mouseup", onMouseUp); +function dragTest(e) { + let val = window.getComputedStyle(e.target).getPropertyValue("--wails-draggable"); + let mousePressed = e.buttons !== void 0 ? e.buttons : e.which; + if (!val || val === "" || val.trim() !== "drag" || mousePressed === 0) { + return false; + } + return e.detail === 1; +} +function onMouseDown(e) { + if (resizeEdge) { + invoke("wails:resize:" + resizeEdge); + e.preventDefault(); + return; + } + if (dragTest(e)) { + if (e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight) { + return; + } + shouldDrag = true; + } else { + shouldDrag = false; + } +} +function onMouseUp() { + shouldDrag = false; +} +function setResize(cursor) { + document.documentElement.style.cursor = cursor || defaultCursor; + resizeEdge = cursor; +} +function onMouseMove(e) { + if (shouldDrag) { + shouldDrag = false; + let mousePressed = e.buttons !== void 0 ? e.buttons : e.which; + if (mousePressed > 0) { + invoke("wails:drag"); + return; + } + } + if (!resizable || !IsWindows()) { + return; + } + if (defaultCursor == null) { + defaultCursor = document.documentElement.style.cursor; + } + let resizeHandleHeight = GetFlag("system.resizeHandleHeight") || 5; + let resizeHandleWidth = GetFlag("system.resizeHandleWidth") || 5; + let cornerExtra = GetFlag("resizeCornerExtra") || 10; + let rightBorder = window.outerWidth - e.clientX < resizeHandleWidth; + let leftBorder = e.clientX < resizeHandleWidth; + let topBorder = e.clientY < resizeHandleHeight; + let bottomBorder = window.outerHeight - e.clientY < resizeHandleHeight; + let rightCorner = window.outerWidth - e.clientX < resizeHandleWidth + cornerExtra; + let leftCorner = e.clientX < resizeHandleWidth + cornerExtra; + let topCorner = e.clientY < resizeHandleHeight + cornerExtra; + let bottomCorner = window.outerHeight - e.clientY < resizeHandleHeight + cornerExtra; + if (!leftBorder && !rightBorder && !topBorder && !bottomBorder && resizeEdge !== void 0) { + setResize(); + } else if (rightCorner && bottomCorner) setResize("se-resize"); + else if (leftCorner && bottomCorner) setResize("sw-resize"); + else if (leftCorner && topCorner) setResize("nw-resize"); + else if (topCorner && rightCorner) setResize("ne-resize"); + else if (leftBorder) setResize("w-resize"); + else if (topBorder) setResize("n-resize"); + else if (bottomBorder) setResize("s-resize"); + else if (rightBorder) setResize("e-resize"); +} + +// desktop/@wailsio/runtime/src/application.js +var application_exports = {}; +__export(application_exports, { + Hide: () => Hide, + Quit: () => Quit, + Show: () => Show +}); +var call6 = newRuntimeCallerWithID(objectNames.Application, ""); +var HideMethod2 = 0; +var ShowMethod2 = 1; +var QuitMethod = 2; +function Hide() { + return call6(HideMethod2); +} +function Show() { + return call6(ShowMethod2); +} +function Quit() { + return call6(QuitMethod); +} + +// desktop/@wailsio/runtime/src/calls.js +var calls_exports = {}; +__export(calls_exports, { + ByID: () => ByID, + ByName: () => ByName, + Call: () => Call, + Plugin: () => Plugin +}); +window._wails = window._wails || {}; +window._wails.callResultHandler = resultHandler; +window._wails.callErrorHandler = errorHandler; +var CallBinding = 0; +var call7 = newRuntimeCallerWithID(objectNames.Call, ""); +var cancelCall = newRuntimeCallerWithID(objectNames.CancelCall, ""); +var callResponses = /* @__PURE__ */ new Map(); +function generateID2() { + let result; + do { + result = nanoid(); + } while (callResponses.has(result)); + return result; +} +function resultHandler(id, data, isJSON) { + const promiseHandler = getAndDeleteResponse(id); + if (promiseHandler) { + promiseHandler.resolve(isJSON ? JSON.parse(data) : data); + } +} +function errorHandler(id, message) { + const promiseHandler = getAndDeleteResponse(id); + if (promiseHandler) { + promiseHandler.reject(message); + } +} +function getAndDeleteResponse(id) { + const response = callResponses.get(id); + callResponses.delete(id); + return response; +} +function callBinding(type, options = {}) { + const id = generateID2(); + const doCancel = () => { + return cancelCall(type, { "call-id": id }); + }; + let queuedCancel = false, callRunning = false; + let p = new Promise((resolve, reject) => { + options["call-id"] = id; + callResponses.set(id, { resolve, reject }); + call7(type, options).then((_) => { + callRunning = true; + if (queuedCancel) { + return doCancel(); + } + }).catch((error) => { + reject(error); + callResponses.delete(id); + }); + }); + p.cancel = () => { + if (callRunning) { + return doCancel(); + } else { + queuedCancel = true; + } + }; + return p; +} +function Call(options) { + return callBinding(CallBinding, options); +} +function ByName(methodName, ...args) { + return callBinding(CallBinding, { + methodName, + args + }); +} +function ByID(methodID, ...args) { + return callBinding(CallBinding, { + methodID, + args + }); +} +function Plugin(pluginName, methodName, ...args) { + return callBinding(CallBinding, { + packageName: "wails-plugins", + structName: pluginName, + methodName, + args + }); +} + +// desktop/@wailsio/runtime/src/clipboard.js +var clipboard_exports = {}; +__export(clipboard_exports, { + SetText: () => SetText, + Text: () => Text +}); +var call8 = newRuntimeCallerWithID(objectNames.Clipboard, ""); +var ClipboardSetText = 0; +var ClipboardText = 1; +function SetText(text) { + return call8(ClipboardSetText, { text }); +} +function Text() { + return call8(ClipboardText); +} + +// desktop/@wailsio/runtime/src/create.js +var create_exports = {}; +__export(create_exports, { + Any: () => Any, + Array: () => Array, + ByteSlice: () => ByteSlice, + Map: () => Map2, + Nullable: () => Nullable, + Struct: () => Struct +}); +function Any(source) { + return ( + /** @type {T} */ + source + ); +} +function ByteSlice(source) { + return ( + /** @type {any} */ + source == null ? "" : source + ); +} +function Array(element) { + if (element === Any) { + return (source) => source === null ? [] : source; + } + return (source) => { + if (source === null) { + return []; + } + for (let i = 0; i < source.length; i++) { + source[i] = element(source[i]); + } + return source; + }; +} +function Map2(key, value) { + if (value === Any) { + return (source) => source === null ? {} : source; + } + return (source) => { + if (source === null) { + return {}; + } + for (const key2 in source) { + source[key2] = value(source[key2]); + } + return source; + }; +} +function Nullable(element) { + if (element === Any) { + return Any; + } + return (source) => source === null ? null : element(source); +} +function Struct(createField) { + let allAny = true; + for (const name in createField) { + if (createField[name] !== Any) { + allAny = false; + break; + } + } + if (allAny) { + return Any; + } + return (source) => { + for (const name in createField) { + if (name in source) { + source[name] = createField[name](source[name]); + } + } + return source; + }; +} + +// desktop/@wailsio/runtime/src/screens.js +var screens_exports = {}; +__export(screens_exports, { + GetAll: () => GetAll, + GetCurrent: () => GetCurrent, + GetPrimary: () => GetPrimary +}); +var call9 = newRuntimeCallerWithID(objectNames.Screens, ""); +var getAll = 0; +var getPrimary = 1; +var getCurrent = 2; +function GetAll() { + return call9(getAll); +} +function GetPrimary() { + return call9(getPrimary); +} +function GetCurrent() { + return call9(getCurrent); +} + +// desktop/@wailsio/runtime/src/index.js +window._wails = window._wails || {}; +window._wails.invoke = invoke; +invoke("wails:runtime:ready"); +export { + application_exports as Application, + browser_exports as Browser, + calls_exports as Call, + clipboard_exports as Clipboard, + create_exports as Create, + dialogs_exports as Dialogs, + events_exports as Events, + flags_exports as Flags, + screens_exports as Screens, + system_exports as System, + wml_exports as WML, + window_default as Window +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2luZGV4LmpzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy93bWwuanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXIuanMiLCAiLi4vLi4vcnVudGltZS9ub2RlX21vZHVsZXMvbmFub2lkL25vbi1zZWN1cmUvaW5kZXguanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3J1bnRpbWUuanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RpYWxvZ3MuanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2V2ZW50cy5qcyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZXZlbnRfdHlwZXMuanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3V0aWxzLmpzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy93aW5kb3cuanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL2NvbXBpbGVkL21haW4uanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3N5c3RlbS5qcyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvY29udGV4dG1lbnUuanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2ZsYWdzLmpzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9kcmFnLmpzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9hcHBsaWNhdGlvbi5qcyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvY2FsbHMuanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZC5qcyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvY3JlYXRlLmpzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9zY3JlZW5zLmpzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLy8gU2V0dXBcbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xuXG5pbXBvcnQgXCIuL2NvbnRleHRtZW51XCI7XG5pbXBvcnQgXCIuL2RyYWdcIjtcblxuLy8gUmUtZXhwb3J0IHB1YmxpYyBBUElcbmltcG9ydCAqIGFzIEFwcGxpY2F0aW9uIGZyb20gXCIuL2FwcGxpY2F0aW9uXCI7XG5pbXBvcnQgKiBhcyBCcm93c2VyIGZyb20gXCIuL2Jyb3dzZXJcIjtcbmltcG9ydCAqIGFzIENhbGwgZnJvbSBcIi4vY2FsbHNcIjtcbmltcG9ydCAqIGFzIENsaXBib2FyZCBmcm9tIFwiLi9jbGlwYm9hcmRcIjtcbmltcG9ydCAqIGFzIENyZWF0ZSBmcm9tIFwiLi9jcmVhdGVcIjtcbmltcG9ydCAqIGFzIERpYWxvZ3MgZnJvbSBcIi4vZGlhbG9nc1wiO1xuaW1wb3J0ICogYXMgRXZlbnRzIGZyb20gXCIuL2V2ZW50c1wiO1xuaW1wb3J0ICogYXMgRmxhZ3MgZnJvbSBcIi4vZmxhZ3NcIjtcbmltcG9ydCAqIGFzIFNjcmVlbnMgZnJvbSBcIi4vc2NyZWVuc1wiO1xuaW1wb3J0ICogYXMgU3lzdGVtIGZyb20gXCIuL3N5c3RlbVwiO1xuaW1wb3J0IFdpbmRvdyBmcm9tIFwiLi93aW5kb3dcIjtcbmltcG9ydCAqIGFzIFdNTCBmcm9tIFwiLi93bWxcIjtcblxuZXhwb3J0IHtcbiAgICBBcHBsaWNhdGlvbixcbiAgICBCcm93c2VyLFxuICAgIENhbGwsXG4gICAgQ2xpcGJvYXJkLFxuICAgIENyZWF0ZSxcbiAgICBEaWFsb2dzLFxuICAgIEV2ZW50cyxcbiAgICBGbGFncyxcbiAgICBTY3JlZW5zLFxuICAgIFN5c3RlbSxcbiAgICBXaW5kb3csXG4gICAgV01MXG59O1xuXG4vLyBOb3RpZnkgYmFja2VuZFxud2luZG93Ll93YWlscy5pbnZva2UgPSBTeXN0ZW0uaW52b2tlO1xuU3lzdGVtLmludm9rZShcIndhaWxzOnJ1bnRpbWU6cmVhZHlcIik7XG4iLCAiLypcbiBfICAgICBfXyAgICAgXyBfX1xufCB8ICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7T3BlblVSTH0gZnJvbSBcIi4vYnJvd3NlclwiO1xuaW1wb3J0IHtRdWVzdGlvbn0gZnJvbSBcIi4vZGlhbG9nc1wiO1xuaW1wb3J0IHtFbWl0LCBXYWlsc0V2ZW50fSBmcm9tIFwiLi9ldmVudHNcIjtcbmltcG9ydCB7Y2FuQWJvcnRMaXN0ZW5lcnMsIHdoZW5SZWFkeX0gZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCBXaW5kb3cgZnJvbSBcIi4vd2luZG93XCI7XG5cbi8qKlxuICogU2VuZHMgYW4gZXZlbnQgd2l0aCB0aGUgZ2l2ZW4gbmFtZSBhbmQgb3B0aW9uYWwgZGF0YS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHNlbmQuXG4gKiBAcGFyYW0ge2FueX0gW2RhdGE9bnVsbF0gLSBPcHRpb25hbCBkYXRhIHRvIHNlbmQgYWxvbmcgd2l0aCB0aGUgZXZlbnQuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gc2VuZEV2ZW50KGV2ZW50TmFtZSwgZGF0YT1udWxsKSB7XG4gICAgRW1pdChuZXcgV2FpbHNFdmVudChldmVudE5hbWUsIGRhdGEpKTtcbn1cblxuLyoqXG4gKiBDYWxscyBhIG1ldGhvZCBvbiBhIHNwZWNpZmllZCB3aW5kb3cuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgdG8gY2FsbCB0aGUgbWV0aG9kIG9uLlxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbWV0aG9kIHRvIGNhbGwuXG4gKi9cbmZ1bmN0aW9uIGNhbGxXaW5kb3dNZXRob2Qod2luZG93TmFtZSwgbWV0aG9kTmFtZSkge1xuICAgIGNvbnN0IHRhcmdldFdpbmRvdyA9IFdpbmRvdy5HZXQod2luZG93TmFtZSk7XG4gICAgY29uc3QgbWV0aG9kID0gdGFyZ2V0V2luZG93W21ldGhvZE5hbWVdO1xuXG4gICAgaWYgKHR5cGVvZiBtZXRob2QgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBXaW5kb3cgbWV0aG9kICcke21ldGhvZE5hbWV9JyBub3QgZm91bmRgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICAgIG1ldGhvZC5jYWxsKHRhcmdldFdpbmRvdyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjYWxsaW5nIHdpbmRvdyBtZXRob2QgJyR7bWV0aG9kTmFtZX0nOiBgLCBlKTtcbiAgICB9XG59XG5cbi8qKlxuICogUmVzcG9uZHMgdG8gYSB0cmlnZ2VyaW5nIGV2ZW50IGJ5IHJ1bm5pbmcgYXBwcm9wcmlhdGUgV01MIGFjdGlvbnMgZm9yIHRoZSBjdXJyZW50IHRhcmdldFxuICpcbiAqIEBwYXJhbSB7RXZlbnR9IGV2XG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5mdW5jdGlvbiBvbldNTFRyaWdnZXJlZChldikge1xuICAgIGNvbnN0IGVsZW1lbnQgPSBldi5jdXJyZW50VGFyZ2V0O1xuXG4gICAgZnVuY3Rpb24gcnVuRWZmZWN0KGNob2ljZSA9IFwiWWVzXCIpIHtcbiAgICAgICAgaWYgKGNob2ljZSAhPT0gXCJZZXNcIilcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCBldmVudFR5cGUgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLWV2ZW50Jyk7XG4gICAgICAgIGNvbnN0IHRhcmdldFdpbmRvdyA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdGFyZ2V0LXdpbmRvdycpIHx8IFwiXCI7XG4gICAgICAgIGNvbnN0IHdpbmRvd01ldGhvZCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtd2luZG93Jyk7XG4gICAgICAgIGNvbnN0IHVybCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtb3BlbnVybCcpO1xuXG4gICAgICAgIGlmIChldmVudFR5cGUgIT09IG51bGwpXG4gICAgICAgICAgICBzZW5kRXZlbnQoZXZlbnRUeXBlKTtcbiAgICAgICAgaWYgKHdpbmRvd01ldGhvZCAhPT0gbnVsbClcbiAgICAgICAgICAgIGNhbGxXaW5kb3dNZXRob2QodGFyZ2V0V2luZG93LCB3aW5kb3dNZXRob2QpO1xuICAgICAgICBpZiAodXJsICE9PSBudWxsKVxuICAgICAgICAgICAgdm9pZCBPcGVuVVJMKHVybCk7XG4gICAgfVxuXG4gICAgY29uc3QgY29uZmlybSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtY29uZmlybScpO1xuXG4gICAgaWYgKGNvbmZpcm0pIHtcbiAgICAgICAgUXVlc3Rpb24oe1xuICAgICAgICAgICAgVGl0bGU6IFwiQ29uZmlybVwiLFxuICAgICAgICAgICAgTWVzc2FnZTogY29uZmlybSxcbiAgICAgICAgICAgIERldGFjaGVkOiBmYWxzZSxcbiAgICAgICAgICAgIEJ1dHRvbnM6IFtcbiAgICAgICAgICAgICAgICB7IExhYmVsOiBcIlllc1wiIH0sXG4gICAgICAgICAgICAgICAgeyBMYWJlbDogXCJOb1wiLCBJc0RlZmF1bHQ6IHRydWUgfVxuICAgICAgICAgICAgXVxuICAgICAgICB9KS50aGVuKHJ1bkVmZmVjdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcnVuRWZmZWN0KCk7XG4gICAgfVxufVxuXG4vKipcbiAqIEB0eXBlIHtzeW1ib2x9XG4gKi9cbmNvbnN0IGNvbnRyb2xsZXIgPSBTeW1ib2woKTtcblxuLyoqXG4gKiBBYm9ydENvbnRyb2xsZXJSZWdpc3RyeSBkb2VzIG5vdCBhY3R1YWxseSByZW1lbWJlciBhY3RpdmUgZXZlbnQgbGlzdGVuZXJzOiBpbnN0ZWFkXG4gKiBpdCB0aWVzIHRoZW0gdG8gYW4gQWJvcnRTaWduYWwgYW5kIHVzZXMgYW4gQWJvcnRDb250cm9sbGVyIHRvIHJlbW92ZSB0aGVtIGFsbCBhdCBvbmNlLlxuICovXG5jbGFzcyBBYm9ydENvbnRyb2xsZXJSZWdpc3RyeSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTdG9yZXMgdGhlIEFib3J0Q29udHJvbGxlciB0aGF0IGNhbiBiZSB1c2VkIHRvIHJlbW92ZSBhbGwgY3VycmVudGx5IGFjdGl2ZSBsaXN0ZW5lcnMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqIEBuYW1lIHtAbGluayBjb250cm9sbGVyfVxuICAgICAgICAgKiBAbWVtYmVyIHtBYm9ydENvbnRyb2xsZXJ9XG4gICAgICAgICAqL1xuICAgICAgICB0aGlzW2NvbnRyb2xsZXJdID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYW4gb3B0aW9ucyBvYmplY3QgZm9yIGFkZEV2ZW50TGlzdGVuZXIgdGhhdCB0aWVzIHRoZSBsaXN0ZW5lclxuICAgICAqIHRvIHRoZSBBYm9ydFNpZ25hbCBmcm9tIHRoZSBjdXJyZW50IEFib3J0Q29udHJvbGxlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnQgQW4gSFRNTCBlbGVtZW50XG4gICAgICogQHBhcmFtIHtzdHJpbmdbXX0gdHJpZ2dlcnMgVGhlIGxpc3Qgb2YgYWN0aXZlIFdNTCB0cmlnZ2VyIGV2ZW50cyBmb3IgdGhlIHNwZWNpZmllZCBlbGVtZW50c1xuICAgICAqIEByZXR1cm5zIHtBZGRFdmVudExpc3RlbmVyT3B0aW9uc31cbiAgICAgKi9cbiAgICBzZXQoZWxlbWVudCwgdHJpZ2dlcnMpIHtcbiAgICAgICAgcmV0dXJuIHsgc2lnbmFsOiB0aGlzW2NvbnRyb2xsZXJdLnNpZ25hbCB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIHJlZ2lzdGVyZWQgZXZlbnQgbGlzdGVuZXJzLlxuICAgICAqXG4gICAgICogQHJldHVybnMge3ZvaWR9XG4gICAgICovXG4gICAgcmVzZXQoKSB7XG4gICAgICAgIHRoaXNbY29udHJvbGxlcl0uYWJvcnQoKTtcbiAgICAgICAgdGhpc1tjb250cm9sbGVyXSA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICB9XG59XG5cbi8qKlxuICogQHR5cGUge3N5bWJvbH1cbiAqL1xuY29uc3QgdHJpZ2dlck1hcCA9IFN5bWJvbCgpO1xuXG4vKipcbiAqIEB0eXBlIHtzeW1ib2x9XG4gKi9cbmNvbnN0IGVsZW1lbnRDb3VudCA9IFN5bWJvbCgpO1xuXG4vKipcbiAqIFdlYWtNYXBSZWdpc3RyeSBtYXBzIGFjdGl2ZSB0cmlnZ2VyIGV2ZW50cyB0byBlYWNoIERPTSBlbGVtZW50IHRocm91Z2ggYSBXZWFrTWFwLlxuICogVGhpcyBlbnN1cmVzIHRoYXQgdGhlIG1hcHBpbmcgcmVtYWlucyBwcml2YXRlIHRvIHRoaXMgbW9kdWxlLCB3aGlsZSBzdGlsbCBhbGxvd2luZyBnYXJiYWdlXG4gKiBjb2xsZWN0aW9uIG9mIHRoZSBpbnZvbHZlZCBlbGVtZW50cy5cbiAqL1xuY2xhc3MgV2Vha01hcFJlZ2lzdHJ5IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFN0b3JlcyB0aGUgY3VycmVudCBlbGVtZW50LXRvLXRyaWdnZXIgbWFwcGluZy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICogQG5hbWUge0BsaW5rIHRyaWdnZXJNYXB9XG4gICAgICAgICAqIEBtZW1iZXIge1dlYWtNYXA8SFRNTEVsZW1lbnQsIHN0cmluZ1tdPn1cbiAgICAgICAgICovXG4gICAgICAgIHRoaXNbdHJpZ2dlck1hcF0gPSBuZXcgV2Vha01hcCgpO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb3VudHMgdGhlIG51bWJlciBvZiBlbGVtZW50cyB3aXRoIGFjdGl2ZSBXTUwgdHJpZ2dlcnMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqIEBuYW1lIHtAbGluayBlbGVtZW50Q291bnR9XG4gICAgICAgICAqIEBtZW1iZXIge251bWJlcn1cbiAgICAgICAgICovXG4gICAgICAgIHRoaXNbZWxlbWVudENvdW50XSA9IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYWN0aXZlIHRyaWdnZXJzIGZvciB0aGUgc3BlY2lmaWVkIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50IEFuIEhUTUwgZWxlbWVudFxuICAgICAqIEBwYXJhbSB7c3RyaW5nW119IHRyaWdnZXJzIFRoZSBsaXN0IG9mIGFjdGl2ZSBXTUwgdHJpZ2dlciBldmVudHMgZm9yIHRoZSBzcGVjaWZpZWQgZWxlbWVudFxuICAgICAqIEByZXR1cm5zIHtBZGRFdmVudExpc3RlbmVyT3B0aW9uc31cbiAgICAgKi9cbiAgICBzZXQoZWxlbWVudCwgdHJpZ2dlcnMpIHtcbiAgICAgICAgdGhpc1tlbGVtZW50Q291bnRdICs9ICF0aGlzW3RyaWdnZXJNYXBdLmhhcyhlbGVtZW50KTtcbiAgICAgICAgdGhpc1t0cmlnZ2VyTWFwXS5zZXQoZWxlbWVudCwgdHJpZ2dlcnMpO1xuICAgICAgICByZXR1cm4ge307XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwgcmVnaXN0ZXJlZCBldmVudCBsaXN0ZW5lcnMuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICAgKi9cbiAgICByZXNldCgpIHtcbiAgICAgICAgaWYgKHRoaXNbZWxlbWVudENvdW50XSA8PSAwKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBkb2N1bWVudC5ib2R5LnF1ZXJ5U2VsZWN0b3JBbGwoJyonKSkge1xuICAgICAgICAgICAgaWYgKHRoaXNbZWxlbWVudENvdW50XSA8PSAwKVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjb25zdCB0cmlnZ2VycyA9IHRoaXNbdHJpZ2dlck1hcF0uZ2V0KGVsZW1lbnQpO1xuICAgICAgICAgICAgdGhpc1tlbGVtZW50Q291bnRdIC09ICh0eXBlb2YgdHJpZ2dlcnMgIT09IFwidW5kZWZpbmVkXCIpO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IHRyaWdnZXIgb2YgdHJpZ2dlcnMgfHwgW10pXG4gICAgICAgICAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHRyaWdnZXIsIG9uV01MVHJpZ2dlcmVkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXNbdHJpZ2dlck1hcF0gPSBuZXcgV2Vha01hcCgpO1xuICAgICAgICB0aGlzW2VsZW1lbnRDb3VudF0gPSAwO1xuICAgIH1cbn1cblxuY29uc3QgdHJpZ2dlclJlZ2lzdHJ5ID0gY2FuQWJvcnRMaXN0ZW5lcnMoKSA/IG5ldyBBYm9ydENvbnRyb2xsZXJSZWdpc3RyeSgpIDogbmV3IFdlYWtNYXBSZWdpc3RyeSgpO1xuXG4vKipcbiAqIEFkZHMgZXZlbnQgbGlzdGVuZXJzIHRvIHRoZSBzcGVjaWZpZWQgZWxlbWVudC5cbiAqXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5mdW5jdGlvbiBhZGRXTUxMaXN0ZW5lcnMoZWxlbWVudCkge1xuICAgIGNvbnN0IHRyaWdnZXJSZWdFeHAgPSAvXFxTKy9nO1xuICAgIGNvbnN0IHRyaWdnZXJBdHRyID0gKGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdHJpZ2dlcicpIHx8IFwiY2xpY2tcIik7XG4gICAgY29uc3QgdHJpZ2dlcnMgPSBbXTtcblxuICAgIGxldCBtYXRjaDtcbiAgICB3aGlsZSAoKG1hdGNoID0gdHJpZ2dlclJlZ0V4cC5leGVjKHRyaWdnZXJBdHRyKSkgIT09IG51bGwpXG4gICAgICAgIHRyaWdnZXJzLnB1c2gobWF0Y2hbMF0pO1xuXG4gICAgY29uc3Qgb3B0aW9ucyA9IHRyaWdnZXJSZWdpc3RyeS5zZXQoZWxlbWVudCwgdHJpZ2dlcnMpO1xuICAgIGZvciAoY29uc3QgdHJpZ2dlciBvZiB0cmlnZ2VycylcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHRyaWdnZXIsIG9uV01MVHJpZ2dlcmVkLCBvcHRpb25zKTtcbn1cblxuLyoqXG4gKiBTY2hlZHVsZXMgYW4gYXV0b21hdGljIHJlbG9hZCBvZiBXTUwgdG8gYmUgcGVyZm9ybWVkIGFzIHNvb24gYXMgdGhlIGRvY3VtZW50IGlzIGZ1bGx5IGxvYWRlZC5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gRW5hYmxlKCkge1xuICAgIHdoZW5SZWFkeShSZWxvYWQpO1xufVxuXG4vKipcbiAqIFJlbG9hZHMgdGhlIFdNTCBwYWdlIGJ5IGFkZGluZyBuZWNlc3NhcnkgZXZlbnQgbGlzdGVuZXJzIGFuZCBicm93c2VyIGxpc3RlbmVycy5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVsb2FkKCkge1xuICAgIHRyaWdnZXJSZWdpc3RyeS5yZXNldCgpO1xuICAgIGRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3RvckFsbCgnW3dtbC1ldmVudF0sIFt3bWwtd2luZG93XSwgW3dtbC1vcGVudXJsXScpLmZvckVhY2goYWRkV01MTGlzdGVuZXJzKTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5Ccm93c2VyLCAnJyk7XG5jb25zdCBCcm93c2VyT3BlblVSTCA9IDA7XG5cbi8qKlxuICogT3BlbiBhIGJyb3dzZXIgd2luZG93IHRvIHRoZSBnaXZlbiBVUkxcbiAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgLSBUaGUgVVJMIHRvIG9wZW5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBPcGVuVVJMKHVybCkge1xuICAgIHJldHVybiBjYWxsKEJyb3dzZXJPcGVuVVJMLCB7dXJsfSk7XG59XG4iLCAibGV0IHVybEFscGhhYmV0ID1cbiAgJ3VzZWFuZG9tLTI2VDE5ODM0MFBYNzVweEpBQ0tWRVJZTUlOREJVU0hXT0xGX0dRWmJmZ2hqa2xxdnd5enJpY3QnXG5leHBvcnQgbGV0IGN1c3RvbUFscGhhYmV0ID0gKGFscGhhYmV0LCBkZWZhdWx0U2l6ZSA9IDIxKSA9PiB7XG4gIHJldHVybiAoc2l6ZSA9IGRlZmF1bHRTaXplKSA9PiB7XG4gICAgbGV0IGlkID0gJydcbiAgICBsZXQgaSA9IHNpemVcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICBpZCArPSBhbHBoYWJldFsoTWF0aC5yYW5kb20oKSAqIGFscGhhYmV0Lmxlbmd0aCkgfCAwXVxuICAgIH1cbiAgICByZXR1cm4gaWRcbiAgfVxufVxuZXhwb3J0IGxldCBuYW5vaWQgPSAoc2l6ZSA9IDIxKSA9PiB7XG4gIGxldCBpZCA9ICcnXG4gIGxldCBpID0gc2l6ZVxuICB3aGlsZSAoaS0tKSB7XG4gICAgaWQgKz0gdXJsQWxwaGFiZXRbKE1hdGgucmFuZG9tKCkgKiA2NCkgfCAwXVxuICB9XG4gIHJldHVybiBpZFxufVxuIiwgIi8qXG4gXyAgICAgX18gICAgIF8gX19cbnwgfCAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQgeyBuYW5vaWQgfSBmcm9tICduYW5vaWQvbm9uLXNlY3VyZSc7XG5cbmNvbnN0IHJ1bnRpbWVVUkwgPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luICsgXCIvd2FpbHMvcnVudGltZVwiO1xuXG4vLyBPYmplY3QgTmFtZXNcbmV4cG9ydCBjb25zdCBvYmplY3ROYW1lcyA9IHtcbiAgICBDYWxsOiAwLFxuICAgIENsaXBib2FyZDogMSxcbiAgICBBcHBsaWNhdGlvbjogMixcbiAgICBFdmVudHM6IDMsXG4gICAgQ29udGV4dE1lbnU6IDQsXG4gICAgRGlhbG9nOiA1LFxuICAgIFdpbmRvdzogNixcbiAgICBTY3JlZW5zOiA3LFxuICAgIFN5c3RlbTogOCxcbiAgICBCcm93c2VyOiA5LFxuICAgIENhbmNlbENhbGw6IDEwLFxufVxuZXhwb3J0IGxldCBjbGllbnRJZCA9IG5hbm9pZCgpO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBydW50aW1lIGNhbGxlciBmdW5jdGlvbiB0aGF0IGludm9rZXMgYSBzcGVjaWZpZWQgbWV0aG9kIG9uIGEgZ2l2ZW4gb2JqZWN0IHdpdGhpbiBhIHNwZWNpZmllZCB3aW5kb3cgY29udGV4dC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IC0gVGhlIG9iamVjdCBvbiB3aGljaCB0aGUgbWV0aG9kIGlzIHRvIGJlIGludm9rZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgY29udGV4dCBpbiB3aGljaCB0aGUgbWV0aG9kIHNob3VsZCBiZSBjYWxsZWQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IEEgcnVudGltZSBjYWxsZXIgZnVuY3Rpb24gdGhhdCB0YWtlcyB0aGUgbWV0aG9kIG5hbWUgYW5kIG9wdGlvbmFsbHkgYXJndW1lbnRzIGFuZCBpbnZva2VzIHRoZSBtZXRob2Qgd2l0aGluIHRoZSBzcGVjaWZpZWQgd2luZG93IGNvbnRleHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdCwgd2luZG93TmFtZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAobWV0aG9kLCBhcmdzPW51bGwpIHtcbiAgICAgICAgcmV0dXJuIHJ1bnRpbWVDYWxsKG9iamVjdCArIFwiLlwiICsgbWV0aG9kLCB3aW5kb3dOYW1lLCBhcmdzKTtcbiAgICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcnVudGltZSBjYWxsZXIgd2l0aCBzcGVjaWZpZWQgSUQuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3QgdG8gaW52b2tlIHRoZSBtZXRob2Qgb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cuXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gLSBUaGUgbmV3IHJ1bnRpbWUgY2FsbGVyIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3QsIHdpbmRvd05hbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKG1ldGhvZCwgYXJncz1udWxsKSB7XG4gICAgICAgIHJldHVybiBydW50aW1lQ2FsbFdpdGhJRChvYmplY3QsIG1ldGhvZCwgd2luZG93TmFtZSwgYXJncyk7XG4gICAgfTtcbn1cblxuXG5mdW5jdGlvbiBydW50aW1lQ2FsbChtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcbiAgICBpZiggbWV0aG9kICkge1xuICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcIm1ldGhvZFwiLCBtZXRob2QpO1xuICAgIH1cbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICB9O1xuICAgIGlmICh3aW5kb3dOYW1lKSB7XG4gICAgICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuICAgIGlmIChhcmdzKSB7XG4gICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiYXJnc1wiLCBKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgfVxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGZldGNoKHVybCwgZmV0Y2hPcHRpb25zKVxuICAgICAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayBjb250ZW50IHR5cGVcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpICYmIHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpLmluZGV4T2YoXCJhcHBsaWNhdGlvbi9qc29uXCIpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS50ZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKHJlc3BvbnNlLnN0YXR1c1RleHQpKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbihkYXRhID0+IHJlc29sdmUoZGF0YSkpXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHJ1bnRpbWVDYWxsV2l0aElEKG9iamVjdElELCBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcbiAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcIm9iamVjdFwiLCBvYmplY3RJRCk7XG4gICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJtZXRob2RcIiwgbWV0aG9kKTtcbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICB9O1xuICAgIGlmICh3aW5kb3dOYW1lKSB7XG4gICAgICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuICAgIGlmIChhcmdzKSB7XG4gICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiYXJnc1wiLCBKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgfVxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBmZXRjaCh1cmwsIGZldGNoT3B0aW9ucylcbiAgICAgICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hlY2sgY29udGVudCB0eXBlXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKSAmJiByZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKS5pbmRleE9mKFwiYXBwbGljYXRpb24vanNvblwiKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcihyZXNwb25zZS5zdGF0dXNUZXh0KSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oZGF0YSA9PiByZXNvbHZlKGRhdGEpKVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgIH0pO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3BlbkZpbGVEaWFsb2dPcHRpb25zXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DaG9vc2VEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNob3Nlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZUZpbGVzXSAtIEluZGljYXRlcyBpZiBmaWxlcyBjYW4gYmUgY2hvc2VuLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ3JlYXRlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjcmVhdGVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbU2hvd0hpZGRlbkZpbGVzXSAtIEluZGljYXRlcyBpZiBoaWRkZW4gZmlsZXMgc2hvdWxkIGJlIHNob3duLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbUmVzb2x2ZXNBbGlhc2VzXSAtIEluZGljYXRlcyBpZiBhbGlhc2VzIHNob3VsZCBiZSByZXNvbHZlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c011bHRpcGxlU2VsZWN0aW9uXSAtIEluZGljYXRlcyBpZiBtdWx0aXBsZSBzZWxlY3Rpb24gaXMgYWxsb3dlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0hpZGVFeHRlbnNpb25dIC0gSW5kaWNhdGVzIGlmIHRoZSBleHRlbnNpb24gc2hvdWxkIGJlIGhpZGRlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhblNlbGVjdEhpZGRlbkV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGV4dGVuc2lvbnMgY2FuIGJlIHNlbGVjdGVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbVHJlYXRzRmlsZVBhY2thZ2VzQXNEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZmlsZSBwYWNrYWdlcyBzaG91bGQgYmUgdHJlYXRlZCBhcyBkaXJlY3Rvcmllcy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c090aGVyRmlsZXR5cGVzXSAtIEluZGljYXRlcyBpZiBvdGhlciBmaWxlIHR5cGVzIGFyZSBhbGxvd2VkLlxuICogQHByb3BlcnR5IHtGaWxlRmlsdGVyW119IFtGaWx0ZXJzXSAtIEFycmF5IG9mIGZpbGUgZmlsdGVycy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGl0bGUgb2YgdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbTWVzc2FnZV0gLSBNZXNzYWdlIHRvIHNob3cgaW4gdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbQnV0dG9uVGV4dF0gLSBUZXh0IHRvIGRpc3BsYXkgb24gdGhlIGJ1dHRvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRGlyZWN0b3J5XSAtIERpcmVjdG9yeSB0byBvcGVuIGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtEZXRhY2hlZF0gLSBJbmRpY2F0ZXMgaWYgdGhlIGRpYWxvZyBzaG91bGQgYXBwZWFyIGRldGFjaGVkIGZyb20gdGhlIG1haW4gd2luZG93LlxuICovXG5cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBTYXZlRmlsZURpYWxvZ09wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRmlsZW5hbWVdIC0gRGVmYXVsdCBmaWxlbmFtZSB0byB1c2UgaW4gdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZURpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBkaXJlY3RvcmllcyBjYW4gYmUgY2hvc2VuLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ2hvb3NlRmlsZXNdIC0gSW5kaWNhdGVzIGlmIGZpbGVzIGNhbiBiZSBjaG9zZW4uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DcmVhdGVEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNyZWF0ZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtTaG93SGlkZGVuRmlsZXNdIC0gSW5kaWNhdGVzIGlmIGhpZGRlbiBmaWxlcyBzaG91bGQgYmUgc2hvd24uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtSZXNvbHZlc0FsaWFzZXNdIC0gSW5kaWNhdGVzIGlmIGFsaWFzZXMgc2hvdWxkIGJlIHJlc29sdmVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQWxsb3dzTXVsdGlwbGVTZWxlY3Rpb25dIC0gSW5kaWNhdGVzIGlmIG11bHRpcGxlIHNlbGVjdGlvbiBpcyBhbGxvd2VkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbSGlkZUV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgdGhlIGV4dGVuc2lvbiBzaG91bGQgYmUgaGlkZGVuLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuU2VsZWN0SGlkZGVuRXh0ZW5zaW9uXSAtIEluZGljYXRlcyBpZiBoaWRkZW4gZXh0ZW5zaW9ucyBjYW4gYmUgc2VsZWN0ZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtUcmVhdHNGaWxlUGFja2FnZXNBc0RpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBmaWxlIHBhY2thZ2VzIHNob3VsZCBiZSB0cmVhdGVkIGFzIGRpcmVjdG9yaWVzLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQWxsb3dzT3RoZXJGaWxldHlwZXNdIC0gSW5kaWNhdGVzIGlmIG90aGVyIGZpbGUgdHlwZXMgYXJlIGFsbG93ZWQuXG4gKiBAcHJvcGVydHkge0ZpbGVGaWx0ZXJbXX0gW0ZpbHRlcnNdIC0gQXJyYXkgb2YgZmlsZSBmaWx0ZXJzLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtUaXRsZV0gLSBUaXRsZSBvZiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtNZXNzYWdlXSAtIE1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtCdXR0b25UZXh0XSAtIFRleHQgdG8gZGlzcGxheSBvbiB0aGUgYnV0dG9uLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtEaXJlY3RvcnldIC0gRGlyZWN0b3J5IHRvIG9wZW4gaW4gdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0RldGFjaGVkXSAtIEluZGljYXRlcyBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cuXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBNZXNzYWdlRGlhbG9nT3B0aW9uc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IFtUaXRsZV0gLSBUaGUgdGl0bGUgb2YgdGhlIGRpYWxvZyB3aW5kb3cuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW01lc3NhZ2VdIC0gVGhlIG1haW4gbWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge0J1dHRvbltdfSBbQnV0dG9uc10gLSBBcnJheSBvZiBidXR0b24gb3B0aW9ucyB0byBzaG93IGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtEZXRhY2hlZF0gLSBUcnVlIGlmIHRoZSBkaWFsb2cgc2hvdWxkIGFwcGVhciBkZXRhY2hlZCBmcm9tIHRoZSBtYWluIHdpbmRvdyAoaWYgYXBwbGljYWJsZSkuXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBCdXR0b25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbTGFiZWxdIC0gVGV4dCB0aGF0IGFwcGVhcnMgd2l0aGluIHRoZSBidXR0b24uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtJc0NhbmNlbF0gLSBUcnVlIGlmIHRoZSBidXR0b24gc2hvdWxkIGNhbmNlbCBhbiBvcGVyYXRpb24gd2hlbiBjbGlja2VkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbSXNEZWZhdWx0XSAtIFRydWUgaWYgdGhlIGJ1dHRvbiBzaG91bGQgYmUgdGhlIGRlZmF1bHQgYWN0aW9uIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyBlbnRlci5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEZpbGVGaWx0ZXJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRGlzcGxheU5hbWVdIC0gRGlzcGxheSBuYW1lIGZvciB0aGUgZmlsdGVyLCBpdCBjb3VsZCBiZSBcIlRleHQgRmlsZXNcIiwgXCJJbWFnZXNcIiBldGMuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW1BhdHRlcm5dIC0gUGF0dGVybiB0byBtYXRjaCBmb3IgdGhlIGZpbHRlciwgZS5nLiBcIioudHh0OyoubWRcIiBmb3IgdGV4dCBtYXJrZG93biBmaWxlcy5cbiAqL1xuXG4vLyBzZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLmRpYWxvZ0Vycm9yQ2FsbGJhY2sgPSBkaWFsb2dFcnJvckNhbGxiYWNrO1xud2luZG93Ll93YWlscy5kaWFsb2dSZXN1bHRDYWxsYmFjayA9IGRpYWxvZ1Jlc3VsdENhbGxiYWNrO1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5cbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gJ25hbm9pZC9ub24tc2VjdXJlJztcblxuLy8gRGVmaW5lIGNvbnN0YW50cyBmcm9tIHRoZSBgbWV0aG9kc2Agb2JqZWN0IGluIFRpdGxlIENhc2VcbmNvbnN0IERpYWxvZ0luZm8gPSAwO1xuY29uc3QgRGlhbG9nV2FybmluZyA9IDE7XG5jb25zdCBEaWFsb2dFcnJvciA9IDI7XG5jb25zdCBEaWFsb2dRdWVzdGlvbiA9IDM7XG5jb25zdCBEaWFsb2dPcGVuRmlsZSA9IDQ7XG5jb25zdCBEaWFsb2dTYXZlRmlsZSA9IDU7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkRpYWxvZywgJycpO1xuY29uc3QgZGlhbG9nUmVzcG9uc2VzID0gbmV3IE1hcCgpO1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBpZCB0aGF0IGlzIG5vdCBwcmVzZW50IGluIGRpYWxvZ1Jlc3BvbnNlcy5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IHVuaXF1ZSBpZFxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZUlEKCkge1xuICAgIGxldCByZXN1bHQ7XG4gICAgZG8ge1xuICAgICAgICByZXN1bHQgPSBuYW5vaWQoKTtcbiAgICB9IHdoaWxlIChkaWFsb2dSZXNwb25zZXMuaGFzKHJlc3VsdCkpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogU2hvd3MgYSBkaWFsb2cgb2Ygc3BlY2lmaWVkIHR5cGUgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0eXBlIC0gdHlwZSBvZiBkaWFsb2dcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN8T3BlbkZpbGVEaWFsb2dPcHRpb25zfFNhdmVGaWxlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIG9wdGlvbnMgZm9yIHRoZSBkaWFsb2dcbiAqIEByZXR1cm5zIHtQcm9taXNlfSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCByZXN1bHQgb2YgZGlhbG9nXG4gKi9cbmZ1bmN0aW9uIGRpYWxvZyh0eXBlLCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBpZCA9IGdlbmVyYXRlSUQoKTtcbiAgICBvcHRpb25zW1wiZGlhbG9nLWlkXCJdID0gaWQ7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgZGlhbG9nUmVzcG9uc2VzLnNldChpZCwge3Jlc29sdmUsIHJlamVjdH0pO1xuICAgICAgICBjYWxsKHR5cGUsIG9wdGlvbnMpLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBIYW5kbGVzIHRoZSBjYWxsYmFjayBmcm9tIGEgZGlhbG9nLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIFRoZSBJRCBvZiB0aGUgZGlhbG9nIHJlc3BvbnNlLlxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgLSBUaGUgZGF0YSByZWNlaXZlZCBmcm9tIHRoZSBkaWFsb2cuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGlzSlNPTiAtIEZsYWcgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSBkYXRhIGlzIGluIEpTT04gZm9ybWF0LlxuICpcbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cbiAqL1xuZnVuY3Rpb24gZGlhbG9nUmVzdWx0Q2FsbGJhY2soaWQsIGRhdGEsIGlzSlNPTikge1xuICAgIGxldCBwID0gZGlhbG9nUmVzcG9uc2VzLmdldChpZCk7XG4gICAgaWYgKHApIHtcbiAgICAgICAgaWYgKGlzSlNPTikge1xuICAgICAgICAgICAgcC5yZXNvbHZlKEpTT04ucGFyc2UoZGF0YSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcC5yZXNvbHZlKGRhdGEpO1xuICAgICAgICB9XG4gICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBDYWxsYmFjayBmdW5jdGlvbiBmb3IgaGFuZGxpbmcgZXJyb3JzIGluIGRpYWxvZy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBUaGUgaWQgb2YgdGhlIGRpYWxvZyByZXNwb25zZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gZGlhbG9nRXJyb3JDYWxsYmFjayhpZCwgbWVzc2FnZSkge1xuICAgIGxldCBwID0gZGlhbG9nUmVzcG9uc2VzLmdldChpZCk7XG4gICAgaWYgKHApIHtcbiAgICAgICAgcC5yZWplY3QobWVzc2FnZSk7XG4gICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgIH1cbn1cblxuXG4vLyBSZXBsYWNlIGBtZXRob2RzYCB3aXRoIGNvbnN0YW50cyBpbiBUaXRsZSBDYXNlXG5cbi8qKlxuICogQHBhcmFtIHtNZXNzYWdlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcbiAqL1xuZXhwb3J0IGNvbnN0IEluZm8gPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ0luZm8sIG9wdGlvbnMpO1xuXG4vKipcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gLSBUaGUgbGFiZWwgb2YgdGhlIGJ1dHRvbiBwcmVzc2VkXG4gKi9cbmV4cG9ydCBjb25zdCBXYXJuaW5nID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dXYXJuaW5nLCBvcHRpb25zKTtcblxuLyoqXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IC0gVGhlIGxhYmVsIG9mIHRoZSBidXR0b24gcHJlc3NlZFxuICovXG5leHBvcnQgY29uc3QgRXJyb3IgPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ0Vycm9yLCBvcHRpb25zKTtcblxuLyoqXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IC0gVGhlIGxhYmVsIG9mIHRoZSBidXR0b24gcHJlc3NlZFxuICovXG5leHBvcnQgY29uc3QgUXVlc3Rpb24gPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ1F1ZXN0aW9uLCBvcHRpb25zKTtcblxuLyoqXG4gKiBAcGFyYW0ge09wZW5GaWxlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmdbXXxzdHJpbmc+fSBSZXR1cm5zIHNlbGVjdGVkIGZpbGUgb3IgbGlzdCBvZiBmaWxlcy4gUmV0dXJucyBibGFuayBzdHJpbmcgaWYgbm8gZmlsZSBpcyBzZWxlY3RlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IE9wZW5GaWxlID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dPcGVuRmlsZSwgb3B0aW9ucyk7XG5cbi8qKlxuICogQHBhcmFtIHtTYXZlRmlsZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gUmV0dXJucyB0aGUgc2VsZWN0ZWQgZmlsZS4gUmV0dXJucyBibGFuayBzdHJpbmcgaWYgbm8gZmlsZSBpcyBzZWxlY3RlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IFNhdmVGaWxlID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dTYXZlRmlsZSwgb3B0aW9ucyk7XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7aW1wb3J0KFwiLi90eXBlc1wiKS5XYWlsc0V2ZW50fSBXYWlsc0V2ZW50XG4gKi9cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcblxuaW1wb3J0IHtFdmVudFR5cGVzfSBmcm9tIFwiLi9ldmVudF90eXBlc1wiO1xuZXhwb3J0IGNvbnN0IFR5cGVzID0gRXZlbnRUeXBlcztcblxuLy8gU2V0dXBcbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xud2luZG93Ll93YWlscy5kaXNwYXRjaFdhaWxzRXZlbnQgPSBkaXNwYXRjaFdhaWxzRXZlbnQ7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkV2ZW50cywgJycpO1xuY29uc3QgRW1pdE1ldGhvZCA9IDA7XG5jb25zdCBldmVudExpc3RlbmVycyA9IG5ldyBNYXAoKTtcblxuY2xhc3MgTGlzdGVuZXIge1xuICAgIGNvbnN0cnVjdG9yKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgICAgICB0aGlzLmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICAgICAgdGhpcy5tYXhDYWxsYmFja3MgPSBtYXhDYWxsYmFja3MgfHwgLTE7XG4gICAgICAgIHRoaXMuQ2FsbGJhY2sgPSAoZGF0YSkgPT4ge1xuICAgICAgICAgICAgY2FsbGJhY2soZGF0YSk7XG4gICAgICAgICAgICBpZiAodGhpcy5tYXhDYWxsYmFja3MgPT09IC0xKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLm1heENhbGxiYWNrcyAtPSAxO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubWF4Q2FsbGJhY2tzID09PSAwO1xuICAgICAgICB9O1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdhaWxzRXZlbnQge1xuICAgIGNvbnN0cnVjdG9yKG5hbWUsIGRhdGEgPSBudWxsKSB7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0dXAoKSB7XG59XG5cbmZ1bmN0aW9uIGRpc3BhdGNoV2FpbHNFdmVudChldmVudCkge1xuICAgIGxldCBsaXN0ZW5lcnMgPSBldmVudExpc3RlbmVycy5nZXQoZXZlbnQubmFtZSk7XG4gICAgaWYgKGxpc3RlbmVycykge1xuICAgICAgICBsZXQgdG9SZW1vdmUgPSBsaXN0ZW5lcnMuZmlsdGVyKGxpc3RlbmVyID0+IHtcbiAgICAgICAgICAgIGxldCByZW1vdmUgPSBsaXN0ZW5lci5DYWxsYmFjayhldmVudCk7XG4gICAgICAgICAgICBpZiAocmVtb3ZlKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0b1JlbW92ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBsaXN0ZW5lcnMuZmlsdGVyKGwgPT4gIXRvUmVtb3ZlLmluY2x1ZGVzKGwpKTtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMubGVuZ3RoID09PSAwKSBldmVudExpc3RlbmVycy5kZWxldGUoZXZlbnQubmFtZSk7XG4gICAgICAgICAgICBlbHNlIGV2ZW50TGlzdGVuZXJzLnNldChldmVudC5uYW1lLCBsaXN0ZW5lcnMpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIFJlZ2lzdGVyIGEgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzIGZvciBhIHNwZWNpZmljIGV2ZW50LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZvci5cbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gbWF4Q2FsbGJhY2tzIC0gVGhlIG1heGltdW0gbnVtYmVyIG9mIHRpbWVzIHRoZSBjYWxsYmFjayBjYW4gYmUgY2FsbGVkIGZvciB0aGUgZXZlbnQuIE9uY2UgdGhlIG1heGltdW0gbnVtYmVyIGlzIHJlYWNoZWQsIHRoZSBjYWxsYmFjayB3aWxsIG5vIGxvbmdlciBiZSBjYWxsZWQuXG4gKlxuIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgIGxldCBsaXN0ZW5lcnMgPSBldmVudExpc3RlbmVycy5nZXQoZXZlbnROYW1lKSB8fCBbXTtcbiAgICBjb25zdCB0aGlzTGlzdGVuZXIgPSBuZXcgTGlzdGVuZXIoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKTtcbiAgICBsaXN0ZW5lcnMucHVzaCh0aGlzTGlzdGVuZXIpO1xuICAgIGV2ZW50TGlzdGVuZXJzLnNldChldmVudE5hbWUsIGxpc3RlbmVycyk7XG4gICAgcmV0dXJuICgpID0+IGxpc3RlbmVyT2ZmKHRoaXNMaXN0ZW5lcik7XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIGEgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgZXhlY3V0ZWQgd2hlbiB0aGUgc3BlY2lmaWVkIGV2ZW50IG9jY3Vycy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50LlxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgZXhlY3V0ZWQuIEl0IHRha2VzIG5vIHBhcmFtZXRlcnMuXG4gKiBAcmV0dXJuIHtmdW5jdGlvbn0gLSBBIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLCB3aWxsIHVucmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZyb20gdGhlIGV2ZW50LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9uKGV2ZW50TmFtZSwgY2FsbGJhY2spIHsgcmV0dXJuIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgLTEpOyB9XG5cbi8qKlxuICogUmVnaXN0ZXJzIGEgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgZXhlY3V0ZWQgb25seSBvbmNlIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFjayAtIFRoZSBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuIHRoZSBldmVudCBvY2N1cnMuXG4gKiBAcmV0dXJuIHtmdW5jdGlvbn0gLSBBIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLCB3aWxsIHVucmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZyb20gdGhlIGV2ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gT25jZShldmVudE5hbWUsIGNhbGxiYWNrKSB7IHJldHVybiBPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIDEpOyB9XG5cbi8qKlxuICogUmVtb3ZlcyB0aGUgc3BlY2lmaWVkIGxpc3RlbmVyIGZyb20gdGhlIGV2ZW50IGxpc3RlbmVycyBjb2xsZWN0aW9uLlxuICogSWYgYWxsIGxpc3RlbmVycyBmb3IgdGhlIGV2ZW50IGFyZSByZW1vdmVkLCB0aGUgZXZlbnQga2V5IGlzIGRlbGV0ZWQgZnJvbSB0aGUgY29sbGVjdGlvbi5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gbGlzdGVuZXIgLSBUaGUgbGlzdGVuZXIgdG8gYmUgcmVtb3ZlZC5cbiAqL1xuZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXIpIHtcbiAgICBjb25zdCBldmVudE5hbWUgPSBsaXN0ZW5lci5ldmVudE5hbWU7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChldmVudE5hbWUpLmZpbHRlcihsID0+IGwgIT09IGxpc3RlbmVyKTtcbiAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCA9PT0gMCkgZXZlbnRMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50TmFtZSk7XG4gICAgZWxzZSBldmVudExpc3RlbmVycy5zZXQoZXZlbnROYW1lLCBsaXN0ZW5lcnMpO1xufVxuXG5cbi8qKlxuICogUmVtb3ZlcyBldmVudCBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQgbmFtZXMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgbGlzdGVuZXJzIGZvci5cbiAqIEBwYXJhbSB7Li4uc3RyaW5nfSBhZGRpdGlvbmFsRXZlbnROYW1lcyAtIEFkZGl0aW9uYWwgZXZlbnQgbmFtZXMgdG8gcmVtb3ZlIGxpc3RlbmVycyBmb3IuXG4gKiBAcmV0dXJuIHt1bmRlZmluZWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBPZmYoZXZlbnROYW1lLCAuLi5hZGRpdGlvbmFsRXZlbnROYW1lcykge1xuICAgIGxldCBldmVudHNUb1JlbW92ZSA9IFtldmVudE5hbWUsIC4uLmFkZGl0aW9uYWxFdmVudE5hbWVzXTtcbiAgICBldmVudHNUb1JlbW92ZS5mb3JFYWNoKGV2ZW50TmFtZSA9PiBldmVudExpc3RlbmVycy5kZWxldGUoZXZlbnROYW1lKSk7XG59XG4vKipcbiAqIFJlbW92ZXMgYWxsIGV2ZW50IGxpc3RlbmVycy5cbiAqXG4gKiBAZnVuY3Rpb24gT2ZmQWxsXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9mZkFsbCgpIHsgZXZlbnRMaXN0ZW5lcnMuY2xlYXIoKTsgfVxuXG4vKipcbiAqIEVtaXRzIGFuIGV2ZW50IHVzaW5nIHRoZSBnaXZlbiBldmVudCBuYW1lLlxuICpcbiAqIEBwYXJhbSB7V2FpbHNFdmVudH0gZXZlbnQgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdC5cbiAqIEByZXR1cm5zIHthbnl9IC0gVGhlIHJlc3VsdCBvZiB0aGUgZW1pdHRlZCBldmVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEVtaXQoZXZlbnQpIHsgcmV0dXJuIGNhbGwoRW1pdE1ldGhvZCwgZXZlbnQpOyB9XG4iLCAiXG5leHBvcnQgY29uc3QgRXZlbnRUeXBlcyA9IHtcblx0V2luZG93czoge1xuXHRcdFN5c3RlbVRoZW1lQ2hhbmdlZDogXCJ3aW5kb3dzOlN5c3RlbVRoZW1lQ2hhbmdlZFwiLFxuXHRcdEFQTVBvd2VyU3RhdHVzQ2hhbmdlOiBcIndpbmRvd3M6QVBNUG93ZXJTdGF0dXNDaGFuZ2VcIixcblx0XHRBUE1TdXNwZW5kOiBcIndpbmRvd3M6QVBNU3VzcGVuZFwiLFxuXHRcdEFQTVJlc3VtZUF1dG9tYXRpYzogXCJ3aW5kb3dzOkFQTVJlc3VtZUF1dG9tYXRpY1wiLFxuXHRcdEFQTVJlc3VtZVN1c3BlbmQ6IFwid2luZG93czpBUE1SZXN1bWVTdXNwZW5kXCIsXG5cdFx0QVBNUG93ZXJTZXR0aW5nQ2hhbmdlOiBcIndpbmRvd3M6QVBNUG93ZXJTZXR0aW5nQ2hhbmdlXCIsXG5cdFx0QXBwbGljYXRpb25TdGFydGVkOiBcIndpbmRvd3M6QXBwbGljYXRpb25TdGFydGVkXCIsXG5cdFx0V2ViVmlld05hdmlnYXRpb25Db21wbGV0ZWQ6IFwid2luZG93czpXZWJWaWV3TmF2aWdhdGlvbkNvbXBsZXRlZFwiLFxuXHRcdFdpbmRvd0luYWN0aXZlOiBcIndpbmRvd3M6V2luZG93SW5hY3RpdmVcIixcblx0XHRXaW5kb3dBY3RpdmU6IFwid2luZG93czpXaW5kb3dBY3RpdmVcIixcblx0XHRXaW5kb3dDbGlja0FjdGl2ZTogXCJ3aW5kb3dzOldpbmRvd0NsaWNrQWN0aXZlXCIsXG5cdFx0V2luZG93TWF4aW1pc2U6IFwid2luZG93czpXaW5kb3dNYXhpbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWF4aW1pc2U6IFwid2luZG93czpXaW5kb3dVbk1heGltaXNlXCIsXG5cdFx0V2luZG93RnVsbHNjcmVlbjogXCJ3aW5kb3dzOldpbmRvd0Z1bGxzY3JlZW5cIixcblx0XHRXaW5kb3dVbkZ1bGxzY3JlZW46IFwid2luZG93czpXaW5kb3dVbkZ1bGxzY3JlZW5cIixcblx0XHRXaW5kb3dSZXN0b3JlOiBcIndpbmRvd3M6V2luZG93UmVzdG9yZVwiLFxuXHRcdFdpbmRvd01pbmltaXNlOiBcIndpbmRvd3M6V2luZG93TWluaW1pc2VcIixcblx0XHRXaW5kb3dVbk1pbmltaXNlOiBcIndpbmRvd3M6V2luZG93VW5NaW5pbWlzZVwiLFxuXHRcdFdpbmRvd0Nsb3NlOiBcIndpbmRvd3M6V2luZG93Q2xvc2VcIixcblx0XHRXaW5kb3dTZXRGb2N1czogXCJ3aW5kb3dzOldpbmRvd1NldEZvY3VzXCIsXG5cdFx0V2luZG93S2lsbEZvY3VzOiBcIndpbmRvd3M6V2luZG93S2lsbEZvY3VzXCIsXG5cdFx0V2luZG93RHJhZ0Ryb3A6IFwid2luZG93czpXaW5kb3dEcmFnRHJvcFwiLFxuXHRcdFdpbmRvd0RyYWdFbnRlcjogXCJ3aW5kb3dzOldpbmRvd0RyYWdFbnRlclwiLFxuXHRcdFdpbmRvd0RyYWdMZWF2ZTogXCJ3aW5kb3dzOldpbmRvd0RyYWdMZWF2ZVwiLFxuXHRcdFdpbmRvd0RyYWdPdmVyOiBcIndpbmRvd3M6V2luZG93RHJhZ092ZXJcIixcblx0XHRXaW5kb3dEaWRNb3ZlOiBcIndpbmRvd3M6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZFJlc2l6ZTogXCJ3aW5kb3dzOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHR9LFxuXHRNYWM6IHtcblx0XHRBcHBsaWNhdGlvbkRpZEJlY29tZUFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUVmZmVjdGl2ZUFwcGVhcmFuY2VcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUljb246IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlSWNvblwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU2NyZWVuUGFyYW1ldGVyc1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uXCIsXG5cdFx0QXBwbGljYXRpb25EaWRGaW5pc2hMYXVuY2hpbmc6IFwibWFjOkFwcGxpY2F0aW9uRGlkRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25EaWRIaWRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZEhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFJlc2lnbkFjdGl2ZU5vdGlmaWNhdGlvbjogXCJtYWM6QXBwbGljYXRpb25EaWRSZXNpZ25BY3RpdmVOb3RpZmljYXRpb25cIixcblx0XHRBcHBsaWNhdGlvbkRpZFVuaGlkZTogXCJtYWM6QXBwbGljYXRpb25EaWRVbmhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25EaWRVcGRhdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxCZWNvbWVBY3RpdmU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbEJlY29tZUFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbEZpbmlzaExhdW5jaGluZzogXCJtYWM6QXBwbGljYXRpb25XaWxsRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsSGlkZTogXCJtYWM6QXBwbGljYXRpb25XaWxsSGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFJlc2lnbkFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsUmVzaWduQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsVGVybWluYXRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxUZXJtaW5hdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxVbmhpZGU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbFVuaGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsVXBkYXRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZTogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZSFcIixcblx0XHRBcHBsaWNhdGlvblNob3VsZEhhbmRsZVJlb3BlbjogXCJtYWM6QXBwbGljYXRpb25TaG91bGRIYW5kbGVSZW9wZW4hXCIsXG5cdFx0V2luZG93RGlkQmVjb21lS2V5OiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dEaWRCZWNvbWVNYWluOiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVNYWluXCIsXG5cdFx0V2luZG93RGlkQmVnaW5TaGVldDogXCJtYWM6V2luZG93RGlkQmVnaW5TaGVldFwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUFscGhhOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VBbHBoYVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUJhY2tpbmdMb2NhdGlvbjogXCJtYWM6V2luZG93RGlkQ2hhbmdlQmFja2luZ0xvY2F0aW9uXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQmFja2luZ1Byb3BlcnRpZXM6IFwibWFjOldpbmRvd0RpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOldpbmRvd0RpZENoYW5nZU9jY2x1c2lvblN0YXRlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW46IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2U6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2VQcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5TcGFjZVByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTaGFyaW5nVHlwZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2hhcmluZ1R5cGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZU9yZGVyaW5nTW9kZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUaXRsZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVGl0bGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUb29sYmFyOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VUb29sYmFyXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd0RpZERlbWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dEaWRFbmRTaGVldDogXCJtYWM6V2luZG93RGlkRW5kU2hlZXRcIixcblx0XHRXaW5kb3dEaWRFbnRlckZ1bGxTY3JlZW46IFwibWFjOldpbmRvd0RpZEVudGVyRnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dEaWRFeGl0RnVsbFNjcmVlbjogXCJtYWM6V2luZG93RGlkRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dEaWRFeGl0VmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEV4aXRWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd0RpZEV4cG9zZTogXCJtYWM6V2luZG93RGlkRXhwb3NlXCIsXG5cdFx0V2luZG93RGlkRm9jdXM6IFwibWFjOldpbmRvd0RpZEZvY3VzXCIsXG5cdFx0V2luZG93RGlkTWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZE1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJtYWM6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT2ZmU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRPcmRlck9mZlNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd0RpZE9yZGVyT25TY3JlZW5cIixcblx0XHRXaW5kb3dEaWRSZXNpZ25LZXk6IFwibWFjOldpbmRvd0RpZFJlc2lnbktleVwiLFxuXHRcdFdpbmRvd0RpZFJlc2lnbk1haW46IFwibWFjOldpbmRvd0RpZFJlc2lnbk1haW5cIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwibWFjOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZTogXCJtYWM6V2luZG93RGlkVXBkYXRlXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd0RpZFVwZGF0ZUFscGhhXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllczogXCJtYWM6V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVNoYWRvd1wiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRpdGxlOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRvb2xiYXI6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVRvb2xiYXJcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5XCIsXG5cdFx0V2luZG93U2hvdWxkQ2xvc2U6IFwibWFjOldpbmRvd1Nob3VsZENsb3NlIVwiLFxuXHRcdFdpbmRvd1dpbGxCZWNvbWVLZXk6IFwibWFjOldpbmRvd1dpbGxCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dXaWxsQmVjb21lTWFpbjogXCJtYWM6V2luZG93V2lsbEJlY29tZU1haW5cIixcblx0XHRXaW5kb3dXaWxsQmVnaW5TaGVldDogXCJtYWM6V2luZG93V2lsbEJlZ2luU2hlZXRcIixcblx0XHRXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlXCIsXG5cdFx0V2luZG93V2lsbENsb3NlOiBcIm1hYzpXaW5kb3dXaWxsQ2xvc2VcIixcblx0XHRXaW5kb3dXaWxsRGVtaW5pYXR1cml6ZTogXCJtYWM6V2luZG93V2lsbERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd1dpbGxFbnRlclZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEV4aXRGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyOiBcIm1hYzpXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsRm9jdXNcIixcblx0XHRXaW5kb3dXaWxsTWluaWF0dXJpemU6IFwibWFjOldpbmRvd1dpbGxNaW5pYXR1cml6ZVwiLFxuXHRcdFdpbmRvd1dpbGxNb3ZlOiBcIm1hYzpXaW5kb3dXaWxsTW92ZVwiLFxuXHRcdFdpbmRvd1dpbGxPcmRlck9mZlNjcmVlbjogXCJtYWM6V2luZG93V2lsbE9yZGVyT2ZmU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd1dpbGxPcmRlck9uU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbFJlc2lnbk1haW46IFwibWFjOldpbmRvd1dpbGxSZXNpZ25NYWluXCIsXG5cdFx0V2luZG93V2lsbFJlc2l6ZTogXCJtYWM6V2luZG93V2lsbFJlc2l6ZVwiLFxuXHRcdFdpbmRvd1dpbGxVbmZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsVW5mb2N1c1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVBbHBoYVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3I6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXM6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllc1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVTaGFkb3dcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlVGl0bGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVUb29sYmFyOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVG9vbGJhclwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd1dpbGxVc2VTdGFuZGFyZEZyYW1lOiBcIm1hYzpXaW5kb3dXaWxsVXNlU3RhbmRhcmRGcmFtZVwiLFxuXHRcdE1lbnVXaWxsT3BlbjogXCJtYWM6TWVudVdpbGxPcGVuXCIsXG5cdFx0TWVudURpZE9wZW46IFwibWFjOk1lbnVEaWRPcGVuXCIsXG5cdFx0TWVudURpZENsb3NlOiBcIm1hYzpNZW51RGlkQ2xvc2VcIixcblx0XHRNZW51V2lsbFNlbmRBY3Rpb246IFwibWFjOk1lbnVXaWxsU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVEaWRTZW5kQWN0aW9uOiBcIm1hYzpNZW51RGlkU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVXaWxsSGlnaGxpZ2h0SXRlbTogXCJtYWM6TWVudVdpbGxIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudURpZEhpZ2hsaWdodEl0ZW06IFwibWFjOk1lbnVEaWRIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudVdpbGxEaXNwbGF5SXRlbTogXCJtYWM6TWVudVdpbGxEaXNwbGF5SXRlbVwiLFxuXHRcdE1lbnVEaWREaXNwbGF5SXRlbTogXCJtYWM6TWVudURpZERpc3BsYXlJdGVtXCIsXG5cdFx0TWVudVdpbGxBZGRJdGVtOiBcIm1hYzpNZW51V2lsbEFkZEl0ZW1cIixcblx0XHRNZW51RGlkQWRkSXRlbTogXCJtYWM6TWVudURpZEFkZEl0ZW1cIixcblx0XHRNZW51V2lsbFJlbW92ZUl0ZW06IFwibWFjOk1lbnVXaWxsUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVEaWRSZW1vdmVJdGVtOiBcIm1hYzpNZW51RGlkUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVXaWxsQmVnaW5UcmFja2luZzogXCJtYWM6TWVudVdpbGxCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudURpZEJlZ2luVHJhY2tpbmc6IFwibWFjOk1lbnVEaWRCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxFbmRUcmFja2luZzogXCJtYWM6TWVudVdpbGxFbmRUcmFja2luZ1wiLFxuXHRcdE1lbnVEaWRFbmRUcmFja2luZzogXCJtYWM6TWVudURpZEVuZFRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxVcGRhdGU6IFwibWFjOk1lbnVXaWxsVXBkYXRlXCIsXG5cdFx0TWVudURpZFVwZGF0ZTogXCJtYWM6TWVudURpZFVwZGF0ZVwiLFxuXHRcdE1lbnVXaWxsUG9wVXA6IFwibWFjOk1lbnVXaWxsUG9wVXBcIixcblx0XHRNZW51RGlkUG9wVXA6IFwibWFjOk1lbnVEaWRQb3BVcFwiLFxuXHRcdE1lbnVXaWxsU2VuZEFjdGlvblRvSXRlbTogXCJtYWM6TWVudVdpbGxTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0TWVudURpZFNlbmRBY3Rpb25Ub0l0ZW06IFwibWFjOk1lbnVEaWRTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0V2ViVmlld0RpZFN0YXJ0UHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkU3RhcnRQcm92aXNpb25hbE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZEZpbmlzaE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZENvbW1pdE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRDb21taXROYXZpZ2F0aW9uXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZFwiLFxuXHRcdFdpbmRvd0ZpbGVEcmFnZ2luZ1BlcmZvcm1lZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nUGVyZm9ybWVkXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRXhpdGVkOiBcIm1hYzpXaW5kb3dGaWxlRHJhZ2dpbmdFeGl0ZWRcIixcblx0fSxcblx0TGludXg6IHtcblx0XHRTeXN0ZW1UaGVtZUNoYW5nZWQ6IFwibGludXg6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdFx0V2luZG93TG9hZENoYW5nZWQ6IFwibGludXg6V2luZG93TG9hZENoYW5nZWRcIixcblx0XHRXaW5kb3dEZWxldGVFdmVudDogXCJsaW51eDpXaW5kb3dEZWxldGVFdmVudFwiLFxuXHRcdFdpbmRvd0RpZE1vdmU6IFwibGludXg6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZFJlc2l6ZTogXCJsaW51eDpXaW5kb3dEaWRSZXNpemVcIixcblx0XHRXaW5kb3dGb2N1c0luOiBcImxpbnV4OldpbmRvd0ZvY3VzSW5cIixcblx0XHRXaW5kb3dGb2N1c091dDogXCJsaW51eDpXaW5kb3dGb2N1c091dFwiLFxuXHRcdEFwcGxpY2F0aW9uU3RhcnR1cDogXCJsaW51eDpBcHBsaWNhdGlvblN0YXJ0dXBcIixcblx0fSxcblx0Q29tbW9uOiB7XG5cdFx0QXBwbGljYXRpb25TdGFydGVkOiBcImNvbW1vbjpBcHBsaWNhdGlvblN0YXJ0ZWRcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJjb21tb246V2luZG93TWF4aW1pc2VcIixcblx0XHRXaW5kb3dVbk1heGltaXNlOiBcImNvbW1vbjpXaW5kb3dVbk1heGltaXNlXCIsXG5cdFx0V2luZG93RnVsbHNjcmVlbjogXCJjb21tb246V2luZG93RnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1VuRnVsbHNjcmVlbjogXCJjb21tb246V2luZG93VW5GdWxsc2NyZWVuXCIsXG5cdFx0V2luZG93UmVzdG9yZTogXCJjb21tb246V2luZG93UmVzdG9yZVwiLFxuXHRcdFdpbmRvd01pbmltaXNlOiBcImNvbW1vbjpXaW5kb3dNaW5pbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWluaW1pc2U6IFwiY29tbW9uOldpbmRvd1VuTWluaW1pc2VcIixcblx0XHRXaW5kb3dDbG9zaW5nOiBcImNvbW1vbjpXaW5kb3dDbG9zaW5nXCIsXG5cdFx0V2luZG93Wm9vbTogXCJjb21tb246V2luZG93Wm9vbVwiLFxuXHRcdFdpbmRvd1pvb21JbjogXCJjb21tb246V2luZG93Wm9vbUluXCIsXG5cdFx0V2luZG93Wm9vbU91dDogXCJjb21tb246V2luZG93Wm9vbU91dFwiLFxuXHRcdFdpbmRvd1pvb21SZXNldDogXCJjb21tb246V2luZG93Wm9vbVJlc2V0XCIsXG5cdFx0V2luZG93Rm9jdXM6IFwiY29tbW9uOldpbmRvd0ZvY3VzXCIsXG5cdFx0V2luZG93TG9zdEZvY3VzOiBcImNvbW1vbjpXaW5kb3dMb3N0Rm9jdXNcIixcblx0XHRXaW5kb3dTaG93OiBcImNvbW1vbjpXaW5kb3dTaG93XCIsXG5cdFx0V2luZG93SGlkZTogXCJjb21tb246V2luZG93SGlkZVwiLFxuXHRcdFdpbmRvd0RQSUNoYW5nZWQ6IFwiY29tbW9uOldpbmRvd0RQSUNoYW5nZWRcIixcblx0XHRXaW5kb3dGaWxlc0Ryb3BwZWQ6IFwiY29tbW9uOldpbmRvd0ZpbGVzRHJvcHBlZFwiLFxuXHRcdFdpbmRvd1J1bnRpbWVSZWFkeTogXCJjb21tb246V2luZG93UnVudGltZVJlYWR5XCIsXG5cdFx0VGhlbWVDaGFuZ2VkOiBcImNvbW1vbjpUaGVtZUNoYW5nZWRcIixcblx0XHRXaW5kb3dEaWRNb3ZlOiBcImNvbW1vbjpXaW5kb3dEaWRNb3ZlXCIsXG5cdFx0V2luZG93RGlkUmVzaXplOiBcImNvbW1vbjpXaW5kb3dEaWRSZXNpemVcIixcblx0fSxcbn07XG4iLCAiLypcbiBfICAgICBfXyAgICAgXyBfX1xufCB8ICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qKlxuICogTG9ncyBhIG1lc3NhZ2UgdG8gdGhlIGNvbnNvbGUgd2l0aCBjdXN0b20gZm9ybWF0dGluZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIG1lc3NhZ2UgdG8gYmUgbG9nZ2VkLlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlYnVnTG9nKG1lc3NhZ2UpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgJyVjIHdhaWxzMyAlYyAnICsgbWVzc2FnZSArICcgJyxcbiAgICAgICAgJ2JhY2tncm91bmQ6ICNhYTAwMDA7IGNvbG9yOiAjZmZmOyBib3JkZXItcmFkaXVzOiAzcHggMHB4IDBweCAzcHg7IHBhZGRpbmc6IDFweDsgZm9udC1zaXplOiAwLjdyZW0nLFxuICAgICAgICAnYmFja2dyb3VuZDogIzAwOTkwMDsgY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDBweCAzcHggM3B4IDBweDsgcGFkZGluZzogMXB4OyBmb250LXNpemU6IDAuN3JlbSdcbiAgICApO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoZSBicm93c2VyIHN1cHBvcnRzIHJlbW92aW5nIGxpc3RlbmVycyBieSB0cmlnZ2VyaW5nIGFuIEFib3J0U2lnbmFsXG4gKiAoc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9FdmVudFRhcmdldC9hZGRFdmVudExpc3RlbmVyI3NpZ25hbClcbiAqXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FuQWJvcnRMaXN0ZW5lcnMoKSB7XG4gICAgaWYgKCFFdmVudFRhcmdldCB8fCAhQWJvcnRTaWduYWwgfHwgIUFib3J0Q29udHJvbGxlcilcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgbGV0IHJlc3VsdCA9IHRydWU7XG5cbiAgICBjb25zdCB0YXJnZXQgPSBuZXcgRXZlbnRUYXJnZXQoKTtcbiAgICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgIHRhcmdldC5hZGRFdmVudExpc3RlbmVyKCd0ZXN0JywgKCkgPT4geyByZXN1bHQgPSBmYWxzZTsgfSwgeyBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsIH0pO1xuICAgIGNvbnRyb2xsZXIuYWJvcnQoKTtcbiAgICB0YXJnZXQuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoJ3Rlc3QnKSk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKioqXG4gVGhpcyB0ZWNobmlxdWUgZm9yIHByb3BlciBsb2FkIGRldGVjdGlvbiBpcyB0YWtlbiBmcm9tIEhUTVg6XG5cbiBCU0QgMi1DbGF1c2UgTGljZW5zZVxuXG4gQ29weXJpZ2h0IChjKSAyMDIwLCBCaWcgU2t5IFNvZnR3YXJlXG4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dFxuIG1vZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG5cbiAyLiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvblxuIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG4gVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCJcbiBBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFXG4gSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXG4gRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRVxuIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMXG4gREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1JcbiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUlxuIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksXG4gT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0VcbiBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuXG4gKioqL1xuXG5sZXQgaXNSZWFkeSA9IGZhbHNlO1xuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IGlzUmVhZHkgPSB0cnVlKTtcblxuZXhwb3J0IGZ1bmN0aW9uIHdoZW5SZWFkeShjYWxsYmFjaykge1xuICAgIGlmIChpc1JlYWR5IHx8IGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdjb21wbGV0ZScpIHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgY2FsbGJhY2spO1xuICAgIH1cbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vLyBJbXBvcnQgc2NyZWVuIGpzZG9jIGRlZmluaXRpb24gZnJvbSAuL3NjcmVlbnMuanNcbi8qKlxuICogQHR5cGVkZWYge2ltcG9ydChcIi4vc2NyZWVuc1wiKS5TY3JlZW59IFNjcmVlblxuICovXG5cblxuLyoqXG4gKiBBIHJlY29yZCBkZXNjcmliaW5nIHRoZSBwb3NpdGlvbiBvZiBhIHdpbmRvdy5cbiAqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBQb3NpdGlvblxuICogQHByb3BlcnR5IHtudW1iZXJ9IHggLSBUaGUgaG9yaXpvbnRhbCBwb3NpdGlvbiBvZiB0aGUgd2luZG93XG4gKiBAcHJvcGVydHkge251bWJlcn0geSAtIFRoZSB2ZXJ0aWNhbCBwb3NpdGlvbiBvZiB0aGUgd2luZG93XG4gKi9cblxuXG4vKipcbiAqIEEgcmVjb3JkIGRlc2NyaWJpbmcgdGhlIHNpemUgb2YgYSB3aW5kb3cuXG4gKlxuICogQHR5cGVkZWYge09iamVjdH0gU2l6ZVxuICogQHByb3BlcnR5IHtudW1iZXJ9IHdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSB3aW5kb3dcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBoZWlnaHQgLSBUaGUgaGVpZ2h0IG9mIHRoZSB3aW5kb3dcbiAqL1xuXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcblxuY29uc3QgUG9zaXRpb25NZXRob2QgICAgICAgICAgICAgICAgICAgID0gMDtcbmNvbnN0IENlbnRlck1ldGhvZCAgICAgICAgICAgICAgICAgICAgICA9IDE7XG5jb25zdCBDbG9zZU1ldGhvZCAgICAgICAgICAgICAgICAgICAgICAgPSAyO1xuY29uc3QgRGlzYWJsZVNpemVDb25zdHJhaW50c01ldGhvZCAgICAgID0gMztcbmNvbnN0IEVuYWJsZVNpemVDb25zdHJhaW50c01ldGhvZCAgICAgICA9IDQ7XG5jb25zdCBGb2N1c01ldGhvZCAgICAgICAgICAgICAgICAgICAgICAgPSA1O1xuY29uc3QgRm9yY2VSZWxvYWRNZXRob2QgICAgICAgICAgICAgICAgID0gNjtcbmNvbnN0IEZ1bGxzY3JlZW5NZXRob2QgICAgICAgICAgICAgICAgICA9IDc7XG5jb25zdCBHZXRTY3JlZW5NZXRob2QgICAgICAgICAgICAgICAgICAgPSA4O1xuY29uc3QgR2V0Wm9vbU1ldGhvZCAgICAgICAgICAgICAgICAgICAgID0gOTtcbmNvbnN0IEhlaWdodE1ldGhvZCAgICAgICAgICAgICAgICAgICAgICA9IDEwO1xuY29uc3QgSGlkZU1ldGhvZCAgICAgICAgICAgICAgICAgICAgICAgID0gMTE7XG5jb25zdCBJc0ZvY3VzZWRNZXRob2QgICAgICAgICAgICAgICAgICAgPSAxMjtcbmNvbnN0IElzRnVsbHNjcmVlbk1ldGhvZCAgICAgICAgICAgICAgICA9IDEzO1xuY29uc3QgSXNNYXhpbWlzZWRNZXRob2QgICAgICAgICAgICAgICAgID0gMTQ7XG5jb25zdCBJc01pbmltaXNlZE1ldGhvZCAgICAgICAgICAgICAgICAgPSAxNTtcbmNvbnN0IE1heGltaXNlTWV0aG9kICAgICAgICAgICAgICAgICAgICA9IDE2O1xuY29uc3QgTWluaW1pc2VNZXRob2QgICAgICAgICAgICAgICAgICAgID0gMTc7XG5jb25zdCBOYW1lTWV0aG9kICAgICAgICAgICAgICAgICAgICAgICAgPSAxODtcbmNvbnN0IE9wZW5EZXZUb29sc01ldGhvZCAgICAgICAgICAgICAgICA9IDE5O1xuY29uc3QgUmVsYXRpdmVQb3NpdGlvbk1ldGhvZCAgICAgICAgICAgID0gMjA7XG5jb25zdCBSZWxvYWRNZXRob2QgICAgICAgICAgICAgICAgICAgICAgPSAyMTtcbmNvbnN0IFJlc2l6YWJsZU1ldGhvZCAgICAgICAgICAgICAgICAgICA9IDIyO1xuY29uc3QgUmVzdG9yZU1ldGhvZCAgICAgICAgICAgICAgICAgICAgID0gMjM7XG5jb25zdCBTZXRQb3NpdGlvbk1ldGhvZCAgICAgICAgICAgICAgICAgPSAyNDtcbmNvbnN0IFNldEFsd2F5c09uVG9wTWV0aG9kICAgICAgICAgICAgICA9IDI1O1xuY29uc3QgU2V0QmFja2dyb3VuZENvbG91ck1ldGhvZCAgICAgICAgID0gMjY7XG5jb25zdCBTZXRGcmFtZWxlc3NNZXRob2QgICAgICAgICAgICAgICAgPSAyNztcbmNvbnN0IFNldEZ1bGxzY3JlZW5CdXR0b25FbmFibGVkTWV0aG9kICA9IDI4O1xuY29uc3QgU2V0TWF4U2l6ZU1ldGhvZCAgICAgICAgICAgICAgICAgID0gMjk7XG5jb25zdCBTZXRNaW5TaXplTWV0aG9kICAgICAgICAgICAgICAgICAgPSAzMDtcbmNvbnN0IFNldFJlbGF0aXZlUG9zaXRpb25NZXRob2QgICAgICAgICA9IDMxO1xuY29uc3QgU2V0UmVzaXphYmxlTWV0aG9kICAgICAgICAgICAgICAgID0gMzI7XG5jb25zdCBTZXRTaXplTWV0aG9kICAgICAgICAgICAgICAgICAgICAgPSAzMztcbmNvbnN0IFNldFRpdGxlTWV0aG9kICAgICAgICAgICAgICAgICAgICA9IDM0O1xuY29uc3QgU2V0Wm9vbU1ldGhvZCAgICAgICAgICAgICAgICAgICAgID0gMzU7XG5jb25zdCBTaG93TWV0aG9kICAgICAgICAgICAgICAgICAgICAgICAgPSAzNjtcbmNvbnN0IFNpemVNZXRob2QgICAgICAgICAgICAgICAgICAgICAgICA9IDM3O1xuY29uc3QgVG9nZ2xlRnVsbHNjcmVlbk1ldGhvZCAgICAgICAgICAgID0gMzg7XG5jb25zdCBUb2dnbGVNYXhpbWlzZU1ldGhvZCAgICAgICAgICAgICAgPSAzOTtcbmNvbnN0IFVuRnVsbHNjcmVlbk1ldGhvZCAgICAgICAgICAgICAgICA9IDQwO1xuY29uc3QgVW5NYXhpbWlzZU1ldGhvZCAgICAgICAgICAgICAgICAgID0gNDE7XG5jb25zdCBVbk1pbmltaXNlTWV0aG9kICAgICAgICAgICAgICAgICAgPSA0MjtcbmNvbnN0IFdpZHRoTWV0aG9kICAgICAgICAgICAgICAgICAgICAgICA9IDQzO1xuY29uc3QgWm9vbU1ldGhvZCAgICAgICAgICAgICAgICAgICAgICAgID0gNDQ7XG5jb25zdCBab29tSW5NZXRob2QgICAgICAgICAgICAgICAgICAgICAgPSA0NTtcbmNvbnN0IFpvb21PdXRNZXRob2QgICAgICAgICAgICAgICAgICAgICA9IDQ2O1xuY29uc3QgWm9vbVJlc2V0TWV0aG9kICAgICAgICAgICAgICAgICAgID0gNDc7XG5cbi8qKlxuICogQHR5cGUge3N5bWJvbH1cbiAqL1xuY29uc3QgY2FsbGVyID0gU3ltYm9sKCk7XG5cbmNsYXNzIFdpbmRvdyB7XG4gICAgLyoqXG4gICAgICogSW5pdGlhbGlzZXMgYSB3aW5kb3cgb2JqZWN0IHdpdGggdGhlIHNwZWNpZmllZCBuYW1lLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgd2luZG93LlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG5hbWUgPSAnJykge1xuICAgICAgICAvKipcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICogQG5hbWUge0BsaW5rIGNhbGxlcn1cbiAgICAgICAgICogQHR5cGUgeyguLi5hcmdzOiBhbnlbXSkgPT4gYW55fVxuICAgICAgICAgKi9cbiAgICAgICAgdGhpc1tjYWxsZXJdID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIG5hbWUpXG5cbiAgICAgICAgLy8gYmluZCBpbnN0YW5jZSBtZXRob2QgdG8gbWFrZSB0aGVtIGVhc2lseSB1c2FibGUgaW4gZXZlbnQgaGFuZGxlcnNcbiAgICAgICAgZm9yIChjb25zdCBtZXRob2Qgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoV2luZG93LnByb3RvdHlwZSkpIHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBtZXRob2QgIT09IFwiY29uc3RydWN0b3JcIlxuICAgICAgICAgICAgICAgICYmIHR5cGVvZiB0aGlzW21ldGhvZF0gPT09IFwiZnVuY3Rpb25cIlxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgdGhpc1ttZXRob2RdID0gdGhpc1ttZXRob2RdLmJpbmQodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBzcGVjaWZpZWQgd2luZG93LlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHdpbmRvdyB0byBnZXQuXG4gICAgICogQHJldHVybiB7V2luZG93fSAtIFRoZSBjb3JyZXNwb25kaW5nIHdpbmRvdyBvYmplY3QuXG4gICAgICovXG4gICAgR2V0KG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBXaW5kb3cobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgYWJzb2x1dGUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPFBvc2l0aW9uPn0gLSBUaGUgY3VycmVudCBhYnNvbHV0ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFBvc2l0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFBvc2l0aW9uTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDZW50ZXJzIHRoZSB3aW5kb3cgb24gdGhlIHNjcmVlbi5cbiAgICAgKlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIENlbnRlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyXShDZW50ZXJNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsb3NlcyB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgQ2xvc2UoKSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oQ2xvc2VNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERpc2FibGVzIG1pbi9tYXggc2l6ZSBjb25zdHJhaW50cy5cbiAgICAgKlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIERpc2FibGVTaXplQ29uc3RyYWludHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oRGlzYWJsZVNpemVDb25zdHJhaW50c01ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW5hYmxlcyBtaW4vbWF4IHNpemUgY29uc3RyYWludHMuXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAgICAgKi9cbiAgICBFbmFibGVTaXplQ29uc3RyYWludHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oRW5hYmxlU2l6ZUNvbnN0cmFpbnRzTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb2N1c2VzIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAgICAgKi9cbiAgICBGb2N1cygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyXShGb2N1c01ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRm9yY2VzIHRoZSB3aW5kb3cgdG8gcmVsb2FkIHRoZSBwYWdlIGFzc2V0cy5cbiAgICAgKlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIEZvcmNlUmVsb2FkKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKEZvcmNlUmVsb2FkTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEb2MuXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAgICAgKi9cbiAgICBGdWxsc2NyZWVuKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKEZ1bGxzY3JlZW5NZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNjcmVlbiB0aGF0IHRoZSB3aW5kb3cgaXMgb24uXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTxTY3JlZW4+fSAtIFRoZSBzY3JlZW4gdGhlIHdpbmRvdyBpcyBjdXJyZW50bHkgb25cbiAgICAgKi9cbiAgICBHZXRTY3JlZW4oKSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oR2V0U2NyZWVuTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHpvb20gbGV2ZWwgb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPG51bWJlcj59IC0gVGhlIGN1cnJlbnQgem9vbSBsZXZlbFxuICAgICAqL1xuICAgIEdldFpvb20oKSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oR2V0Wm9vbU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTxudW1iZXI+fSAtIFRoZSBjdXJyZW50IGhlaWdodCBvZiB0aGUgd2luZG93XG4gICAgICovXG4gICAgSGVpZ2h0KCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKEhlaWdodE1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGlkZXMgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIEhpZGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oSGlkZU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoZSB3aW5kb3cgaXMgZm9jdXNlZC5cbiAgICAgKlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPGJvb2xlYW4+fSAtIFdoZXRoZXIgdGhlIHdpbmRvdyBpcyBjdXJyZW50bHkgZm9jdXNlZFxuICAgICAqL1xuICAgIElzRm9jdXNlZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyXShJc0ZvY3VzZWRNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgd2luZG93IGlzIGZ1bGxzY3JlZW4uXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gLSBXaGV0aGVyIHRoZSB3aW5kb3cgaXMgY3VycmVudGx5IGZ1bGxzY3JlZW5cbiAgICAgKi9cbiAgICBJc0Z1bGxzY3JlZW4oKSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oSXNGdWxsc2NyZWVuTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHdpbmRvdyBpcyBtYXhpbWlzZWQuXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gLSBXaGV0aGVyIHRoZSB3aW5kb3cgaXMgY3VycmVudGx5IG1heGltaXNlZFxuICAgICAqL1xuICAgIElzTWF4aW1pc2VkKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKElzTWF4aW1pc2VkTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHdpbmRvdyBpcyBtaW5pbWlzZWQuXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gLSBXaGV0aGVyIHRoZSB3aW5kb3cgaXMgY3VycmVudGx5IG1pbmltaXNlZFxuICAgICAqL1xuICAgIElzTWluaW1pc2VkKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKElzTWluaW1pc2VkTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNYXhpbWlzZXMgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIE1heGltaXNlKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKE1heGltaXNlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNaW5pbWlzZXMgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIE1pbmltaXNlKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKE1pbmltaXNlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBuYW1lIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3dcbiAgICAgKi9cbiAgICBOYW1lKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKE5hbWVNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE9wZW5zIHRoZSBkZXZlbG9wbWVudCB0b29scyBwYW5lLlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgT3BlbkRldlRvb2xzKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKE9wZW5EZXZUb29sc01ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdyB0byB0aGUgc2NyZWVuLlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEByZXR1cm4ge1Byb21pc2U8UG9zaXRpb24+fSAtIFRoZSBjdXJyZW50IHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcbiAgICAgKi9cbiAgICBSZWxhdGl2ZVBvc2l0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFJlbGF0aXZlUG9zaXRpb25NZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbG9hZHMgdGhlIHBhZ2UgYXNzZXRzLlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgUmVsb2FkKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFJlbG9hZE1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoZSB3aW5kb3cgaXMgcmVzaXphYmxlLlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IC0gV2hldGhlciB0aGUgd2luZG93IGlzIGN1cnJlbnRseSByZXNpemFibGVcbiAgICAgKi9cbiAgICBSZXNpemFibGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oUmVzaXphYmxlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXN0b3JlcyB0aGUgd2luZG93IHRvIGl0cyBwcmV2aW91cyBzdGF0ZSBpZiBpdCB3YXMgcHJldmlvdXNseSBtaW5pbWlzZWQsIG1heGltaXNlZCBvciBmdWxsc2NyZWVuLlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgUmVzdG9yZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyXShSZXN0b3JlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBhYnNvbHV0ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB4IC0gVGhlIGRlc2lyZWQgaG9yaXpvbnRhbCBhYnNvbHV0ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHkgLSBUaGUgZGVzaXJlZCB2ZXJ0aWNhbCBhYnNvbHV0ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93XG4gICAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAgICAgKi9cbiAgICBTZXRQb3NpdGlvbih4LCB5KSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oU2V0UG9zaXRpb25NZXRob2QsIHsgeCwgeSB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSB3aW5kb3cgdG8gYmUgYWx3YXlzIG9uIHRvcC5cbiAgICAgKlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGFsd2F5c09uVG9wIC0gV2hldGhlciB0aGUgd2luZG93IHNob3VsZCBzdGF5IG9uIHRvcFxuICAgICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgU2V0QWx3YXlzT25Ub3AoYWx3YXlzT25Ub3ApIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyXShTZXRBbHdheXNPblRvcE1ldGhvZCwgeyBhbHdheXNPblRvcCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBiYWNrZ3JvdW5kIGNvbG91ciBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSByIC0gVGhlIGRlc2lyZWQgcmVkIGNvbXBvbmVudCBvZiB0aGUgd2luZG93IGJhY2tncm91bmRcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZyAtIFRoZSBkZXNpcmVkIGdyZWVuIGNvbXBvbmVudCBvZiB0aGUgd2luZG93IGJhY2tncm91bmRcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYiAtIFRoZSBkZXNpcmVkIGJsdWUgY29tcG9uZW50IG9mIHRoZSB3aW5kb3cgYmFja2dyb3VuZFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBhIC0gVGhlIGRlc2lyZWQgYWxwaGEgY29tcG9uZW50IG9mIHRoZSB3aW5kb3cgYmFja2dyb3VuZFxuICAgICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgU2V0QmFja2dyb3VuZENvbG91cihyLCBnLCBiLCBhKSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oU2V0QmFja2dyb3VuZENvbG91ck1ldGhvZCwgeyByLCBnLCBiLCBhIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIHdpbmRvdyBmcmFtZSBhbmQgdGl0bGUgYmFyLlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gZnJhbWVsZXNzIC0gV2hldGhlciB0aGUgd2luZG93IHNob3VsZCBiZSBmcmFtZWxlc3NcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIFNldEZyYW1lbGVzcyhmcmFtZWxlc3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyXShTZXRGcmFtZWxlc3NNZXRob2QsIHsgZnJhbWVsZXNzIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERpc2FibGVzIHRoZSBzeXN0ZW0gZnVsbHNjcmVlbiBidXR0b24uXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHBhcmFtIHtib29sZWFufSBlbmFibGVkIC0gV2hldGhlciB0aGUgZnVsbHNjcmVlbiBidXR0b24gc2hvdWxkIGJlIGVuYWJsZWRcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIFNldEZ1bGxzY3JlZW5CdXR0b25FbmFibGVkKGVuYWJsZWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyXShTZXRGdWxsc2NyZWVuQnV0dG9uRW5hYmxlZE1ldGhvZCwgeyBlbmFibGVkIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aCAtIFRoZSBkZXNpcmVkIG1heGltdW0gd2lkdGggb2YgdGhlIHdpbmRvd1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgLSBUaGUgZGVzaXJlZCBtYXhpbXVtIGhlaWdodCBvZiB0aGUgd2luZG93XG4gICAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAgICAgKi9cbiAgICBTZXRNYXhTaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyXShTZXRNYXhTaXplTWV0aG9kLCB7IHdpZHRoLCBoZWlnaHQgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbWluaW11bSBzaXplIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIGRlc2lyZWQgbWluaW11bSB3aWR0aCBvZiB0aGUgd2luZG93XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodCAtIFRoZSBkZXNpcmVkIG1pbmltdW0gaGVpZ2h0IG9mIHRoZSB3aW5kb3dcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIFNldE1pblNpemUod2lkdGgsIGhlaWdodCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFNldE1pblNpemVNZXRob2QsIHsgd2lkdGgsIGhlaWdodCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSByZWxhdGl2ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93IHRvIHRoZSBzY3JlZW4uXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHggLSBUaGUgZGVzaXJlZCBob3Jpem9udGFsIHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcbiAgICAgKiBAcGFyYW0ge251bWJlcn0geSAtIFRoZSBkZXNpcmVkIHZlcnRpY2FsIHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIFNldFJlbGF0aXZlUG9zaXRpb24oeCwgeSkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFNldFJlbGF0aXZlUG9zaXRpb25NZXRob2QsIHsgeCwgeSB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHdoZXRoZXIgdGhlIHdpbmRvdyBpcyByZXNpemFibGUuXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHBhcmFtIHtib29sZWFufSByZXNpemFibGUgLSBXaGV0aGVyIHRoZSB3aW5kb3cgc2hvdWxkIGJlIHJlc2l6YWJsZVxuICAgICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgU2V0UmVzaXphYmxlKHJlc2l6YWJsZSkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFNldFJlc2l6YWJsZU1ldGhvZCwgeyByZXNpemFibGUgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgc2l6ZSBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aCAtIFRoZSBkZXNpcmVkIHdpZHRoIG9mIHRoZSB3aW5kb3dcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIGRlc2lyZWQgaGVpZ2h0IG9mIHRoZSB3aW5kb3dcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIFNldFNpemUod2lkdGgsIGhlaWdodCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFNldFNpemVNZXRob2QsIHsgd2lkdGgsIGhlaWdodCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSB0aXRsZSBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0aXRsZSAtIFRoZSBkZXNpcmVkIHRpdGxlIG9mIHRoZSB3aW5kb3dcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIFNldFRpdGxlKHRpdGxlKSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oU2V0VGl0bGVNZXRob2QsIHsgdGl0bGUgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB6b29tIC0gVGhlIGRlc2lyZWQgem9vbSBsZXZlbFxuICAgICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgU2V0Wm9vbSh6b29tKSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oU2V0Wm9vbU1ldGhvZCwgeyB6b29tIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNob3dzIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAgICAgKi9cbiAgICBTaG93KCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFNob3dNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPFNpemU+fSAtIFRoZSBjdXJyZW50IHNpemUgb2YgdGhlIHdpbmRvd1xuICAgICAqL1xuICAgIFNpemUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oU2l6ZU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVG9nZ2xlcyB0aGUgd2luZG93IGJldHdlZW4gZnVsbHNjcmVlbiBhbmQgbm9ybWFsLlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgVG9nZ2xlRnVsbHNjcmVlbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyXShUb2dnbGVGdWxsc2NyZWVuTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUb2dnbGVzIHRoZSB3aW5kb3cgYmV0d2VlbiBtYXhpbWlzZWQgYW5kIG5vcm1hbC5cbiAgICAgKlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIFRvZ2dsZU1heGltaXNlKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFRvZ2dsZU1heGltaXNlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbi1mdWxsc2NyZWVucyB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgVW5GdWxsc2NyZWVuKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFVuRnVsbHNjcmVlbk1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW4tbWF4aW1pc2VzIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAgICAgKi9cbiAgICBVbk1heGltaXNlKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFVuTWF4aW1pc2VNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVuLW1pbmltaXNlcyB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgVW5NaW5pbWlzZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyXShVbk1pbmltaXNlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB3aWR0aCBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEByZXR1cm4ge1Byb21pc2U8bnVtYmVyPn0gLSBUaGUgY3VycmVudCB3aWR0aCBvZiB0aGUgd2luZG93XG4gICAgICovXG4gICAgV2lkdGgoKSB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlcl0oV2lkdGhNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFpvb21zIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAgICAgKi9cbiAgICBab29tKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFpvb21NZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluY3JlYXNlcyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgd2VidmlldyBjb250ZW50LlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgWm9vbUluKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFpvb21Jbk1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVjcmVhc2VzIHRoZSB6b29tIGxldmVsIG9mIHRoZSB3ZWJ2aWV3IGNvbnRlbnQuXG4gICAgICpcbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAgICAgKi9cbiAgICBab29tT3V0KCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFpvb21PdXRNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc2V0cyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgd2VidmlldyBjb250ZW50LlxuICAgICAqXG4gICAgICogQHB1YmxpY1xuICAgICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgWm9vbVJlc2V0KCkge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJdKFpvb21SZXNldE1ldGhvZCk7XG4gICAgfVxufVxuXG4vKipcbiAqIFRoZSB3aW5kb3cgd2l0aGluIHdoaWNoIHRoZSBzY3JpcHQgaXMgcnVubmluZy5cbiAqXG4gKiBAdHlwZSB7V2luZG93fVxuICovXG5jb25zdCB0aGlzV2luZG93ID0gbmV3IFdpbmRvdygnJyk7XG5cbmV4cG9ydCBkZWZhdWx0IHRoaXNXaW5kb3c7XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCAqIGFzIFJ1bnRpbWUgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjXCI7XG5cbi8vIE5PVEU6IHRoZSBmb2xsb3dpbmcgbWV0aG9kcyBNVVNUIGJlIGltcG9ydGVkIGV4cGxpY2l0bHkgYmVjYXVzZSBvZiBob3cgZXNidWlsZCBpbmplY3Rpb24gd29ya3NcbmltcG9ydCB7RW5hYmxlIGFzIEVuYWJsZVdNTH0gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dtbFwiO1xuaW1wb3J0IHtkZWJ1Z0xvZ30gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3V0aWxzXCI7XG5cbndpbmRvdy53YWlscyA9IFJ1bnRpbWU7XG5FbmFibGVXTUwoKTtcblxuaWYgKERFQlVHKSB7XG4gICAgZGVidWdMb2coXCJXYWlscyBSdW50aW1lIExvYWRlZFwiKVxufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcbmxldCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5TeXN0ZW0sICcnKTtcbmNvbnN0IHN5c3RlbUlzRGFya01vZGUgPSAwO1xuY29uc3QgZW52aXJvbm1lbnQgPSAxO1xuXG5leHBvcnQgZnVuY3Rpb24gaW52b2tlKG1zZykge1xuICAgIGlmKHdpbmRvdy5jaHJvbWUpIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5jaHJvbWUud2Vidmlldy5wb3N0TWVzc2FnZShtc2cpO1xuICAgIH1cbiAgICByZXR1cm4gd2luZG93LndlYmtpdC5tZXNzYWdlSGFuZGxlcnMuZXh0ZXJuYWwucG9zdE1lc3NhZ2UobXNnKTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIFJldHJpZXZlcyB0aGUgc3lzdGVtIGRhcmsgbW9kZSBzdGF0dXMuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxib29sZWFuPn0gLSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIGJvb2xlYW4gdmFsdWUgaW5kaWNhdGluZyBpZiB0aGUgc3lzdGVtIGlzIGluIGRhcmsgbW9kZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzRGFya01vZGUoKSB7XG4gICAgcmV0dXJuIGNhbGwoc3lzdGVtSXNEYXJrTW9kZSk7XG59XG5cbi8qKlxuICogRmV0Y2hlcyB0aGUgY2FwYWJpbGl0aWVzIG9mIHRoZSBhcHBsaWNhdGlvbiBmcm9tIHRoZSBzZXJ2ZXIuXG4gKlxuICogQGFzeW5jXG4gKiBAZnVuY3Rpb24gQ2FwYWJpbGl0aWVzXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxPYmplY3Q+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgY2FwYWJpbGl0aWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQ2FwYWJpbGl0aWVzKCkge1xuICAgIGxldCByZXNwb25zZSA9IGZldGNoKFwiL3dhaWxzL2NhcGFiaWxpdGllc1wiKTtcbiAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xufVxuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9TSW5mb1xuICogQHByb3BlcnR5IHtzdHJpbmd9IEJyYW5kaW5nIC0gVGhlIGJyYW5kaW5nIG9mIHRoZSBPUy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBJRCAtIFRoZSBJRCBvZiB0aGUgT1MuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBPUy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBWZXJzaW9uIC0gVGhlIHZlcnNpb24gb2YgdGhlIE9TLlxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gRW52aXJvbm1lbnRJbmZvXG4gKiBAcHJvcGVydHkge3N0cmluZ30gQXJjaCAtIFRoZSBhcmNoaXRlY3R1cmUgb2YgdGhlIHN5c3RlbS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gRGVidWcgLSBUcnVlIGlmIHRoZSBhcHBsaWNhdGlvbiBpcyBydW5uaW5nIGluIGRlYnVnIG1vZGUsIG90aGVyd2lzZSBmYWxzZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBPUyAtIFRoZSBvcGVyYXRpbmcgc3lzdGVtIGluIHVzZS5cbiAqIEBwcm9wZXJ0eSB7T1NJbmZvfSBPU0luZm8gLSBEZXRhaWxzIG9mIHRoZSBvcGVyYXRpbmcgc3lzdGVtLlxuICogQHByb3BlcnR5IHtPYmplY3R9IFBsYXRmb3JtSW5mbyAtIEFkZGl0aW9uYWwgcGxhdGZvcm0gaW5mb3JtYXRpb24uXG4gKi9cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIFJldHJpZXZlcyBlbnZpcm9ubWVudCBkZXRhaWxzLlxuICogQHJldHVybnMge1Byb21pc2U8RW52aXJvbm1lbnRJbmZvPn0gLSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBvYmplY3QgY29udGFpbmluZyBPUyBhbmQgc3lzdGVtIGFyY2hpdGVjdHVyZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEVudmlyb25tZW50KCkge1xuICAgIHJldHVybiBjYWxsKGVudmlyb25tZW50KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgb3BlcmF0aW5nIHN5c3RlbSBpcyBXaW5kb3dzLlxuICpcbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgdGhlIG9wZXJhdGluZyBzeXN0ZW0gaXMgV2luZG93cywgb3RoZXJ3aXNlIGZhbHNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSXNXaW5kb3dzKCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Lk9TID09PSBcIndpbmRvd3NcIjtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgb3BlcmF0aW5nIHN5c3RlbSBpcyBMaW51eC5cbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgTGludXgsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzTGludXgoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuT1MgPT09IFwibGludXhcIjtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQgaXMgYSBtYWNPUyBvcGVyYXRpbmcgc3lzdGVtLlxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBlbnZpcm9ubWVudCBpcyBtYWNPUywgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSXNNYWMoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuT1MgPT09IFwiZGFyd2luXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGFyY2hpdGVjdHVyZSBpcyBBTUQ2NC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGFyY2hpdGVjdHVyZSBpcyBBTUQ2NCwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSXNBTUQ2NCgpIHtcbiAgICByZXR1cm4gd2luZG93Ll93YWlscy5lbnZpcm9ubWVudC5BcmNoID09PSBcImFtZDY0XCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGFyY2hpdGVjdHVyZSBpcyBBUk0uXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIGN1cnJlbnQgYXJjaGl0ZWN0dXJlIGlzIEFSTSwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSXNBUk0oKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuQXJjaCA9PT0gXCJhcm1cIjtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQgaXMgQVJNNjQgYXJjaGl0ZWN0dXJlLlxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufSAtIFJldHVybnMgdHJ1ZSBpZiB0aGUgZW52aXJvbm1lbnQgaXMgQVJNNjQgYXJjaGl0ZWN0dXJlLCBvdGhlcndpc2UgcmV0dXJucyBmYWxzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQVJNNjQoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuQXJjaCA9PT0gXCJhcm02NFwiO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gSXNEZWJ1ZygpIHtcbiAgICByZXR1cm4gd2luZG93Ll93YWlscy5lbnZpcm9ubWVudC5EZWJ1ZyA9PT0gdHJ1ZTtcbn1cblxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcbmltcG9ydCB7SXNEZWJ1Z30gZnJvbSBcIi4vc3lzdGVtXCI7XG5cbi8vIHNldHVwXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBjb250ZXh0TWVudUhhbmRsZXIpO1xuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5Db250ZXh0TWVudSwgJycpO1xuY29uc3QgQ29udGV4dE1lbnVPcGVuID0gMDtcblxuZnVuY3Rpb24gb3BlbkNvbnRleHRNZW51KGlkLCB4LCB5LCBkYXRhKSB7XG4gICAgdm9pZCBjYWxsKENvbnRleHRNZW51T3Blbiwge2lkLCB4LCB5LCBkYXRhfSk7XG59XG5cbmZ1bmN0aW9uIGNvbnRleHRNZW51SGFuZGxlcihldmVudCkge1xuICAgIC8vIENoZWNrIGZvciBjdXN0b20gY29udGV4dCBtZW51XG4gICAgbGV0IGVsZW1lbnQgPSBldmVudC50YXJnZXQ7XG4gICAgbGV0IGN1c3RvbUNvbnRleHRNZW51ID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCkuZ2V0UHJvcGVydHlWYWx1ZShcIi0tY3VzdG9tLWNvbnRleHRtZW51XCIpO1xuICAgIGN1c3RvbUNvbnRleHRNZW51ID0gY3VzdG9tQ29udGV4dE1lbnUgPyBjdXN0b21Db250ZXh0TWVudS50cmltKCkgOiBcIlwiO1xuICAgIGlmIChjdXN0b21Db250ZXh0TWVudSkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBsZXQgY3VzdG9tQ29udGV4dE1lbnVEYXRhID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCkuZ2V0UHJvcGVydHlWYWx1ZShcIi0tY3VzdG9tLWNvbnRleHRtZW51LWRhdGFcIik7XG4gICAgICAgIG9wZW5Db250ZXh0TWVudShjdXN0b21Db250ZXh0TWVudSwgZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSwgY3VzdG9tQ29udGV4dE1lbnVEYXRhKTtcbiAgICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgcHJvY2Vzc0RlZmF1bHRDb250ZXh0TWVudShldmVudCk7XG59XG5cblxuLypcbi0tZGVmYXVsdC1jb250ZXh0bWVudTogYXV0bzsgKGRlZmF1bHQpIHdpbGwgc2hvdyB0aGUgZGVmYXVsdCBjb250ZXh0IG1lbnUgaWYgY29udGVudEVkaXRhYmxlIGlzIHRydWUgT1IgdGV4dCBoYXMgYmVlbiBzZWxlY3RlZCBPUiBlbGVtZW50IGlzIGlucHV0IG9yIHRleHRhcmVhXG4tLWRlZmF1bHQtY29udGV4dG1lbnU6IHNob3c7IHdpbGwgYWx3YXlzIHNob3cgdGhlIGRlZmF1bHQgY29udGV4dCBtZW51XG4tLWRlZmF1bHQtY29udGV4dG1lbnU6IGhpZGU7IHdpbGwgYWx3YXlzIGhpZGUgdGhlIGRlZmF1bHQgY29udGV4dCBtZW51XG5cblRoaXMgcnVsZSBpcyBpbmhlcml0ZWQgbGlrZSBub3JtYWwgQ1NTIHJ1bGVzLCBzbyBuZXN0aW5nIHdvcmtzIGFzIGV4cGVjdGVkXG4qL1xuZnVuY3Rpb24gcHJvY2Vzc0RlZmF1bHRDb250ZXh0TWVudShldmVudCkge1xuXG4gICAgLy8gRGVidWcgYnVpbGRzIGFsd2F5cyBzaG93IHRoZSBtZW51XG4gICAgaWYgKElzRGVidWcoKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUHJvY2VzcyBkZWZhdWx0IGNvbnRleHQgbWVudVxuICAgIGNvbnN0IGVsZW1lbnQgPSBldmVudC50YXJnZXQ7XG4gICAgY29uc3QgY29tcHV0ZWRTdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpO1xuICAgIGNvbnN0IGRlZmF1bHRDb250ZXh0TWVudUFjdGlvbiA9IGNvbXB1dGVkU3R5bGUuZ2V0UHJvcGVydHlWYWx1ZShcIi0tZGVmYXVsdC1jb250ZXh0bWVudVwiKS50cmltKCk7XG4gICAgc3dpdGNoIChkZWZhdWx0Q29udGV4dE1lbnVBY3Rpb24pIHtcbiAgICAgICAgY2FzZSBcInNob3dcIjpcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY2FzZSBcImhpZGVcIjpcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAvLyBDaGVjayBpZiBjb250ZW50RWRpdGFibGUgaXMgdHJ1ZVxuICAgICAgICAgICAgaWYgKGVsZW1lbnQuaXNDb250ZW50RWRpdGFibGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRleHQgaGFzIGJlZW4gc2VsZWN0ZWRcbiAgICAgICAgICAgIGNvbnN0IHNlbGVjdGlvbiA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgICAgIGNvbnN0IGhhc1NlbGVjdGlvbiA9IChzZWxlY3Rpb24udG9TdHJpbmcoKS5sZW5ndGggPiAwKVxuICAgICAgICAgICAgaWYgKGhhc1NlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0aW9uLnJhbmdlQ291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByYW5nZSA9IHNlbGVjdGlvbi5nZXRSYW5nZUF0KGkpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0cyA9IHJhbmdlLmdldENsaWVudFJlY3RzKCk7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgcmVjdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlY3QgPSByZWN0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KHJlY3QubGVmdCwgcmVjdC50b3ApID09PSBlbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGFnbmFtZSBpcyBpbnB1dCBvciB0ZXh0YXJlYVxuICAgICAgICAgICAgaWYgKGVsZW1lbnQudGFnTmFtZSA9PT0gXCJJTlBVVFwiIHx8IGVsZW1lbnQudGFnTmFtZSA9PT0gXCJURVhUQVJFQVwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1NlbGVjdGlvbiB8fCAoIWVsZW1lbnQucmVhZE9ubHkgJiYgIWVsZW1lbnQuZGlzYWJsZWQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGhpZGUgZGVmYXVsdCBjb250ZXh0IG1lbnVcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbi8qKlxuICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBrZXkgZnJvbSB0aGUgZmxhZyBtYXAuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGtleVN0cmluZyAtIFRoZSBrZXkgdG8gcmV0cmlldmUgdGhlIHZhbHVlIGZvci5cbiAqIEByZXR1cm4geyp9IC0gVGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgc3BlY2lmaWVkIGtleS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldEZsYWcoa2V5U3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZmxhZ3Nba2V5U3RyaW5nXTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byByZXRyaWV2ZSBmbGFnICdcIiArIGtleVN0cmluZyArIFwiJzogXCIgKyBlKTtcbiAgICB9XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQge2ludm9rZSwgSXNXaW5kb3dzfSBmcm9tIFwiLi9zeXN0ZW1cIjtcbmltcG9ydCB7R2V0RmxhZ30gZnJvbSBcIi4vZmxhZ3NcIjtcblxuLy8gU2V0dXBcbmxldCBzaG91bGREcmFnID0gZmFsc2U7XG5sZXQgcmVzaXphYmxlID0gZmFsc2U7XG5sZXQgcmVzaXplRWRnZSA9IG51bGw7XG5sZXQgZGVmYXVsdEN1cnNvciA9IFwiYXV0b1wiO1xuXG53aW5kb3cuX3dhaWxzID0gd2luZG93Ll93YWlscyB8fCB7fTtcblxud2luZG93Ll93YWlscy5zZXRSZXNpemFibGUgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJlc2l6YWJsZSA9IHZhbHVlO1xufTtcblxud2luZG93Ll93YWlscy5lbmREcmFnID0gZnVuY3Rpb24oKSB7XG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS5jdXJzb3IgPSAnZGVmYXVsdCc7XG4gICAgc2hvdWxkRHJhZyA9IGZhbHNlO1xufTtcblxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIG9uTW91c2VEb3duKTtcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBvbk1vdXNlTW92ZSk7XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIG9uTW91c2VVcCk7XG5cblxuZnVuY3Rpb24gZHJhZ1Rlc3QoZSkge1xuICAgIGxldCB2YWwgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlLnRhcmdldCkuZ2V0UHJvcGVydHlWYWx1ZShcIi0td2FpbHMtZHJhZ2dhYmxlXCIpO1xuICAgIGxldCBtb3VzZVByZXNzZWQgPSBlLmJ1dHRvbnMgIT09IHVuZGVmaW5lZCA/IGUuYnV0dG9ucyA6IGUud2hpY2g7XG4gICAgaWYgKCF2YWwgfHwgdmFsID09PSBcIlwiIHx8IHZhbC50cmltKCkgIT09IFwiZHJhZ1wiIHx8IG1vdXNlUHJlc3NlZCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBlLmRldGFpbCA9PT0gMTtcbn1cblxuZnVuY3Rpb24gb25Nb3VzZURvd24oZSkge1xuXG4gICAgLy8gQ2hlY2sgZm9yIHJlc2l6aW5nXG4gICAgaWYgKHJlc2l6ZUVkZ2UpIHtcbiAgICAgICAgaW52b2tlKFwid2FpbHM6cmVzaXplOlwiICsgcmVzaXplRWRnZSk7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChkcmFnVGVzdChlKSkge1xuICAgICAgICAvLyBUaGlzIGNoZWNrcyBmb3IgY2xpY2tzIG9uIHRoZSBzY3JvbGwgYmFyXG4gICAgICAgIGlmIChlLm9mZnNldFggPiBlLnRhcmdldC5jbGllbnRXaWR0aCB8fCBlLm9mZnNldFkgPiBlLnRhcmdldC5jbGllbnRIZWlnaHQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzaG91bGREcmFnID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzaG91bGREcmFnID0gZmFsc2U7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBvbk1vdXNlVXAoKSB7XG4gICAgc2hvdWxkRHJhZyA9IGZhbHNlO1xufVxuXG5mdW5jdGlvbiBzZXRSZXNpemUoY3Vyc29yKSB7XG4gICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmN1cnNvciA9IGN1cnNvciB8fCBkZWZhdWx0Q3Vyc29yO1xuICAgIHJlc2l6ZUVkZ2UgPSBjdXJzb3I7XG59XG5cbmZ1bmN0aW9uIG9uTW91c2VNb3ZlKGUpIHtcbiAgICBpZiAoc2hvdWxkRHJhZykge1xuICAgICAgICBzaG91bGREcmFnID0gZmFsc2U7XG4gICAgICAgIGxldCBtb3VzZVByZXNzZWQgPSBlLmJ1dHRvbnMgIT09IHVuZGVmaW5lZCA/IGUuYnV0dG9ucyA6IGUud2hpY2g7XG4gICAgICAgIGlmIChtb3VzZVByZXNzZWQgPiAwKSB7XG4gICAgICAgICAgICBpbnZva2UoXCJ3YWlsczpkcmFnXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICghcmVzaXphYmxlIHx8ICFJc1dpbmRvd3MoKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChkZWZhdWx0Q3Vyc29yID09IG51bGwpIHtcbiAgICAgICAgZGVmYXVsdEN1cnNvciA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5jdXJzb3I7XG4gICAgfVxuICAgIGxldCByZXNpemVIYW5kbGVIZWlnaHQgPSBHZXRGbGFnKFwic3lzdGVtLnJlc2l6ZUhhbmRsZUhlaWdodFwiKSB8fCA1O1xuICAgIGxldCByZXNpemVIYW5kbGVXaWR0aCA9IEdldEZsYWcoXCJzeXN0ZW0ucmVzaXplSGFuZGxlV2lkdGhcIikgfHwgNTtcblxuICAgIC8vIEV4dHJhIHBpeGVscyBmb3IgdGhlIGNvcm5lciBhcmVhc1xuICAgIGxldCBjb3JuZXJFeHRyYSA9IEdldEZsYWcoXCJyZXNpemVDb3JuZXJFeHRyYVwiKSB8fCAxMDtcblxuICAgIGxldCByaWdodEJvcmRlciA9IHdpbmRvdy5vdXRlcldpZHRoIC0gZS5jbGllbnRYIDwgcmVzaXplSGFuZGxlV2lkdGg7XG4gICAgbGV0IGxlZnRCb3JkZXIgPSBlLmNsaWVudFggPCByZXNpemVIYW5kbGVXaWR0aDtcbiAgICBsZXQgdG9wQm9yZGVyID0gZS5jbGllbnRZIDwgcmVzaXplSGFuZGxlSGVpZ2h0O1xuICAgIGxldCBib3R0b21Cb3JkZXIgPSB3aW5kb3cub3V0ZXJIZWlnaHQgLSBlLmNsaWVudFkgPCByZXNpemVIYW5kbGVIZWlnaHQ7XG5cbiAgICAvLyBBZGp1c3QgZm9yIGNvcm5lcnNcbiAgICBsZXQgcmlnaHRDb3JuZXIgPSB3aW5kb3cub3V0ZXJXaWR0aCAtIGUuY2xpZW50WCA8IChyZXNpemVIYW5kbGVXaWR0aCArIGNvcm5lckV4dHJhKTtcbiAgICBsZXQgbGVmdENvcm5lciA9IGUuY2xpZW50WCA8IChyZXNpemVIYW5kbGVXaWR0aCArIGNvcm5lckV4dHJhKTtcbiAgICBsZXQgdG9wQ29ybmVyID0gZS5jbGllbnRZIDwgKHJlc2l6ZUhhbmRsZUhlaWdodCArIGNvcm5lckV4dHJhKTtcbiAgICBsZXQgYm90dG9tQ29ybmVyID0gd2luZG93Lm91dGVySGVpZ2h0IC0gZS5jbGllbnRZIDwgKHJlc2l6ZUhhbmRsZUhlaWdodCArIGNvcm5lckV4dHJhKTtcblxuICAgIC8vIElmIHdlIGFyZW4ndCBvbiBhbiBlZGdlLCBidXQgd2VyZSwgcmVzZXQgdGhlIGN1cnNvciB0byBkZWZhdWx0XG4gICAgaWYgKCFsZWZ0Qm9yZGVyICYmICFyaWdodEJvcmRlciAmJiAhdG9wQm9yZGVyICYmICFib3R0b21Cb3JkZXIgJiYgcmVzaXplRWRnZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHNldFJlc2l6ZSgpO1xuICAgIH1cbiAgICAvLyBBZGp1c3RlZCBmb3IgY29ybmVyIGFyZWFzXG4gICAgZWxzZSBpZiAocmlnaHRDb3JuZXIgJiYgYm90dG9tQ29ybmVyKSBzZXRSZXNpemUoXCJzZS1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAobGVmdENvcm5lciAmJiBib3R0b21Db3JuZXIpIHNldFJlc2l6ZShcInN3LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Q29ybmVyICYmIHRvcENvcm5lcikgc2V0UmVzaXplKFwibnctcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKHRvcENvcm5lciAmJiByaWdodENvcm5lcikgc2V0UmVzaXplKFwibmUtcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGxlZnRCb3JkZXIpIHNldFJlc2l6ZShcInctcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKHRvcEJvcmRlcikgc2V0UmVzaXplKFwibi1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAoYm90dG9tQm9yZGVyKSBzZXRSZXNpemUoXCJzLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChyaWdodEJvcmRlcikgc2V0UmVzaXplKFwiZS1yZXNpemVcIik7XG59IiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZVwiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQXBwbGljYXRpb24sICcnKTtcblxuY29uc3QgSGlkZU1ldGhvZCA9IDA7XG5jb25zdCBTaG93TWV0aG9kID0gMTtcbmNvbnN0IFF1aXRNZXRob2QgPSAyO1xuXG4vKipcbiAqIEhpZGVzIGEgY2VydGFpbiBtZXRob2QgYnkgY2FsbGluZyB0aGUgSGlkZU1ldGhvZCBmdW5jdGlvbi5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XG4gICAgcmV0dXJuIGNhbGwoSGlkZU1ldGhvZCk7XG59XG5cbi8qKlxuICogQ2FsbHMgdGhlIFNob3dNZXRob2QgYW5kIHJldHVybnMgdGhlIHJlc3VsdC5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gU2hvdygpIHtcbiAgICByZXR1cm4gY2FsbChTaG93TWV0aG9kKTtcbn1cblxuLyoqXG4gKiBDYWxscyB0aGUgUXVpdE1ldGhvZCB0byB0ZXJtaW5hdGUgdGhlIHByb2dyYW0uXG4gKlxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFF1aXQoKSB7XG4gICAgcmV0dXJuIGNhbGwoUXVpdE1ldGhvZCk7XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZVwiO1xuaW1wb3J0IHsgbmFub2lkIH0gZnJvbSAnbmFub2lkL25vbi1zZWN1cmUnO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLmNhbGxSZXN1bHRIYW5kbGVyID0gcmVzdWx0SGFuZGxlcjtcbndpbmRvdy5fd2FpbHMuY2FsbEVycm9ySGFuZGxlciA9IGVycm9ySGFuZGxlcjtcblxuXG5jb25zdCBDYWxsQmluZGluZyA9IDA7XG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5DYWxsLCAnJyk7XG5jb25zdCBjYW5jZWxDYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5DYW5jZWxDYWxsLCAnJyk7XG5sZXQgY2FsbFJlc3BvbnNlcyA9IG5ldyBNYXAoKTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgSUQgdXNpbmcgdGhlIG5hbm9pZCBsaWJyYXJ5LlxuICpcbiAqIEByZXR1cm4ge3N0cmluZ30gLSBBIHVuaXF1ZSBJRCB0aGF0IGRvZXMgbm90IGV4aXN0IGluIHRoZSBjYWxsUmVzcG9uc2VzIHNldC5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVJRCgpIHtcbiAgICBsZXQgcmVzdWx0O1xuICAgIGRvIHtcbiAgICAgICAgcmVzdWx0ID0gbmFub2lkKCk7XG4gICAgfSB3aGlsZSAoY2FsbFJlc3BvbnNlcy5oYXMocmVzdWx0KSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBIYW5kbGVzIHRoZSByZXN1bHQgb2YgYSBjYWxsIHJlcXVlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSByZXF1ZXN0IHRvIGhhbmRsZSB0aGUgcmVzdWx0IGZvci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhIC0gVGhlIHJlc3VsdCBkYXRhIG9mIHRoZSByZXF1ZXN0LlxuICogQHBhcmFtIHtib29sZWFufSBpc0pTT04gLSBJbmRpY2F0ZXMgd2hldGhlciB0aGUgZGF0YSBpcyBKU09OIG9yIG5vdC5cbiAqXG4gKiBAcmV0dXJuIHt1bmRlZmluZWR9IC0gVGhpcyBtZXRob2QgZG9lcyBub3QgcmV0dXJuIGFueSB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gcmVzdWx0SGFuZGxlcihpZCwgZGF0YSwgaXNKU09OKSB7XG4gICAgY29uc3QgcHJvbWlzZUhhbmRsZXIgPSBnZXRBbmREZWxldGVSZXNwb25zZShpZCk7XG4gICAgaWYgKHByb21pc2VIYW5kbGVyKSB7XG4gICAgICAgIHByb21pc2VIYW5kbGVyLnJlc29sdmUoaXNKU09OID8gSlNPTi5wYXJzZShkYXRhKSA6IGRhdGEpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBIYW5kbGVzIHRoZSBlcnJvciBmcm9tIGEgY2FsbCByZXF1ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIFRoZSBpZCBvZiB0aGUgcHJvbWlzZSBoYW5kbGVyLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBUaGUgZXJyb3IgbWVzc2FnZSB0byByZWplY3QgdGhlIHByb21pc2UgaGFuZGxlciB3aXRoLlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGVycm9ySGFuZGxlcihpZCwgbWVzc2FnZSkge1xuICAgIGNvbnN0IHByb21pc2VIYW5kbGVyID0gZ2V0QW5kRGVsZXRlUmVzcG9uc2UoaWQpO1xuICAgIGlmIChwcm9taXNlSGFuZGxlcikge1xuICAgICAgICBwcm9taXNlSGFuZGxlci5yZWplY3QobWVzc2FnZSk7XG4gICAgfVxufVxuXG4vKipcbiAqIFJldHJpZXZlcyBhbmQgcmVtb3ZlcyB0aGUgcmVzcG9uc2UgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBJRCBmcm9tIHRoZSBjYWxsUmVzcG9uc2VzIG1hcC5cbiAqXG4gKiBAcGFyYW0ge2FueX0gaWQgLSBUaGUgSUQgb2YgdGhlIHJlc3BvbnNlIHRvIGJlIHJldHJpZXZlZCBhbmQgcmVtb3ZlZC5cbiAqXG4gKiBAcmV0dXJucyB7YW55fSBUaGUgcmVzcG9uc2Ugb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gSUQuXG4gKi9cbmZ1bmN0aW9uIGdldEFuZERlbGV0ZVJlc3BvbnNlKGlkKSB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBjYWxsUmVzcG9uc2VzLmdldChpZCk7XG4gICAgY2FsbFJlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgIHJldHVybiByZXNwb25zZTtcbn1cblxuLyoqXG4gKiBFeGVjdXRlcyBhIGNhbGwgdXNpbmcgdGhlIHByb3ZpZGVkIHR5cGUgYW5kIG9wdGlvbnMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSB0eXBlIC0gVGhlIHR5cGUgb2YgY2FsbCB0byBleGVjdXRlLlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSAtIEFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgdGhlIGNhbGwuXG4gKiBAcmV0dXJuIHtQcm9taXNlfSAtIEEgcHJvbWlzZSB0aGF0IHdpbGwgYmUgcmVzb2x2ZWQgb3IgcmVqZWN0ZWQgYmFzZWQgb24gdGhlIHJlc3VsdCBvZiB0aGUgY2FsbC4gSXQgYWxzbyBoYXMgYSBjYW5jZWwgbWV0aG9kIHRvIGNhbmNlbCBhIGxvbmcgcnVubmluZyByZXF1ZXN0LlxuICovXG5mdW5jdGlvbiBjYWxsQmluZGluZyh0eXBlLCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBpZCA9IGdlbmVyYXRlSUQoKTtcbiAgICBjb25zdCBkb0NhbmNlbCA9ICgpID0+IHsgcmV0dXJuIGNhbmNlbENhbGwodHlwZSwge1wiY2FsbC1pZFwiOiBpZH0pIH07XG4gICAgbGV0IHF1ZXVlZENhbmNlbCA9IGZhbHNlLCBjYWxsUnVubmluZyA9IGZhbHNlO1xuICAgIGxldCBwID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBvcHRpb25zW1wiY2FsbC1pZFwiXSA9IGlkO1xuICAgICAgICBjYWxsUmVzcG9uc2VzLnNldChpZCwgeyByZXNvbHZlLCByZWplY3QgfSk7XG4gICAgICAgIGNhbGwodHlwZSwgb3B0aW9ucykuXG4gICAgICAgICAgICB0aGVuKChfKSA9PiB7XG4gICAgICAgICAgICAgICAgY2FsbFJ1bm5pbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGlmIChxdWV1ZWRDYW5jZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvQ2FuY2VsKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuXG4gICAgICAgICAgICBjYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIGNhbGxSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH0pO1xuICAgIHAuY2FuY2VsID0gKCkgPT4ge1xuICAgICAgICBpZiAoY2FsbFJ1bm5pbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBkb0NhbmNlbCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcXVldWVkQ2FuY2VsID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gcDtcbn1cblxuLyoqXG4gKiBDYWxsIG1ldGhvZC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIFRoZSBvcHRpb25zIGZvciB0aGUgbWV0aG9kLlxuICogQHJldHVybnMge09iamVjdH0gLSBUaGUgcmVzdWx0IG9mIHRoZSBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQ2FsbChvcHRpb25zKSB7XG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCBvcHRpb25zKTtcbn1cblxuLyoqXG4gKiBFeGVjdXRlcyBhIG1ldGhvZCBieSBuYW1lLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2ROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIG1ldGhvZCBpbiB0aGUgZm9ybWF0ICdwYWNrYWdlLnN0cnVjdC5tZXRob2QnLlxuICogQHBhcmFtIHsuLi4qfSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIG5hbWUgaXMgbm90IGEgc3RyaW5nIG9yIGlzIG5vdCBpbiB0aGUgY29ycmVjdCBmb3JtYXQuXG4gKiBAcmV0dXJucyB7Kn0gVGhlIHJlc3VsdCBvZiB0aGUgbWV0aG9kIGV4ZWN1dGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEJ5TmFtZShtZXRob2ROYW1lLCAuLi5hcmdzKSB7XG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCB7XG4gICAgICAgIG1ldGhvZE5hbWUsXG4gICAgICAgIGFyZ3NcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBDYWxscyBhIG1ldGhvZCBieSBpdHMgSUQgd2l0aCB0aGUgc3BlY2lmaWVkIGFyZ3VtZW50cy5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gbWV0aG9kSUQgLSBUaGUgSUQgb2YgdGhlIG1ldGhvZCB0byBjYWxsLlxuICogQHBhcmFtIHsuLi4qfSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXG4gKiBAcmV0dXJuIHsqfSAtIFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQnlJRChtZXRob2RJRCwgLi4uYXJncykge1xuICAgIHJldHVybiBjYWxsQmluZGluZyhDYWxsQmluZGluZywge1xuICAgICAgICBtZXRob2RJRCxcbiAgICAgICAgYXJnc1xuICAgIH0pO1xufVxuXG4vKipcbiAqIENhbGxzIGEgbWV0aG9kIG9uIGEgcGx1Z2luLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwbHVnaW5OYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHBsdWdpbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2ROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIG1ldGhvZCB0byBjYWxsLlxuICogQHBhcmFtIHsuLi4qfSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXG4gKiBAcmV0dXJucyB7Kn0gLSBUaGUgcmVzdWx0IG9mIHRoZSBtZXRob2QgY2FsbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFBsdWdpbihwbHVnaW5OYW1lLCBtZXRob2ROYW1lLCAuLi5hcmdzKSB7XG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCB7XG4gICAgICAgIHBhY2thZ2VOYW1lOiBcIndhaWxzLXBsdWdpbnNcIixcbiAgICAgICAgc3RydWN0TmFtZTogcGx1Z2luTmFtZSxcbiAgICAgICAgbWV0aG9kTmFtZSxcbiAgICAgICAgYXJnc1xuICAgIH0pO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQ2xpcGJvYXJkLCAnJyk7XG5jb25zdCBDbGlwYm9hcmRTZXRUZXh0ID0gMDtcbmNvbnN0IENsaXBib2FyZFRleHQgPSAxO1xuXG4vKipcbiAqIFNldHMgdGhlIHRleHQgdG8gdGhlIENsaXBib2FyZC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdGV4dCAtIFRoZSB0ZXh0IHRvIGJlIHNldCB0byB0aGUgQ2xpcGJvYXJkLlxuICogQHJldHVybiB7UHJvbWlzZX0gLSBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBvcGVyYXRpb24gaXMgc3VjY2Vzc2Z1bC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldFRleHQodGV4dCkge1xuICAgIHJldHVybiBjYWxsKENsaXBib2FyZFNldFRleHQsIHt0ZXh0fSk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBDbGlwYm9hcmQgdGV4dFxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgdGV4dCBmcm9tIHRoZSBDbGlwYm9hcmQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBUZXh0KCkge1xuICAgIHJldHVybiBjYWxsKENsaXBib2FyZFRleHQpO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbi8qKlxuICogQW55IGlzIGEgZHVtbXkgY3JlYXRpb24gZnVuY3Rpb24gZm9yIHNpbXBsZSBvciB1bmtub3duIHR5cGVzLlxuICogQHRlbXBsYXRlIFRcbiAqIEBwYXJhbSB7YW55fSBzb3VyY2VcbiAqIEByZXR1cm5zIHtUfVxuICovXG5leHBvcnQgZnVuY3Rpb24gQW55KHNvdXJjZSkge1xuICAgIHJldHVybiAvKiogQHR5cGUge1R9ICovKHNvdXJjZSk7XG59XG5cbi8qKlxuICogQnl0ZVNsaWNlIGlzIGEgY3JlYXRpb24gZnVuY3Rpb24gdGhhdCByZXBsYWNlc1xuICogbnVsbCBzdHJpbmdzIHdpdGggZW1wdHkgc3RyaW5ncy5cbiAqIEBwYXJhbSB7YW55fSBzb3VyY2VcbiAqIEByZXR1cm5zIHtzdHJpbmd9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBCeXRlU2xpY2Uoc291cmNlKSB7XG4gICAgcmV0dXJuIC8qKiBAdHlwZSB7YW55fSAqLygoc291cmNlID09IG51bGwpID8gXCJcIiA6IHNvdXJjZSk7XG59XG5cbi8qKlxuICogQXJyYXkgdGFrZXMgYSBjcmVhdGlvbiBmdW5jdGlvbiBmb3IgYW4gYXJiaXRyYXJ5IHR5cGVcbiAqIGFuZCByZXR1cm5zIGFuIGluLXBsYWNlIGNyZWF0aW9uIGZ1bmN0aW9uIGZvciBhbiBhcnJheVxuICogd2hvc2UgZWxlbWVudHMgYXJlIG9mIHRoYXQgdHlwZS5cbiAqIEB0ZW1wbGF0ZSBUXG4gKiBAcGFyYW0geyhzb3VyY2U6IGFueSkgPT4gVH0gZWxlbWVudFxuICogQHJldHVybnMgeyhzb3VyY2U6IGFueSkgPT4gVFtdfVxuICovXG5leHBvcnQgZnVuY3Rpb24gQXJyYXkoZWxlbWVudCkge1xuICAgIGlmIChlbGVtZW50ID09PSBBbnkpIHtcbiAgICAgICAgcmV0dXJuIChzb3VyY2UpID0+IChzb3VyY2UgPT09IG51bGwgPyBbXSA6IHNvdXJjZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIChzb3VyY2UpID0+IHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc291cmNlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBzb3VyY2VbaV0gPSBlbGVtZW50KHNvdXJjZVtpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9O1xufVxuXG4vKipcbiAqIE1hcCB0YWtlcyBjcmVhdGlvbiBmdW5jdGlvbnMgZm9yIHR3byBhcmJpdHJhcnkgdHlwZXNcbiAqIGFuZCByZXR1cm5zIGFuIGluLXBsYWNlIGNyZWF0aW9uIGZ1bmN0aW9uIGZvciBhbiBvYmplY3RcbiAqIHdob3NlIGtleXMgYW5kIHZhbHVlcyBhcmUgb2YgdGhvc2UgdHlwZXMuXG4gKiBAdGVtcGxhdGUgSywgVlxuICogQHBhcmFtIHsoc291cmNlOiBhbnkpID0+IEt9IGtleVxuICogQHBhcmFtIHsoc291cmNlOiBhbnkpID0+IFZ9IHZhbHVlXG4gKiBAcmV0dXJucyB7KHNvdXJjZTogYW55KSA9PiB7IFtfOiBLXTogViB9fVxuICovXG5leHBvcnQgZnVuY3Rpb24gTWFwKGtleSwgdmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT09IEFueSkge1xuICAgICAgICByZXR1cm4gKHNvdXJjZSkgPT4gKHNvdXJjZSA9PT0gbnVsbCA/IHt9IDogc291cmNlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gKHNvdXJjZSkgPT4ge1xuICAgICAgICBpZiAoc291cmNlID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gc291cmNlKSB7XG4gICAgICAgICAgICBzb3VyY2Vba2V5XSA9IHZhbHVlKHNvdXJjZVtrZXldKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc291cmNlO1xuICAgIH07XG59XG5cbi8qKlxuICogTnVsbGFibGUgdGFrZXMgYSBjcmVhdGlvbiBmdW5jdGlvbiBmb3IgYW4gYXJiaXRyYXJ5IHR5cGVcbiAqIGFuZCByZXR1cm5zIGEgY3JlYXRpb24gZnVuY3Rpb24gZm9yIGEgbnVsbGFibGUgdmFsdWUgb2YgdGhhdCB0eXBlLlxuICogQHRlbXBsYXRlIFRcbiAqIEBwYXJhbSB7KHNvdXJjZTogYW55KSA9PiBUfSBlbGVtZW50XG4gKiBAcmV0dXJucyB7KHNvdXJjZTogYW55KSA9PiAoVCB8IG51bGwpfVxuICovXG5leHBvcnQgZnVuY3Rpb24gTnVsbGFibGUoZWxlbWVudCkge1xuICAgIGlmIChlbGVtZW50ID09PSBBbnkpIHtcbiAgICAgICAgcmV0dXJuIEFueTtcbiAgICB9XG5cbiAgICByZXR1cm4gKHNvdXJjZSkgPT4gKHNvdXJjZSA9PT0gbnVsbCA/IG51bGwgOiBlbGVtZW50KHNvdXJjZSkpO1xufVxuXG4vKipcbiAqIFN0cnVjdCB0YWtlcyBhbiBvYmplY3QgbWFwcGluZyBmaWVsZCBuYW1lcyB0byBjcmVhdGlvbiBmdW5jdGlvbnNcbiAqIGFuZCByZXR1cm5zIGFuIGluLXBsYWNlIGNyZWF0aW9uIGZ1bmN0aW9uIGZvciBhIHN0cnVjdC5cbiAqIEB0ZW1wbGF0ZSB7eyBbXzogc3RyaW5nXTogKChzb3VyY2U6IGFueSkgPT4gYW55KSB9fSBUXG4gKiBAdGVtcGxhdGUge3sgW0tleSBpbiBrZXlvZiBUXT86IFJldHVyblR5cGU8VFtLZXldPiB9fSBVXG4gKiBAcGFyYW0ge1R9IGNyZWF0ZUZpZWxkXG4gKiBAcmV0dXJucyB7KHNvdXJjZTogYW55KSA9PiBVfVxuICovXG5leHBvcnQgZnVuY3Rpb24gU3RydWN0KGNyZWF0ZUZpZWxkKSB7XG4gICAgbGV0IGFsbEFueSA9IHRydWU7XG4gICAgZm9yIChjb25zdCBuYW1lIGluIGNyZWF0ZUZpZWxkKSB7XG4gICAgICAgIGlmIChjcmVhdGVGaWVsZFtuYW1lXSAhPT0gQW55KSB7XG4gICAgICAgICAgICBhbGxBbnkgPSBmYWxzZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChhbGxBbnkpIHtcbiAgICAgICAgcmV0dXJuIEFueTtcbiAgICB9XG5cbiAgICByZXR1cm4gKHNvdXJjZSkgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IG5hbWUgaW4gY3JlYXRlRmllbGQpIHtcbiAgICAgICAgICAgIGlmIChuYW1lIGluIHNvdXJjZSkge1xuICAgICAgICAgICAgICAgIHNvdXJjZVtuYW1lXSA9IGNyZWF0ZUZpZWxkW25hbWVdKHNvdXJjZVtuYW1lXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9O1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gU2l6ZVxuICogQHByb3BlcnR5IHtudW1iZXJ9IFdpZHRoIC0gVGhlIHdpZHRoLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IEhlaWdodCAtIFRoZSBoZWlnaHQuXG4gKi9cblxuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFJlY3RcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIFggY29vcmRpbmF0ZSBvZiB0aGUgb3JpZ2luLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFkgLSBUaGUgWSBjb29yZGluYXRlIG9mIHRoZSBvcmlnaW4uXG4gKiBAcHJvcGVydHkge251bWJlcn0gV2lkdGggLSBUaGUgd2lkdGggb2YgdGhlIHJlY3RhbmdsZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBIZWlnaHQgLSBUaGUgaGVpZ2h0IG9mIHRoZSByZWN0YW5nbGUuXG4gKi9cblxuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNjcmVlblxuICogQHByb3BlcnR5IHtzdHJpbmd9IElkIC0gVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBzY3JlZW4uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTmFtZSAtIEh1bWFuIHJlYWRhYmxlIG5hbWUgb2YgdGhlIHNjcmVlbi5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBTY2FsZUZhY3RvciAtIFRoZSBzY2FsZSBmYWN0b3Igb2YgdGhlIHNjcmVlbiAoRFBJLzk2KS4gMSA9IHN0YW5kYXJkIERQSSwgMiA9IEhpRFBJIChSZXRpbmEpLCBldGMuXG4gKiBAcHJvcGVydHkge251bWJlcn0gWCAtIFRoZSBYIGNvb3JkaW5hdGUgb2YgdGhlIHNjcmVlbi5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBZIC0gVGhlIFkgY29vcmRpbmF0ZSBvZiB0aGUgc2NyZWVuLlxuICogQHByb3BlcnR5IHtTaXplfSBTaXplIC0gQ29udGFpbnMgdGhlIHdpZHRoIGFuZCBoZWlnaHQgb2YgdGhlIHNjcmVlbi5cbiAqIEBwcm9wZXJ0eSB7UmVjdH0gQm91bmRzIC0gQ29udGFpbnMgdGhlIGJvdW5kcyBvZiB0aGUgc2NyZWVuIGluIHRlcm1zIG9mIFgsIFksIFdpZHRoLCBhbmQgSGVpZ2h0LlxuICogQHByb3BlcnR5IHtSZWN0fSBQaHlzaWNhbEJvdW5kcyAtIENvbnRhaW5zIHRoZSBwaHlzaWNhbCBib3VuZHMgb2YgdGhlIHNjcmVlbiBpbiB0ZXJtcyBvZiBYLCBZLCBXaWR0aCwgYW5kIEhlaWdodCAoYmVmb3JlIHNjYWxpbmcpLlxuICogQHByb3BlcnR5IHtSZWN0fSBXb3JrQXJlYSAtIENvbnRhaW5zIHRoZSBhcmVhIG9mIHRoZSBzY3JlZW4gdGhhdCBpcyBhY3R1YWxseSB1c2FibGUgKGV4Y2x1ZGluZyB0YXNrYmFyIGFuZCBvdGhlciBzeXN0ZW0gVUkpLlxuICogQHByb3BlcnR5IHtSZWN0fSBQaHlzaWNhbFdvcmtBcmVhIC0gQ29udGFpbnMgdGhlIHBoeXNpY2FsIFdvcmtBcmVhIG9mIHRoZSBzY3JlZW4gKGJlZm9yZSBzY2FsaW5nKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gSXNQcmltYXJ5IC0gVHJ1ZSBpZiB0aGlzIGlzIHRoZSBwcmltYXJ5IG1vbml0b3Igc2VsZWN0ZWQgYnkgdGhlIHVzZXIgaW4gdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gKiBAcHJvcGVydHkge251bWJlcn0gUm90YXRpb24gLSBUaGUgcm90YXRpb24gb2YgdGhlIHNjcmVlbi5cbiAqL1xuXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLlNjcmVlbnMsICcnKTtcblxuY29uc3QgZ2V0QWxsID0gMDtcbmNvbnN0IGdldFByaW1hcnkgPSAxO1xuY29uc3QgZ2V0Q3VycmVudCA9IDI7XG5cbi8qKlxuICogR2V0cyBhbGwgc2NyZWVucy5cbiAqIEByZXR1cm5zIHtQcm9taXNlPFNjcmVlbltdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgb2YgU2NyZWVuIG9iamVjdHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRBbGwoKSB7XG4gICAgcmV0dXJuIGNhbGwoZ2V0QWxsKTtcbn1cbi8qKlxuICogR2V0cyB0aGUgcHJpbWFyeSBzY3JlZW4uXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxTY3JlZW4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgcHJpbWFyeSBzY3JlZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRQcmltYXJ5KCkge1xuICAgIHJldHVybiBjYWxsKGdldFByaW1hcnkpO1xufVxuLyoqXG4gKiBHZXRzIHRoZSBjdXJyZW50IGFjdGl2ZSBzY3JlZW4uXG4gKlxuICogQHJldHVybnMge1Byb21pc2U8U2NyZWVuPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgY3VycmVudCBhY3RpdmUgc2NyZWVuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gR2V0Q3VycmVudCgpIHtcbiAgICByZXR1cm4gY2FsbChnZXRDdXJyZW50KTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7OztBQ0FBO0FBQUE7QUFBQTtBQUFBO0FBQUE7OztBQ0FBO0FBQUE7QUFBQTtBQUFBOzs7QUNBQSxJQUFJLGNBQ0Y7QUFXSyxJQUFJLFNBQVMsQ0FBQyxPQUFPLE9BQU87QUFDakMsTUFBSSxLQUFLO0FBQ1QsTUFBSSxJQUFJO0FBQ1IsU0FBTyxLQUFLO0FBQ1YsVUFBTSxZQUFhLEtBQUssT0FBTyxJQUFJLEtBQU0sQ0FBQztBQUFBLEVBQzVDO0FBQ0EsU0FBTztBQUNUOzs7QUNOQSxJQUFNLGFBQWEsT0FBTyxTQUFTLFNBQVM7QUFHckMsSUFBTSxjQUFjO0FBQUEsRUFDdkIsTUFBTTtBQUFBLEVBQ04sV0FBVztBQUFBLEVBQ1gsYUFBYTtBQUFBLEVBQ2IsUUFBUTtBQUFBLEVBQ1IsYUFBYTtBQUFBLEVBQ2IsUUFBUTtBQUFBLEVBQ1IsUUFBUTtBQUFBLEVBQ1IsU0FBUztBQUFBLEVBQ1QsUUFBUTtBQUFBLEVBQ1IsU0FBUztBQUFBLEVBQ1QsWUFBWTtBQUNoQjtBQUNPLElBQUksV0FBVyxPQUFPO0FBc0J0QixTQUFTLHVCQUF1QixRQUFRLFlBQVk7QUFDdkQsU0FBTyxTQUFVLFFBQVEsT0FBSyxNQUFNO0FBQ2hDLFdBQU8sa0JBQWtCLFFBQVEsUUFBUSxZQUFZLElBQUk7QUFBQSxFQUM3RDtBQUNKO0FBcUNBLFNBQVMsa0JBQWtCLFVBQVUsUUFBUSxZQUFZLE1BQU07QUFDM0QsTUFBSSxNQUFNLElBQUksSUFBSSxV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QUF5QztBQUFBLElBQ3pDLDBCQUEwQjtBQUFBLElBQzFCLG9DQUFvQztBQUFBLElBQ3BDLHNDQUFzQztBQUFBLElBQ3RDLG9DQUFvQztBQUFBLElBQ3BDLDBDQUEwQztBQUFBLElBQzFDLCtCQUErQjtBQUFBLElBQy9CLG9CQUFvQjtBQUFBLElBQ3BCLHdDQUF3QztBQUFBLElBQ3hDLHNCQUFzQjtBQUFBLElBQ3RCLHNCQUFzQjtBQUFBLElBQ3RCLDZCQUE2QjtBQUFBLElBQzdCLGdDQUFnQztBQUFBLElBQ2hDLHFCQUFxQjtBQUFBLElBQ3JCLDZCQUE2QjtBQUFBLElBQzdCLDBCQUEwQjtBQUFBLElBQzFCLHVCQUF1QjtBQUFBLElBQ3ZCLHVCQUF1QjtBQUFBLElBQ3ZCLDJCQUEyQjtBQUFBLElBQzNCLCtCQUErQjtBQUFBLElBQy9CLG9CQUFvQjtBQUFBLElBQ3BCLHFCQUFxQjtBQUFBLElBQ3JCLHFCQUFxQjtBQUFBLElBQ3JCLHNCQUFzQjtBQUFBLElBQ3RCLGdDQUFnQztBQUFBLElBQ2hDLGtDQUFrQztBQUFBLElBQ2xDLG1DQUFtQztBQUFBLElBQ25DLG9DQUFvQztBQUFBLElBQ3BDLCtCQUErQjtBQUFBLElBQy9CLDZCQUE2QjtBQUFBLElBQzdCLHVCQUF1QjtBQUFBLElBQ3ZCLGlDQUFpQztBQUFBLElBQ2pDLDhCQUE4QjtBQUFBLElBQzlCLDRCQUE0QjtBQUFBLElBQzVCLHNDQUFzQztBQUFBLElBQ3RDLDRCQUE0QjtBQUFBLElBQzVCLHNCQUFzQjtBQUFBLElBQ3RCLGtDQUFrQztBQUFBLElBQ2xDLHNCQUFzQjtBQUFBLElBQ3RCLHdCQUF3QjtBQUFBLElBQ3hCLDJCQUEyQjtBQUFBLElBQzNCLHdCQUF3QjtBQUFBLElBQ3hCLG1CQUFtQjtBQUFBLElBQ25CLDBCQUEwQjtBQUFBLElBQzFCLDhCQUE4QjtBQUFBLElBQzlCLHlCQUF5QjtBQUFBLElBQ3pCLDZCQUE2QjtBQUFBLElBQzdCLGlCQUFpQjtBQUFBLElBQ2pCLGdCQUFnQjtBQUFBLElBQ2hCLHNCQUFzQjtBQUFBLElBQ3RCLGVB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QUFRLE9BQU8sQ0FBQyxDQUFDO0FBQUEsSUFDakM7QUFDQSxXQUFPO0FBQUEsRUFDWDtBQUNKO0FBV08sU0FBU0MsS0FBSSxLQUFLLE9BQU87QUFDNUIsTUFBSSxVQUFVLEtBQUs7QUFDZixXQUFPLENBQUMsV0FBWSxXQUFXLE9BQU8sQ0FBQyxJQUFJO0FBQUEsRUFDL0M7QUFFQSxTQUFPLENBQUMsV0FBVztBQUNmLFFBQUksV0FBVyxNQUFNO0FBQ2pCLGFBQU8sQ0FBQztBQUFBLElBQ1o7QUFDQSxlQUFXQyxRQUFPLFFBQVE7QUFDdEIsYUFBT0EsSUFBRyxJQUFJLE1BQU0sT0FBT0EsSUFBRyxDQUFDO0FBQUEsSUFDbkM7QUFDQSxXQUFPO0FBQUEsRUFDWDtBQUNKO0FBU08sU0FBUyxTQUFTLFNBQVM7QUFDOUIsTUFBSSxZQUFZLEtBQUs7QUFDakIsV0FBTztBQUFBLEVBQ1g7QUFFQSxTQUFPLENBQUMsV0FBWSxXQUFXLE9BQU8sT0FBTyxRQUFRLE1BQU07QUFDL0Q7QUFVTyxTQUFTLE9BQU8sYUFBYTtBQUNoQyxNQUFJLFNBQVM7QUFDYixhQUFXLFFBQVEsYUFBYTtBQUM1QixRQUFJLFlBQVksSUFBSSxNQUFNLEtBQUs7QUFDM0IsZUFBUztBQUNUO0FBQUEsSUFDSjtBQUFBLEVBQ0o7QUFDQSxNQUFJLFFBQVE7QUFDUixXQUFPO0FBQUEsRUFDWDtBQUVBLFNBQU8sQ0FBQyxXQUFXO0FBQ2YsZUFBVyxRQUFRLGFBQWE7QUFDNUIsVUFBSSxRQUFRLFFBQVE7QUFDaEIsZUFBTyxJQUFJLElBQUksWUFBWSxJQUFJLEVBQUUsT0FBTyxJQUFJLENBQUM7QUFBQSxNQUNqRDtBQUFBLElBQ0o7QUFDQSxXQUFPO0FBQUEsRUFDWDtBQUNKOzs7QUM1SEE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBOENBLElBQU1DLFFBQU8sdUJBQXVCLFlBQVksU0FBUyxFQUFFO0FBRTNELElBQU0sU0FBUztBQUNmLElBQU0sYUFBYTtBQUNuQixJQUFNLGFBQWE7QUFNWixTQUFTLFNBQVM7QUFDckIsU0FBT0EsTUFBSyxNQUFNO0FBQ3RCO0FBS08sU0FBUyxhQUFhO0FBQ3pCLFNBQU9BLE1BQUssVUFBVTtBQUMxQjtBQU1PLFNBQVMsYUFBYTtBQUN6QixTQUFPQSxNQUFLLFVBQVU7QUFDMUI7OztBbkI5REEsT0FBTyxTQUFTLE9BQU8sVUFBVSxDQUFDO0FBbUNsQyxPQUFPLE9BQU8sU0FBZ0I7QUFDdkIsT0FBTyxxQkFBcUI7IiwKICAibmFtZXMiOiBbIkVycm9yIiwgImNhbGwiLCAiRXJyb3IiLCAiY2FsbCIsICJldmVudE5hbWUiLCAiY29udHJvbGxlciIsICJyZXNpemFibGUiLCAiY2FsbCIsICJjYWxsIiwgImNhbGwiLCAiSGlkZU1ldGhvZCIsICJTaG93TWV0aG9kIiwgImNhbGwiLCAiZ2VuZXJhdGVJRCIsICJjYWxsIiwgIk1hcCIsICJNYXAiLCAia2V5IiwgImNhbGwiXQp9Cg== diff --git a/frontend/runtime.js b/frontend/runtime.js new file mode 100644 index 0000000..7c1ffb2 --- /dev/null +++ b/frontend/runtime.js @@ -0,0 +1 @@ +var ge=Object.defineProperty;var w=(e,i)=>{for(var n in i)ge(e,n,{get:i[n],enumerable:!0})};var G={};w(G,{Application:()=>$,Browser:()=>I,Call:()=>ee,Clipboard:()=>ie,Create:()=>ne,Dialogs:()=>B,Events:()=>N,Flags:()=>Q,Screens:()=>oe,System:()=>X,WML:()=>j,Window:()=>E});var j={};w(j,{Enable:()=>Z,Reload:()=>me});var I={};w(I,{OpenURL:()=>P});var fe="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var D=(e=21)=>{let i="",n=e;for(;n--;)i+=fe[Math.random()*64|0];return i};var De=window.location.origin+"/wails/runtime",l={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9,CancelCall:10},Me=D();function d(e,i){return function(n,t=null){return Ce(e,n,i,t)}}function Ce(e,i,n,t){let r=new URL(De);r.searchParams.append("object",e),r.searchParams.append("method",i);let s={headers:{}};return n&&(s.headers["x-wails-window-name"]=n),t&&r.searchParams.append("args",JSON.stringify(t)),s.headers["x-wails-client-id"]=Me,new Promise((c,m)=>{fetch(r,s).then(a=>{if(a.ok)return a.headers.get("Content-Type")&&a.headers.get("Content-Type").indexOf("application/json")!==-1?a.json():a.text();m(Error(a.statusText))}).then(a=>c(a)).catch(a=>m(a))})}var Se=d(l.Browser,""),xe=0;function P(e){return Se(xe,{url:e})}var B={};w(B,{Error:()=>Be,Info:()=>Ie,OpenFile:()=>ze,Question:()=>T,SaveFile:()=>ke,Warning:()=>Te});window._wails=window._wails||{};window._wails.dialogErrorCallback=Pe;window._wails.dialogResultCallback=Oe;var Ae=0,ve=1,be=2,Re=3,Ee=4,ye=5,Ue=d(l.Dialog,""),h=new Map;function Fe(){let e;do e=D();while(h.has(e));return e}function M(e,i={}){let n=Fe();return i["dialog-id"]=n,new Promise((t,r)=>{h.set(n,{resolve:t,reject:r}),Ue(e,i).catch(s=>{r(s),h.delete(n)})})}function Oe(e,i,n){let t=h.get(e);t&&(n?t.resolve(JSON.parse(i)):t.resolve(i),h.delete(e))}function Pe(e,i){let n=h.get(e);n&&(n.reject(i),h.delete(e))}var Ie=e=>M(Ae,e),Te=e=>M(ve,e),Be=e=>M(be,e),T=e=>M(Re,e),ze=e=>M(Ee,e),ke=e=>M(ye,e);var N={};w(N,{Emit:()=>L,Off:()=>Ye,OffAll:()=>Ke,On:()=>Ze,OnMultiple:()=>k,Once:()=>je,Types:()=>Le,WailsEvent:()=>A,setup:()=>Ve});var ae={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver",WindowDidMove:"windows:WindowDidMove",WindowDidResize:"windows:WindowDidResize"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowDidMove:"linux:WindowDidMove",WindowDidResize:"linux:WindowDidResize",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged",WindowDidMove:"common:WindowDidMove",WindowDidResize:"common:WindowDidResize"}};var Le=ae;window._wails=window._wails||{};window._wails.dispatchWailsEvent=_e;var Ne=d(l.Events,""),He=0,u=new Map,z=class{constructor(i,n,t){this.eventName=i,this.maxCallbacks=t||-1,this.Callback=r=>(n(r),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},A=class{constructor(i,n=null){this.name=i,this.data=n}};function Ve(){}function _e(e){let i=u.get(e.name);if(i){let n=i.filter(t=>{if(t.Callback(e))return!0});n.length>0&&(i=i.filter(t=>!n.includes(t)),i.length===0?u.delete(e.name):u.set(e.name,i))}}function k(e,i,n){let t=u.get(e)||[],r=new z(e,i,n);return t.push(r),u.set(e,t),()=>Ge(r)}function Ze(e,i){return k(e,i,-1)}function je(e,i){return k(e,i,1)}function Ge(e){let i=e.eventName,n=u.get(i).filter(t=>t!==e);n.length===0?u.delete(i):u.set(i,n)}function Ye(e,...i){[e,...i].forEach(t=>u.delete(t))}function Ke(){u.clear()}function L(e){return Ne(He,e)}function le(){if(!EventTarget||!AbortSignal||!AbortController)return!1;let e=!0,i=new EventTarget,n=new AbortController;return i.addEventListener("test",()=>{e=!1},{signal:n.signal}),n.abort(),i.dispatchEvent(new CustomEvent("test")),e}var de=!1;document.addEventListener("DOMContentLoaded",()=>de=!0);function se(e){de||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}var Xe=0,Qe=1,Je=2,qe=3,$e=4,ei=5,ii=6,ni=7,ti=8,oi=9,ri=10,ai=11,li=12,di=13,si=14,ci=15,wi=16,mi=17,ui=18,pi=19,Wi=20,hi=21,gi=22,fi=23,Di=24,Mi=25,Ci=26,Si=27,xi=28,Ai=29,vi=30,bi=31,Ri=32,Ei=33,yi=34,Ui=35,Fi=36,Oi=37,Pi=38,Ii=39,Ti=40,Bi=41,zi=42,ki=43,Li=44,Ni=45,Hi=46,Vi=47,o=Symbol(),H=class e{constructor(i=""){this[o]=d(l.Window,i);for(let n of Object.getOwnPropertyNames(e.prototype))n!=="constructor"&&typeof this[n]=="function"&&(this[n]=this[n].bind(this))}Get(i){return new e(i)}Position(){return this[o](Xe)}Center(){return this[o](Qe)}Close(){return this[o](Je)}DisableSizeConstraints(){return this[o](qe)}EnableSizeConstraints(){return this[o]($e)}Focus(){return this[o](ei)}ForceReload(){return this[o](ii)}Fullscreen(){return this[o](ni)}GetScreen(){return this[o](ti)}GetZoom(){return this[o](oi)}Height(){return this[o](ri)}Hide(){return this[o](ai)}IsFocused(){return this[o](li)}IsFullscreen(){return this[o](di)}IsMaximised(){return this[o](si)}IsMinimised(){return this[o](ci)}Maximise(){return this[o](wi)}Minimise(){return this[o](mi)}Name(){return this[o](ui)}OpenDevTools(){return this[o](pi)}RelativePosition(){return this[o](Wi)}Reload(){return this[o](hi)}Resizable(){return this[o](gi)}Restore(){return this[o](fi)}SetPosition(i,n){return this[o](Di,{x:i,y:n})}SetAlwaysOnTop(i){return this[o](Mi,{alwaysOnTop:i})}SetBackgroundColour(i,n,t,r){return this[o](Ci,{r:i,g:n,b:t,a:r})}SetFrameless(i){return this[o](Si,{frameless:i})}SetFullscreenButtonEnabled(i){return this[o](xi,{enabled:i})}SetMaxSize(i,n){return this[o](Ai,{width:i,height:n})}SetMinSize(i,n){return this[o](vi,{width:i,height:n})}SetRelativePosition(i,n){return this[o](bi,{x:i,y:n})}SetResizable(i){return this[o](Ri,{resizable:i})}SetSize(i,n){return this[o](Ei,{width:i,height:n})}SetTitle(i){return this[o](yi,{title:i})}SetZoom(i){return this[o](Ui,{zoom:i})}Show(){return this[o](Fi)}Size(){return this[o](Oi)}ToggleFullscreen(){return this[o](Pi)}ToggleMaximise(){return this[o](Ii)}UnFullscreen(){return this[o](Ti)}UnMaximise(){return this[o](Bi)}UnMinimise(){return this[o](zi)}Width(){return this[o](ki)}Zoom(){return this[o](Li)}ZoomIn(){return this[o](Ni)}ZoomOut(){return this[o](Hi)}ZoomReset(){return this[o](Vi)}},_i=new H(""),E=_i;function Zi(e,i=null){L(new A(e,i))}function ji(e,i){let n=E.Get(e),t=n[i];if(typeof t=="function")try{t.call(n)}catch{}}function ce(e){let i=e.currentTarget;function n(r="Yes"){if(r!=="Yes")return;let s=i.getAttribute("wml-event"),c=i.getAttribute("wml-target-window")||"",m=i.getAttribute("wml-window"),a=i.getAttribute("wml-openurl");s!==null&&Zi(s),m!==null&&ji(c,m),a!==null&&P(a)}let t=i.getAttribute("wml-confirm");t?T({Title:"Confirm",Message:t,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(n):n()}var y=Symbol(),V=class{constructor(){this[y]=new AbortController}set(i,n){return{signal:this[y].signal}}reset(){this[y].abort(),this[y]=new AbortController}},v=Symbol(),C=Symbol(),_=class{constructor(){this[v]=new WeakMap,this[C]=0}set(i,n){return this[C]+=!this[v].has(i),this[v].set(i,n),{}}reset(){if(!(this[C]<=0)){for(let i of document.body.querySelectorAll("*")){if(this[C]<=0)break;let n=this[v].get(i);this[C]-=typeof n<"u";for(let t of n||[])i.removeEventListener(t,ce)}this[v]=new WeakMap,this[C]=0}}},we=le()?new V:new _;function Gi(e){let i=/\S+/g,n=e.getAttribute("wml-trigger")||"click",t=[],r;for(;(r=i.exec(n))!==null;)t.push(r[0]);let s=we.set(e,t);for(let c of t)e.addEventListener(c,ce,s)}function Z(){se(me)}function me(){we.reset(),document.body.querySelectorAll("[wml-event], [wml-window], [wml-openurl]").forEach(Gi)}window.wails=G;Z();var X={};w(X,{Capabilities:()=>Qi,Environment:()=>Ji,IsAMD64:()=>en,IsARM:()=>nn,IsARM64:()=>tn,IsDarkMode:()=>Xi,IsDebug:()=>K,IsLinux:()=>qi,IsMac:()=>$i,IsWindows:()=>Y,invoke:()=>g});var ue=d(l.System,""),Yi=0,Ki=1;function g(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function Xi(){return ue(Yi)}function Qi(){return fetch("/wails/capabilities").json()}function Ji(){return ue(Ki)}function Y(){return window._wails.environment.OS==="windows"}function qi(){return window._wails.environment.OS==="linux"}function $i(){return window._wails.environment.OS==="darwin"}function en(){return window._wails.environment.Arch==="amd64"}function nn(){return window._wails.environment.Arch==="arm"}function tn(){return window._wails.environment.Arch==="arm64"}function K(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",ln);var on=d(l.ContextMenu,""),rn=0;function an(e,i,n,t){on(rn,{id:e,x:i,y:n,data:t})}function ln(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let t=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");an(n,e.clientX,e.clientY,t);return}dn(e)}function dn(e){if(K())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let r=window.getSelection(),s=r.toString().length>0;if(s)for(let c=0;cb});function b(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}var S=!1,pe=!1,U=null,J="auto";window._wails=window._wails||{};window._wails.setResizable=function(e){pe=e};window._wails.endDrag=function(){document.body.style.cursor="default",S=!1};window.addEventListener("mousedown",cn);window.addEventListener("mousemove",mn);window.addEventListener("mouseup",wn);function sn(e){let i=window.getComputedStyle(e.target).getPropertyValue("--wails-draggable"),n=e.buttons!==void 0?e.buttons:e.which;return!i||i===""||i.trim()!=="drag"||n===0?!1:e.detail===1}function cn(e){if(U){g("wails:resize:"+U),e.preventDefault();return}if(sn(e)){if(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)return;S=!0}else S=!1}function wn(){S=!1}function W(e){document.documentElement.style.cursor=e||J,U=e}function mn(e){if(S&&(S=!1,(e.buttons!==void 0?e.buttons:e.which)>0)){g("wails:drag");return}if(!pe||!Y())return;J==null&&(J=document.documentElement.style.cursor);let i=b("system.resizeHandleHeight")||5,n=b("system.resizeHandleWidth")||5,t=b("resizeCornerExtra")||10,r=window.outerWidth-e.clientXhn,Quit:()=>fn,Show:()=>gn});var q=d(l.Application,""),un=0,pn=1,Wn=2;function hn(){return q(un)}function gn(){return q(pn)}function fn(){return q(Wn)}var ee={};w(ee,{ByID:()=>bn,ByName:()=>vn,Call:()=>An,Plugin:()=>Rn});window._wails=window._wails||{};window._wails.callResultHandler=Sn;window._wails.callErrorHandler=xn;var F=0,Dn=d(l.Call,""),Mn=d(l.CancelCall,""),R=new Map;function Cn(){let e;do e=D();while(R.has(e));return e}function Sn(e,i,n){let t=We(e);t&&t.resolve(n?JSON.parse(i):i)}function xn(e,i){let n=We(e);n&&n.reject(i)}function We(e){let i=R.get(e);return R.delete(e),i}function O(e,i={}){let n=Cn(),t=()=>Mn(e,{"call-id":n}),r=!1,s=!1,c=new Promise((m,a)=>{i["call-id"]=n,R.set(n,{resolve:m,reject:a}),Dn(e,i).then(p=>{if(s=!0,r)return t()}).catch(p=>{a(p),R.delete(n)})});return c.cancel=()=>{if(s)return t();r=!0},c}function An(e){return O(F,e)}function vn(e,...i){return O(F,{methodName:e,args:i})}function bn(e,...i){return O(F,{methodID:e,args:i})}function Rn(e,i,...n){return O(F,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}var ie={};w(ie,{SetText:()=>Un,Text:()=>Fn});var he=d(l.Clipboard,""),En=0,yn=1;function Un(e){return he(En,{text:e})}function Fn(){return he(yn)}var ne={};w(ne,{Any:()=>f,Array:()=>Pn,ByteSlice:()=>On,Map:()=>In,Nullable:()=>Tn,Struct:()=>Bn});function f(e){return e}function On(e){return e??""}function Pn(e){return e===f?i=>i===null?[]:i:i=>{if(i===null)return[];for(let n=0;nn===null?{}:n:n=>{if(n===null)return{};for(let t in n)n[t]=i(n[t]);return n}}function Tn(e){return e===f?f:i=>i===null?null:e(i)}function Bn(e){let i=!0;for(let n in e)if(e[n]!==f){i=!1;break}return i?f:n=>{for(let t in e)t in n&&(n[t]=e[t](n[t]));return n}}var oe={};w(oe,{GetAll:()=>Nn,GetCurrent:()=>Vn,GetPrimary:()=>Hn});var te=d(l.Screens,""),zn=0,kn=1,Ln=2;function Nn(){return te(zn)}function Hn(){return te(kn)}function Vn(){return te(Ln)}window._wails=window._wails||{};window._wails.invoke=g;g("wails:runtime:ready");export{$ as Application,I as Browser,ee as Call,ie as Clipboard,ne as Create,B as Dialogs,N as Events,Q as Flags,oe as Screens,X as System,j as WML,E as Window}; diff --git a/frontend/src/components/footer/index.tsx b/frontend/src/components/footer/index.tsx new file mode 100644 index 0000000..dacb864 --- /dev/null +++ b/frontend/src/components/footer/index.tsx @@ -0,0 +1,11 @@ + +export default function Footer() { + return( +
+ + +
+ ) +} diff --git a/frontend/src/components/themeController/index.tsx b/frontend/src/components/themeController/index.tsx new file mode 100644 index 0000000..b7acdb6 --- /dev/null +++ b/frontend/src/components/themeController/index.tsx @@ -0,0 +1,29 @@ +import { useEffect, useState } from "react"; + +export default function ThemeController() { + const [theme, setTheme] = useState(localStorage.getItem("theme") ?? "light"); + const handleToggle = (e: any) => { + if (e.target.checked) { + setTheme("cupcake"); + } else { + setTheme("night"); + } + }; + + useEffect(() => { + localStorage.setItem('theme', theme!) + const localTheme = localStorage.getItem('theme') + document.querySelector('html')?.setAttribute('data-theme', localTheme!) + }, [theme]); + + + return ( + + ) +} \ No newline at end of file diff --git a/frontend/src/hooks/index.ts b/frontend/src/hooks/index.ts new file mode 100644 index 0000000..747e97a --- /dev/null +++ b/frontend/src/hooks/index.ts @@ -0,0 +1 @@ +export * from "./useGlobalEvents"; \ No newline at end of file diff --git a/frontend/src/hooks/useGlobalEvents.tsx b/frontend/src/hooks/useGlobalEvents.tsx new file mode 100644 index 0000000..5d7bb48 --- /dev/null +++ b/frontend/src/hooks/useGlobalEvents.tsx @@ -0,0 +1,65 @@ +// useGlobalEvents.ts +import { useEffect } from "react"; +import { Events } from "@wailsio/runtime"; + +export function useGlobalEvents({ + setGameRunning, + setServerRunning, + setProxyRunning, + setProgressUpdate, + setMaxProgressUpdate, + setProgressDownload, + setDownloadSpeed, + setMessageUpdate, + +}: { + setGameRunning: (v: boolean) => void; + setServerRunning: (v: boolean) => void; + setProxyRunning: (v: boolean) => void; + setProgressUpdate: (v: number) => void; + setMaxProgressUpdate: (v: number) => void; + setProgressDownload: (v: number) => void; + setDownloadSpeed: (v: number) => void; + setMessageUpdate: (v: string) => void; +}) { + useEffect(() => { + const onGameExit = () => setGameRunning(false); + const onServerExit = () => setServerRunning(false); + const onProxyExit = () => setProxyRunning(false); + + const onDownload = (event: any) => { + const { percent, speed } = event.data[0]; + setProgressDownload(Number(percent)); + setDownloadSpeed(Number(speed)); + }; + + const onUpdateProgress = (event: any) => { + const { progress, maxProgress } = event.data[0]; + setProgressUpdate(Number(progress)); + setMaxProgressUpdate(Number(maxProgress)); + }; + + const onMessageUpdate = (event: any) => { + const { message } = event.data[0]; + setMessageUpdate(message); + }; + + Events.On("download:server", onDownload); + Events.On("download:proxy", onDownload); + Events.On("game:exit", onGameExit); + Events.On("server:exit", onServerExit); + Events.On("proxy:exit", onProxyExit); + Events.On("hdiffz:progress", onUpdateProgress); + Events.On("hdiffz:message", onMessageUpdate); + + return () => { + Events.Off("download:server"); + Events.Off("download:proxy"); + Events.Off("game:exit"); + Events.Off("server:exit"); + Events.Off("proxy:exit"); + Events.Off("hdiffz:progress"); + Events.Off("hdiffz:message"); + }; + }, []); +} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx new file mode 100644 index 0000000..0b34da1 --- /dev/null +++ b/frontend/src/main.tsx @@ -0,0 +1,29 @@ +import { StrictMode } from 'react' +import ReactDOM from 'react-dom/client' +import { RouterProvider, createRouter } from '@tanstack/react-router' +import './styles/index.css' +import "../runtime.js" +import "@wailsio/runtime"; +// Import the generated route tree +import { routeTree } from './routeTree.gen.js' + +// Create a new router instance +const router = createRouter({ routeTree }) + +// Register the router instance for type safety +declare module '@tanstack/react-router' { + interface Register { + router: typeof router + } +} + +// Render the app +const rootElement = document.getElementById('root')! +if (!rootElement.innerHTML) { + const root = ReactDOM.createRoot(rootElement) + root.render( + + + , + ) +} \ No newline at end of file diff --git a/frontend/src/pages/about/index.tsx b/frontend/src/pages/about/index.tsx new file mode 100644 index 0000000..7649738 --- /dev/null +++ b/frontend/src/pages/about/index.tsx @@ -0,0 +1,31 @@ +import { Link } from "@tanstack/react-router"; + +export default function AboutPage() { + return ( +
+
+

About

+ +
+

+ Hello! I'm Kain, a developer passionate about building useful tools and improving user experiences. +

+

+ I created a lightweight and modern Game Launcher to help users easily launch and manage their games with better performance and simplicity. +

+

+ The launcher is built using Go + Wails, with a clean and responsive interface styled with Tailwind CSS and DaisyUI. +

+

+ My goal is to make tools that are fast, efficient, and enjoyable to use — and this launcher is just the beginning. +

+
+ +
+ Back to Home +
+
+
+ ); + } + \ No newline at end of file diff --git a/frontend/src/pages/analysis/index.tsx b/frontend/src/pages/analysis/index.tsx new file mode 100644 index 0000000..bcfd19b --- /dev/null +++ b/frontend/src/pages/analysis/index.tsx @@ -0,0 +1,198 @@ +import { Link } from '@tanstack/react-router'; + +export default function AnalysisPage() { + return ( +
+
+

+ Firefly Analysis & Veritas Plugin +

+ + {/* About Veritas Section */} +
+

+ 🔬 + About Veritas +

+ +
+
+
+
+

+ Veritas is a powerful{" "} + Damage Logger designed for analyzing damage in real-time during gameplay. +

+

It's lightweight, fast, and easy to use for comprehensive damage analysis.

+
+
+ +
+
+ 📁 + GitHub Repository +
+ + https://github.com/hessiser/veritas + +
+
+
+ + {/* Web Analysis Tools Section */} +
+

+ 🌐 + Web Analysis Tools +

+ +
+

+ Use these web applications for real-time damage analysis with Veritas: +

+ +
+
+
+ 🏆 + Master Website +
+ + https://sranalysis.kain.id.vn/ + +
+ +
+
+ 🔄 + Backup Website +
+ + https://sr-analysis.vercel.app/ + +
+
+ +
+
+
💡
+

+ Tip: If your country has issues loading from the master site, please use the backup site instead. +

+
+
+
+
+ + {/* Installation Instructions */} +
+

+ ⚠️ + Installation Instructions +

+ +
+
+
📋
+
+

Important Setup Step

+

+ After downloading Veritas, you must rename the file for it to work properly: +

+
+

+ Rename: veritas.dllastrolabe.dll +

+

+ Then place astrolabe.dll into your game directory. +

+
+
+
+
+
+ + {/* Usage Instructions */} +
+

+ 🛠️ + How to Use Web App +

+ +
+ {/* Firefly GO Local */} +
+

+ 🚀 + For Firefly GO Local +

+
+
+ 1. +

Launch the game and your Firefly Private Server (PS).

+
+
+ 2. +

Open one of the web analysis tools.

+
+
+ 3. +

Go to Connection Settings → select Connection Type: PS → click Connect.

+
+
+ 4. +

Once connected, play the game. The tool will automatically analyze in the background.

+
+
+
+ + {/* Other Private Servers */} +
+

+ 🌐 + For Other Private Servers +

+
+
+ 1. +

Launch the game and your Private Server.

+
+
+ 2. +

Open one of the web analysis tools.

+
+
+ 3. +

Go to Connection Settings → select Connection Type: Native → click Connect.

+
+
+ 4. +

Once connected, play the game normally.

+
+
+
+
+
+ +
+ Back to Home +
+
+
+ ); +} \ No newline at end of file diff --git a/frontend/src/pages/hdiffz/index.tsx b/frontend/src/pages/hdiffz/index.tsx new file mode 100644 index 0000000..5ebca31 --- /dev/null +++ b/frontend/src/pages/hdiffz/index.tsx @@ -0,0 +1,345 @@ +import useSettingStore from "@/stores/settingStore" +import { Check, Folder, File, X, Settings } from "lucide-react" +import { useEffect } from "react" +import { toast } from "react-toastify" +import { FSService, HdiffzService} from "@bindings/firefly-launcher/internal" +import { motion } from "motion/react" +import useHdiffzStore from "@/stores/hdiffzStore" + +export default function HdiffzPage() { + const { gameDir, setGameDir } = useSettingStore() + const { + isLoading, + setIsLoading, + folderCheckResult, + setFolderCheckResult, + diffDir, + setDiffDir, + diffCheckResult, + setDiffCheckResult, + isDiffLoading, + setIsDiffLoading, + progressUpdate, + setProgressUpdate, + maxProgressUpdate, + setMaxProgressUpdate, + stageType, + setStageType, + messageUpdate, + setMessageUpdate + } = useHdiffzStore() + + useEffect(() => { + const getLanguage = async () => { + if (gameDir) { + const subPath = 'StarRail_Data/StreamingAssets/DesignData/Windows' + const fullPath = `${gameDir}/${subPath}` + + const exists = await FSService.DirExists(fullPath) + if (exists) { + setFolderCheckResult('success') + } else { + setFolderCheckResult('error') + setGameDir('') + } + } + } + getLanguage() + }, [gameDir]) + + const handlePickGameFolder = async () => { + try { + setIsLoading({game: true, diff: false}) + const basePath = await FSService.PickFolder() + if (basePath) { + setGameDir(basePath) + const subPath = 'StarRail_Data/StreamingAssets/DesignData/Windows' + const fullPath = `${basePath}/${subPath}` + + const exists = await FSService.DirExists(fullPath) + setFolderCheckResult(exists ? 'success' : 'error') + setGameDir(exists ? basePath : '') + if (!exists) { + toast.error('Game directory not found. Please select the correct folder.') + } + } else { + toast.error('No folder path selected') + setFolderCheckResult('error') + setGameDir('') + } + } catch (err: any) { + toast.error('PickFolder error:', err) + setFolderCheckResult('error') + } finally { + setIsLoading({game: false, diff: false}) + } + } + + const handlePickDiffFile = async () => { + try { + setIsLoading({game: false, diff: true}) + const basePath = await FSService.PickFile() + if (basePath) { + if (!basePath.endsWith(".7z") && !basePath.endsWith(".zip") && !basePath.endsWith(".rar")) { + toast.error('Not valid file type') + setDiffCheckResult('error') + setDiffDir('') + return + } + const [exists, error] = await FSService.FileExistsInZip(basePath, "StarRail_Data\\StreamingAssets\\BinaryVersion.bytes") + if (!exists) { + toast.error(error) + setDiffCheckResult('error') + setDiffDir('') + return + } + setDiffDir(basePath) + setDiffCheckResult('success') + } else { + toast.error('No file path selected') + setDiffCheckResult('error') + setDiffDir('') + } + } catch (err: any) { + toast.error('PickFile error:', err) + setDiffCheckResult('error') + } finally { + setIsLoading({game: false, diff: false}) + } + } + + const handleUpdateGame = async () => { + try { + setIsDiffLoading(true) + if (!gameDir || !diffDir) { + toast.error('Please select game directory and diff file') + setIsDiffLoading(false) + return + } + setStageType('Version Validate') + setProgressUpdate(0) + setMaxProgressUpdate(1) + const [validVersion, errorVersion] = await HdiffzService.VersionValidate(gameDir, diffDir) + if (!validVersion) { + toast.error(errorVersion) + setIsDiffLoading(false) + return + } + setProgressUpdate(1) + + setStageType('Data Extract') + const [validData, errorData] = await HdiffzService.DataExtract(gameDir, diffDir) + if (!validData) { + toast.error(errorData) + setIsDiffLoading(false) + return + } + + setStageType('Cut Data') + setMessageUpdate('') + const [validCut, errorCut] = await HdiffzService.CutData(gameDir) + if (!validCut) { + toast.error(errorCut) + setIsDiffLoading(false) + return + } + + setStageType('Patch Data') + const [validPatch, errorPatch] = await HdiffzService.PatchData(gameDir) + if (!validPatch) { + toast.error(errorPatch) + setIsDiffLoading(false) + return + } + + setStageType('Delete old files') + const [validDelete, errorDelete] = await HdiffzService.DeleteFiles(gameDir) + if (!validDelete) { + toast.error(errorDelete) + setIsDiffLoading(false) + return + } + toast.success('Update game completed') + } catch (err: any) { + console.error(err) + toast.error('PickFile error:', err) + setIsDiffLoading(false) + } finally { + setIsDiffLoading(false) + } + } + + return ( +
+
+ {/* Header */} +
+

+ 🎮 Game Update by Hdiffz +

+

Help you update game with hdiffz

+
+ + {/* Main Content */} +
+ + {/* Folder Selection Section */} +
+

+ + Game Directory +

+ +
+
+ + + {gameDir && ( +
+

+ {gameDir} +

+
+ )} +
+ {folderCheckResult && ( +
+ {folderCheckResult === 'success' ? ( + <> + + Valid game directory found! + + ) : ( + <> + + Game directory not found. Please select the correct folder. + + )} +
+ )} +
+
+ + {/* Folder Selection Section */} +
+

+ + Diff file Directory +

+ +
+
+ + + {diffDir && ( +
+

+ {diffDir} +

+
+ )} +
+ {diffCheckResult && ( +
+ {diffCheckResult === 'success' ? ( + <> + + Valid diff file found! + + ) : ( + <> + + Diff file not found. Please select the correct file. + + )} +
+ )} +
+ + {/* Apply Button */} +
+ +
+
+ + {isDiffLoading && ( +
+
+
+

+ Update Game +

+
+ +
+
+
+
+ {stageType}: +
+ {stageType !== 'Cut Data' && {progressUpdate.toFixed(0)} / {maxProgressUpdate.toFixed(0)}} + {stageType === 'Cut Data' && {messageUpdate}} +
+
+
+ +
+
+ Please wait... +
+
+
+ +
+
+
+ )} + + {/* Instructions */} +
+

📋 Instructions:

+
    +
  1. 1. Click "Select Game Folder" and choose your game's root directory
  2. +
  3. 2. Wait for the system to validate the game directory
  4. +
  5. 3. Click "Select Diff file Folder" and choose your diff file's root directory
  6. +
  7. 4. Wait for the system to validate the diff file directory
  8. +
  9. 5. Click "Update Game" to save your changes
  10. +
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/frontend/src/pages/howto/index.tsx b/frontend/src/pages/howto/index.tsx new file mode 100644 index 0000000..4b8e93e --- /dev/null +++ b/frontend/src/pages/howto/index.tsx @@ -0,0 +1,245 @@ +import { Link } from '@tanstack/react-router'; + +export default function HowToPage() { + return ( +
+
+

How to Use

+ + {/* Section 1: Launcher Features */} +
+

+ 🚀 + Using the Launcher Features +

+
+
+
🔄
+

Automatically update Firefly Go and proxy tools when launching.

+
+
+
🎮
+

Launch the game directly through the launcher with correct parameters and runtime environment.

+
+
+
🌐
+

Support switching in-game language (e.g., EN, JP, ZH, KR) via{" "} + Language Tools +

+
+
+
📦
+

Patch and update game files using{" "} + Hdiffz Tool + {" "}(HDiffPatch) — fast & lightweight incremental updates. +

+
+
+
+ + {/* Section 2: FireflyGo Commands */} +
+

+ 📜 + FireflyGo Chat Commands +

+ +

+ Below are in-game chat commands you can use. Some commands require you to enable{" "} + Theorycraft Mode. +

+ + {/* Theorycraft Mode Warning */} +
+
+
🔒
+
+

Theorycraft Mode Required

+

The following commands are only available when Theorycraft Mode is enabled:

+
+ /cycle + /hp + /log +
+
+
+
+ + {/* Commands List */} +
+

Available Commands:

+ + {/* Theorycraft Toggle */} +
+
+
⚙️
+
+

Theorycraft Mode

+
+

/theorycraft 1 — Enable Theorycraft Mode

+

/theorycraft 0 — Disable Theorycraft Mode

+
+
+
+
+ + {/* Cycle Command */} +
+
+
🔄
+
+

Cycle Control (Theorycraft only)

+
+

/cycle N — Set cycle count in battle

+

Example: /cycle 30 sets battle to 30 cycles

+

/cycle 0 disables custom cycle

+
+
+
+
+ + {/* HP Command */} +
+
+
❤️
+
+

HP Override (Theorycraft only)

+
+

/hp WAVE HP — Set monster HP for a specific wave

+

Example: /hp 1 2000000 sets Wave 1 monster HP to 2,000,000

+

/hp 0 disables HP override

+
+
+
+
+ + {/* Log Command */} +
+
+
📝
+
+

Battle Log (Theorycraft only)

+
+

/log 1 — Enable battle log output

+

/log 0 — Disable battle log

+

Output will be written as .json

+
+
+
+
+ + {/* Skip Command */} +
+
+
⏭️
+
+

Skip Nodes

+
+

/skip N — Skip nodes in MOC / AS / Pure Fiction

+

Example: /skip 2 skips node 2

+

/skip 0 disables skipping

+
+
+
+
+ + {/* ID Command */} +
+
+
🔄
+
+

Character Path Switch

+
+

/id CHAR_ID — Switch path for multi-form characters

+

Example: /id 8008 to change MC (Trailblazer) form

+

Works with IDs like 8001 → 8008, 1001 → 1224

+
+
+
+
+ + {/* Update Command */} +
+
+
🔄
+
+

Refresh Data

+
+

/update — Refresh server data from current freesr-data.json

+
+
+
+
+
+
+ + {/* Section 3: Other Notes */} +
+

+ 📌 + Other Notes +

+ +
+ {/* Administrator Note */} +
+
+
⚠️
+
+

Administrator Rights

+

+ Always run the launcher as Administrator for file permission access. +

+
+
+
+ + {/* Backup Note */} +
+
+
💾
+
+

Backup Data

+

+ Backup your config.json and{' '} + freesr-data.json regularly. +

+
+
+
+ + {/* Voice Pack Note */} +
+
+
🎵
+
+

Enable Voice Packs in Beta Client

+
+
+ 1. +
+

Copy the desired voice folder (e.g., Japanese, English) from:

+ + Star Rail\Games\StarRail_Data\Persistent\Audio\AudioPackage\Windows + +

to the beta folder by clicking "Open Voice Folder" on the Home tab.

+
+
+
+ 2. +

When launching the game for the first time, it may delete the voice folder. If so, repeat step 1 to restore it.

+
+
+
+
+
+
+
+ +
+ Back to Home +
+
+
+ ); +} \ No newline at end of file diff --git a/frontend/src/pages/language/index.tsx b/frontend/src/pages/language/index.tsx new file mode 100644 index 0000000..bc4c259 --- /dev/null +++ b/frontend/src/pages/language/index.tsx @@ -0,0 +1,285 @@ +import { useEffect, useState } from 'react' +import { Folder, Settings, Check, X, Globe, Mic } from 'lucide-react' +import { FSService } from '@bindings/firefly-launcher/internal' +import { LanguageService } from '@bindings/firefly-launcher/internal' +import { toast } from 'react-toastify' +import useSettingStore from '@/stores/settingStore' + +export default function LanguagePage() { + const { gameDir, setGameDir } = useSettingStore() + const [folderCheckResult, setFolderCheckResult] = useState<'success' | 'error' | null>(null) + + const [textLang, setTextLang] = useState('') + const [voiceLang, setVoiceLang] = useState('') + + const [selectedTextLang, setSelectedTextLang] = useState('') + const [selectedVoiceLang, setSelectedVoiceLang] = useState('') + + const [isLoading, setIsLoading] = useState(false) + const [isSettingLanguage, setIsSettingLanguage] = useState(false) + + const languageOptions = [ + { value: 'en', label: 'English', flag: '🇺🇸' }, + { value: 'cn', label: 'Chinese', flag: '🇨🇳' }, + { value: 'jp', label: 'Japanese', flag: '🇯🇵' }, + { value: 'kr', label: 'Korean', flag: '🇰🇷' } + ] + + useEffect(() => { + const getLanguage = async () => { + if (gameDir) { + const subPath = 'StarRail_Data/StreamingAssets/DesignData/Windows' + const fullPath = `${gameDir}/${subPath}` + + const exists = await FSService.DirExists(fullPath) + if (exists) { + const [textLang, voiceLang] = await LanguageService.GetLanguage(fullPath) + setTextLang(textLang) + setVoiceLang(voiceLang) + setFolderCheckResult('success') + setSelectedTextLang(textLang) + setSelectedVoiceLang(voiceLang) + } else { + setTextLang('') + setVoiceLang('') + setSelectedTextLang('') + setSelectedVoiceLang('') + setFolderCheckResult('error') + setGameDir('') + } + } + } + getLanguage() + }, [gameDir]) + + const handlePickFolder = async () => { + try { + setIsLoading(true) + const basePath = await FSService.PickFolder() + if (basePath) { + setGameDir(basePath) + const subPath = 'StarRail_Data/StreamingAssets/DesignData/Windows' + const fullPath = `${basePath}/${subPath}` + const exists = await FSService.DirExists(fullPath) + setFolderCheckResult(exists ? 'success' : 'error') + setGameDir(exists ? basePath : "") + if (!exists) { + toast.error('Game directory not found. Please select the correct folder.') + } + } else { + toast.error('No folder path selected') + setFolderCheckResult('error') + setGameDir('') + } + } catch (err: any) { + toast.error('PickFolder error:', err) + setFolderCheckResult('error') + } finally { + setIsLoading(false) + } + } + + const handleSetLanguage = async () => { + if (!gameDir) { + toast.error('No folder path selected') + return + } + try { + setIsSettingLanguage(true) + const result = await LanguageService.SetLanguage( + `${gameDir}/StarRail_Data/StreamingAssets/DesignData/Windows`, + selectedTextLang, + selectedVoiceLang + ) + if (result) { + toast.success('Language set successfully') + setTextLang(selectedTextLang) + setVoiceLang(selectedVoiceLang) + } + else { + toast.error('Language set failed') + } + + } catch (err: any) { + toast.error('SetLanguage error:', err) + } finally { + setIsSettingLanguage(false) + } + } + + const getLanguageLabel = (code: string) => { + const lang = languageOptions.find(l => l.value === code) + return lang ? `${lang.flag} ${lang.label}` : code + } + + return ( +
+
+ {/* Header */} +
+

+ 🎮 Game Language Manager +

+

Manage text and voice language settings for your game

+
+ + {/* Main Content */} +
+ + {/* Folder Selection Section */} +
+

+ + Game Directory +

+ +
+
+ + + {gameDir && ( +
+

+ {gameDir} +

+
+ )} +
+ {folderCheckResult && ( +
+ {folderCheckResult === 'success' ? ( + <> + + Valid game directory found! + + ) : ( + <> + + Game directory not found. Please select the correct folder. + + )} +
+ )} +
+
+ + {/* Current Language Display */} + {(textLang && voiceLang) && ( +
+

+ + Current Languages +

+ +
+
+
+ + Text Language +
+

+ {getLanguageLabel(textLang)} +

+
+ +
+
+ + Voice Language +
+

+ {getLanguageLabel(voiceLang)} +

+
+
+
+ )} + + {/* Language Selection */} +
+

+ + Language Settings +

+ +
+ {/* Text Language */} +
+ + +
+ + {/* Voice Language */} +
+ + +
+
+ + {/* Apply Button */} +
+ +
+
+ + {/* Instructions */} +
+

📋 Instructions:

+
    +
  1. 1. Click "Select Game Folder" and choose your game's root directory
  2. +
  3. 2. Wait for the system to validate the game directory
  4. +
  5. 3. Select your preferred text and voice languages
  6. +
  7. 4. Click "Apply Language Settings" to save your changes
  8. +
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/frontend/src/pages/launcher/index.tsx b/frontend/src/pages/launcher/index.tsx new file mode 100644 index 0000000..6ef90b9 --- /dev/null +++ b/frontend/src/pages/launcher/index.tsx @@ -0,0 +1,498 @@ +import { useEffect } from 'react'; +import { Play, Menu, FolderOpen, MessageCircleQuestionMark } from 'lucide-react'; +import { FSService, GitService } from '@bindings/firefly-launcher/internal'; +import { toast } from 'react-toastify'; +import path from 'path-browserify' +import useSettingStore from '@/stores/settingStore'; +import useModalStore from '@/stores/modalStore'; +import useLauncherStore from '@/stores/launcherStore'; +import { motion } from 'motion/react'; +import { Link } from '@tanstack/react-router'; + +export default function LauncherPage() { + const { gamePath, + setGamePath, + setGameDir, + serverPath, + proxyPath, + gameDir, + serverVersion, + proxyVersion, + setServerVersion, + setProxyVersion, + setServerPath, + setProxyPath + } = useSettingStore() + const { isOpenNotification, setIsOpenNotification } = useModalStore() + const { + isLoading, + modelName, + downloadType, + serverReady, + proxyReady, + isDownloading, + serverRunning, + proxyRunning, + gameRunning, + progressDownload, + downloadSpeed, + setIsLoading, + setModelName, + setDownloadType, + setServerReady, + setProxyReady, + setIsDownloading, + setServerRunning, + setProxyRunning, + setGameRunning, + } = useLauncherStore() + + + useEffect(() => { + const check = async () => { + if (!serverPath || !proxyPath || !serverVersion || !proxyVersion) { + setServerReady(false) + setProxyReady(false) + return + } + + const serverExists = await FSService.FileExists(serverPath) + const proxyExists = await FSService.FileExists(proxyPath) + setServerReady(serverExists) + setProxyReady(proxyExists) + } + + check() + }, [serverPath, proxyPath, serverVersion, proxyVersion]) + + useEffect(() => { + const checkStartUp = async (): Promise => { + let isExists = false + if (serverPath && proxyPath && serverVersion && proxyVersion) { + isExists = true + setServerReady(true) + setProxyReady(true) + } + const dataUpdate = await handlerCheckUpdate() + const exitGame = await FSService.FileExists(gamePath) + if (!exitGame) { + setGameRunning(false) + setGamePath("") + setGameDir("") + } + if (!dataUpdate.server.isUpdate && !dataUpdate.proxy.isUpdate) { + setServerReady(true) + setProxyReady(true) + return + } + if (!isExists) { + setServerReady(false) + setProxyReady(false) + } + setModelName(!isExists ? "Download Data" : "Update Data") + setIsOpenNotification(true) + } + checkStartUp() + }, []); + + const handlePickFile = async () => { + try { + setIsLoading(true) + const basePath = await FSService.PickFile() + if (basePath.endsWith("StarRail.exe") || basePath.endsWith("launcher.exe")) { + const normalized = basePath.replace(/\\/g, '/') + const folderPath = path.dirname(normalized) + const fullPath = `${folderPath}/StarRail_Data/StreamingAssets/DesignData/Windows` + const exists = await FSService.DirExists(fullPath) + if (!exists) { + toast.error('Game directory not found. Please select the correct folder.') + } else { + setGamePath(basePath) + setGameDir(folderPath) + toast.success('Game path set successfully') + } + } else { + toast.error('Not valid file type') + } + } catch (err: any) { + toast.error('PickFolder error:', err) + } finally { + setIsLoading(false) + } + } + + function sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + const handleStartGame = async () => { + if (!gamePath) { + return + } + if (gameRunning) { + return + } + try { + setIsLoading(true) + if (!proxyRunning && !gamePath.endsWith("launcher.exe")) { + const resultProxy = await FSService.StartWithConsole(proxyPath) + if (!resultProxy) { + toast.error('Failed to start proxy') + return + } + setProxyRunning(true) + } + await sleep(500) + if (!serverRunning) { + const resultServer = await FSService.StartWithConsole(serverPath) + if (!resultServer) { + toast.error('Failed to start server') + return + } + setServerRunning(true) + } + await sleep(2000) + if (gamePath.endsWith("launcher.exe")) { + const resultGame = await FSService.StartWithConsole(gamePath) + if (!resultGame) { + toast.error('Failed to start game') + return + } + } else { + const resultGame = await FSService.StartApp(gamePath) + if (!resultGame) { + toast.error('Failed to start game') + return + } + } + setGameRunning(true) + + } catch (err: any) { + toast.error('StartGame error:', err) + } finally { + setIsLoading(false) + } + } + + const handlerCheckUpdate = async (): Promise> => { + let isUpdateServer = false + let isUpdateProxy = false + const [serverOk, serverNewVersion, serverError] = await GitService.GetLatestServerVersion(serverVersion) + const serverExists = await FSService.FileExists(serverPath) + if (serverOk) { + if (serverNewVersion !== serverVersion || !serverExists) { + isUpdateServer = true + } + } else { + toast.error("Server error: " + serverError) + } + const [proxyOk, proxyNewVersion, proxyError] = await GitService.GetLatestProxyVersion(proxyVersion) + const proxyExists = await FSService.FileExists(proxyPath) + if (proxyOk) { + if (proxyNewVersion !== proxyVersion || !proxyExists) { + isUpdateProxy = true + } + } else { + toast.error("Proxy error: " + proxyError) + } + return { server: { isUpdate: isUpdateServer, version: serverNewVersion }, proxy: { isUpdate: isUpdateProxy, version: proxyNewVersion } } + } + + const handlerUpdateServer = async (updateInfo: Record) => { + setIsDownloading(true) + for (const [key, value] of Object.entries(updateInfo)) { + if (value.isUpdate) { + if (key === "server") { + setDownloadType("Downloading server...") + const [ok, error] = await GitService.DownloadServerProgress(value.version) + if (ok) { + setDownloadType("Unzipping server...") + GitService.UnzipServer() + setDownloadType("Download server successfully") + setServerVersion(value.version) + + setServerPath("./server/firefly-go_win.exe") + } else { + toast.error(error) + setDownloadType("Download server failed") + } + } else if (key === "proxy") { + setDownloadType("Downloading proxy...") + const [ok, error] = await GitService.DownloadProxyProgress(value.version) + if (ok) { + setDownloadType("Unzipping proxy...") + GitService.UnzipProxy() + setDownloadType("Download proxy successfully") + setProxyVersion(value.version) + setProxyPath("./proxy/FireflyProxy.exe") + + } else { + toast.error(error) + setDownloadType("Download proxy failed") + } + } + + } + } + setDownloadType("") + setIsDownloading(false) + setServerReady(true) + setProxyReady(true) + } + + // Handle ESC key to close modal + useEffect(() => { + const handleEscKey = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + setIsOpenNotification(false); + } + + }; + + window.addEventListener('keydown', handleEscKey); + return () => window.removeEventListener('keydown', handleEscKey); + }, [isOpenNotification]); + + + return ( +
+
+ + {/* Header */} +
+
Firefly GO
+
+ +
+ + + +
+ + SRTools Logo + +
+
+ + SRTools Logo + +
+
+ + SRTools Logo + +
+ +
+ + + +
+
+ + + {/* Bottom Panel */} + {serverReady && proxyReady && !isDownloading && ( +
+
+ {gamePath === "" ? ( + + ) : ( + + )} + +
+
+ +
+
    +
  • +
  • +
  • +
  • +
  • +
+ +
+
+
+ )} + + {/* Downloading */} + {isDownloading && ( +
+
+
+ {downloadType} +
+ {downloadSpeed.toFixed(1)} MB/s + {progressDownload.toFixed(1)}% +
+
+
+ +
+
+ {progressDownload < 100 ? 'Please wait...' : 'Complete!'} +
+
+
+ )} + + {/* Version Info */} + {serverReady && proxyReady && !isDownloading && ( +
+

Version server: {serverVersion}

+

Version proxy: {proxyVersion}

+
+ )} + + {/* Modal */} + {isOpenNotification && ( +
+
+ {modelName !== "Download Data" && ( + setIsOpenNotification(false)} + > + ✕ + + )} + +
+

+ {modelName} +

+
+ +
+
+

+ {modelName === "Download Data" + ? "Download required data!" + : "Do you want to update data?"} +

+
+ +
+ {modelName !== "Download Data" && ( + setIsOpenNotification(false)} + > + Cancel + + )} + { + setIsOpenNotification(false) + const dataCheck = await handlerCheckUpdate() + await handlerUpdateServer(dataCheck) + }} + > + Yes + +
+
+
+
+ )} +
+ ) +} diff --git a/frontend/src/pages/srtools/index.tsx b/frontend/src/pages/srtools/index.tsx new file mode 100644 index 0000000..915c011 --- /dev/null +++ b/frontend/src/pages/srtools/index.tsx @@ -0,0 +1,116 @@ +import { Link } from "@tanstack/react-router"; + +export default function SrToolsPage() { + return ( +
+
+

SR Tools

+ + {/* Section 1: About SR Tools */} +
+

+ ℹ️ + About SR Tools +

+
+
+
🏠
+

This site uses a self-hosted version of SR Tools available at{" "} + + srtools.kain.id.vn + +

+
+
+
👨‍💻
+

The original tool was created by a third-party developer named Amazing. This version is directly based on that work, without modification to core logic.

+
+
+
🔗
+

There is also a more modern version by the same author available at{" "} + + srtools.neonteam.dev + + {" "}and the original version at{" "} + + srtools.pages.dev + +

+
+
+
+ + {/* Section 2: Main Features */} +
+

+ 🔧 + Main Features +

+
+
+
⚙️
+

Configure characters, light cones, relics, traces, and eidolons easily in your browser.

+
+
+
🔌
+

Instantly apply setups to Firefly Private Server using Connect PS — no manual file uploads required.

+
+
+
📂
+

Export and import full builds using freesr-data.json.

+
+
+
+

Fast testing workflow — no sync cooldowns, instant in-game updates.

+
+
+
+ + {/* Section 3: Getting Started */} +
+

+ 🚀 + Getting Started +

+
+
+
1️⃣
+

Access the tool through your browser at the self-hosted instance.

+
+
+
2️⃣
+

Configure your character builds with the intuitive web interface.

+
+
+
3️⃣
+

Use Connect PS feature to instantly sync with your private server.

+
+
+
4️⃣
+

Test your builds in-game with real-time updates and modifications.

+
+
+
+ +
+ Back to Home +
+
+
+ ); +} \ No newline at end of file diff --git a/frontend/src/routeTree.gen.ts b/frontend/src/routeTree.gen.ts new file mode 100644 index 0000000..8d0151d --- /dev/null +++ b/frontend/src/routeTree.gen.ts @@ -0,0 +1,189 @@ +/* eslint-disable */ + +// @ts-nocheck + +// noinspection JSUnusedGlobalSymbols + +// This file was automatically generated by TanStack Router. +// You should NOT make any changes in this file as it will be overwritten. +// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. + +import { Route as rootRouteImport } from './routes/__root' +import { Route as SrtoolsRouteImport } from './routes/srtools' +import { Route as LanguageRouteImport } from './routes/language' +import { Route as HowtoRouteImport } from './routes/howto' +import { Route as HdiffzRouteImport } from './routes/hdiffz' +import { Route as AnalysisRouteImport } from './routes/analysis' +import { Route as AboutRouteImport } from './routes/about' +import { Route as IndexRouteImport } from './routes/index' + +const SrtoolsRoute = SrtoolsRouteImport.update({ + id: '/srtools', + path: '/srtools', + getParentRoute: () => rootRouteImport, +} as any) +const LanguageRoute = LanguageRouteImport.update({ + id: '/language', + path: '/language', + getParentRoute: () => rootRouteImport, +} as any) +const HowtoRoute = HowtoRouteImport.update({ + id: '/howto', + path: '/howto', + getParentRoute: () => rootRouteImport, +} as any) +const HdiffzRoute = HdiffzRouteImport.update({ + id: '/hdiffz', + path: '/hdiffz', + getParentRoute: () => rootRouteImport, +} as any) +const AnalysisRoute = AnalysisRouteImport.update({ + id: '/analysis', + path: '/analysis', + getParentRoute: () => rootRouteImport, +} as any) +const AboutRoute = AboutRouteImport.update({ + id: '/about', + path: '/about', + getParentRoute: () => rootRouteImport, +} as any) +const IndexRoute = IndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => rootRouteImport, +} as any) + +export interface FileRoutesByFullPath { + '/': typeof IndexRoute + '/about': typeof AboutRoute + '/analysis': typeof AnalysisRoute + '/hdiffz': typeof HdiffzRoute + '/howto': typeof HowtoRoute + '/language': typeof LanguageRoute + '/srtools': typeof SrtoolsRoute +} +export interface FileRoutesByTo { + '/': typeof IndexRoute + '/about': typeof AboutRoute + '/analysis': typeof AnalysisRoute + '/hdiffz': typeof HdiffzRoute + '/howto': typeof HowtoRoute + '/language': typeof LanguageRoute + '/srtools': typeof SrtoolsRoute +} +export interface FileRoutesById { + __root__: typeof rootRouteImport + '/': typeof IndexRoute + '/about': typeof AboutRoute + '/analysis': typeof AnalysisRoute + '/hdiffz': typeof HdiffzRoute + '/howto': typeof HowtoRoute + '/language': typeof LanguageRoute + '/srtools': typeof SrtoolsRoute +} +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: + | '/' + | '/about' + | '/analysis' + | '/hdiffz' + | '/howto' + | '/language' + | '/srtools' + fileRoutesByTo: FileRoutesByTo + to: + | '/' + | '/about' + | '/analysis' + | '/hdiffz' + | '/howto' + | '/language' + | '/srtools' + id: + | '__root__' + | '/' + | '/about' + | '/analysis' + | '/hdiffz' + | '/howto' + | '/language' + | '/srtools' + fileRoutesById: FileRoutesById +} +export interface RootRouteChildren { + IndexRoute: typeof IndexRoute + AboutRoute: typeof AboutRoute + AnalysisRoute: typeof AnalysisRoute + HdiffzRoute: typeof HdiffzRoute + HowtoRoute: typeof HowtoRoute + LanguageRoute: typeof LanguageRoute + SrtoolsRoute: typeof SrtoolsRoute +} + +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/srtools': { + id: '/srtools' + path: '/srtools' + fullPath: '/srtools' + preLoaderRoute: typeof SrtoolsRouteImport + parentRoute: typeof rootRouteImport + } + '/language': { + id: '/language' + path: '/language' + fullPath: '/language' + preLoaderRoute: typeof LanguageRouteImport + parentRoute: typeof rootRouteImport + } + '/howto': { + id: '/howto' + path: '/howto' + fullPath: '/howto' + preLoaderRoute: typeof HowtoRouteImport + parentRoute: typeof rootRouteImport + } + '/hdiffz': { + id: '/hdiffz' + path: '/hdiffz' + fullPath: '/hdiffz' + preLoaderRoute: typeof HdiffzRouteImport + parentRoute: typeof rootRouteImport + } + '/analysis': { + id: '/analysis' + path: '/analysis' + fullPath: '/analysis' + preLoaderRoute: typeof AnalysisRouteImport + parentRoute: typeof rootRouteImport + } + '/about': { + id: '/about' + path: '/about' + fullPath: '/about' + preLoaderRoute: typeof AboutRouteImport + parentRoute: typeof rootRouteImport + } + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexRouteImport + parentRoute: typeof rootRouteImport + } + } +} + +const rootRouteChildren: RootRouteChildren = { + IndexRoute: IndexRoute, + AboutRoute: AboutRoute, + AnalysisRoute: AnalysisRoute, + HdiffzRoute: HdiffzRoute, + HowtoRoute: HowtoRoute, + LanguageRoute: LanguageRoute, + SrtoolsRoute: SrtoolsRoute, +} +export const routeTree = rootRouteImport + ._addFileChildren(rootRouteChildren) + ._addFileTypes() diff --git a/frontend/src/routes/__root.tsx b/frontend/src/routes/__root.tsx new file mode 100644 index 0000000..d3b5d10 --- /dev/null +++ b/frontend/src/routes/__root.tsx @@ -0,0 +1,102 @@ +import { createRootRoute, Link, Outlet } from '@tanstack/react-router' +import ThemeController from '../components/themeController' +import { ToastContainer } from 'react-toastify' +import { useGlobalEvents } from '@/hooks'; +import useLauncherStore from '@/stores/launcherStore'; +import useHdiffzStore from '@/stores/hdiffzStore'; + +export const Route = createRootRoute({ + component: RootLayout +}) + +function RootLayout() { + const { setGameRunning, setServerRunning, setProxyRunning, setProgressDownload, setDownloadSpeed } = useLauncherStore() + const { setProgressUpdate, setMaxProgressUpdate, setMessageUpdate } = useHdiffzStore() + useGlobalEvents({ + setGameRunning, + setServerRunning, + setProxyRunning, + setProgressUpdate, + setMaxProgressUpdate, + setProgressDownload, + setDownloadSpeed, + setMessageUpdate, + }); + + return ( + <> +
+
+
+
+ +
+
    +
  • Home
  • + +
  • + Tools +
      +
    • Language
    • +
    • Hdiffz
    • +
    +
  • +
  • + Plugins +
      +
    • Analysis (Veritas)
    • +
    • SrTools
    • +
    +
  • +
  • How to?
  • +
  • About
  • +
+
+ +

+ Firefly Lauc + + her + +

+

By Kain

+ +
+
+
    +
  • Home
  • +
  • +
    + Tools +
      +
    • Language
    • +
    • Hdiffz
    • +
    +
    +
  • +
  • +
    + Plugins +
      +
    • Analysis (Veritas)
    • +
    • SrTools
    • +
    +
    +
  • +
  • How to?
  • +
  • About
  • +
+
+
+ +
+
+
+ +
+ + + ) +} \ No newline at end of file diff --git a/frontend/src/routes/about.tsx b/frontend/src/routes/about.tsx new file mode 100644 index 0000000..fa37b44 --- /dev/null +++ b/frontend/src/routes/about.tsx @@ -0,0 +1,8 @@ +import { createFileRoute } from '@tanstack/react-router' +import AboutPage from '@/pages/about' + +export const Route = createFileRoute('/about')({ + component: AboutPage, + +}) + diff --git a/frontend/src/routes/analysis.tsx b/frontend/src/routes/analysis.tsx new file mode 100644 index 0000000..150c88b --- /dev/null +++ b/frontend/src/routes/analysis.tsx @@ -0,0 +1,7 @@ +import { createFileRoute } from '@tanstack/react-router' +import AnalysisPage from '@/pages/analysis' + +export const Route = createFileRoute('/analysis')({ + component: AnalysisPage, +}) + diff --git a/frontend/src/routes/hdiffz.tsx b/frontend/src/routes/hdiffz.tsx new file mode 100644 index 0000000..442ff5b --- /dev/null +++ b/frontend/src/routes/hdiffz.tsx @@ -0,0 +1,7 @@ +import HdiffzPage from '@/pages/hdiffz' +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/hdiffz')({ + component: HdiffzPage, +}) + diff --git a/frontend/src/routes/howto.tsx b/frontend/src/routes/howto.tsx new file mode 100644 index 0000000..b8f5e1c --- /dev/null +++ b/frontend/src/routes/howto.tsx @@ -0,0 +1,6 @@ +import { createFileRoute } from '@tanstack/react-router' +import HowToPage from '@/pages/howto' + +export const Route = createFileRoute('/howto')({ + component: HowToPage, +}) diff --git a/frontend/src/routes/index.tsx b/frontend/src/routes/index.tsx new file mode 100644 index 0000000..b12731f --- /dev/null +++ b/frontend/src/routes/index.tsx @@ -0,0 +1,7 @@ +import { createFileRoute } from '@tanstack/react-router' +import LauncherPage from '@/pages/launcher' + +export const Route = createFileRoute('/')({ + component: LauncherPage, +}) + diff --git a/frontend/src/routes/language.tsx b/frontend/src/routes/language.tsx new file mode 100644 index 0000000..d2dc0c9 --- /dev/null +++ b/frontend/src/routes/language.tsx @@ -0,0 +1,7 @@ +import LanguagePage from '@/pages/language' +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/language')({ + component: LanguagePage, +}) + diff --git a/frontend/src/routes/srtools.tsx b/frontend/src/routes/srtools.tsx new file mode 100644 index 0000000..d95a227 --- /dev/null +++ b/frontend/src/routes/srtools.tsx @@ -0,0 +1,8 @@ +import SrToolsPage from '@/pages/srtools' +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/srtools')({ + component: SrToolsPage, +}) + + diff --git a/frontend/src/stores/hdiffzStore.ts b/frontend/src/stores/hdiffzStore.ts new file mode 100644 index 0000000..9efee7f --- /dev/null +++ b/frontend/src/stores/hdiffzStore.ts @@ -0,0 +1,46 @@ + +import { create } from 'zustand' + +interface LauncherState { + folderCheckResult: 'success' | 'error' | null, + isLoading: {game: boolean, diff: boolean}, + diffDir: string, + diffCheckResult: 'success' | 'error' | null, + isDiffLoading: boolean, + progressUpdate: number, + maxProgressUpdate: number, + messageUpdate: string, + stageType: string, + setMessageUpdate: (value: string) => void, + setIsLoading: (value: {game: boolean, diff: boolean}) => void, + setFolderCheckResult: (value: 'success' | 'error' | null) => void, + setDiffDir: (value: string) => void, + setDiffCheckResult: (value: 'success' | 'error' | null) => void, + setIsDiffLoading: (value: boolean) => void, + setProgressUpdate: (value: number) => void, + setMaxProgressUpdate: (value: number) => void, + setStageType: (value: string) => void, +} + +const useLauncherStore = create((set, get) => ({ + isLoading: {game: false, diff: false}, + folderCheckResult: null, + diffDir: "", + diffCheckResult: null, + isDiffLoading: false, + progressUpdate: 0, + maxProgressUpdate: 0, + messageUpdate: "", + stageType: "", + setIsLoading: (value: {game: boolean, diff: boolean}) => set({ isLoading: value }), + setFolderCheckResult: (value: 'success' | 'error' | null) => set({ folderCheckResult: value }), + setDiffDir: (value: string) => set({ diffDir: value }), + setDiffCheckResult: (value: 'success' | 'error' | null) => set({ diffCheckResult: value }), + setIsDiffLoading: (value: boolean) => set({ isDiffLoading: value }), + setProgressUpdate: (value: number) => set({ progressUpdate: value }), + setMaxProgressUpdate: (value: number) => set({ maxProgressUpdate: value }), + setMessageUpdate: (value: string) => set({ messageUpdate: value }), + setStageType: (value: string) => set({ stageType: value }), +})); + +export default useLauncherStore; \ No newline at end of file diff --git a/frontend/src/stores/launcherStore.ts b/frontend/src/stores/launcherStore.ts new file mode 100644 index 0000000..535c27d --- /dev/null +++ b/frontend/src/stores/launcherStore.ts @@ -0,0 +1,54 @@ + +import { create } from 'zustand' + +interface LauncherState { + modelName: string; + downloadType: string; + serverReady: boolean; + proxyReady: boolean; + isDownloading: boolean; + serverRunning: boolean; + proxyRunning: boolean; + isLoading: boolean; + gameRunning: boolean; + progressDownload: number; + downloadSpeed: number; + setModelName: (value: string) => void; + setDownloadType: (value: string) => void; + setServerReady: (value: boolean) => void; + setProxyReady: (value: boolean) => void; + setIsDownloading: (value: boolean) => void; + setServerRunning: (value: boolean) => void; + setProxyRunning: (value: boolean) => void; + setIsLoading: (value: boolean) => void; + setGameRunning: (value: boolean) => void; + setProgressDownload: (value: number) => void; + setDownloadSpeed: (value: number) => void; +} + +const useLauncherStore = create((set, get) => ({ + isLoading: false, + modelName: "Download Data", + downloadType: "", + serverReady: false, + proxyReady: false, + isDownloading: false, + serverRunning: false, + proxyRunning: false, + gameRunning: false, + progressDownload: 0, + downloadSpeed: 0, + setIsLoading: (value: boolean) => set({ isLoading: value }), + setModelName: (value: string) => set({ modelName: value }), + setDownloadType: (value: string) => set({ downloadType: value }), + setServerReady: (value: boolean) => set({ serverReady: value }), + setProxyReady: (value: boolean) => set({ proxyReady: value }), + setIsDownloading: (value: boolean) => set({ isDownloading: value }), + setServerRunning: (value: boolean) => set({ serverRunning: value }), + setProxyRunning: (value: boolean) => set({ proxyRunning: value }), + setGameRunning: (value: boolean) => set({ gameRunning: value }), + setProgressDownload: (value: number) => set({ progressDownload: value }), + setDownloadSpeed: (value: number) => set({ downloadSpeed: value }), +})); + +export default useLauncherStore; \ No newline at end of file diff --git a/frontend/src/stores/modalStore.ts b/frontend/src/stores/modalStore.ts new file mode 100644 index 0000000..8edc873 --- /dev/null +++ b/frontend/src/stores/modalStore.ts @@ -0,0 +1,14 @@ + +import { create } from 'zustand' + +interface ModalState { + isOpenNotification: boolean; + setIsOpenNotification: (modal: boolean) => void; +} + +const useModalStore = create((set, get) => ({ + isOpenNotification: false, + setIsOpenNotification: (modal: boolean) => set({ isOpenNotification: modal }), +})); + +export default useModalStore; \ No newline at end of file diff --git a/frontend/src/stores/settingStore.ts b/frontend/src/stores/settingStore.ts new file mode 100644 index 0000000..0f717ed --- /dev/null +++ b/frontend/src/stores/settingStore.ts @@ -0,0 +1,47 @@ +import { create } from 'zustand' +import { createJSONStorage, persist } from 'zustand/middleware'; + + +interface SettingState { + locale: string; + gamePath: string; + gameDir: string; + serverPath: string; + proxyPath: string; + serverVersion: string; + proxyVersion: string; + setLocale: (newLocale: string) => void; + setGamePath: (newGamePath: string) => void; + setGameDir: (newGameDir: string) => void; + setServerPath: (newServerPath: string) => void; + setProxyPath: (newProxyPath: string) => void; + setServerVersion: (newServerVersion: string) => void; + setProxyVersion: (newProxyVersion: string) => void; +} + +const useSettingStore = create()( + persist( + (set) => ({ + locale: "en", + gamePath: "", + gameDir: "", + serverPath: "", + proxyPath: "", + serverVersion: "", + proxyVersion: "", + setLocale: (newLocale: string) => set({ locale: newLocale }), + setGamePath: (newGamePath: string) => set({ gamePath: newGamePath }), + setGameDir: (newGameDir: string) => set({ gameDir: newGameDir }), + setServerPath: (newServerPath: string) => set({ serverPath: newServerPath }), + setProxyPath: (newProxyPath: string) => set({ proxyPath: newProxyPath }), + setServerVersion: (newServerVersion: string) => set({ serverVersion: newServerVersion }), + setProxyVersion: (newProxyVersion: string) => set({ proxyVersion: newProxyVersion }), + }), + { + name: 'setting-storage', + storage: createJSONStorage(() => localStorage), + } + ) +); + +export default useSettingStore; \ No newline at end of file diff --git a/frontend/src/styles/index.css b/frontend/src/styles/index.css new file mode 100644 index 0000000..3634c4d --- /dev/null +++ b/frontend/src/styles/index.css @@ -0,0 +1,5 @@ +@import "tailwindcss"; +@plugin "daisyui"; +@plugin "daisyui" { + themes: night --default, night --prefersdark, cupcake; +} \ No newline at end of file diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 0000000..ed0e74b --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "baseUrl": ".", + "paths": { + "@bindings/*": ["bindings/*"], + "@/*": ["src/*"] + }, + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": false, + "noImplicitAny": false, + "noFallthroughCasesInSwitch": true + }, + "include": ["src", "bindings"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json new file mode 100644 index 0000000..42872c5 --- /dev/null +++ b/frontend/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts new file mode 100644 index 0000000..b82e79c --- /dev/null +++ b/frontend/vite.config.ts @@ -0,0 +1,27 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import { tanstackRouter } from '@tanstack/router-plugin/vite' +import tailwindcss from '@tailwindcss/vite' +import path from 'path' + +export default defineConfig({ + base: '/', + build: { + outDir: 'dist', + }, + plugins: [ + tanstackRouter({ + target: 'react', + routesDirectory: 'src/routes', + autoCodeSplitting: false, + }), + tailwindcss(), + react(), + ], + resolve: { + alias: { + '@bindings': path.resolve(__dirname, 'bindings'), + '@': path.resolve(__dirname, 'src'), + }, + }, +}) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..2c6a49a --- /dev/null +++ b/go.mod @@ -0,0 +1,54 @@ +module firefly-launcher + +go 1.22.4 + +toolchain go1.24.4 + +require ( + github.com/wailsapp/wails/v3 v3.0.0-alpha.9 + golang.org/x/sys v0.28.0 +) + +require ( + dario.cat/mergo v1.0.1 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/ProtonMail/go-crypto v1.0.0 // indirect + github.com/adrg/xdg v0.5.0 // indirect + github.com/bep/debounce v1.2.1 // indirect + github.com/cloudflare/circl v1.3.8 // indirect + github.com/cyphar/filepath-securejoin v0.2.5 // indirect + github.com/ebitengine/purego v0.4.0-alpha.4 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.6.0 // indirect + github.com/go-git/go-git/v5 v5.12.0 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/google/uuid v1.4.0 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/leaanthony/go-ansi-parser v1.6.1 // indirect + github.com/leaanthony/u v1.1.0 // indirect + github.com/lmittmann/tint v1.0.4 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/samber/lo v1.38.1 // indirect + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect + github.com/skeema/knownhosts v1.2.2 // indirect + github.com/wailsapp/go-webview2 v1.0.19 // indirect + github.com/wailsapp/mimetype v1.4.1 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect + golang.org/x/mod v0.19.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/tools v0.23.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..60cc9a5 --- /dev/null +++ b/go.sum @@ -0,0 +1,194 @@ +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= +github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY= +github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= +github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI= +github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= +github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo= +github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/ebitengine/purego v0.4.0-alpha.4 h1:Y7yIV06Yo5M2BAdD7EVPhfp6LZ0tEcQo5770OhYUVes= +github.com/ebitengine/purego v0.4.0-alpha.4/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= +github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8= +github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= +github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= +github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= +github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= +github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= +github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI= +github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= +github.com/lmittmann/tint v1.0.4 h1:LeYihpJ9hyGvE0w+K2okPTGUdVLfng1+nDNVR4vWISc= +github.com/lmittmann/tint v1.0.4/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= +github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= +github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= +github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/wailsapp/go-webview2 v1.0.19 h1:7U3QcDj1PrBPaxJNCui2k1SkWml+Q5kvFUFyTImA6NU= +github.com/wailsapp/go-webview2 v1.0.19/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= +github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= +github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= +github.com/wailsapp/wails/v3 v3.0.0-alpha.9 h1:b8CfRrhPno8Fra0xFp4Ifyj+ogmXBc35rsQWvcrHtsI= +github.com/wailsapp/wails/v3 v3.0.0-alpha.9/go.mod h1:dSv6s722nSWaUyUiapAM1DHc5HKggNGY1a79shO85/g= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/fs-service.go b/internal/fs-service.go new file mode 100644 index 0000000..86addc7 --- /dev/null +++ b/internal/fs-service.go @@ -0,0 +1,142 @@ +package internal + +import ( + "firefly-launcher/pkg/sevenzip" + "fmt" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + + "github.com/wailsapp/wails/v3/pkg/application" + "golang.org/x/sys/windows" +) + +type FSService struct{} + +func (f *FSService) PickFolder() (string, error) { + dialog := application.OpenFileDialog(). + CanChooseDirectories(true). + CanCreateDirectories(true). + ResolvesAliases(true) + if runtime.GOOS == "darwin" { + dialog.SetMessage("Select a file/directory") + } else { + dialog.SetTitle("Select a file/directory") + } + if path, err := dialog.PromptForSingleSelection(); err == nil { + return path, nil + } + return "", nil +} + +func (f *FSService) PickFile() (string, error) { + dialog := application.OpenFileDialog(). + CanChooseFiles(true). + ResolvesAliases(true) + if runtime.GOOS == "darwin" { + dialog.SetMessage("Select a file/directory") + } else { + dialog.SetTitle("Select a file/directory") + } + if path, err := dialog.PromptForSingleSelection(); err == nil { + return path, nil + } + return "", nil +} + +func (f *FSService) DirExists(path string) bool { + info, err := os.Stat(path) + if err != nil { + return false + } + return info.IsDir() +} + +func (f *FSService) FileExists(path string) bool { + if info, err := os.Stat(path); err == nil { + return info.Mode().IsRegular() + } + return false +} + +func (f *FSService) StartApp(path string) (bool, error) { + cmd := exec.Command(path) + err := cmd.Start() + if err != nil { + return false, err + } + if strings.HasSuffix(path, "StarRail.exe") { + go func() { + _ = cmd.Wait() + application.Get().EmitEvent("game:exit") + }() + } + + return true, nil +} + +func (f *FSService) StartWithConsole(path string) (bool, error) { + absPath, err := filepath.Abs(path) + if err != nil { + return false, err + } + + if _, err := os.Stat(absPath); os.IsNotExist(err) { + return false, fmt.Errorf("file not found: %s", absPath) + } + cmd := exec.Command(absPath) + cmd.Dir = filepath.Dir(absPath) + cmd.Stdin = nil + cmd.Stdout = nil + cmd.Stderr = nil + + cmd.SysProcAttr = &windows.SysProcAttr{ + CreationFlags: windows.CREATE_NEW_CONSOLE | + windows.CREATE_BREAKAWAY_FROM_JOB, + NoInheritHandles: true, + } + + err = cmd.Start() + + if err != nil { + return false, err + } + + go func() { + _ = cmd.Wait() + if strings.HasSuffix(path, "launcher.exe") { + application.Get().EmitEvent("game:exit") + } else if strings.HasSuffix(path, "firefly-go_win.exe") { + application.Get().EmitEvent("server:exit") + } else if strings.HasSuffix(path, "FireflyProxy.exe") { + application.Get().EmitEvent("proxy:exit") + } + }() + return true, nil +} + +func (f *FSService) OpenFolder(path string) (bool, string) { + absPath, err := filepath.Abs(path) + if err != nil { + return false, "failed to resolve absolute path: " + err.Error() + } + + if !f.DirExists(absPath) { + return false, "directory not found: " + absPath + } + + url := "file:///" + filepath.ToSlash(absPath) + application.Get().BrowserOpenURL(url) + + return true, "" +} + +func (f *FSService) FileExistsInZip(archivePath, fileInside string) (bool, string) { + exists, err := sevenzip.IsFileIn7z(archivePath, fileInside) + if err != nil { + return false, err.Error() + } + return exists, "" +} diff --git a/internal/git-service.go b/internal/git-service.go new file mode 100644 index 0000000..73dcca4 --- /dev/null +++ b/internal/git-service.go @@ -0,0 +1,203 @@ +package internal + +import ( + "encoding/json" + "firefly-launcher/pkg/constant" + "firefly-launcher/pkg/models" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + + "github.com/wailsapp/wails/v3/pkg/application" +) + +type GitService struct{} + +func (g *GitService) GetLatestServerVersion(oldVersion string) (bool, string, string) { + resp, err := http.Get(constant.ServerGitUrl) + if err != nil { + return false, "", err.Error() + } + defer resp.Body.Close() + + body, _ := io.ReadAll(resp.Body) + + var releases []models.ReleaseType + err = json.Unmarshal(body, &releases) + if err != nil { + return false, "", err.Error() + } + + if len(releases) == 0 { + return false, "", "no releases found" + } + + return true, releases[0].TagName, "" +} + +func (g *GitService) DownloadServerProgress(version string) (bool, string) { + + resp, err := http.Get(constant.ServerGitUrl) + if err != nil { + panic(err) + } + defer resp.Body.Close() + + body, _ := io.ReadAll(resp.Body) + + var releases []*models.ReleaseType + err = json.Unmarshal(body, &releases) + if err != nil { + return false, err.Error() + } + + if len(releases) == 0 { + return false, "no releases found" + } + + var releaseData *models.ReleaseType + for _, release := range releases { + if release.TagName == version { + releaseData = release + break + } + } + + if releaseData == nil || releaseData.TagName == "" { + return false, "no release found" + } + + var assetWin models.AssetType + for _, asset := range releaseData.Assets { + if asset.Name == constant.ServerZipFile { + assetWin = asset + break + } + } + + if assetWin.Name == "" { + return false, "no assets found" + } + + if err := os.Mkdir(constant.ServerStorageUrl, 0755); err != nil { + if !os.IsExist(err) { + return false, err.Error() + } + } + + saveFile := filepath.Join(constant.ServerStorageUrl, assetWin.Name) + + resp, err = http.Get(assetWin.BrowserDownloadURL) + if err != nil { + return false, err.Error() + } + defer resp.Body.Close() + + DownloadFile(saveFile, assetWin.BrowserDownloadURL, func(percent float64, speed float64) { + application.Get().EmitEvent("download:server", map[string]interface{}{ + "percent": fmt.Sprintf("%.2f", percent), + "speed": fmt.Sprintf("%.2f", speed), + }) + }) + return true, "" +} + +func (g *GitService) UnzipServer() { + unzipParallel(filepath.Join(constant.ServerStorageUrl, constant.ServerZipFile), constant.ServerStorageUrl) + os.Remove(filepath.Join(constant.ServerStorageUrl, constant.ServerZipFile)) +} + +func (g *GitService) GetLatestProxyVersion(oldVersion string) (bool, string, string) { + resp, err := http.Get(constant.ProxyGitUrl) + if err != nil { + return false, "", err.Error() + } + defer resp.Body.Close() + + body, _ := io.ReadAll(resp.Body) + + var releases []models.ReleaseType + err = json.Unmarshal(body, &releases) + if err != nil { + return false, "", err.Error() + } + + if len(releases) == 0 { + return false, "", "no releases found" + } + + return true, releases[0].TagName, "" +} + +func (g *GitService) DownloadProxyProgress(version string) (bool, string) { + resp, err := http.Get(constant.ProxyGitUrl) + if err != nil { + panic(err) + } + defer resp.Body.Close() + + body, _ := io.ReadAll(resp.Body) + + var releases []*models.ReleaseType + err = json.Unmarshal(body, &releases) + if err != nil { + return false, err.Error() + } + + if len(releases) == 0 { + return false, "no releases found" + } + + var releaseData *models.ReleaseType + for _, release := range releases { + if release.TagName == version { + releaseData = release + break + } + } + + if releaseData == nil || releaseData.TagName == "" { + return false, "no release found" + } + + var assetWin models.AssetType + for _, asset := range releaseData.Assets { + if asset.Name == constant.ProxyZipFile { + assetWin = asset + break + } + } + + if assetWin.Name == "" { + return false, "no assets found" + } + + if err := os.Mkdir(constant.ProxyStorageUrl, 0755); err != nil { + if !os.IsExist(err) { + return false, err.Error() + } + } + saveFile := filepath.Join(constant.ProxyStorageUrl, assetWin.Name) + + resp, err = http.Get(assetWin.BrowserDownloadURL) + if err != nil { + return false, err.Error() + } + defer resp.Body.Close() + + DownloadFile(saveFile, assetWin.BrowserDownloadURL, func(percent float64, speed float64) { + application.Get().EmitEvent("download:proxy", map[string]interface{}{ + "percent": fmt.Sprintf("%.2f", percent), + "speed": fmt.Sprintf("%.2f", speed), + }) + + }) + return true, "" +} + +func (g *GitService) UnzipProxy() { + unzipParallel(filepath.Join(constant.ProxyStorageUrl, constant.ProxyZipFile), constant.ProxyStorageUrl) + os.Remove(filepath.Join(constant.ProxyStorageUrl, constant.ProxyZipFile)) +} diff --git a/internal/hdiffz-service.go b/internal/hdiffz-service.go new file mode 100644 index 0000000..b49e54e --- /dev/null +++ b/internal/hdiffz-service.go @@ -0,0 +1,212 @@ +package internal + +import ( + "bufio" + "encoding/json" + "firefly-launcher/pkg/constant" + "firefly-launcher/pkg/models" + "firefly-launcher/pkg/sevenzip" + "firefly-launcher/pkg/verifier" + "fmt" + "io" + "os" + "os/exec" + "path/filepath" + "strings" + "syscall" + + "github.com/wailsapp/wails/v3/pkg/application" +) + +type HdiffzService struct{} + +func (h *HdiffzService) VersionValidate(gamePath, patchPath string) (bool, string) { + oldVersionData, err := models.ParseBinaryVersion(filepath.Join(gamePath, "StarRail_Data\\StreamingAssets\\BinaryVersion.bytes")) + if err != nil { + return false, err.Error() + } + + if _, err := os.Stat(patchPath); err != nil { + return false, err.Error() + } + + if _, err := os.Stat(constant.TempUrl); os.IsNotExist(err) { + if err := os.MkdirAll(constant.TempUrl, os.ModePerm); err != nil { + return false, err.Error() + } + } + if err := sevenzip.ExtractAFileFromZip(patchPath, "StarRail_Data\\StreamingAssets\\BinaryVersion.bytes", constant.TempUrl); err != nil { + return false, err.Error() + } + + binPath := filepath.Join(constant.TempUrl, "BinaryVersion.bytes") + newVersionData, err := models.ParseBinaryVersion(binPath) + if err != nil { + return false, err.Error() + } + defer os.Remove(binPath) + + v := newVersionData.Subtract(*oldVersionData) + if v != 0 && v != 1 { + return false, fmt.Sprintf("the diff version %s not valid with game version %s", newVersionData, oldVersionData) + } + + return true, "validated" +} +func (h *HdiffzService) DataExtract(gamePath, patchPath string) (bool, string) { + if _, err := os.Stat(gamePath); err != nil { + return false, err.Error() + } + + if _, err := os.Stat(patchPath); err != nil { + return false, err.Error() + } + + if _, err := os.Stat(constant.TempUrl); os.IsNotExist(err) { + if err := os.MkdirAll(constant.TempUrl, os.ModePerm); err != nil { + return false, err.Error() + } + } + + if err := sevenzip.ExtractAllFilesFromZip(patchPath, constant.TempUrl); err != nil { + os.RemoveAll(constant.TempUrl) + return false, err.Error() + } + + validator, err := verifier.NewVerifier(gamePath, constant.TempUrl) + if err != nil { + os.RemoveAll(constant.TempUrl) + return false, err.Error() + } + + if err := validator.VerifyAll(); err != nil { + os.RemoveAll(constant.TempUrl) + return false, err.Error() + } + + return true, "validated" +} + +func (h *HdiffzService) CutData(gamePath string) (bool, string) { + if _, err := os.Stat(constant.TempUrl); os.IsNotExist(err) { + return false, err.Error() + } + + err := filepath.Walk(constant.TempUrl, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + relPath, err := filepath.Rel(constant.TempUrl, path) + if err != nil { + return err + } + destPath := filepath.Join(gamePath, relPath) + application.Get().EmitEvent("hdiffz:message", map[string]string{"message": destPath}) + if info.IsDir() { + return os.MkdirAll(destPath, os.ModePerm) + } + + if err := os.MkdirAll(filepath.Dir(destPath), os.ModePerm); err != nil { + return err + } + + if err := os.Rename(path, destPath); err != nil { + srcFile, err := os.Open(path) + if err != nil { + return err + } + defer srcFile.Close() + + dstFile, err := os.Create(destPath) + if err != nil { + return err + } + defer dstFile.Close() + + if _, err := io.Copy(dstFile, srcFile); err != nil { + return err + } + _ = os.Remove(path) + } + return nil + }) + + if err != nil { + return false, err.Error() + } + + _ = os.RemoveAll(constant.TempUrl) + + return true, "cut completed" +} + +func (h *HdiffzService) PatchData(gamePath string) (bool, string) { + data, err := os.ReadFile(filepath.Join(gamePath, "hdiffmap.json")) + if err != nil { + return false, err.Error() + } + + var jsonData struct { + DiffMap []*models.DiffMapType `json:"diff_map"` + } + if err := json.Unmarshal(data, &jsonData); err != nil { + return false, err.Error() + } + + for i, entry := range jsonData.DiffMap { + application.Get().EmitEvent( + "hdiffz:progress", map[string]int{ + "progress": i, + "maxProgress": len(jsonData.DiffMap), + }) + sourceFile := filepath.Join(gamePath, entry.SourceFileName) + patchFile := filepath.Join(gamePath, entry.PatchFileName) + targetFile := filepath.Join(gamePath, entry.TargetFileName) + + if _, err := os.Stat(sourceFile); os.IsNotExist(err) { + continue + } + if _, err := os.Stat(patchFile); os.IsNotExist(err) { + continue + } + + cmd := exec.Command(constant.ToolHPatchzExe.String(), sourceFile, patchFile, targetFile) + cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} + _, err := cmd.CombinedOutput() + if err != nil { + continue + } + } + + return true, "patching completed" +} + +func (h *HdiffzService) DeleteFiles(gamePath string) (bool, string) { + var deleteFiles []string + + file, err := os.Open(filepath.Join(gamePath, "deletefiles.txt")) + if err != nil { + return false, "" + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if line != "" { + deleteFiles = append(deleteFiles, line) + } + } + + if err := scanner.Err(); err != nil { + return false, "" + } + + for i, file := range deleteFiles { + os.Remove(filepath.Join(gamePath, file)) + application.Get().EmitEvent("hdiffz:progress", map[string]int{"progress": i, "maxProgress": len(deleteFiles)}) + } + + return true, "" +} diff --git a/internal/language-service.go b/internal/language-service.go new file mode 100644 index 0000000..8f95e63 --- /dev/null +++ b/internal/language-service.go @@ -0,0 +1,146 @@ +package internal + +import ( + "bytes" + "fmt" + "os" + "path/filepath" +) + +type LanguageService struct{} + +func isValidLang(lang string) bool { + valid := []string{"en", "jp", "cn", "kr"} + for _, v := range valid { + if lang == v { + return true + } + } + return false +} + +func (l *LanguageService) GetLanguage(path string) (string, string, error) { + files, err := os.ReadDir(path) + if err != nil { + return "", "", err + } + + for _, file := range files { + filePath := filepath.Join(path, file.Name()) + + content, err := os.ReadFile(filePath) + if err != nil { + continue + } + + patternToFind := []byte("SpriteOutput/UI/Fonts/RPG_CN.ttf") + idx := bytes.Index(content, patternToFind) + if idx == -1 { + continue + } + + pattern := []byte("Korean") + idx = bytes.Index(content, pattern) + if idx == -1 { + continue + } + + // Move to os text language + idx += 10 + idx += 4 + osText := string(content[idx : idx+2]) + idx += 3 * 4 + + // Move to cn voice language + idx += 1 + idx += 5 + cnVoice := string(content[idx : idx+2]) + idx += 3 * 2 // skip 2 entries + + // Move to os voice language + idx += 1 + idx += 5 + osVoice := string(content[idx : idx+2]) + idx += 3 * 5 // skip 5 entries + + // Move to cn text language + idx += 1 + idx += 4 + cnText := string(content[idx : idx+2]) + + textLang := osText + voiceLang := osVoice + if !isValidLang(textLang) { + textLang = cnText + } + if !isValidLang(voiceLang) { + voiceLang = cnVoice + } + + return textLang, voiceLang, nil + } + + return "", "", fmt.Errorf("couldn't find file to read language from") +} + +func replaceBytes(content []byte, idx int, choice string, param int) int { + for i := 0; i < param; i++ { + copy(content[idx:idx+2], []byte(choice)) + idx += 3 + } + return idx +} + +func (l *LanguageService) SetLanguage(path string, text, voice string) (bool, error) { + files, err := os.ReadDir(path) + if err != nil { + return false, err + } + + for _, file := range files { + filePath := filepath.Join(path, file.Name()) + + content, err := os.ReadFile(filePath) + if err != nil { + continue + } + + patternToFind := []byte("SpriteOutput/UI/Fonts/RPG_CN.ttf") + idx := bytes.Index(content, patternToFind) + if idx == -1 { + continue + } + + pattern := []byte("Korean") + idx = bytes.Index(content, pattern) + if idx == -1 { + continue + } + + idx += 10 + idx += 4 + idx = replaceBytes(content, idx, text, 4) + idx += 1 + + idx += 5 + idx = replaceBytes(content, idx, voice, 2) + idx += 1 + + idx += 5 + idx = replaceBytes(content, idx, voice, 5) + + idx += 1 + + idx += 4 + _ = replaceBytes(content, idx, text, 2) + + err = os.WriteFile(filePath, content, 0644) + if err != nil { + return false, err + } + + return true, nil + } + + return false, fmt.Errorf("couldn't find file to patch. Make sure this file is placed in the correct folder") +} diff --git a/internal/util.go b/internal/util.go new file mode 100644 index 0000000..40953eb --- /dev/null +++ b/internal/util.go @@ -0,0 +1,192 @@ +package internal + +import ( + "archive/zip" + "fmt" + "io" + "math" + "net/http" + "os" + "path/filepath" + "runtime" + "sync" + "time" +) + +func humanFormat(bytes int64) string { + n := float64(bytes) + for _, unit := range []string{"", "Ki", "Mi", "Gi"} { + if math.Abs(n) < 1024.0 { + return fmt.Sprintf("%3.1f%sB", n, unit) + } + n /= 1024.0 + } + return fmt.Sprintf("%.1fTiB", n) +} + +type WriteCounter struct { + Total uint64 + StartTime time.Time + OnEmit func(percent float64, speedMBps float64) + TotalSize int64 + lastLoggedPercent int +} + +func NewWriteCounter(total int64, onEmit func(percent float64, speedMBps float64)) *WriteCounter { + return &WriteCounter{ + StartTime: time.Now(), + TotalSize: total, + lastLoggedPercent: -1, + OnEmit: onEmit, + } +} + +func (wc *WriteCounter) Write(p []byte) (int, error) { + n := len(p) + wc.Total += uint64(n) + wc.PrintProgress() + return n, nil +} + +func (wc *WriteCounter) PrintProgress() { + elapsed := time.Since(wc.StartTime).Seconds() + if elapsed < 0.001 { + elapsed = 0.001 + } + + speed := float64(wc.Total) / 1024 / 1024 / elapsed // MB/s + percent := float64(wc.Total) / float64(wc.TotalSize) * 100 + if wc.OnEmit != nil { + wc.OnEmit(percent, speed) + } +} + +func DownloadFile(filepath string, url string, onEmit func(percent float64, speed float64)) error { + tmpPath := filepath + ".tmp" + + resp, err := http.Get(url) + if err != nil { + return fmt.Errorf("failed to get file: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("bad status: %s", resp.Status) + } + + out, err := os.Create(tmpPath) + if err != nil { + return fmt.Errorf("failed to create tmp file: %w", err) + } + + counter := NewWriteCounter(resp.ContentLength, onEmit) + _, err = io.Copy(out, io.TeeReader(resp.Body, counter)) + if closeErr := out.Close(); closeErr != nil { + return fmt.Errorf("failed to close tmp file: %w", closeErr) + } + if err != nil { + return fmt.Errorf("failed to download file: %w", err) + } + + // Delete destination file if it exists + if _, err := os.Stat(filepath); err == nil { + if err := os.Remove(filepath); err != nil { + return fmt.Errorf("failed to remove existing file: %w", err) + } + } + + for i := 0; i < 3; i++ { + err = os.Rename(tmpPath, filepath) + if err == nil { + break + } + time.Sleep(300 * time.Millisecond) + } + if err != nil { + return fmt.Errorf("failed to rename after retries: %w", err) + } + + return nil +} + + + +func unzipParallel(src string, dest string) error { + numCPU := runtime.NumCPU() + + reserved := 1 + if numCPU > 4 { + reserved = 2 + } + maxWorkers := numCPU - reserved + if maxWorkers < 1 { + maxWorkers = 1 + } + r, err := zip.OpenReader(src) + if err != nil { + return err + } + defer r.Close() + + err = os.MkdirAll(dest, 0755) + if err != nil { + return err + } + + type job struct { + f *zip.File + } + jobs := make(chan job) + var wg sync.WaitGroup + + // Worker pool + for i := 0; i < maxWorkers; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for j := range jobs { + err := extractFile(j.f, dest) + if err != nil { + fmt.Printf("Error extracting %s: %v\n", j.f.Name, err) + } + } + }() + } + + // Feed jobs + for _, f := range r.File { + jobs <- job{f} + } + close(jobs) + wg.Wait() + + return nil +} + +func extractFile(f *zip.File, dest string) error { + fp := filepath.Join(dest, f.Name) + + if f.FileInfo().IsDir() { + return os.MkdirAll(fp, f.Mode()) + } + + err := os.MkdirAll(filepath.Dir(fp), 0755) + if err != nil { + return err + } + + rc, err := f.Open() + if err != nil { + return err + } + defer rc.Close() + + out, err := os.OpenFile(fp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) + if err != nil { + return err + } + defer out.Close() + + _, err = io.Copy(out, rc) + return err +} \ No newline at end of file diff --git a/main.go b/main.go new file mode 100644 index 0000000..b3801bc --- /dev/null +++ b/main.go @@ -0,0 +1,106 @@ +package main + +import ( + "embed" + _ "embed" + "firefly-launcher/internal" + "firefly-launcher/pkg/constant" + "fmt" + "log" + "os" + "path/filepath" + + "github.com/wailsapp/wails/v3/pkg/application" +) + +// Wails uses Go's `embed` package to embed the frontend files into the binary. +// Any files in the frontend/dist folder will be embedded into the binary and +// made available to the frontend. +// See https://pkg.go.dev/embed for more information. + +//go:embed all:frontend/dist +var assets embed.FS + +//go:embed all:assets +var tools embed.FS + +func fileExists(path string) bool { + info, err := os.Stat(path) + return err == nil && !info.IsDir() +} + +func extractFile(embedPath, outPath string) error { + data, err := tools.ReadFile(embedPath) + if err != nil { + return fmt.Errorf("can't read file embed %s: %w", embedPath, err) + } + + if err := os.MkdirAll(filepath.Dir(outPath), 0755); err != nil { + return fmt.Errorf("can't create directory %s: %w", filepath.Dir(outPath), err) + } + + return os.WriteFile(outPath, data, 0755) +} + +// main function serves as the application's entry point. It initializes the application, creates a window, +// and starts a goroutine that emits a time-based event every second. It subsequently runs the application and +// logs any error that might occur. +func main() { + for outPath, embedPath := range constant.RequiredFiles { + if !fileExists(outPath.String()) { + err := extractFile(embedPath, outPath.String()) + if err != nil { + fmt.Println("can't copy file:", err) + } + } + } + // Create a new Wails application by providing the necessary options. + // Variables 'Name' and 'Description' are for application metadata. + // 'Assets' configures the asset server with the 'FS' variable pointing to the frontend files. + // 'Bind' is a list of Go struct instances. The frontend has access to the methods of these instances. + // 'Mac' options tailor the application when running an macOS. + app := application.New(application.Options{ + Name: "firefly-launcher", + Description: "Firefly Launcher - Kain", + Services: []application.Service{ + application.NewService(&internal.FSService{}), + application.NewService(&internal.LanguageService{}), + application.NewService(&internal.GitService{}), + application.NewService(&internal.HdiffzService{}), + }, + Assets: application.AssetOptions{ + Handler: application.AssetFileServerFS(assets), + + }, + Mac: application.MacOptions{ + ApplicationShouldTerminateAfterLastWindowClosed: true, + }, + }) + + // Create a new window with the necessary options. + // 'Title' is the title of the window. + // 'Mac' options tailor the window when running on macOS. + // 'BackgroundColour' is the background colour of the window. + // 'URL' is the URL that will be loaded into the webview. + + app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + + Title: "Firefly Launcher - Kain", + Mac: application.MacWindow{ + InvisibleTitleBarHeight: 50, + Backdrop: application.MacBackdropTranslucent, + TitleBar: application.MacTitleBarHiddenInset, + }, + + BackgroundColour: application.NewRGB(27, 38, 54), + Width: 1200, + Height: 600, + URL: "/", + DevToolsEnabled: true, + }) + + err := app.Run() + if err != nil { + log.Fatal(err) + } +} diff --git a/pkg/constant/constant.go b/pkg/constant/constant.go new file mode 100644 index 0000000..0bbfbf0 --- /dev/null +++ b/pkg/constant/constant.go @@ -0,0 +1,35 @@ +package constant + +const ProxyGitUrl = "https://git.kain.io.vn/api/v1/repos/Firefly-Shelter/Firefly_Proxy/releases" +const ServerGitUrl = "https://git.kain.io.vn/api/v1/repos/Firefly-Shelter/FireflyGo_Local_Archive/releases" +const ServerStorageUrl = "./server" +const ProxyStorageUrl = "./proxy" +const ServerZipFile = "prebuild_win_x86.zip" +const ProxyZipFile = "64bit.zip" +const TempUrl = "./temp" + +type ToolFile string + +const ( + Tool7zaExe ToolFile = "bin/7za.exe" + Tool7zaDLL ToolFile = "bin/7za.dll" + Tool7zxaDLL ToolFile = "bin/7zxa.dll" + ToolHPatchzExe ToolFile = "bin/hpatchz.exe" + ToolHDiffzExe ToolFile = "bin/hdiffz.exe" +) + +var RequiredFiles = map[ToolFile]string{ + Tool7zaExe: "assets/7zip/7za.exe", + Tool7zaDLL: "assets/7zip/7za.dll", + Tool7zxaDLL: "assets/7zip/7zxa.dll", + ToolHPatchzExe: "assets/HDiffPatch/hpatchz.exe", + ToolHDiffzExe: "assets/HDiffPatch/hdiffz.exe", +} + +func (t ToolFile) GetEmbedPath() string { + return RequiredFiles[t] +} + +func (t ToolFile) String() string { + return string(t) +} diff --git a/pkg/models/binary-version.go b/pkg/models/binary-version.go new file mode 100644 index 0000000..8fa0d66 --- /dev/null +++ b/pkg/models/binary-version.go @@ -0,0 +1,73 @@ +package models + +import ( + "errors" + "fmt" + "os" + "strconv" + "strings" +) + +type BinaryVersion struct { + Major int + Minor int + Patch int +} + +func ParseBinaryVersion(path string) (*BinaryVersion, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + content := string(data) + + dashPos := strings.LastIndex(content, "-") + if dashPos == -1 { + return nil, errors.New("no dash found in version string") + } + + start := dashPos - 6 + if start < 0 { + start = 0 + } + + versionSlice := content[start:] + end := strings.Index(versionSlice, "-") + if end == -1 { + end = len(versionSlice) + } + + versionStr := versionSlice[:end] + parts := strings.SplitN(versionStr, ".", 3) + if len(parts) != 3 { + return nil, errors.New("invalid version format") + } + + major, err := strconv.Atoi(parts[0]) + if err != nil { + return nil, err + } + minor, err := strconv.Atoi(parts[1]) + if err != nil { + return nil, err + } + patch, err := strconv.Atoi(parts[2]) + if err != nil { + return nil, err + } + + return &BinaryVersion{major, minor, patch}, nil +} + +func (v *BinaryVersion) String() string { + return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch) +} + +func (v BinaryVersion) ToInt() int { + return v.Major*100 + v.Minor*10 + v.Patch +} + +func (v BinaryVersion) Subtract(other BinaryVersion) int { + return v.ToInt() - other.ToInt() +} diff --git a/pkg/models/hdiffmap.go b/pkg/models/hdiffmap.go new file mode 100644 index 0000000..48443b0 --- /dev/null +++ b/pkg/models/hdiffmap.go @@ -0,0 +1,15 @@ +package models + +type DiffMapType struct { + SourceFileName string `json:"source_file_name"` + SourceFileMD5 string `json:"source_file_md5"` + SourceFileSize int64 `json:"source_file_size"` + + TargetFileName string `json:"target_file_name"` + TargetFileMD5 string `json:"target_file_md5"` + TargetFileSize int64 `json:"target_file_size"` + + PatchFileName string `json:"patch_file_name"` + PatchFileMD5 string `json:"patch_file_md5"` + PatchFileSize int64 `json:"patch_file_size"` +} \ No newline at end of file diff --git a/pkg/models/release.go b/pkg/models/release.go new file mode 100644 index 0000000..9f131db --- /dev/null +++ b/pkg/models/release.go @@ -0,0 +1,56 @@ +package models + +type ReleaseType struct { + ID int `json:"id"` + TagName string `json:"tag_name"` + TargetCommitish string `json:"target_commitish"` + Name string `json:"name"` + Body string `json:"body"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + TarballURL string `json:"tarball_url"` + ZipballURL string `json:"zipball_url"` + UploadURL string `json:"upload_url"` + Draft bool `json:"draft"` + Prerelease bool `json:"prerelease"` + CreatedAt string `json:"created_at"` + PublishedAt string `json:"published_at"` + Author AuthorType `json:"author"` + Assets []AssetType `json:"assets"` +} + +type AuthorType struct { + ID int `json:"id"` + Login string `json:"login"` + LoginName string `json:"login_name"` + SourceID int `json:"source_id"` + FullName string `json:"full_name"` + Email string `json:"email"` + AvatarURL string `json:"avatar_url"` + HTMLURL string `json:"html_url"` + Language string `json:"language"` + IsAdmin bool `json:"is_admin"` + LastLogin string `json:"last_login"` + Created string `json:"created"` + Restricted bool `json:"restricted"` + Active bool `json:"active"` + ProhibitLogin bool `json:"prohibit_login"` + Location string `json:"location"` + Website string `json:"website"` + Description string `json:"description"` + Visibility string `json:"visibility"` + FollowersCount int `json:"followers_count"` + FollowingCount int `json:"following_count"` + StarredReposCount int `json:"starred_repos_count"` + Username string `json:"username"` +} + +type AssetType struct { + ID int `json:"id"` + Name string `json:"name"` + Size int `json:"size"` + DownloadCount int `json:"download_count"` + CreatedAt string `json:"created_at"` + UUID string `json:"uuid"` + BrowserDownloadURL string `json:"browser_download_url"` +} diff --git a/pkg/sevenzip/sevenzip.go b/pkg/sevenzip/sevenzip.go new file mode 100644 index 0000000..5e96fd4 --- /dev/null +++ b/pkg/sevenzip/sevenzip.go @@ -0,0 +1,44 @@ +package sevenzip + +import ( + "bytes" + "firefly-launcher/pkg/constant" + "fmt" + "os" + "os/exec" + "strings" +) + +func IsFileIn7z(archivePath, fileInside string) (bool, error) { + cmd := exec.Command(constant.Tool7zaExe.String(), "l", archivePath) + var out bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &out + + if err := cmd.Run(); err != nil { + return false, fmt.Errorf("7za list failed: %v\nOutput: %s", err, out.String()) + } + + lines := strings.Split(out.String(), "\n") + for _, line := range lines { + if strings.Contains(line, fileInside) { + return true, nil + } + } + + return false, fmt.Errorf("%s not found in %s", fileInside, archivePath) +} + +func ExtractAFileFromZip(archivePath, fileInside, outDir string) error { + cmd := exec.Command(constant.Tool7zaExe.String(), "e", archivePath, fileInside, "-o"+outDir, "-y") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + +func ExtractAllFilesFromZip(archivePath, outDir string) error { + cmd := exec.Command(constant.Tool7zaExe.String(), "x", archivePath, "-o"+outDir, "-y") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} diff --git a/pkg/verifier/verifier.go b/pkg/verifier/verifier.go new file mode 100644 index 0000000..03b3240 --- /dev/null +++ b/pkg/verifier/verifier.go @@ -0,0 +1,98 @@ +package verifier + +import ( + "crypto/md5" + "encoding/hex" + "encoding/json" + "firefly-launcher/pkg/models" + "fmt" + "io" + "os" + "path/filepath" + + "github.com/wailsapp/wails/v3/pkg/application" +) + +type Verifier struct { + GamePath string + HdiffPath string + DiffMapEntries []*models.DiffMapType +} + +func NewVerifier(gamePath, hdiffPath string) (*Verifier, error) { + data, err := os.ReadFile(hdiffPath + "/hdiffmap.json") + if err != nil { + return nil, err + } + + var jsonData struct { + DiffMap []*models.DiffMapType `json:"diff_map"` + } + if err := json.Unmarshal(data, &jsonData); err != nil { + return nil, err + } + + return &Verifier{ + GamePath: gamePath, + HdiffPath: hdiffPath, + DiffMapEntries: jsonData.DiffMap, + }, nil +} + +func (v *Verifier) VerifyAll() error { + for i, entry := range v.DiffMapEntries { + application.Get().EmitEvent( + "hdiffz:progress", map[string]int{ + "progress": i, + "maxProgress": len(v.DiffMapEntries), + }) + if err := check(entry.SourceFileName, entry.SourceFileSize, entry.SourceFileMD5, v.GamePath); err != nil { + return fmt.Errorf("source_file failed: %w", err) + } + // if err := check(entry.PatchFileName, entry.PatchFileSize, entry.PatchFileMD5, v.HdiffPath); err != nil { + // return fmt.Errorf("patch_file failed: %w", err) + // } + } + return nil +} + +func check(relPath string, expectedSize int64, expectedMD5, base string) error { + fullPath := filepath.Join(base, relPath) + + info, err := os.Stat(fullPath) + if err != nil { + return fmt.Errorf("file not found: %s", fullPath) + } + + if info.Size() != expectedSize { + return fmt.Errorf("file size mismatch for %s: expected %d, got %d", + fullPath, expectedSize, info.Size()) + } + + md5Hash, err := fileMD5(fullPath) + if err != nil { + return fmt.Errorf("error reading %s: %w", fullPath, err) + } + + if md5Hash != expectedMD5 { + return fmt.Errorf("md5 mismatch for %s: expected %s, got %s", + fullPath, expectedMD5, md5Hash) + } + + return nil +} + +func fileMD5(path string) (string, error) { + f, err := os.Open(path) + if err != nil { + return "", err + } + defer f.Close() + + h := md5.New() + if _, err := io.Copy(h, f); err != nil { + return "", err + } + + return hex.EncodeToString(h.Sum(nil)), nil +}