diff --git a/.gitignore b/.gitignore index 8028c98fb..b5fcfdfbd 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,8 @@ build *.warnings *.pyc /offline-tools/ +.idea +venv *.egg-info /misc/config_tools/dist +/misc/config_tools/configurator/src-tauri/tauri.conf.json \ No newline at end of file diff --git a/Makefile b/Makefile index 13b734193..2a961d9b2 100644 --- a/Makefile +++ b/Makefile @@ -80,6 +80,8 @@ HV_CFG_LOG = $(HV_OUT)/cfg.log VM_CONFIGS_DIR = $(T)/misc/config_tools ASL_COMPILER ?= $(shell which iasl) DPKG_BIN ?= $(shell which dpkg) +YARN_BIN ?= $(shell which yarn) +CARGO_BIN ?= $(shell which cargo) .PHONY: all hypervisor devicemodel tools life_mngr doc all: hypervisor devicemodel tools @@ -113,6 +115,13 @@ board_inspector: echo -e "The 'dpkg' utility is not available. Unable to create Debian package for board_inspector."; \ fi +configurator: + @if [ -x "$(YARN_BIN)" ] && [ -x "$(CARGO_BIN)" ]; then \ + python3 misc/packaging/gen_acrn_deb.py configurator $(ROOT_OUT) ; \ + else \ + echo -e "'yarn' or 'cargo' utility is not available. Unable to create Debian package for configurator."; \ + fi + hypervisor: hvdefconfig $(MAKE) $(HV_MAKEOPTS) @echo -e "ACRN Configuration Summary:" > $(HV_CFG_LOG) diff --git a/misc/config_tools/configurator/.gitignore b/misc/config_tools/configurator/.gitignore new file mode 100644 index 000000000..f8fcebd05 --- /dev/null +++ b/misc/config_tools/configurator/.gitignore @@ -0,0 +1,27 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +build +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# TS temp file +tauri-plugin.js.map +tauri-plugin.js diff --git a/misc/config_tools/configurator/README.md b/misc/config_tools/configurator/README.md new file mode 100644 index 000000000..97248c8d7 --- /dev/null +++ b/misc/config_tools/configurator/README.md @@ -0,0 +1,79 @@ +# ACRN Configurator + +This version based on tauri, WIP. + +## Features + +### Support Platforms + +- [x] Linux (.deb, AppImage) +- [x] Windows 7,8,10 (.exe, .msi) +- [x] macOS (.app, .dmg) + + +## Setting Up + +### 1. Install System Dependencies + +Please follow [this guide](https://tauri.studio/docs/getting-started/prerequisites) +to install system dependencies **(including yarn)**. + +### 2. Clone Project And Install Project Dependencies. + +#### Linux + +```bash +sudo apt install git +git clone https://github.com/projectacrn/acrn-hypervisor +cd acrn-hypervisor/misc/config_tools/configurator +python3 -m pip install -r requirements.txt +yarn +``` + +#### Windows && macOS + +Similar to Linux. + +On macOS, you may need to install git and python3 via `brew`. + +In Windows environment maybe you need to install git and python3 via chocolatey or manually, +and replace the command line `python3` with `py -3`. + +### 3. How To Build + +#### Linux + +Run this command in the acrn-hypervisor directory. + +```shell +make configurator +``` + +#### Windows/macOS + +Run follow command in the 'acrn-hypervisor' directory. + +```shell +python3 misc/config_tools/scenario_config/schema_slicer.py +python3 misc/config_tools/scenario_config/xs2js.py +cd misc/config_tools/configurator +yarn build +``` + +### 4. How To Run + +#### Linux + +Run this command in the acrn-hypervisor directory. + +```shell +sudo apt install ./build/acrn-configurator_*.deb +acrn-configurator +``` + +#### Windows/macOS + +You can find msi(Windows)/dmg(macOS) folder under the +`misc/config_tools/configurator/src-tauri/target/release/bundle` + +directory, the installer in the folder. diff --git a/misc/config_tools/configurator/index.html b/misc/config_tools/configurator/index.html new file mode 100644 index 000000000..6a0629e54 --- /dev/null +++ b/misc/config_tools/configurator/index.html @@ -0,0 +1,24 @@ + + + + + + + Vite App + + + +
+ + + + diff --git a/misc/config_tools/configurator/package.json b/misc/config_tools/configurator/package.json new file mode 100644 index 000000000..2f13d8b10 --- /dev/null +++ b/misc/config_tools/configurator/package.json @@ -0,0 +1,47 @@ +{ + "name": "acrn-configurator", + "private": true, + "version": "0.2.1", + "author": { + "name": "Feng, Weiyi", + "email": "weiyix.feng@intel.com", + "url": "https://github.com/Weiyi-Feng" + }, + "description": "ACRN Configurator", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "tauri": "tauri" + }, + "dependencies": { + "@fortawesome/fontawesome-svg-core": "^1.3.0", + "@fortawesome/free-regular-svg-icons": "^6.0.0", + "@fortawesome/free-solid-svg-icons": "^6.0.0", + "@fortawesome/react-fontawesome": "^0.1.17", + "@popperjs/core": "^2.11.2", + "@rjsf/core": "^4.0.1", + "@rollup/plugin-replace": "^4.0.0", + "@tauri-apps/api": "^1.0.0-rc.1", + "bootstrap": "^5.1.3", + "js-base64": "^3.7.2", + "lodash": "^4.17.21", + "node-fetch": "2", + "query-string": "^7.1.1", + "react": "^17.0.2", + "react-bootstrap": "^2.1.2", + "react-dom": "^17.0.2", + "react-icons": "^4.3.1", + "react-router": "^6.2.1", + "react-router-dom": "^6.2.1", + "vconsole": "^3.14.3" + }, + "devDependencies": { + "@tauri-apps/cli": "^1.0.0-rc.5", + "@types/lodash": "^4.14.179", + "@types/node": "^17.0.21", + "@vitejs/plugin-react": "^1.0.7", + "sass": "^1.49.9", + "vite": "^2.8.0" + } +} diff --git a/misc/config_tools/configurator/requirements.txt b/misc/config_tools/configurator/requirements.txt new file mode 100644 index 000000000..a519e4a90 --- /dev/null +++ b/misc/config_tools/configurator/requirements.txt @@ -0,0 +1,7 @@ +lxml +xmltodict +xmlschema +defusedxml +requests +bs4 +sphinx diff --git a/misc/config_tools/configurator/src-tauri/.gitignore b/misc/config_tools/configurator/src-tauri/.gitignore new file mode 100644 index 000000000..dd7b1f523 --- /dev/null +++ b/misc/config_tools/configurator/src-tauri/.gitignore @@ -0,0 +1,14 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ +WixTools + +# These are backup files generated by rustfmt +**/*.rs.bk + +config.json +bundle.json + +# ts temp file +types/*.js +types/*.map diff --git a/misc/config_tools/configurator/src-tauri/Cargo.lock b/misc/config_tools/configurator/src-tauri/Cargo.lock new file mode 100644 index 000000000..20c550165 --- /dev/null +++ b/misc/config_tools/configurator/src-tauri/Cargo.lock @@ -0,0 +1,4243 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "acrn-configurator" +version = "0.1.0" +dependencies = [ + "dirs 4.0.0", + "env_logger", + "glob", + "itertools", + "log", + "serde", + "serde_json", + "tauri", + "tauri-build", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + +[[package]] +name = "ashpd" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "098dee97729c0164b39a8a7de9c20e4b0eb9cd57f87c8bb465224587b44b1683" +dependencies = [ + "enumflags2", + "futures", + "rand 0.8.5", + "serde", + "serde_repr", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90622698a1218e0b2fb846c97b5f19a0831f6baddee73d9454156365ccfa473b" +dependencies = [ + "easy-parallel", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "once_cell", + "slab", +] + +[[package]] +name = "async-io" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" +dependencies = [ + "concurrent-queue", + "futures-lite", + "libc", + "log", + "once_cell", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "winapi", +] + +[[package]] +name = "async-lock" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-recursion" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-task" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d306121baf53310a3fd342d88dc0824f6bbeace68347593658525565abee8" + +[[package]] +name = "async-trait" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atk" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c3d816ce6f0e2909a96830d6911c2aff044370b1ef92d7f267b43bae5addedd" +dependencies = [ + "atk-sys", + "bitflags", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58aeb089fb698e06db8089971c7ee317ab9644bade33383f63631437b03aafb6" +dependencies = [ + "glib-sys 0.15.6", + "gobject-sys 0.15.5", + "libc", + "system-deps 6.0.2", +] + +[[package]] +name = "attohttpc" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e69e13a99a7e6e070bb114f7ff381e58c7ccc188630121fc4c2fe4bcf24cd072" +dependencies = [ + "flate2", + "http", + "log", + "native-tls", + "openssl", + "serde", + "serde_json", + "serde_urlencoded", + "url", + "wildmatch", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "blake2b_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "constant_time_eq", +] + +[[package]] +name = "blake3" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" +dependencies = [ + "arrayref", + "arrayvec 0.7.2", + "cc", + "cfg-if", + "constant_time_eq", + "digest", + "rayon", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "memchr", +] + +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "bzip2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "cache-padded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" + +[[package]] +name = "cairo-rs" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8b14c80d8d1a02fa6d914b9d1afeeca9bc34257f8300d9696e1e331ae114223" +dependencies = [ + "bitflags", + "cairo-sys-rs", + "glib", + "libc", + "thiserror", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" +dependencies = [ + "glib-sys 0.15.6", + "libc", + "system-deps 6.0.2", +] + +[[package]] +name = "cargo_toml" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e270ef0cd868745878982f7ce470aa898d0d4bb248af67f0cf66f54617913ef" +dependencies = [ + "serde", + "serde_derive", + "toml", +] + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cfb" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca453e8624711b2f0f4eb47076a318feda166252a827ee25d067b43de83dcba0" +dependencies = [ + "byteorder", + "uuid", +] + +[[package]] +name = "cfg-expr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b412e83326147c2bb881f8b40edfbf9905b9b8abaebd0e47ca190ba62fda8f0e" +dependencies = [ + "smallvec", +] + +[[package]] +name = "cfg-expr" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3431df59f28accaf4cb4eed4a9acc66bea3f3c3753aa6cdc2f024174ef232af7" +dependencies = [ + "smallvec", +] + +[[package]] +name = "cfg-expr" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e068cb2806bbc15b439846dc16c5f89f8599f2c3e4d73d4449d38f9b2f0b6c5" +dependencies = [ + "smallvec", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi", +] + +[[package]] +name = "clap" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5177fac1ab67102d8989464efd043c6ff44191b1557ec1ddd489b4f7e1447e77" +dependencies = [ + "atty", + "bitflags", + "indexmap", + "os_str_bytes", + "strsim 0.10.0", + "termcolor", + "textwrap", +] + +[[package]] +name = "cocoa" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832" +dependencies = [ + "bitflags", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" +dependencies = [ + "bitflags", + "block", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "concurrent-queue" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +dependencies = [ + "cache-padded", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "core-graphics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +dependencies = [ + "bitflags", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +dependencies = [ + "bitflags", + "core-foundation", + "foreign-types", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00d6d2ea26e8b151d99093005cb442fb9a37aeaca582a03ec70946f49ab5ed9" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "crypto-common" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa 0.4.8", + "matches", + "phf 0.8.0", + "proc-macro2", + "quote", + "smallvec", + "syn", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "ctor" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "cty" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" + +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core 0.10.2", + "darling_macro 0.10.2", +] + +[[package]] +name = "darling" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" +dependencies = [ + "darling_core 0.13.1", + "darling_macro 0.13.1", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.9.3", + "syn", +] + +[[package]] +name = "darling_core" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core 0.10.2", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" +dependencies = [ + "darling_core 0.13.1", + "quote", + "syn", +] + +[[package]] +name = "deflate" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707b6a7b384888a70c8d2e8650b3e60170dfc6a67bb4aa67b6dfca57af4bedb4" +dependencies = [ + "adler32", + "byteorder", +] + +[[package]] +name = "deflate" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" +dependencies = [ + "adler32", + "byteorder", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn", +] + +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +dependencies = [ + "libc", + "redox_users 0.3.5", + "winapi", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users 0.4.0", + "winapi", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users 0.4.0", + "winapi", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dtoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" + +[[package]] +name = "dtoa-short" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde03329ae10e79ede66c9ce4dc930aa8599043b0743008548680f25b91502d6" +dependencies = [ + "dtoa", +] + +[[package]] +name = "easy-parallel" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946" + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "embed_plist" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" + +[[package]] +name = "enumflags2" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a25c90b056b3f84111cf183cbeddef0d3a0bbe9a674f057e1a1533c315f24def" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "144ec79496cbab6f84fa125dc67be9264aef22eb8a28da8454d9c33f15108da4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "env_logger" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "event-listener" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" + +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] +name = "field-offset" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92" +dependencies = [ + "memoffset", + "rustc_version 0.3.3", +] + +[[package]] +name = "filetime" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.2.10", + "winapi", +] + +[[package]] +name = "flate2" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide 0.4.4", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-executor" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "gdk" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6e05c1f572ab0e1f15be94217f0dc29088c248b14f792a5ff0af0d84bcda9e8" +dependencies = [ + "bitflags", + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8750501d75f318c2ec0314701bc8403901303210def80bafd13f6b6059a3f45" +dependencies = [ + "bitflags", + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413424d9818621fa3cfc8a3a915cdb89a7c3c507d56761b4ec83a9a98e587171" +dependencies = [ + "gio-sys 0.15.6", + "glib-sys 0.15.6", + "gobject-sys 0.15.5", + "libc", + "system-deps 6.0.2", +] + +[[package]] +name = "gdk-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e7a08c1e8f06f4177fb7e51a777b8c1689f743a7bc11ea91d44d2226073a88" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys 0.15.6", + "glib-sys 0.15.6", + "gobject-sys 0.15.5", + "libc", + "pango-sys", + "pkg-config", + "system-deps 6.0.2", +] + +[[package]] +name = "gdkx11-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b7f8c7a84b407aa9b143877e267e848ff34106578b64d1e0a24bf550716178" +dependencies = [ + "gdk-sys", + "glib-sys 0.15.6", + "libc", + "system-deps 6.0.2", + "x11", +] + +[[package]] +name = "generator" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1d9279ca822891c1a4dae06d185612cf8fc6acfe5dff37781b41297811b12ee" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "winapi", +] + +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "gio" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96efd8a1c00d890f6b45671916e165b5e43ccec61957d443aff6d7e44f62d348" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-io", + "gio-sys 0.15.6", + "glib", + "libc", + "once_cell", + "thiserror", +] + +[[package]] +name = "gio-sys" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0a41df66e57fcc287c4bcf74fc26b884f31901ea9792ec75607289b456f48fa" +dependencies = [ + "glib-sys 0.14.0", + "gobject-sys 0.14.0", + "libc", + "system-deps 3.2.0", + "winapi", +] + +[[package]] +name = "gio-sys" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d0fa5052773f5a56b8ae47dab09d040f5d9ce1311f4f99006e16e9a08269296" +dependencies = [ + "glib-sys 0.15.6", + "gobject-sys 0.15.5", + "libc", + "system-deps 6.0.2", + "winapi", +] + +[[package]] +name = "glib" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa570813c504bdf7539a9400180c2dd4b789a819556fb86da7226d7d1b037b49" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "glib-macros", + "glib-sys 0.15.6", + "gobject-sys 0.15.5", + "libc", + "once_cell", + "smallvec", + "thiserror", +] + +[[package]] +name = "glib-macros" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41bfd8d227dead0829ac142454e97531b93f576d0805d779c42bfd799c65c572" +dependencies = [ + "anyhow", + "heck 0.4.0", + "proc-macro-crate 1.1.3", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c1d60554a212445e2a858e42a0e48cece1bd57b311a19a9468f70376cf554ae" +dependencies = [ + "libc", + "system-deps 3.2.0", +] + +[[package]] +name = "glib-sys" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4366377bd56697de8aaee24e673c575d2694d72e7756324ded2b0428829a7b8" +dependencies = [ + "libc", + "system-deps 6.0.2", +] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "globset" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "gobject-sys" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa92cae29759dae34ab5921d73fff5ad54b3d794ab842c117e36cafc7994c3f5" +dependencies = [ + "glib-sys 0.14.0", + "libc", + "system-deps 3.2.0", +] + +[[package]] +name = "gobject-sys" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df6859463843c20cf3837e3a9069b6ab2051aeeadf4c899d33344f4aea83189a" +dependencies = [ + "glib-sys 0.15.6", + "libc", + "system-deps 6.0.2", +] + +[[package]] +name = "gtk" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2d1326b36af927fe46ae2f89a8fec38c6f0d279ebc5ef07ffeeabb70300bfc" +dependencies = [ + "atk", + "bitflags", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "once_cell", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5bc2f0587cba247f60246a0ca11fe25fb733eabc3de12d1965fc07efab87c84" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys 0.15.6", + "glib-sys 0.15.6", + "gobject-sys 0.15.5", + "libc", + "pango-sys", + "system-deps 6.0.2", +] + +[[package]] +name = "gtk3-macros" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24f518afe90c23fba585b2d7697856f9e6a7bbc62f65588035e66f6afb01a2e9" +dependencies = [ + "anyhow", + "proc-macro-crate 1.1.3", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "html5ever" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafcf38a1a36118242d29b92e1b08ef84e67e4a5ed06e0a80be20e6a32bfed6b" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "http" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.1", +] + +[[package]] +name = "http-range" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "ico" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a4b3331534254a9b64095ae60d3dc2a8225a7a70229cd5888be127cdc1f6804" +dependencies = [ + "byteorder", + "png 0.11.0", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "ignore" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" +dependencies = [ + "crossbeam-utils", + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + +[[package]] +name = "indexmap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "infer" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f92b41dab759f9e8427c03f519c344a14655490b8db548dac1e57a75b3258391" +dependencies = [ + "cfb", +] + +[[package]] +name = "inflate" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5f9f47468e9a76a6452271efadc88fe865a82be91fe75e6c0c57b87ccea59d4" +dependencies = [ + "adler32", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "javascriptcore-rs" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf053e7843f2812ff03ef5afe34bb9c06ffee120385caad4f6b9967fcd37d41c" +dependencies = [ + "bitflags", + "glib", + "javascriptcore-rs-sys", +] + +[[package]] +name = "javascriptcore-rs-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "905fbb87419c5cde6e3269537e4ea7d46431f3008c5d057e915ef3f115e7793c" +dependencies = [ + "glib-sys 0.15.6", + "gobject-sys 0.15.5", + "libc", + "system-deps 5.0.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "json-patch" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f995a3c8f2bc3dd52a18a583e90f9ec109c047fa1603a853e46bcda14d2e279d" +dependencies = [ + "serde", + "serde_json", + "treediff", +] + +[[package]] +name = "kuchiki" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ea8e9c6e031377cff82ee3001dc8026cdf431ed4e2e6b51f98ab8c73484a358" +dependencies = [ + "cssparser", + "html5ever", + "matches", + "selectors", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" + +[[package]] +name = "lock_api" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "loom" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc5c7d328e32cc4954e8e01193d7f0ef5ab257b5090b70a964e099a36034309" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "mac-notification-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb6b71a9a89cd38b395d994214297447e8e63b1ba5708a9a2b0b1048ceda76" +dependencies = [ + "cc", + "chrono", + "dirs 1.0.5", + "objc-foundation", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "markup5ever" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" +dependencies = [ + "log", + "phf 0.8.0", + "phf_codegen", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" +dependencies = [ + "adler32", +] + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "native-tls" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "ndk" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d64d6af06fde0e527b1ba5c7b79a6cc89cfc46325b0b2887dffe8f70197e0c3c" +dependencies = [ + "bitflags", + "jni-sys", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3c5cc68637e21fe8f077f6a1c9e0b9ca495bb74895226b476310f613325884" + +[[package]] +name = "ndk-glue" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b1454575120e3265d2442222299c711ace58ba417532ee4f0fc71b860016b93" +dependencies = [ + "lazy_static", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-macro", + "ndk-sys", +] + +[[package]] +name = "ndk-macro" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d" +dependencies = [ + "darling 0.10.2", + "proc-macro-crate 0.1.5", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ndk-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nix" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "notify-rust" +version = "4.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "367e1355a950d3e758e414f3ca1b3981a57a2aa1fa3338eb0059f5b230b6ffa4" +dependencies = [ + "mac-notification-sys", + "serde", + "winrt-notification", + "zbus", + "zvariant", + "zvariant_derive", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "720d3ea1055e4e4574c0c0b0f8c3fd4f24c4cdaf465948206dea090b57b526ad" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d992b768490d7fe0d8586d9b5745f6c49f557da6d81dc982b1d167ad4edbb21" +dependencies = [ + "proc-macro-crate 1.1.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "open" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a82915836ef43159bb6a3c64d884c42329ccd0b8afdca737cf1e3dd701709dc" +dependencies = [ + "pathdiff", + "winapi", +] + +[[package]] +name = "openssl" +version = "0.10.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "ordered-stream" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44630c059eacfd6e08bdaa51b1db2ce33119caa4ddc1235e923109aa5f25ccb1" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "os_info" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "023df84d545ef479cf67fd2f4459a613585c9db4852c2fad12ab70587859d340" +dependencies = [ + "log", + "serde", + "winapi", +] + +[[package]] +name = "os_pipe" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c92f2b54f081d635c77e7120862d48db8e91f7f21cef23ab1b4fe9971c59f55" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + +[[package]] +name = "pango" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c7420fc01a390ec200da7395b64d705f5d82fe03e5d0708aee422c46538be7" +dependencies = [ + "bitflags", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7022c2fb88cd2d9d55e1a708a8c53a3ae8678234c4a54bf623400aeb7f31fac2" +dependencies = [ + "glib-sys 0.15.6", + "gobject-sys 0.15.5", + "libc", + "system-deps 6.0.2", +] + +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.10", + "smallvec", + "winapi", +] + +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +dependencies = [ + "ucd-trie", +] + +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_macros 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_macros 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared 0.8.0", + "rand 0.7.3", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_macros" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + +[[package]] +name = "png" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0b0cabbbd20c2d7f06dbf015e06aad59b6ca3d9ed14848783e98af9aaf19925" +dependencies = [ + "bitflags", + "deflate 0.7.20", + "inflate", + "num-iter", +] + +[[package]] +name = "png" +version = "0.16.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" +dependencies = [ + "bitflags", + "crc32fast", + "deflate 0.8.6", + "miniz_oxide 0.3.7", +] + +[[package]] +name = "polling" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" +dependencies = [ + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "winapi", +] + +[[package]] +name = "pollster" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5da3b0203fd7ee5720aa0b5e790b591aa5d3f41c3ed2c34a3a393382198af2f7" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + +[[package]] +name = "proc-macro-crate" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +dependencies = [ + "thiserror", + "toml", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom 0.2.5", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "raw-window-handle" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba75eee94a9d5273a68c9e1e105d9cffe1ef700532325788389e5a83e2522b7" +dependencies = [ + "cty", +] + +[[package]] +name = "rayon" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "lazy_static", + "num_cpus", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" +dependencies = [ + "getrandom 0.1.16", + "redox_syscall 0.1.57", + "rust-argon2", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom 0.2.5", + "redox_syscall 0.2.10", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rfd" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aaf1d71ccd44689f7c2c72da1117fd8db71f72a76fe9b5c5dbb17ab903007e0" +dependencies = [ + "ashpd", + "block", + "dispatch", + "glib-sys 0.15.6", + "gobject-sys 0.15.5", + "gtk-sys", + "js-sys", + "lazy_static", + "log", + "objc", + "objc-foundation", + "objc_id", + "pollster", + "raw-window-handle", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows 0.30.0", +] + +[[package]] +name = "rust-argon2" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" +dependencies = [ + "base64", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils", +] + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.6", +] + +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi", +] + +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "security-framework" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "matches", + "phf 0.8.0", + "phf_codegen", + "precomputed-hash", + "servo_arc", + "smallvec", + "thin-slice", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d" + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +dependencies = [ + "itoa 1.0.1", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.1", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1e6ec4d8950e5b1e894eac0d360742f3b1407a6078a604a731c4b3f49cefbc" +dependencies = [ + "rustversion", + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12e47be9471c72889ebafb5e14d5ff930d89ae7a67bbdb5f8abb564f845a927e" +dependencies = [ + "darling 0.13.1", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serialize-to-javascript" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9823f2d3b6a81d98228151fdeaf848206a7855a7a042bbf9bf870449a66cafb" +dependencies = [ + "serde", + "serde_json", + "serialize-to-javascript-impl", +] + +[[package]] +name = "serialize-to-javascript-impl" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "servo_arc" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" +dependencies = [ + "nodrop", + "stable_deref_trait", +] + +[[package]] +name = "sha1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "sha2" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shared_child" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "siphasher" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e" + +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "soup2-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f056675eda9a7417163e5f742bb119e8e1d385edd2ada8f7031a7230a3ec10a" +dependencies = [ + "bitflags", + "gio-sys 0.14.0", + "glib-sys 0.14.0", + "gobject-sys 0.14.0", + "libc", + "system-deps 5.0.0", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "state" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cf4f5369e6d3044b5e365c9690f451516ac8f0954084622b49ea3fde2f6de5" +dependencies = [ + "loom", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "string_cache" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33994d0838dc2d152d17a62adf608a869b5e846b65b389af7f3dbc1de45c5b26" +dependencies = [ + "lazy_static", + "new_debug_unreachable", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2" + +[[package]] +name = "strum" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e" +dependencies = [ + "strum_macros 0.22.0", +] + +[[package]] +name = "strum_macros" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strum_macros" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "system-deps" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "480c269f870722b3b08d2f13053ce0c2ab722839f472863c3e2d61ff3a1c2fa6" +dependencies = [ + "anyhow", + "cfg-expr 0.8.1", + "heck 0.3.3", + "itertools", + "pkg-config", + "strum 0.21.0", + "strum_macros 0.21.1", + "thiserror", + "toml", + "version-compare 0.0.11", +] + +[[package]] +name = "system-deps" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18db855554db7bd0e73e06cf7ba3df39f97812cb11d3f75e71c39bf45171797e" +dependencies = [ + "cfg-expr 0.9.1", + "heck 0.3.3", + "pkg-config", + "toml", + "version-compare 0.0.11", +] + +[[package]] +name = "system-deps" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709" +dependencies = [ + "cfg-expr 0.10.2", + "heck 0.4.0", + "pkg-config", + "toml", + "version-compare 0.1.0", +] + +[[package]] +name = "tao" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b3b3bbc9151bce45db3cf9ccb808730c8df8786d0223f34591f6e5890503939" +dependencies = [ + "bitflags", + "cairo-rs", + "cc", + "cocoa", + "core-foundation", + "core-graphics", + "crossbeam-channel", + "dispatch", + "gdk", + "gdk-pixbuf", + "gdk-sys", + "gdkx11-sys", + "gio", + "glib", + "glib-sys 0.15.6", + "gtk", + "instant", + "lazy_static", + "libc", + "log", + "ndk", + "ndk-glue", + "ndk-sys", + "objc", + "parking_lot", + "raw-window-handle", + "scopeguard", + "serde", + "tao-core-video-sys", + "unicode-segmentation", + "windows 0.30.0", + "windows_macros", + "x11-dl", +] + +[[package]] +name = "tao-core-video-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271450eb289cb4d8d0720c6ce70c72c8c858c93dd61fc625881616752e6b98f6" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "objc", +] + +[[package]] +name = "tar" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "tauri" +version = "1.0.0-rc.3" +source = "git+https://github.com/Weiyi-Feng/tauri.git#015e15cfd00cebe8d23cd9170493227c61cc4322" +dependencies = [ + "anyhow", + "attohttpc", + "bincode", + "cfg_aliases", + "clap", + "dirs-next", + "either", + "embed_plist", + "flate2", + "futures", + "futures-lite", + "glib", + "glob", + "gtk", + "http", + "ignore", + "memchr", + "notify-rust", + "once_cell", + "open", + "os_info", + "os_pipe", + "percent-encoding", + "rand 0.8.5", + "raw-window-handle", + "regex", + "rfd", + "semver 1.0.6", + "serde", + "serde_json", + "serde_repr", + "serialize-to-javascript", + "shared_child", + "state", + "tar", + "tauri-macros", + "tauri-runtime", + "tauri-runtime-wry", + "tauri-utils 1.0.0-rc.2", + "tempfile", + "thiserror", + "tokio", + "url", + "uuid", + "zip", +] + +[[package]] +name = "tauri-build" +version = "1.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "855e47d8cfb2219fc14d2eed2c09bfb35f9ecd71a40ca2084aeeee2d23e0b60d" +dependencies = [ + "anyhow", + "cargo_toml", + "serde_json", + "tauri-utils 1.0.0-rc.3", + "winres", +] + +[[package]] +name = "tauri-codegen" +version = "1.0.0-rc.2" +source = "git+https://github.com/Weiyi-Feng/tauri.git#015e15cfd00cebe8d23cd9170493227c61cc4322" +dependencies = [ + "base64", + "blake3", + "proc-macro2", + "quote", + "regex", + "serde", + "serde_json", + "sha2", + "tauri-utils 1.0.0-rc.2", + "thiserror", + "uuid", + "walkdir", + "zstd", +] + +[[package]] +name = "tauri-macros" +version = "1.0.0-rc.2" +source = "git+https://github.com/Weiyi-Feng/tauri.git#015e15cfd00cebe8d23cd9170493227c61cc4322" +dependencies = [ + "heck 0.4.0", + "proc-macro2", + "quote", + "syn", + "tauri-codegen", + "tauri-utils 1.0.0-rc.2", +] + +[[package]] +name = "tauri-runtime" +version = "0.3.2" +source = "git+https://github.com/Weiyi-Feng/tauri.git#015e15cfd00cebe8d23cd9170493227c61cc4322" +dependencies = [ + "gtk", + "http", + "http-range", + "infer", + "serde", + "serde_json", + "tauri-utils 1.0.0-rc.2", + "thiserror", + "uuid", + "webview2-com", + "windows 0.30.0", +] + +[[package]] +name = "tauri-runtime-wry" +version = "0.3.2" +source = "git+https://github.com/Weiyi-Feng/tauri.git#015e15cfd00cebe8d23cd9170493227c61cc4322" +dependencies = [ + "gtk", + "ico", + "infer", + "png 0.16.8", + "tauri-runtime", + "tauri-utils 1.0.0-rc.2", + "uuid", + "webview2-com", + "windows 0.30.0", + "wry", +] + +[[package]] +name = "tauri-utils" +version = "1.0.0-rc.2" +source = "git+https://github.com/Weiyi-Feng/tauri.git#015e15cfd00cebe8d23cd9170493227c61cc4322" +dependencies = [ + "ctor", + "heck 0.4.0", + "html5ever", + "json-patch", + "kuchiki", + "phf 0.10.1", + "proc-macro2", + "quote", + "serde", + "serde_json", + "serde_with", + "serialize-to-javascript", + "thiserror", + "url", + "zstd", +] + +[[package]] +name = "tauri-utils" +version = "1.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21f11483d205c77d1ec398e80566485101696335983e69832cc6c41ab1e07266" +dependencies = [ + "ctor", + "glob", + "heck 0.4.0", + "html5ever", + "json-patch", + "kuchiki", + "phf 0.10.1", + "proc-macro2", + "quote", + "serde", + "serde_json", + "serde_with", + "serialize-to-javascript", + "thiserror", + "url", + "walkdir", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall 0.2.10", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "tendril" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9ef557cb397a4f0a5a3a628f06515f78563f2209e64d47055d9dc6052bf5e33" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" + +[[package]] +name = "thin-slice" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "tinyvec" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +dependencies = [ + "bytes", + "memchr", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "tracing" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" +dependencies = [ + "lazy_static", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e0ab7bdc962035a87fba73f3acca9b8a8d0034c2e6f60b84aeaaddddc155dce" +dependencies = [ + "ansi_term", + "lazy_static", + "matchers", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "treediff" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "761e8d5ad7ce14bb82b7e61ccc0ca961005a275a060b9644a2431aa11553c2ff" +dependencies = [ + "serde_json", +] + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "ucd-trie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" + +[[package]] +name = "unicode-bidi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "url" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.5", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version-compare" +version = "0.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c18c859eead79d8b95d09e4678566e8d70105c4e7b251f707a03df32442661b" + +[[package]] +name = "version-compare" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasm-bindgen" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" + +[[package]] +name = "web-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webkit2gtk" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cbd39499e917de9dad36eb11c09f665eb984d432638ae7971feed98eb96df88" +dependencies = [ + "bitflags", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys 0.15.6", + "glib", + "glib-sys 0.15.6", + "gobject-sys 0.15.5", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddcce6f1e0fc7715d651dba29875741509f5fc12f4e2976907272a74405f2b01" +dependencies = [ + "atk-sys", + "bitflags", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys 0.15.6", + "glib-sys 0.15.6", + "gobject-sys 0.15.5", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pango-sys", + "pkg-config", + "soup2-sys", + "system-deps 5.0.0", +] + +[[package]] +name = "webview2-com" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb8e90ac2d9ce39cdb70017aaec641be09fbdd702b7b332b9896d053eb469524" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows 0.30.0", + "windows_macros", +] + +[[package]] +name = "webview2-com-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515c6c82fcee93f6edaacc72c8e233dbe4ff3ca569dce1901dfc36c404a3e99" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "webview2-com-sys" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92160310b3322397e4ff8a8285a7429d73a07a68fda44ee80879605b93e53f76" +dependencies = [ + "regex", + "serde", + "serde_json", + "thiserror", + "windows 0.30.0", + "windows-bindgen", +] + +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + +[[package]] +name = "wildmatch" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6c48bd20df7e4ced539c12f570f937c6b4884928a87fee70a479d72f031d4e0" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9f39345ae0c8ab072c0ac7fe8a8b411636aa34f89be19ddd0d9226544f13944" +dependencies = [ + "windows_i686_gnu 0.24.0", + "windows_i686_msvc 0.24.0", + "windows_x86_64_gnu 0.24.0", + "windows_x86_64_msvc 0.24.0", +] + +[[package]] +name = "windows" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b749ebd2304aa012c5992d11a25d07b406bdbe5f79d371cb7a918ce501a19eb0" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu 0.30.0", + "windows_i686_msvc 0.30.0", + "windows_x86_64_gnu 0.30.0", + "windows_x86_64_msvc 0.30.0", +] + +[[package]] +name = "windows-bindgen" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "944c545fcae9dd66488308f8b69aa3ba34f53714416ecfcdcbbfa4b6821e27c6" +dependencies = [ + "windows_quote", + "windows_reader", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29277a4435d642f775f63c7d1faeb927adba532886ce0287bd985bffb16b6bca" + +[[package]] +name = "windows_gen" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30dff4d91d22520628bb94b66f2bb313cb16a09a515a32320a84a1b449bc94c0" +dependencies = [ + "windows_quote", + "windows_reader", +] + +[[package]] +name = "windows_i686_gnu" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0866510a3eca9aed73a077490bbbf03e5eaac4e1fd70849d89539e5830501fd" + +[[package]] +name = "windows_i686_gnu" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1145e1989da93956c68d1864f32fb97c8f561a8f89a5125f6a2b7ea75524e4b8" + +[[package]] +name = "windows_i686_msvc" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf0ffed56b7e9369a29078d2ab3aaeceea48eb58999d2cff3aa2494a275b95c6" + +[[package]] +name = "windows_i686_msvc" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a09e3a0d4753b73019db171c1339cd4362c8c44baf1bcea336235e955954a6" + +[[package]] +name = "windows_macros" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ae44ab917e9005fe710d99d52d227ca0164b10a09be90649142cc3fab825d3" +dependencies = [ + "syn", + "windows_gen", + "windows_quote", + "windows_reader", +] + +[[package]] +name = "windows_quote" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71f02c51a77e6248c1206aaa920802c32d50a05205e229b118d7f3afd3036667" + +[[package]] +name = "windows_reader" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e44e6df0da993cda589c5ac852272fbb2a0ead67a031a017dd3eac11528a2d72" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384a173630588044205a2993b6864a2f56e5a8c1e7668c07b93ec18cf4888dc4" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca64fcb0220d58db4c119e050e7af03c69e6f4f415ef69ec1773d9aab422d5a" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd8f062d8ca5446358159d79a90be12c543b3a965c847c8f3eedf14b321d399" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08cabc9f0066848fef4bc6a1c1668e6efce38b661d2aeec75d18d8617eebb5f1" + +[[package]] +name = "winres" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c" +dependencies = [ + "toml", +] + +[[package]] +name = "winrt-notification" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "007a0353840b23e0c6dc73e5b962ff58ed7f6bc9ceff3ce7fe6fbad8d496edf4" +dependencies = [ + "strum 0.22.0", + "windows 0.24.0", + "xml-rs", +] + +[[package]] +name = "wry" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9514586e5c964d30cc7123c9aea9880ff7b3cb1c43f6a1dc8703941eb72ac89f" +dependencies = [ + "cocoa", + "core-graphics", + "gdk", + "gio", + "glib", + "gtk", + "http", + "libc", + "log", + "objc", + "objc_id", + "once_cell", + "serde", + "serde_json", + "tao", + "thiserror", + "url", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows 0.30.0", + "windows_macros", +] + +[[package]] +name = "x11" +version = "2.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd0565fa8bfba8c5efe02725b14dff114c866724eff2cfd44d76cea74bcd87a" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "x11-dl" +version = "2.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" +dependencies = [ + "lazy_static", + "libc", + "pkg-config", +] + +[[package]] +name = "xattr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +dependencies = [ + "libc", +] + +[[package]] +name = "xml-rs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + +[[package]] +name = "zbus" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb86f3d4592e26a48b2719742aec94f8ae6238ebde20d98183ee185d1275e9a" +dependencies = [ + "async-broadcast", + "async-channel", + "async-executor", + "async-io", + "async-lock", + "async-recursion", + "async-task", + "async-trait", + "byteorder", + "derivative", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "lazy_static", + "nix", + "once_cell", + "ordered-stream", + "rand 0.8.5", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "winapi", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36823cc10fddc3c6b19f048903262dacaf8274170e9a255784bdd8b4570a8040" +dependencies = [ + "proc-macro-crate 1.1.3", + "proc-macro2", + "quote", + "regex", + "syn", +] + +[[package]] +name = "zbus_names" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45dfcdcf87b71dad505d30cc27b1b7b88a64b6d1c435648f48f9dbc1fdc4b7e1" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + +[[package]] +name = "zip" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" +dependencies = [ + "byteorder", + "bzip2", + "crc32fast", + "flate2", + "thiserror", + "time", +] + +[[package]] +name = "zstd" +version = "0.10.0+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b1365becbe415f3f0fcd024e2f7b45bacfb5bdd055f0dc113571394114e7bdd" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "4.1.4+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f7cd17c9af1a4d6c24beb1cc54b17e2ef7b593dc92f19e9d9acad8b182bbaee" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "1.6.3+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc49afa5c8d634e75761feda8c592051e7eeb4683ba827211eb0d731d3402ea8" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "zvariant" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49ea5dc38b2058fae6a5b79009388143dadce1e91c26a67f984a0fc0381c8033" +dependencies = [ + "byteorder", + "enumflags2", + "libc", + "serde", + "static_assertions", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2cecc5a61c2a053f7f653a24cd15b3b0195d7f7ddb5042c837fb32e161fb7a" +dependencies = [ + "proc-macro-crate 1.1.3", + "proc-macro2", + "quote", + "syn", +] diff --git a/misc/config_tools/configurator/src-tauri/Cargo.toml b/misc/config_tools/configurator/src-tauri/Cargo.toml new file mode 100644 index 000000000..01dadc0f5 --- /dev/null +++ b/misc/config_tools/configurator/src-tauri/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "acrn-configurator" +version = "0.1.0" +description = "ACRN Configurator" +authors = ["Feng, Weiyi "] +license = "BSD" +repository = "https://github.com/projectacrn/acrn-hypervisor" +default-run = "acrn-configurator" +edition = "2021" +rust-version = "1.57" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[build-dependencies] +tauri-build = { version = "1.0.0-rc.3", features = [] } + +[dependencies] +serde_json = "1.0" +serde = { version = "1.0", features = ["derive"] } +tauri = { git = "https://github.com/Weiyi-Feng/tauri.git", features = ["api-all", "cli"] } +log = "0.4.14" +env_logger = "0.9.0" +glob = "0.3.0" +dirs = "4.0.0" +itertools = "0.10.3" + +[features] +# by default Tauri runs in production mode +# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL +default = ["custom-protocol"] +# this feature is used used for production builds where `devPath` points to the filesystem +# DO NOT remove this +custom-protocol = ["tauri/custom-protocol"] diff --git a/misc/config_tools/configurator/src-tauri/build.rs b/misc/config_tools/configurator/src-tauri/build.rs new file mode 100644 index 000000000..795b9b7c8 --- /dev/null +++ b/misc/config_tools/configurator/src-tauri/build.rs @@ -0,0 +1,3 @@ +fn main() { + tauri_build::build() +} diff --git a/misc/config_tools/configurator/src-tauri/icons/128x128.png b/misc/config_tools/configurator/src-tauri/icons/128x128.png new file mode 100644 index 000000000..6be5e50e9 Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/128x128.png differ diff --git a/misc/config_tools/configurator/src-tauri/icons/128x128@2x.png b/misc/config_tools/configurator/src-tauri/icons/128x128@2x.png new file mode 100644 index 000000000..e81becee5 Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/128x128@2x.png differ diff --git a/misc/config_tools/configurator/src-tauri/icons/32x32.png b/misc/config_tools/configurator/src-tauri/icons/32x32.png new file mode 100644 index 000000000..a437dd517 Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/32x32.png differ diff --git a/misc/config_tools/configurator/src-tauri/icons/Square107x107Logo.png b/misc/config_tools/configurator/src-tauri/icons/Square107x107Logo.png new file mode 100644 index 000000000..0ca4f2719 Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/Square107x107Logo.png differ diff --git a/misc/config_tools/configurator/src-tauri/icons/Square142x142Logo.png b/misc/config_tools/configurator/src-tauri/icons/Square142x142Logo.png new file mode 100644 index 000000000..b81f82039 Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/Square142x142Logo.png differ diff --git a/misc/config_tools/configurator/src-tauri/icons/Square150x150Logo.png b/misc/config_tools/configurator/src-tauri/icons/Square150x150Logo.png new file mode 100644 index 000000000..624c7bfba Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/Square150x150Logo.png differ diff --git a/misc/config_tools/configurator/src-tauri/icons/Square284x284Logo.png b/misc/config_tools/configurator/src-tauri/icons/Square284x284Logo.png new file mode 100644 index 000000000..c021d2ba7 Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/Square284x284Logo.png differ diff --git a/misc/config_tools/configurator/src-tauri/icons/Square30x30Logo.png b/misc/config_tools/configurator/src-tauri/icons/Square30x30Logo.png new file mode 100644 index 000000000..621970023 Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/Square30x30Logo.png differ diff --git a/misc/config_tools/configurator/src-tauri/icons/Square310x310Logo.png b/misc/config_tools/configurator/src-tauri/icons/Square310x310Logo.png new file mode 100644 index 000000000..f9bc04839 Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/Square310x310Logo.png differ diff --git a/misc/config_tools/configurator/src-tauri/icons/Square44x44Logo.png b/misc/config_tools/configurator/src-tauri/icons/Square44x44Logo.png new file mode 100644 index 000000000..d5fbfb2ab Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/Square44x44Logo.png differ diff --git a/misc/config_tools/configurator/src-tauri/icons/Square71x71Logo.png b/misc/config_tools/configurator/src-tauri/icons/Square71x71Logo.png new file mode 100644 index 000000000..63440d798 Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/Square71x71Logo.png differ diff --git a/misc/config_tools/configurator/src-tauri/icons/Square89x89Logo.png b/misc/config_tools/configurator/src-tauri/icons/Square89x89Logo.png new file mode 100644 index 000000000..f3f705af2 Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/Square89x89Logo.png differ diff --git a/misc/config_tools/configurator/src-tauri/icons/StoreLogo.png b/misc/config_tools/configurator/src-tauri/icons/StoreLogo.png new file mode 100644 index 000000000..455638826 Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/StoreLogo.png differ diff --git a/misc/config_tools/configurator/src-tauri/icons/icon.icns b/misc/config_tools/configurator/src-tauri/icons/icon.icns new file mode 100644 index 000000000..8254645a7 Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/icon.icns differ diff --git a/misc/config_tools/configurator/src-tauri/icons/icon.ico b/misc/config_tools/configurator/src-tauri/icons/icon.ico new file mode 100644 index 000000000..b3636e4b2 Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/icon.ico differ diff --git a/misc/config_tools/configurator/src-tauri/icons/icon.png b/misc/config_tools/configurator/src-tauri/icons/icon.png new file mode 100644 index 000000000..e1cd2619e Binary files /dev/null and b/misc/config_tools/configurator/src-tauri/icons/icon.png differ diff --git a/misc/config_tools/configurator/src-tauri/rustfmt.toml b/misc/config_tools/configurator/src-tauri/rustfmt.toml new file mode 100644 index 000000000..d962cdac2 --- /dev/null +++ b/misc/config_tools/configurator/src-tauri/rustfmt.toml @@ -0,0 +1,13 @@ +max_width = 100 +hard_tabs = false +tab_spaces = 2 +newline_style = "Auto" +use_small_heuristics = "Default" +reorder_imports = true +reorder_modules = true +remove_nested_parens = true +edition = "2021" +merge_derives = true +use_try_shorthand = false +use_field_init_shorthand = false +force_explicit_abi = true diff --git a/misc/config_tools/configurator/src-tauri/src/configurator.rs b/misc/config_tools/configurator/src-tauri/src/configurator.rs new file mode 100644 index 000000000..abcdf386d --- /dev/null +++ b/misc/config_tools/configurator/src-tauri/src/configurator.rs @@ -0,0 +1,316 @@ +use std::borrow::Borrow; +use std::fs; +use std::ops::Add; +use std::path::{Path, PathBuf}; + +use serde::{Deserialize, Serialize}; +use glob::{glob_with, MatchOptions}; +use itertools::Itertools; + +#[derive(Serialize, Deserialize, Clone, Copy, Debug)] +#[repr(u16)] +#[non_exhaustive] +pub enum HistoryType { + WorkingFolder = 1, + Board, + Scenario, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct History { + pub working_folder: Vec, + pub board_file: Vec, + pub scenario_file: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ConfigData { + pub history: History, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Configurator { + pub config_write_enable: bool, + pub config_path: PathBuf, + + pub config_data: ConfigData, + pub working_folder: String, + +} + + +pub fn write_file(path: PathBuf, content: String) -> Result<(), String> { + fs::write(path, content).map_err(|e| e.to_string()) +} + +impl ConfigData { + fn new() -> ConfigData { + let history = History { working_folder: vec![], board_file: vec![], scenario_file: vec![] }; + ConfigData { history } + } + + pub fn serialize(&self) -> String { + serde_json::to_string(&self).unwrap_or_else(|_| { + let default = ConfigData::new(); + ConfigData::serialize(&default) + }) + } + + /// deserialize data + fn deserialize(config_json: String) -> Result { + match serde_json::from_str(&config_json.to_string()) { + Ok(config_data) => Ok(config_data), + Err(e) => Err(e.to_string()) + } + } +} + + +impl Configurator { + pub fn new() -> Self { + match Self::ensure_config_file() { + Ok(config_file_path) => { + // read config.json + Self::init(config_file_path) + } + Err(e) => { + log::warn!("get config file path error! error: {}", e.to_string()); + log::warn!("Use blank config and disable config write to start configurator."); + Self { + config_write_enable: false, + config_path: Path::new(".").to_path_buf(), + config_data: ConfigData::new(), + working_folder: "".to_string(), + } + } + } + } + + fn ensure_config_file() -> Result { + // get config_dir or home_dir path + // Todo: 讨论fallback逻辑是否可行 + let config_base = match dirs::config_dir() { + None => { + log::info!("get config_dir error! fallback to get home_dir."); + match dirs::home_dir() { + None => { + return Err("get config_dir and home_dir error!".to_string()); + } + Some(path) => path + } + } + Some(path) => path + }; + + + // get acrn-configurator dir path and check it exist + let config_dir = config_base.join(".acrn-configurator"); + log::info!("current config_dir is {}.", config_dir.to_str().unwrap()); + if !config_dir.is_dir() { + match fs::create_dir(&config_dir) { + Err(e) => { + //Todo: 明确无法创建 .acrn-configurator 文件夹时的处理逻辑 + log::warn!("Create configurator config dir failed, {}", e.to_string()); + return Err(e.to_string()); + } + _ => {} + } + } + + + // get config.json file path and check it exist + let default_config_path = config_dir.join("config.json"); + if !default_config_path.is_file() { + let empty_config = ConfigData::new(); + match fs::write(&default_config_path, empty_config.serialize()) { + Ok(_) => {} + Err(e) => return Err(e.to_string()) + }; + } + Ok(default_config_path) + } + + pub fn init(config_file_path: PathBuf) -> Configurator { + let config_json = match fs::read_to_string(&config_file_path) { + Ok(data) => { data } + Err(e) => { + log::warn!("read config error! error: {}", e.to_string()); + log::warn!("Use default blank config to start due to read config failed."); + return Configurator { + config_write_enable: false, + config_path: config_file_path, + config_data: ConfigData::new(), + working_folder: "".to_string(), + }; + } + }; + + let config_data = match ConfigData::deserialize(config_json) { + Ok(config_data) => { + log::info!("success load config: {}", config_data.serialize()); + config_data + } + Err(e) => { + log::warn!("Deserialize json data error! error: {}", e); + log::warn!("Use default blank config to start due to deserialize config failed."); + ConfigData::new() + } + }; + log::info!("Using config: {}", config_data.serialize()); + Configurator { + config_write_enable: true, + config_path: config_file_path, + config_data, + working_folder: "".to_string(), + } + } + + + pub fn save_config(&self) { + if !self.config_write_enable { + return; + } + match fs::write(&self.config_path, self.config_data.serialize()) { + Ok(_) => {} + Err(e) => { + log::warn!("Write config error! error:{}",e.to_string()) + } + } + } + + pub fn add_history(&mut self, history_type: HistoryType, path: &Path) { + let path_string: String = path.to_string_lossy().parse().unwrap(); + match history_type { + HistoryType::WorkingFolder => { + self.config_data.history.working_folder.insert(0, path_string); + self.config_data.history.working_folder = self.config_data.history.working_folder.clone().into_iter().unique().collect() + } + HistoryType::Board => { + self.config_data.history.board_file.insert(0, path_string); + self.config_data.history.board_file = self.config_data.history.board_file.clone().into_iter().unique().collect() + } + HistoryType::Scenario => { + self.config_data.history.scenario_file.insert(0, path_string); + self.config_data.history.scenario_file = self.config_data.history.scenario_file.clone().into_iter().unique().collect() + } + }; + } + + pub fn get_history(&self, history_type: HistoryType) -> &[String] { + match history_type { + HistoryType::WorkingFolder => { + self.config_data.history.working_folder.borrow() + } + HistoryType::Board => { + self.config_data.history.board_file.borrow() + } + HistoryType::Scenario => { + self.config_data.history.scenario_file.borrow() + } + } + } + + pub fn force_reset(&mut self) { + self.config_data = ConfigData::new(); + self.save_config() + } + + pub fn set_working_folder(&mut self, working_folder: String) { + self.working_folder = working_folder + } + + pub fn write_board(&self, board_name: String, board_xml_string: String) -> Result<(), String> { + let options = MatchOptions { + case_sensitive: false, + ..Default::default() + }; + let pattern = self.working_folder.clone().add("/.*\\.board\\.xml"); + let files = match glob_with(&pattern, options).map_err(|e| e.to_string()) { + Ok(files) => { files } + Err(e) => return Err(e.to_string()) + }; + for entry in files { + match entry { + Ok(filepath) => { + match fs::remove_file(&filepath) { + Ok(_) => {} + Err(e) => { + let err_msg = format!( + "Can not delete file:{} error: {}", + filepath.to_str().unwrap_or_else(|| "").to_string(), e.to_string() + ); + log::warn!("{}",err_msg); + return Err(err_msg); + } + } + } + Err(e) => { + log::error!("find old board error! error:{}", e.to_string()) + } + } + } + + let board_basename = board_name.add(".board.xml"); + let board_xml_path = Path::new(&self.working_folder).join(board_basename); + write_file(board_xml_path, board_xml_string) + } +} + +static mut WORKING_FOLDER: String = String::new(); + +#[tauri::command] +pub fn get_history(history_type: HistoryType) -> Result { + let configurator = Configurator::new(); + let history = serde_json::to_string(configurator.get_history(history_type)).unwrap_or_else(|_| String::from("[]")); + Ok(history) +} + +#[tauri::command] +pub fn add_history(history_type: HistoryType, path: String) -> Result<(), &'static str> { + let path_buf = Path::new(&path); + if !(path_buf.is_dir() || path_buf.is_file()) { + return Err("Not a validate dir or file path."); + } + let mut configurator = Configurator::new(); + configurator.add_history(history_type, path_buf); + configurator.save_config(); + Ok(()) +} + +#[tauri::command] +pub fn set_working_folder(working_folder: String) -> Result<(), ()> { + unsafe { + WORKING_FOLDER = working_folder; + } + Ok(()) +} + + +#[tauri::command] +pub fn write_board(board_name: String, contents: String) -> Result<(), String> { + let mut configurator = Configurator::new(); + unsafe { + configurator.set_working_folder(WORKING_FOLDER.clone()); + } + configurator.write_board(board_name, contents) +} + + +#[tauri::command] +pub fn force_reset() -> Result<(), ()> { + let mut configurator = Configurator::new(); + configurator.force_reset(); + Ok(()) +} + +#[tauri::command] +pub fn get_home() -> Result { + match dirs::home_dir() { + None => { + Ok(String::new()) + } + Some(path) => { + Ok(path.to_str().unwrap().to_string()) + } + } +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src-tauri/src/filesystem.rs b/misc/config_tools/configurator/src-tauri/src/filesystem.rs new file mode 100644 index 000000000..ceba9adbe --- /dev/null +++ b/misc/config_tools/configurator/src-tauri/src/filesystem.rs @@ -0,0 +1,102 @@ +use serde::Serialize; +use std::fs::{self, File}; +use std::io; +use std::io::prelude::*; +use std::path::Path; + +#[tauri::command] +pub fn fs_read_text_file(path: &str) -> Result { + let mut file = File::open(path).map_err(|e| e.to_string())?; + let mut contents = String::new(); + file + .read_to_string(&mut contents) + .map_err(|e| e.to_string())?; + Ok(contents) +} + +#[tauri::command] +pub fn fs_write_text_file(path: &str, contents: &str) -> Result<(), String> { + let mut file = File::create(path).map_err(|e| e.to_string())?; + file + .write_all(contents.as_bytes()) + .map_err(|e| e.to_string())?; + Ok(()) +} + +#[tauri::command] +pub fn fs_read_binary_file(path: &str) -> Result, String> { + let mut file = File::open(path).map_err(|e| e.to_string())?; + let mut contents = Vec::new(); + file.read_to_end(&mut contents).map_err(|e| e.to_string())?; + Ok(contents) +} + +#[tauri::command] +pub fn fs_write_binary_file(path: &str, contents: &[u8]) -> Result<(), String> { + let mut file = File::create(path).map_err(|e| e.to_string())?; + file.write_all(contents).map_err(|e| e.to_string())?; + Ok(()) +} + +#[derive(Serialize)] +pub struct DirEntry { + path: String, + children: Option>, +} + +fn read_dir>( + path: P, + recursive: bool, +) -> io::Result> { + let path = path.as_ref(); + let mut entries = Vec::new(); + for entry in fs::read_dir(path)? { + let entry = entry?; + let path = entry.path().to_str().unwrap().to_string(); + let children = if recursive && entry.file_type()?.is_dir() { + Some(read_dir(&path, true)?) + } else { + None + }; + entries.push(DirEntry { path, children }); + } + Ok(entries) +} + +#[tauri::command] +pub fn fs_read_dir( + path: &str, + recursive: bool, +) -> Result, String> { + read_dir(path, recursive).map_err(|e| e.to_string()) +} + +#[tauri::command] +pub fn fs_rename(from: &str, to: &str) -> Result<(), String> { + fs::rename(from, to).map_err(|e| e.to_string()) +} + +#[tauri::command] +pub fn fs_delete_file(path: &str) -> Result<(), String> { + fs::remove_file(path).map_err(|e| e.to_string()) +} + +#[tauri::command] +pub fn fs_delete_dir(path: &str) -> Result<(), String> { + fs::remove_dir_all(path).map_err(|e| e.to_string()) +} + +#[tauri::command] +pub fn fs_create_dir(path: &str) -> Result<(), String> { + fs::create_dir(path).map_err(|e| e.to_string()) +} + +#[tauri::command] +pub fn fs_is_file(path: &str) -> bool { + fs::metadata(path).map(|m| m.is_file()).unwrap_or(false) +} + +#[tauri::command] +pub fn fs_is_dir(path: &str) -> bool { + fs::metadata(path).map(|m| m.is_dir()).unwrap_or(false) +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src-tauri/src/main.rs b/misc/config_tools/configurator/src-tauri/src/main.rs new file mode 100644 index 000000000..4b2eff6ed --- /dev/null +++ b/misc/config_tools/configurator/src-tauri/src/main.rs @@ -0,0 +1,80 @@ +#![cfg_attr( +all(not(debug_assertions), target_os = "windows"), +windows_subsystem = "windows" +)] + +mod filesystem; +mod configurator; + +use log::*; + +use tauri::{api::cli::get_matches, utils::config::CliConfig, PackageInfo, RunEvent}; + +fn main() { + env_logger::init(); + // Init context + let context = tauri::generate_context!(); + + // Build app instance and run + let app = tauri::Builder::default() + .invoke_handler(tauri::generate_handler![ + filesystem::fs_rename, + filesystem::fs_read_dir, + filesystem::fs_read_text_file, + filesystem::fs_read_binary_file, + filesystem::fs_write_text_file, + filesystem::fs_write_binary_file, + filesystem::fs_read_dir, + filesystem::fs_delete_file, + filesystem::fs_delete_dir, + filesystem::fs_create_dir, + filesystem::fs_is_file, + filesystem::fs_is_dir, + configurator::get_history, + configurator::add_history, + configurator::set_working_folder, + configurator::write_board, + configurator::force_reset, + configurator::get_home + ]) + .setup(|app| { + // Handle cli cmdline + let app_config = app.config(); + let cli_config = app_config.tauri.cli.as_ref().unwrap(); + let package_info = app.package_info(); + handle_cli_arg_data(&cli_config, &package_info); + Ok(()) + }) + .build(context) + .expect("error while running tauri application"); + + app.run(|_app, event| { + if let RunEvent::Exit = event { + info!("Received Exit event"); + } + }); +} + + +fn handle_cli_arg_data(cli_config: &CliConfig, pkg_info: &PackageInfo) { + match get_matches(cli_config, pkg_info) { + Ok(matches) => { + let mut exit_flag = false; + if let Some(arg_data) = matches.args.get("help") { + println!("{}", arg_data.value.as_str().unwrap_or("No help available")); + exit_flag = true; + } + if let Some(arg_data) = matches.args.get("version") { + println!("{}", arg_data.value.as_str().unwrap_or("No version data available")); + exit_flag = true + } + if exit_flag { + std::process::exit(1); + } + } + Err(e) => { + error!("{}", e.to_string()); + std::process::exit(1); + } + } +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src-tauri/tauri.json b/misc/config_tools/configurator/src-tauri/tauri.json new file mode 100644 index 000000000..e67cfc84e --- /dev/null +++ b/misc/config_tools/configurator/src-tauri/tauri.json @@ -0,0 +1,78 @@ +{ + "$schema": "types/schema.json", + "package": { + "productName": "acrn-configurator", + "version": "../package.json" + }, + "build": { + "distDir": "../build", + "devPath": "http://localhost:3000", + "beforeDevCommand": "", + "beforeBuildCommand": "" + }, + "tauri": { + "cli": { + "args": [ + { + "name": "debug", + "takesValue": false + } + ] + }, + "bundle": { + "active": true, + "targets": "all", + "identifier": "com.tauri.dev", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "resources": [], + "externalBin": [], + "copyright": "", + "category": "DeveloperTool", + "shortDescription": "", + "longDescription": "", + "deb": { + "depends": [], + "useBootstrapper": false + }, + "macOS": { + "frameworks": [], + "minimumSystemVersion": "", + "useBootstrapper": false, + "exceptionDomain": "", + "signingIdentity": null, + "providerShortName": null, + "entitlements": null + }, + "windows": { + "certificateThumbprint": null, + "digestAlgorithm": "sha256", + "timestampUrl": "" + } + }, + "updater": { + "active": false + }, + "allowlist": { + "all": true + }, + "windows": [ + { + "title": "ACRN Configurator", + "width": 1366, + "height": 768, + "resizable": true, + "fullscreen": false, + "decorations": false + } + ], + "security": { + "csp": null + } + } +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src-tauri/types/config.ts b/misc/config_tools/configurator/src-tauri/types/config.ts new file mode 100644 index 000000000..4d1756429 --- /dev/null +++ b/misc/config_tools/configurator/src-tauri/types/config.ts @@ -0,0 +1,114 @@ +export default interface Config { + "$schema"?: string + package?: PackageConfig + tauri: TauriConfig + build: BuildConfig + plugins?: {} +} + +interface PackageConfig { + /// App name. + productName?: string, + /// App version. It is a semver version number or a path to a `package.json` file contaning the `version` field. + version?: string +} + +interface TauriConfig { + pattern?: { + /** + * Brownfield pattern. + */ + Brownfield: any, + /// Isolation pattern. Recommended for security purposes. + Isolation: { + /// The dir containing the index.html file that contains the secure isolation application. + dir: string, + }, + } + + windows: WindowConfig[] + /** + * app's CLI definition + */ + cli?: {} + bundle?: {} + allowlist?: {} + security?: {} + updater?: {} + system_tray?: {} + macos_private_api?: {} + +} + +interface WindowConfig { + /// The window identifier. It must be alphanumeric. + label?: string, + /// The window webview URL. + url?: string, + /// Whether the file drop is enabled or not on the webview. By default it is enabled. + /// + /// Disabling it is required to use drag and drop on the frontend on Windows. + file_drop_enabled?: boolean, + /// Whether or not the window starts centered or not. + center?: boolean, + /// The horizontal position of the window's top left corner + x?: number, + /// The vertical position of the window's top left corner + y?: number, + /// The window width. + width?: number, + /// The window height. + height?: number, + /// The min window width. + min_width?: number, + /// The min window height. + min_height?: number, + /// The max window width. + max_width?: number, + /// The max window height. + max_height?: number, + /// Whether the window is resizable or not. + resizable?: boolean, + /// The window title. + title?: string, + /// Whether the window starts as fullscreen or not. + fullscreen?: boolean, + /// Whether the window will be initially hidden or focused. + focus?: boolean, + /// Whether the window is transparent or not. + /// + /// Note that on `macOS` this requires the `macos-private-api` feature flag, enabled under `tauri.conf.json > tauri > macosPrivateApi`. + /// WARNING: Using private APIs on `macOS` prevents your application from being accepted for the `App Store`. + transparent?: boolean, + /// Whether the window is maximized or not. + maximized?: boolean, + /// Whether the window is visible or not. + visible?: boolean, + /// Whether the window should have borders and bars. + decorations?: boolean, + /// Whether the window should always be on top of other windows. + always_on_top?: boolean, + /// Whether or not the window icon should be added to the taskbar. + skip_taskbar?: boolean, +} + +interface BuildConfig { + /// The binary used to build and run the application. + runner?: string, + /// The path or URL to use on development. + devPath?: string, + /// The path to the app's dist dir. This path must contain your index.html file. + distDir?: string, + /// A shell command to run before `tauri dev` kicks in. + /// + /// The TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation. + beforeDevCommand?: string, + /// A shell command to run before `tauri build` kicks in. + /// + /// The TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation. + beforeBuildCommand?: string, + /// Features passed to `cargo` commands. + features?: string[], + /// Whether we should inject the Tauri API on `window.__TAURI__` or not. + withGlobalTauri?: boolean, +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src-tauri/types/schema.json b/misc/config_tools/configurator/src-tauri/types/schema.json new file mode 100644 index 000000000..0572ffdeb --- /dev/null +++ b/misc/config_tools/configurator/src-tauri/types/schema.json @@ -0,0 +1,2173 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Config", + "description": "The config type mapped to `tauri.conf.json`.", + "type": "object", + "properties": { + "$schema": { + "type": "string", + "default": "types/schema.json" + }, + "build": { + "description": "The build configuration.", + "default": { + "devPath": "http://localhost:8080/", + "distDir": "../dist", + "withGlobalTauri": false + }, + "allOf": [ + { + "$ref": "#/definitions/BuildConfig" + } + ] + }, + "package": { + "description": "Package settings.", + "default": { + "productName": null, + "version": null + }, + "allOf": [ + { + "$ref": "#/definitions/PackageConfig" + } + ] + }, + "plugins": { + "description": "The plugins config.", + "default": {}, + "allOf": [ + { + "$ref": "#/definitions/PluginConfig" + } + ] + }, + "tauri": { + "description": "The Tauri configuration.", + "default": { + "allowlist": { + "all": false, + "clipboard": { + "all": false, + "readText": false, + "writeText": false + }, + "dialog": { + "all": false, + "ask": false, + "confirm": false, + "message": false, + "open": false, + "save": false + }, + "fs": { + "all": false, + "copyFile": false, + "createDir": false, + "readDir": false, + "readFile": false, + "removeDir": false, + "removeFile": false, + "renameFile": false, + "scope": [], + "writeFile": false + }, + "globalShortcut": { + "all": false + }, + "http": { + "all": false, + "request": false, + "scope": [] + }, + "notification": { + "all": false + }, + "os": { + "all": false + }, + "path": { + "all": false + }, + "process": { + "all": false, + "exit": false, + "relaunch": false, + "relaunchDangerousAllowSymlinkMacos": false + }, + "protocol": { + "all": false, + "asset": false, + "assetScope": [] + }, + "shell": { + "all": false, + "execute": false, + "open": false, + "scope": [], + "sidecar": false + }, + "window": { + "all": false, + "center": false, + "close": false, + "create": false, + "hide": false, + "maximize": false, + "minimize": false, + "print": false, + "requestUserAttention": false, + "setAlwaysOnTop": false, + "setDecorations": false, + "setFocus": false, + "setFullscreen": false, + "setIcon": false, + "setMaxSize": false, + "setMinSize": false, + "setPosition": false, + "setResizable": false, + "setSize": false, + "setSkipTaskbar": false, + "setTitle": false, + "show": false, + "startDragging": false, + "unmaximize": false, + "unminimize": false + } + }, + "bundle": { + "active": false, + "deb": { + "files": {}, + "useBootstrapper": false + }, + "icon": [], + "identifier": "", + "macOS": { + "minimumSystemVersion": "10.13", + "useBootstrapper": false + }, + "windows": { + "certificateThumbprint": null, + "digestAlgorithm": null, + "timestampUrl": null, + "webviewFixedRuntimePath": null, + "wix": null + } + }, + "macOSPrivateApi": false, + "pattern": { + "use": "brownfield" + }, + "security": { + "freezePrototype": false + }, + "updater": { + "active": false, + "dialog": true, + "pubkey": "" + }, + "windows": [] + }, + "allOf": [ + { + "$ref": "#/definitions/TauriConfig" + } + ] + } + }, + "additionalProperties": false, + "definitions": { + "AllowlistConfig": { + "description": "Allowlist configuration.", + "type": "object", + "properties": { + "all": { + "description": "Use this flag to enable all API features.", + "default": false, + "type": "boolean" + }, + "clipboard": { + "description": "Clipboard APIs allowlist.", + "default": { + "all": false, + "readText": false, + "writeText": false + }, + "allOf": [ + { + "$ref": "#/definitions/ClipboardAllowlistConfig" + } + ] + }, + "dialog": { + "description": "Dialog API allowlist.", + "default": { + "all": false, + "ask": false, + "confirm": false, + "message": false, + "open": false, + "save": false + }, + "allOf": [ + { + "$ref": "#/definitions/DialogAllowlistConfig" + } + ] + }, + "fs": { + "description": "File system API allowlist.", + "default": { + "all": false, + "copyFile": false, + "createDir": false, + "readDir": false, + "readFile": false, + "removeDir": false, + "removeFile": false, + "renameFile": false, + "scope": [], + "writeFile": false + }, + "allOf": [ + { + "$ref": "#/definitions/FsAllowlistConfig" + } + ] + }, + "globalShortcut": { + "description": "Global shortcut API allowlist.", + "default": { + "all": false + }, + "allOf": [ + { + "$ref": "#/definitions/GlobalShortcutAllowlistConfig" + } + ] + }, + "http": { + "description": "HTTP API allowlist.", + "default": { + "all": false, + "request": false, + "scope": [] + }, + "allOf": [ + { + "$ref": "#/definitions/HttpAllowlistConfig" + } + ] + }, + "notification": { + "description": "Notification API allowlist.", + "default": { + "all": false + }, + "allOf": [ + { + "$ref": "#/definitions/NotificationAllowlistConfig" + } + ] + }, + "os": { + "description": "OS allowlist.", + "default": { + "all": false + }, + "allOf": [ + { + "$ref": "#/definitions/OsAllowlistConfig" + } + ] + }, + "path": { + "description": "Path API allowlist.", + "default": { + "all": false + }, + "allOf": [ + { + "$ref": "#/definitions/PathAllowlistConfig" + } + ] + }, + "process": { + "description": "Process API allowlist.", + "default": { + "all": false, + "exit": false, + "relaunch": false, + "relaunchDangerousAllowSymlinkMacos": false + }, + "allOf": [ + { + "$ref": "#/definitions/ProcessAllowlistConfig" + } + ] + }, + "protocol": { + "description": "Custom protocol allowlist.", + "default": { + "all": false, + "asset": false, + "assetScope": [] + }, + "allOf": [ + { + "$ref": "#/definitions/ProtocolAllowlistConfig" + } + ] + }, + "shell": { + "description": "Shell API allowlist.", + "default": { + "all": false, + "execute": false, + "open": false, + "scope": [], + "sidecar": false + }, + "allOf": [ + { + "$ref": "#/definitions/ShellAllowlistConfig" + } + ] + }, + "window": { + "description": "Window API allowlist.", + "default": { + "all": false, + "center": false, + "close": false, + "create": false, + "hide": false, + "maximize": false, + "minimize": false, + "print": false, + "requestUserAttention": false, + "setAlwaysOnTop": false, + "setDecorations": false, + "setFocus": false, + "setFullscreen": false, + "setIcon": false, + "setMaxSize": false, + "setMinSize": false, + "setPosition": false, + "setResizable": false, + "setSize": false, + "setSkipTaskbar": false, + "setTitle": false, + "show": false, + "startDragging": false, + "unmaximize": false, + "unminimize": false + }, + "allOf": [ + { + "$ref": "#/definitions/WindowAllowlistConfig" + } + ] + } + }, + "additionalProperties": false + }, + "AppUrl": { + "description": "The `dev_path` and `dist_dir` options.", + "anyOf": [ + { + "description": "The app's external URL, or the path to the directory containing the app assets.", + "allOf": [ + { + "$ref": "#/definitions/WindowUrl" + } + ] + }, + { + "description": "An array of files to embed on the app.", + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "BuildConfig": { + "description": "The Build configuration object.", + "type": "object", + "properties": { + "beforeBuildCommand": { + "description": "A shell command to run before `tauri build` kicks in.\n\nThe TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation.", + "type": [ + "string", + "null" + ] + }, + "beforeDevCommand": { + "description": "A shell command to run before `tauri dev` kicks in.\n\nThe TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation.", + "type": [ + "string", + "null" + ] + }, + "devPath": { + "description": "The path or URL to use on development.", + "default": "http://localhost:8080/", + "allOf": [ + { + "$ref": "#/definitions/AppUrl" + } + ] + }, + "distDir": { + "description": "The path to the app's dist dir. This path must contain your index.html file.", + "default": "../dist", + "allOf": [ + { + "$ref": "#/definitions/AppUrl" + } + ] + }, + "features": { + "description": "Features passed to `cargo` commands.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "runner": { + "description": "The binary used to build and run the application.", + "type": [ + "string", + "null" + ] + }, + "withGlobalTauri": { + "description": "Whether we should inject the Tauri API on `window.__TAURI__` or not.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "BundleConfig": { + "description": "Configuration for tauri-bundler.", + "type": "object", + "required": [ + "identifier" + ], + "properties": { + "active": { + "description": "Whether we should build your app with tauri-bundler or plain `cargo build`", + "default": false, + "type": "boolean" + }, + "category": { + "description": "The application kind.", + "type": [ + "string", + "null" + ] + }, + "copyright": { + "description": "A copyright string associated with your application.", + "type": [ + "string", + "null" + ] + }, + "deb": { + "description": "Configuration for the Debian bundle.", + "default": { + "files": {}, + "useBootstrapper": false + }, + "allOf": [ + { + "$ref": "#/definitions/DebConfig" + } + ] + }, + "externalBin": { + "description": "A list of—either absolute or relative—paths to binaries to embed with your application.\n\nNote that Tauri will look for system-specific binaries following the pattern \"binary-name{-target-triple}{.system-extension}\".\n\nE.g. for the external binary \"my-binary\", Tauri looks for:\n\n- \"my-binary-x86_64-pc-windows-msvc.exe\" for Windows - \"my-binary-x86_64-apple-darwin\" for macOS - \"my-binary-x86_64-unknown-linux-gnu\" for Linux\n\nso don't forget to provide binaries for all targeted platforms.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "icon": { + "description": "The app's icons", + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "identifier": { + "description": "The app's identifier", + "type": "string" + }, + "longDescription": { + "description": "A longer, multi-line description of the application.", + "type": [ + "string", + "null" + ] + }, + "macOS": { + "description": "Configuration for the macOS bundles.", + "default": { + "minimumSystemVersion": "10.13", + "useBootstrapper": false + }, + "allOf": [ + { + "$ref": "#/definitions/MacConfig" + } + ] + }, + "resources": { + "description": "App resources to bundle. Each resource is a path to a file or directory. Glob patterns are supported.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "shortDescription": { + "description": "A short description of your application.", + "type": [ + "string", + "null" + ] + }, + "targets": { + "description": "The bundle targets, currently supports [\"deb\", \"app\", \"msi\", \"appimage\", \"dmg\"] or \"all\"", + "anyOf": [ + { + "$ref": "#/definitions/BundleTarget" + }, + { + "type": "null" + } + ] + }, + "windows": { + "description": "Configuration for the Windows bundle.", + "default": { + "certificateThumbprint": null, + "digestAlgorithm": null, + "timestampUrl": null, + "webviewFixedRuntimePath": null, + "wix": null + }, + "allOf": [ + { + "$ref": "#/definitions/WindowsConfig" + } + ] + } + }, + "additionalProperties": false + }, + "BundleTarget": { + "description": "Targets to bundle.", + "anyOf": [ + { + "description": "A list of bundle targets.", + "type": "array", + "items": { + "type": "string" + } + }, + { + "description": "A single bundle target.", + "type": "string" + } + ] + }, + "CliArg": { + "description": "A CLI argument definition.", + "type": "object", + "required": [ + "name" + ], + "properties": { + "conflictsWith": { + "description": "Sets a conflicting argument by name i.e. when using this argument, the following argument can't be present and vice versa.", + "type": [ + "string", + "null" + ] + }, + "conflictsWithAll": { + "description": "The same as conflictsWith but allows specifying multiple two-way conflicts per argument.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "description": { + "description": "The argument description which will be shown on the help information. Typically, this is a short (one line) description of the arg.", + "type": [ + "string", + "null" + ] + }, + "index": { + "description": "The positional argument index, starting at 1.\n\nThe index refers to position according to other positional argument. It does not define position in the argument list as a whole. When utilized with multiple=true, only the last positional argument may be defined as multiple (i.e. the one with the highest index).", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "longDescription": { + "description": "The argument long description which will be shown on the help information. Typically this a more detailed (multi-line) message that describes the argument.", + "type": [ + "string", + "null" + ] + }, + "maxValues": { + "description": "Specifies the maximum number of values are for this argument. For example, if you had a -f argument where you wanted up to 3 'files', you would set .max_values(3), and this argument would be satisfied if the user provided, 1, 2, or 3 values.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "minValues": { + "description": "Specifies the minimum number of values for this argument. For example, if you had a -f argument where you wanted at least 2 'files', you would set `minValues: 2`, and this argument would be satisfied if the user provided, 2 or more values.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "multiple": { + "description": "Specifies that the argument may have an unknown number of multiple values. Without any other settings, this argument may appear only once.\n\nFor example, --opt val1 val2 is allowed, but --opt val1 val2 --opt val3 is not.\n\nNOTE: Setting this requires `takes_value` to be set to true.", + "type": [ + "boolean", + "null" + ] + }, + "multipleOccurrences": { + "description": "Specifies that the argument may appear more than once. For flags, this results in the number of occurrences of the flag being recorded. For example -ddd or -d -d -d would count as three occurrences. For options or arguments that take a value, this does not affect how many values they can accept. (i.e. only one at a time is allowed)\n\nFor example, --opt val1 --opt val2 is allowed, but --opt val1 val2 is not.", + "type": [ + "boolean", + "null" + ] + }, + "name": { + "description": "The unique argument name", + "type": "string" + }, + "numberOfValues": { + "description": "Specifies how many values are required to satisfy this argument. For example, if you had a `-f ` argument where you wanted exactly 3 'files' you would set `number_of_values = 3`, and this argument wouldn't be satisfied unless the user provided 3 and only 3 values.\n\n**NOTE:** Does *not* require `multiple_occurrences = true` to be set. Setting `multiple_occurrences = true` would allow `-f -f ` where as *not* setting it would only allow one occurrence of this argument.\n\n**NOTE:** implicitly sets `takes_value = true` and `multiple_values = true`.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "possibleValues": { + "description": "Specifies a list of possible values for this argument. At runtime, the CLI verifies that only one of the specified values was used, or fails with an error message.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "requireEquals": { + "description": "Requires that options use the --option=val syntax i.e. an equals between the option and associated value.", + "type": [ + "boolean", + "null" + ] + }, + "required": { + "description": "Sets whether or not the argument is required by default.\n\n- Required by default means it is required, when no other conflicting rules have been evaluated - Conflicting rules take precedence over being required.", + "type": [ + "boolean", + "null" + ] + }, + "requiredIfEq": { + "description": "Allows specifying that an argument is required conditionally with the signature [arg, value] the requirement will only become valid if the `arg`'s value equals `${value}`.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "requiredUnlessPresent": { + "description": "Sets an arg that override this arg's required setting i.e. this arg will be required unless this other argument is present.", + "type": [ + "string", + "null" + ] + }, + "requiredUnlessPresentAll": { + "description": "Sets args that override this arg's required setting i.e. this arg will be required unless all these other arguments are present.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "requiredUnlessPresentAny": { + "description": "Sets args that override this arg's required setting i.e. this arg will be required unless at least one of these other arguments are present.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "requires": { + "description": "Tets an argument by name that is required when this one is present i.e. when using this argument, the following argument must be present.", + "type": [ + "string", + "null" + ] + }, + "requiresAll": { + "description": "Sts multiple arguments by names that are required when this one is present i.e. when using this argument, the following arguments must be present.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "requiresIf": { + "description": "Allows a conditional requirement with the signature [arg, value] the requirement will only become valid if `arg`'s value equals `${value}`.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "short": { + "description": "The short version of the argument, without the preceding -.\n\nNOTE: Any leading - characters will be stripped, and only the first non - character will be used as the short version.", + "type": [ + "string", + "null" + ], + "maxLength": 1, + "minLength": 1 + }, + "takesValue": { + "description": "Specifies that the argument takes a value at run time.\n\nNOTE: values for arguments may be specified in any of the following methods - Using a space such as -o value or --option value - Using an equals and no space such as -o=value or --option=value - Use a short and no space such as -ovalue", + "type": [ + "boolean", + "null" + ] + } + }, + "additionalProperties": false + }, + "CliConfig": { + "description": "describes a CLI configuration", + "type": "object", + "properties": { + "afterHelp": { + "description": "Adds additional help information to be displayed in addition to auto-generated help. This information is displayed after the auto-generated help information. This is often used to describe how to use the arguments, or caveats to be noted.", + "type": [ + "string", + "null" + ] + }, + "args": { + "description": "List of arguments for the command", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/CliArg" + } + }, + "beforeHelp": { + "description": "Adds additional help information to be displayed in addition to auto-generated help. This information is displayed before the auto-generated help information. This is often used for header information.", + "type": [ + "string", + "null" + ] + }, + "description": { + "description": "Command description which will be shown on the help information.", + "type": [ + "string", + "null" + ] + }, + "longDescription": { + "description": "Command long description which will be shown on the help information.", + "type": [ + "string", + "null" + ] + }, + "subcommands": { + "description": "List of subcommands of this command", + "type": [ + "object", + "null" + ], + "additionalProperties": { + "$ref": "#/definitions/CliConfig" + } + } + }, + "additionalProperties": false + }, + "ClipboardAllowlistConfig": { + "description": "Allowlist for the clipboard APIs.", + "type": "object", + "properties": { + "all": { + "description": "Use this flag to enable all clipboard APIs.", + "default": false, + "type": "boolean" + }, + "readText": { + "description": "Enables the clipboard's `readText` API.", + "default": false, + "type": "boolean" + }, + "writeText": { + "description": "Enables the clipboard's `writeText` API.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "DebConfig": { + "description": "Configuration for Debian (.deb) bundles.", + "type": "object", + "properties": { + "depends": { + "description": "The list of deb dependencies your application relies on.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "files": { + "description": "The files to include on the package.", + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "useBootstrapper": { + "description": "Enable the boostrapper script.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "DialogAllowlistConfig": { + "description": "Allowlist for the dialog APIs.", + "type": "object", + "properties": { + "all": { + "description": "Use this flag to enable all dialog API features.", + "default": false, + "type": "boolean" + }, + "ask": { + "description": "Allows the API to show a dialog window with Yes/No buttons.", + "default": false, + "type": "boolean" + }, + "confirm": { + "description": "Allows the API to show a dialog window with Ok/Cancel buttons.", + "default": false, + "type": "boolean" + }, + "message": { + "description": "Allows the API to show a message dialog window.", + "default": false, + "type": "boolean" + }, + "open": { + "description": "Allows the API to open a dialog window to pick files.", + "default": false, + "type": "boolean" + }, + "save": { + "description": "Allows the API to open a dialog window to pick where to save files.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "FsAllowlistConfig": { + "description": "Allowlist for the file system APIs.", + "type": "object", + "properties": { + "all": { + "description": "Use this flag to enable all file system API features.", + "default": false, + "type": "boolean" + }, + "copyFile": { + "description": "Copy file from local filesystem.", + "default": false, + "type": "boolean" + }, + "createDir": { + "description": "Create directory from local filesystem.", + "default": false, + "type": "boolean" + }, + "readDir": { + "description": "Read directory from local filesystem.", + "default": false, + "type": "boolean" + }, + "readFile": { + "description": "Read file from local filesystem.", + "default": false, + "type": "boolean" + }, + "removeDir": { + "description": "Remove directory from local filesystem.", + "default": false, + "type": "boolean" + }, + "removeFile": { + "description": "Remove file from local filesystem.", + "default": false, + "type": "boolean" + }, + "renameFile": { + "description": "Rename file from local filesystem.", + "default": false, + "type": "boolean" + }, + "scope": { + "description": "The access scope for the filesystem APIs.", + "default": [], + "allOf": [ + { + "$ref": "#/definitions/FsAllowlistScope" + } + ] + }, + "writeFile": { + "description": "Write file to local filesystem.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "FsAllowlistScope": { + "description": "Filesystem scope definition. It is a list of glob patterns that restrict the API access from the webview.\n\nEach pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`.", + "type": "array", + "items": { + "type": "string" + } + }, + "GlobalShortcutAllowlistConfig": { + "description": "Allowlist for the global shortcut APIs.", + "type": "object", + "properties": { + "all": { + "description": "Use this flag to enable all global shortcut API features.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "HttpAllowlistConfig": { + "description": "Allowlist for the HTTP APIs.", + "type": "object", + "properties": { + "all": { + "description": "Use this flag to enable all HTTP API features.", + "default": false, + "type": "boolean" + }, + "request": { + "description": "Allows making HTTP requests.", + "default": false, + "type": "boolean" + }, + "scope": { + "description": "The access scope for the HTTP APIs.", + "default": [], + "allOf": [ + { + "$ref": "#/definitions/HttpAllowlistScope" + } + ] + } + }, + "additionalProperties": false + }, + "HttpAllowlistScope": { + "description": "HTTP API scope definition. It is a list of URLs that can be accessed by the webview when using the HTTP APIs. The scoped URL is matched against the request URL using a glob pattern.\n\n# Examples\n\n- \"https://*\": allows all HTTPS urls - \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path - \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"", + "type": "array", + "items": { + "type": "string", + "format": "uri" + } + }, + "MacConfig": { + "description": "Configuration for the macOS bundles.", + "type": "object", + "properties": { + "entitlements": { + "description": "Path to the entitlements file.", + "type": [ + "string", + "null" + ] + }, + "exceptionDomain": { + "description": "Allows your application to communicate with the outside world. It should be a lowercase, without port and protocol domain name.", + "type": [ + "string", + "null" + ] + }, + "frameworks": { + "description": "A list of strings indicating any macOS X frameworks that need to be bundled with the application.\n\nIf a name is used, \".framework\" must be omitted and it will look for standard install locations. You may also use a path to a specific framework.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "license": { + "description": "The path to the license file to add to the DMG bundle.", + "type": [ + "string", + "null" + ] + }, + "minimumSystemVersion": { + "description": "A version string indicating the minimum macOS X version that the bundled application supports. Defaults to `10.13`. Setting it to `null` completely removes the `LSMinimumSystemVersion` field on the bundle's `Info.plist` and the `MACOSX_DEPLOYMENT_TARGET` environment variable.", + "default": "10.13", + "type": [ + "string", + "null" + ] + }, + "providerShortName": { + "description": "Provider short name for notarization.", + "type": [ + "string", + "null" + ] + }, + "signingIdentity": { + "description": "Identity to use for code signing.", + "type": [ + "string", + "null" + ] + }, + "useBootstrapper": { + "description": "Enable the boostrapper script.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "NotificationAllowlistConfig": { + "description": "Allowlist for the notification APIs.", + "type": "object", + "properties": { + "all": { + "description": "Use this flag to enable all notification API features.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "OsAllowlistConfig": { + "description": "Allowlist for the OS APIs.", + "type": "object", + "properties": { + "all": { + "description": "Use this flag to enable all OS API features.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "PackageConfig": { + "description": "The package configuration.", + "type": "object", + "properties": { + "productName": { + "description": "App name.", + "type": [ + "string", + "null" + ] + }, + "version": { + "description": "App version. It is a semver version number or a path to a `package.json` file contaning the `version` field.", + "default": null, + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, + "PathAllowlistConfig": { + "description": "Allowlist for the path APIs.", + "type": "object", + "properties": { + "all": { + "description": "Use this flag to enable all path API features.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "PatternKind": { + "description": "The application pattern.", + "oneOf": [ + { + "description": "Brownfield pattern.", + "type": "object", + "required": [ + "use" + ], + "properties": { + "use": { + "type": "string", + "enum": [ + "brownfield" + ] + } + } + }, + { + "description": "Isolation pattern. Recommended for security purposes.", + "type": "object", + "required": [ + "options", + "use" + ], + "properties": { + "options": { + "type": "object", + "required": [ + "dir" + ], + "properties": { + "dir": { + "description": "The dir containing the index.html file that contains the secure isolation application.", + "type": "string" + } + } + }, + "use": { + "type": "string", + "enum": [ + "isolation" + ] + } + } + } + ] + }, + "PluginConfig": { + "description": "The plugin configs holds a HashMap mapping a plugin name to its configuration object.", + "type": "object", + "additionalProperties": true + }, + "ProcessAllowlistConfig": { + "description": "Allowlist for the process APIs.", + "type": "object", + "properties": { + "all": { + "description": "Use this flag to enable all process APIs.", + "default": false, + "type": "boolean" + }, + "exit": { + "description": "Enables the exit API.", + "default": false, + "type": "boolean" + }, + "relaunch": { + "description": "Enables the relaunch API.", + "default": false, + "type": "boolean" + }, + "relaunchDangerousAllowSymlinkMacos": { + "description": "Dangerous option that allows macOS to relaunch even if the binary contains a symlink.\n\nThis is due to macOS having less symlink protection. Highly recommended to not set this flag unless you have a very specific reason too, and understand the implications of it.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "ProtocolAllowlistConfig": { + "description": "Allowlist for the custom protocols.", + "type": "object", + "properties": { + "all": { + "description": "Use this flag to enable all custom protocols.", + "default": false, + "type": "boolean" + }, + "asset": { + "description": "Enables the asset protocol.", + "default": false, + "type": "boolean" + }, + "assetScope": { + "description": "The access scope for the asset protocol.", + "default": [], + "allOf": [ + { + "$ref": "#/definitions/FsAllowlistScope" + } + ] + } + }, + "additionalProperties": false + }, + "SecurityConfig": { + "description": "Security configuration.", + "type": "object", + "properties": { + "csp": { + "description": "The Content Security Policy that will be injected on all HTML files on the built application. If [`dev_csp`](SecurityConfig.dev_csp) is not specified, this value is also injected on dev.\n\nThis is a really important part of the configuration since it helps you ensure your WebView is secured. See .", + "type": [ + "string", + "null" + ] + }, + "devCsp": { + "description": "The Content Security Policy that will be injected on all HTML files on development.\n\nThis is a really important part of the configuration since it helps you ensure your WebView is secured. See .", + "type": [ + "string", + "null" + ] + }, + "freezePrototype": { + "description": "Freeze the `Object.prototype` when using the custom protocol.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "ShellAllowedArg": { + "description": "A command argument allowed to be executed by the webview API.", + "anyOf": [ + { + "description": "A non-configurable argument that is passed to the command in the order it was specified.", + "type": "string" + }, + { + "description": "A variable that is set while calling the command from the webview API.", + "type": "object", + "required": [ + "validator" + ], + "properties": { + "validator": { + "description": "[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\n[regex]: https://docs.rs/regex/latest/regex/#syntax", + "type": "string" + } + }, + "additionalProperties": false + } + ] + }, + "ShellAllowedArgs": { + "description": "A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration.", + "anyOf": [ + { + "description": "Use a simple boolean to allow all or disable all arguments to this command configuration.", + "type": "boolean" + }, + { + "description": "A specific set of [`ShellAllowedArg`] that are valid to call for the command configuration.", + "type": "array", + "items": { + "$ref": "#/definitions/ShellAllowedArg" + } + } + ] + }, + "ShellAllowedCommand": { + "description": "A command allowed to be executed by the webview API.", + "type": "object", + "required": [ + "cmd", + "name" + ], + "properties": { + "args": { + "description": "The allowed arguments for the command execution.", + "default": false, + "allOf": [ + { + "$ref": "#/definitions/ShellAllowedArgs" + } + ] + }, + "cmd": { + "description": "The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`.", + "type": "string" + }, + "name": { + "description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.", + "type": "string" + }, + "sidecar": { + "description": "If this command is a sidecar command.", + "default": false, + "type": "boolean" + } + } + }, + "ShellAllowlistConfig": { + "description": "Allowlist for the shell APIs.", + "type": "object", + "properties": { + "all": { + "description": "Use this flag to enable all shell API features.", + "default": false, + "type": "boolean" + }, + "execute": { + "description": "Enable binary execution.", + "default": false, + "type": "boolean" + }, + "open": { + "description": "Open URL with the user's default application.", + "default": false, + "allOf": [ + { + "$ref": "#/definitions/ShellAllowlistOpen" + } + ] + }, + "scope": { + "description": "Access scope for the binary execution APIs. Sidecars are automatically enabled.", + "default": [], + "allOf": [ + { + "$ref": "#/definitions/ShellAllowlistScope" + } + ] + }, + "sidecar": { + "description": "Enable sidecar execution, allowing the JavaScript layer to spawn a sidecar command, an executable that is shipped with the application. For more information see .", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "ShellAllowlistOpen": { + "description": "Defines the `shell > open` api scope.", + "anyOf": [ + { + "description": "If the shell open API should be enabled.\n\nIf enabled, the default validation regex (`^https?://`) is used.", + "type": "boolean" + }, + { + "description": "Enable the shell open API, with a custom regex that the opened path must match against.\n\nIf using a custom regex to support a non-http(s) schema, care should be used to prevent values that allow flag-like strings to pass validation. e.g. `--enable-debugging`, `-i`, `/R`.", + "type": "string" + } + ] + }, + "ShellAllowlistScope": { + "description": "Shell scope definition. It is a list of command names and associated CLI arguments that restrict the API access from the webview.", + "type": "array", + "items": { + "$ref": "#/definitions/ShellAllowedCommand" + } + }, + "SystemTrayConfig": { + "description": "Configuration for application system tray icon.", + "type": "object", + "required": [ + "iconPath" + ], + "properties": { + "iconAsTemplate": { + "description": "A Boolean value that determines whether the image represents a [template](https://developer.apple.com/documentation/appkit/nsimage/1520017-template?language=objc) image on macOS.", + "default": false, + "type": "boolean" + }, + "iconPath": { + "description": "Path to the icon to use on the system tray.\n\nIt is forced to be a `.png` file on Linux and macOS, and a `.ico` file on Windows.", + "type": "string" + } + }, + "additionalProperties": false + }, + "TauriConfig": { + "description": "The Tauri configuration object.", + "type": "object", + "properties": { + "allowlist": { + "description": "The allowlist configuration.", + "default": { + "all": false, + "clipboard": { + "all": false, + "readText": false, + "writeText": false + }, + "dialog": { + "all": false, + "ask": false, + "confirm": false, + "message": false, + "open": false, + "save": false + }, + "fs": { + "all": false, + "copyFile": false, + "createDir": false, + "readDir": false, + "readFile": false, + "removeDir": false, + "removeFile": false, + "renameFile": false, + "scope": [], + "writeFile": false + }, + "globalShortcut": { + "all": false + }, + "http": { + "all": false, + "request": false, + "scope": [] + }, + "notification": { + "all": false + }, + "os": { + "all": false + }, + "path": { + "all": false + }, + "process": { + "all": false, + "exit": false, + "relaunch": false, + "relaunchDangerousAllowSymlinkMacos": false + }, + "protocol": { + "all": false, + "asset": false, + "assetScope": [] + }, + "shell": { + "all": false, + "execute": false, + "open": false, + "scope": [], + "sidecar": false + }, + "window": { + "all": false, + "center": false, + "close": false, + "create": false, + "hide": false, + "maximize": false, + "minimize": false, + "print": false, + "requestUserAttention": false, + "setAlwaysOnTop": false, + "setDecorations": false, + "setFocus": false, + "setFullscreen": false, + "setIcon": false, + "setMaxSize": false, + "setMinSize": false, + "setPosition": false, + "setResizable": false, + "setSize": false, + "setSkipTaskbar": false, + "setTitle": false, + "show": false, + "startDragging": false, + "unmaximize": false, + "unminimize": false + } + }, + "allOf": [ + { + "$ref": "#/definitions/AllowlistConfig" + } + ] + }, + "bundle": { + "description": "The bundler configuration.", + "default": { + "active": false, + "deb": { + "files": {}, + "useBootstrapper": false + }, + "icon": [], + "identifier": "", + "macOS": { + "minimumSystemVersion": "10.13", + "useBootstrapper": false + }, + "windows": { + "certificateThumbprint": null, + "digestAlgorithm": null, + "timestampUrl": null, + "webviewFixedRuntimePath": null, + "wix": null + } + }, + "allOf": [ + { + "$ref": "#/definitions/BundleConfig" + } + ] + }, + "cli": { + "description": "The CLI configuration.", + "anyOf": [ + { + "$ref": "#/definitions/CliConfig" + }, + { + "type": "null" + } + ] + }, + "macOSPrivateApi": { + "description": "MacOS private API configuration. Enables the transparent background API and sets the `fullScreenEnabled` preference to `true`.", + "default": false, + "type": "boolean" + }, + "pattern": { + "description": "The pattern to use.", + "default": { + "use": "brownfield" + }, + "allOf": [ + { + "$ref": "#/definitions/PatternKind" + } + ] + }, + "security": { + "description": "Security configuration.", + "default": { + "freezePrototype": false + }, + "allOf": [ + { + "$ref": "#/definitions/SecurityConfig" + } + ] + }, + "systemTray": { + "description": "Configuration for app system tray.", + "anyOf": [ + { + "$ref": "#/definitions/SystemTrayConfig" + }, + { + "type": "null" + } + ] + }, + "updater": { + "description": "The updater configuration.", + "default": { + "active": false, + "dialog": true, + "pubkey": "" + }, + "allOf": [ + { + "$ref": "#/definitions/UpdaterConfig" + } + ] + }, + "windows": { + "description": "The windows configuration.", + "default": [], + "type": "array", + "items": { + "$ref": "#/definitions/WindowConfig" + } + } + }, + "additionalProperties": false + }, + "UpdaterConfig": { + "description": "The Updater configuration object.", + "type": "object", + "properties": { + "active": { + "description": "Whether the updater is active or not.", + "default": false, + "type": "boolean" + }, + "dialog": { + "description": "Display built-in dialog or use event system if disabled.", + "default": true, + "type": "boolean" + }, + "endpoints": { + "description": "The updater endpoints. TLS is enforced on production.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/UpdaterEndpoint" + } + }, + "pubkey": { + "description": "Signature public key.", + "default": "", + "type": "string" + } + }, + "additionalProperties": false + }, + "UpdaterEndpoint": { + "description": "A URL to an updater server.\n\nThe URL must use the `https` scheme on production.", + "type": "string", + "format": "uri" + }, + "WindowAllowlistConfig": { + "description": "Allowlist for the window APIs.", + "type": "object", + "properties": { + "all": { + "description": "Use this flag to enable all window API features.", + "default": false, + "type": "boolean" + }, + "center": { + "description": "Allows centering the window.", + "default": false, + "type": "boolean" + }, + "close": { + "description": "Allows closing the window.", + "default": false, + "type": "boolean" + }, + "create": { + "description": "Allows dynamic window creation.", + "default": false, + "type": "boolean" + }, + "hide": { + "description": "Allows hiding the window.", + "default": false, + "type": "boolean" + }, + "maximize": { + "description": "Allows maximizing the window.", + "default": false, + "type": "boolean" + }, + "minimize": { + "description": "Allows minimizing the window.", + "default": false, + "type": "boolean" + }, + "print": { + "description": "Allows opening the system dialog to print the window content.", + "default": false, + "type": "boolean" + }, + "requestUserAttention": { + "description": "Allows requesting user attention on the window.", + "default": false, + "type": "boolean" + }, + "setAlwaysOnTop": { + "description": "Allows setting the always_on_top flag of the window.", + "default": false, + "type": "boolean" + }, + "setDecorations": { + "description": "Allows setting the decorations flag of the window.", + "default": false, + "type": "boolean" + }, + "setFocus": { + "description": "Allows focusing the window.", + "default": false, + "type": "boolean" + }, + "setFullscreen": { + "description": "Allows setting the fullscreen flag of the window.", + "default": false, + "type": "boolean" + }, + "setIcon": { + "description": "Allows changing the window icon.", + "default": false, + "type": "boolean" + }, + "setMaxSize": { + "description": "Allows setting the window maximum size.", + "default": false, + "type": "boolean" + }, + "setMinSize": { + "description": "Allows setting the window minimum size.", + "default": false, + "type": "boolean" + }, + "setPosition": { + "description": "Allows changing the position of the window.", + "default": false, + "type": "boolean" + }, + "setResizable": { + "description": "Allows setting the resizable flag of the window.", + "default": false, + "type": "boolean" + }, + "setSize": { + "description": "Allows setting the window size.", + "default": false, + "type": "boolean" + }, + "setSkipTaskbar": { + "description": "Allows setting the skip_taskbar flag of the window.", + "default": false, + "type": "boolean" + }, + "setTitle": { + "description": "Allows changing the window title.", + "default": false, + "type": "boolean" + }, + "show": { + "description": "Allows showing the window.", + "default": false, + "type": "boolean" + }, + "startDragging": { + "description": "Allows start dragging on the window.", + "default": false, + "type": "boolean" + }, + "unmaximize": { + "description": "Allows unmaximizing the window.", + "default": false, + "type": "boolean" + }, + "unminimize": { + "description": "Allows unminimizing the window.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false + }, + "WindowConfig": { + "description": "The window configuration object.", + "type": "object", + "properties": { + "alwaysOnTop": { + "description": "Whether the window should always be on top of other windows.", + "default": false, + "type": "boolean" + }, + "center": { + "description": "Whether or not the window starts centered or not.", + "default": false, + "type": "boolean" + }, + "decorations": { + "description": "Whether the window should have borders and bars.", + "default": true, + "type": "boolean" + }, + "fileDropEnabled": { + "description": "Whether the file drop is enabled or not on the webview. By default it is enabled.\n\nDisabling it is required to use drag and drop on the frontend on Windows.", + "default": true, + "type": "boolean" + }, + "focus": { + "description": "Whether the window will be initially hidden or focused.", + "default": true, + "type": "boolean" + }, + "fullscreen": { + "description": "Whether the window starts as fullscreen or not.", + "default": false, + "type": "boolean" + }, + "height": { + "description": "The window height.", + "default": 600.0, + "type": "number", + "format": "double" + }, + "label": { + "description": "The window identifier. It must be alphanumeric.", + "default": "main", + "type": "string" + }, + "maxHeight": { + "description": "The max window height.", + "type": [ + "number", + "null" + ], + "format": "double" + }, + "maxWidth": { + "description": "The max window width.", + "type": [ + "number", + "null" + ], + "format": "double" + }, + "maximized": { + "description": "Whether the window is maximized or not.", + "default": false, + "type": "boolean" + }, + "minHeight": { + "description": "The min window height.", + "type": [ + "number", + "null" + ], + "format": "double" + }, + "minWidth": { + "description": "The min window width.", + "type": [ + "number", + "null" + ], + "format": "double" + }, + "resizable": { + "description": "Whether the window is resizable or not.", + "default": true, + "type": "boolean" + }, + "skipTaskbar": { + "description": "Whether or not the window icon should be added to the taskbar.", + "default": false, + "type": "boolean" + }, + "title": { + "description": "The window title.", + "default": "Tauri App", + "type": "string" + }, + "transparent": { + "description": "Whether the window is transparent or not.\n\nNote that on `macOS` this requires the `macos-private-api` feature flag, enabled under `tauri.conf.json > tauri > macosPrivateApi`. WARNING: Using private APIs on `macOS` prevents your application from being accepted for the `App Store`.", + "default": false, + "type": "boolean" + }, + "url": { + "description": "The window webview URL.", + "default": "index.html", + "allOf": [ + { + "$ref": "#/definitions/WindowUrl" + } + ] + }, + "visible": { + "description": "Whether the window is visible or not.", + "default": true, + "type": "boolean" + }, + "width": { + "description": "The window width.", + "default": 800.0, + "type": "number", + "format": "double" + }, + "x": { + "description": "The horizontal position of the window's top left corner", + "type": [ + "number", + "null" + ], + "format": "double" + }, + "y": { + "description": "The vertical position of the window's top left corner", + "type": [ + "number", + "null" + ], + "format": "double" + } + }, + "additionalProperties": false + }, + "WindowUrl": { + "description": "An URL to open on a Tauri webview window.", + "anyOf": [ + { + "description": "An external URL.", + "type": "string", + "format": "uri" + }, + { + "description": "An app URL.", + "type": "string" + } + ] + }, + "WindowsConfig": { + "description": "Windows bundler configuration.", + "type": "object", + "properties": { + "certificateThumbprint": { + "description": "Specifies the SHA1 hash of the signing certificate.", + "type": [ + "string", + "null" + ] + }, + "digestAlgorithm": { + "description": "Specifies the file digest algorithm to use for creating file signatures. Required for code signing. SHA-256 is recommended.", + "type": [ + "string", + "null" + ] + }, + "timestampUrl": { + "description": "Server to use during timestamping.", + "type": [ + "string", + "null" + ] + }, + "webviewFixedRuntimePath": { + "description": "Path to the webview fixed runtime to use.\n\nThe fixed version can be downloaded [on the official website](https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section). The `.cab` file must be extracted to a folder and this folder path must be defined on this field.", + "type": [ + "string", + "null" + ] + }, + "wix": { + "description": "Configuration for the MSI generated with WiX.", + "anyOf": [ + { + "$ref": "#/definitions/WixConfig" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + "WixConfig": { + "description": "Configuration for the MSI bundle using WiX.", + "type": "object", + "properties": { + "bannerPath": { + "description": "Path to a bitmap file to use as the installation user interface banner. This bitmap will appear at the top of all but the first page of the installer.\n\nThe required dimensions are 493px × 58px.", + "type": [ + "string", + "null" + ] + }, + "componentGroupRefs": { + "description": "The ComponentGroup element ids you want to reference from the fragments.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "componentRefs": { + "description": "The Component element ids you want to reference from the fragments.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "dialogImagePath": { + "description": "Path to a bitmap file to use on the installation user interface dialogs. It is used on the welcome and completion dialogs. The required dimensions are 493px × 312px.", + "type": [ + "string", + "null" + ] + }, + "enableElevatedUpdateTask": { + "description": "Create an elevated update task within Windows Task Scheduler.", + "default": false, + "type": "boolean" + }, + "featureGroupRefs": { + "description": "The FeatureGroup element ids you want to reference from the fragments.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "featureRefs": { + "description": "The Feature element ids you want to reference from the fragments.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "fragmentPaths": { + "description": "A list of paths to .wxs files with WiX fragments to use.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "language": { + "description": "The installer languages to build. See .", + "default": "en-US", + "allOf": [ + { + "$ref": "#/definitions/WixLanguage" + } + ] + }, + "license": { + "description": "The path to the license file to render on the installer.\n\nMust be an RTF file, so if a different extension is provided, we convert it to the RTF format.", + "type": [ + "string", + "null" + ] + }, + "mergeRefs": { + "description": "The Merge element ids you want to reference from the fragments.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "skipWebviewInstall": { + "description": "Disables the Webview2 runtime installation after app install.", + "default": false, + "type": "boolean" + }, + "template": { + "description": "A custom .wxs template to use.", + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, + "WixLanguage": { + "description": "The languages to build using WiX.", + "anyOf": [ + { + "description": "A single language to build, without configuration.", + "type": "string" + }, + { + "description": "A list of languages to build, without configuration.", + "type": "array", + "items": { + "type": "string" + } + }, + { + "description": "A map of languages and its configuration.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/WixLanguageConfig" + } + } + ] + }, + "WixLanguageConfig": { + "description": "Configuration for a target language for the WiX build.", + "type": "object", + "properties": { + "localePath": { + "description": "The path to a locale (`.wxl`) file. See .", + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + } + } +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/ACRNContext.jsx b/misc/config_tools/configurator/src/ACRNContext.jsx new file mode 100644 index 000000000..c77737cc1 --- /dev/null +++ b/misc/config_tools/configurator/src/ACRNContext.jsx @@ -0,0 +1,37 @@ +import React, {createContext} from 'react' +import {Helper, TauriLocalFSBackend} from "./lib/helper"; +import {Configurator} from "./lib/acrn"; + +// 1. Use React createContext API to create ACRN Context +export const ACRNContext = createContext({ + helper: () => { + }, + configurator: () => { + } +}) + +// 2. Create Context Provider +export class ACRNProvider extends React.Component { + constructor(props) { + super(props); + let fsBackend = new TauriLocalFSBackend() + let helper = new Helper(fsBackend, fsBackend) + let configurator = new Configurator(helper) + this.state = { + helper: helper, + configurator: configurator + } + } + + render() { + console.log(this.state) + return ( + + {this.props.children} + + ) + } +} + +// 3. export Consumer +export const ACRNConsumer = ACRNContext.Consumer diff --git a/misc/config_tools/configurator/src/App.css b/misc/config_tools/configurator/src/App.css new file mode 100644 index 000000000..126662e34 --- /dev/null +++ b/misc/config_tools/configurator/src/App.css @@ -0,0 +1,97 @@ +a { + /* Browse for folder… */ + font-family: Roboto, serif; + font-style: normal; + font-weight: bold; + font-size: 16px; + line-height: 19px; + + color: #2A958D; + text-decoration: auto; +} + +@media (min-width: 576px) { + .border-end-sm { + border-right: 1px solid #dee2e6 !important; + } +} + +.btn-lg { + min-height: 50px; + border-radius: 30px; + font-family: Roboto, serif; + font-style: normal; + font-weight: bold; + line-height: 23px; + text-align: center; + text-transform: capitalize; + + color: #FFFFFF; +} + +.btn-primary { + background-color: #007B81; + border-color: #007B81; +} + +.btn-primary:hover { + background-color: #004B50; + border-color: #004B50; +} + +select { + height: 49px; + background-image: url("assets/images/dropdown_arrow.svg") !important; + background-repeat: no-repeat; + background-position: right 0.75rem center; + background-size: 16px 12px; + border: 1px solid #ced4da; + border-radius: 0.25rem; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + appearance: none; +} + +select:focus { + border: 1px solid #69BFAD; + box-sizing: border-box; + box-shadow: 0 0 6px rgba(105, 191, 173, 0.37); + border-radius: 5px; +} + + +.banner-text { + max-width: 594px; + + font-family: Roboto, serif; + font-style: normal; + font-weight: normal; + font-size: 28px; + line-height: 37px; + letter-spacing: -0.175px; + + color: #FFFFFF; +} + +.bg-gray { + background: #F5F5F5; +} + +.text-right { + text-align: right; +} + +table { + width: 100%; +} + +.descInfoBtn { + color: gray; +} + +.descInfoBtn:hover { + color: lightgray; +} + +.rst-paragraph:last-child{ + margin-bottom: 0; +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/App.jsx b/misc/config_tools/configurator/src/App.jsx new file mode 100644 index 000000000..f6adc1ff3 --- /dev/null +++ b/misc/config_tools/configurator/src/App.jsx @@ -0,0 +1,25 @@ +import {ACRNProvider} from "./ACRNContext"; +import {HashRouter, Routes, Route} from "react-router-dom"; +import './App.css' +import Welcome from "./pages/Welcome/Welcome"; +import Error from "./pages/Error/Error"; +import Config from "./pages/Config/Config"; + +import "bootstrap/dist/js/bootstrap" + +function App() { + return ( + + + + }/> + }/> + }/> + + + + ) +} + + +export default App diff --git a/misc/config_tools/configurator/src/assets/fonts/Roboto-Regular.woff b/misc/config_tools/configurator/src/assets/fonts/Roboto-Regular.woff new file mode 100644 index 000000000..b867bd559 Binary files /dev/null and b/misc/config_tools/configurator/src/assets/fonts/Roboto-Regular.woff differ diff --git a/misc/config_tools/configurator/src/assets/fonts/Roboto-Regular.woff2 b/misc/config_tools/configurator/src/assets/fonts/Roboto-Regular.woff2 new file mode 100644 index 000000000..c63fb57ca Binary files /dev/null and b/misc/config_tools/configurator/src/assets/fonts/Roboto-Regular.woff2 differ diff --git a/misc/config_tools/configurator/src/assets/fonts/Roboto.css b/misc/config_tools/configurator/src/assets/fonts/Roboto.css new file mode 100644 index 000000000..528a25e6b --- /dev/null +++ b/misc/config_tools/configurator/src/assets/fonts/Roboto.css @@ -0,0 +1,9 @@ +@font-face { + font-family: 'Roboto'; + src: url('Roboto-Regular.woff2') format('woff2'), + url('Roboto-Regular.woff') format('woff'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + diff --git a/misc/config_tools/configurator/src/assets/images/back_arrow_icon.svg b/misc/config_tools/configurator/src/assets/images/back_arrow_icon.svg new file mode 100644 index 000000000..9b8f0f5ea --- /dev/null +++ b/misc/config_tools/configurator/src/assets/images/back_arrow_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/misc/config_tools/configurator/src/assets/images/dropdown_arrow.svg b/misc/config_tools/configurator/src/assets/images/dropdown_arrow.svg new file mode 100644 index 000000000..def5bc0ad --- /dev/null +++ b/misc/config_tools/configurator/src/assets/images/dropdown_arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/misc/config_tools/configurator/src/assets/schema/dynamicScenario.py b/misc/config_tools/configurator/src/assets/schema/dynamicScenario.py new file mode 100644 index 000000000..091e38e88 --- /dev/null +++ b/misc/config_tools/configurator/src/assets/schema/dynamicScenario.py @@ -0,0 +1,78 @@ +""" + +public var board_xml +public function get_enum(source, selector) + +enum = { + 'type': 'dynamicEnum', + 'function': 'get_enum', + 'source': 'board_xml', + 'selector': element['xs:annotation']['@acrn:options'], + 'sorted': element['xs:annotation'].get('@acrn:options-sorted-by', None) +} + +params defined before this document string in js side like +```js +let params = JSON.stringify({board_xml: boardXMLText, scenario_json: JSON.stringify(scenario_json)}) +params = Base64.encode(params); +return runPyCode(` +params="${params}" +${dynamicScenario} +`) +``` +""" + +import json +from base64 import b64decode + +import elementpath +import lxml.etree as etree + +# local test var set +if 'params' not in globals(): + # params = b64encode(open(r"board.xml",'rb').read()) + raise NotImplementedError + +# Main flow +# noinspection PyUnresolvedReferences,PyUnboundLocalVariable +params: str = b64decode(params).decode('utf-8') +params: dict = json.loads(params) +board_xml = etree.XML(params["board_xml"]) +scenario_json = params['scenario_json'] + + +def get_enum(source, options): + elements = [str(x) for x in elementpath.select(source, options) if x] + elements = list(set(elements)) + if not elements: + elements = [''] + return elements + + +def dynamic_enum(**kwargs): + # value from env + function, source = [globals()[kwargs[key]] for key in ['function', 'source']] + # value from given + selector, sorted_func = [kwargs[key] for key in ['selector', 'sorted']] + + # get enum data + enum = function(source, selector) + if sorted_func: + enum = sorted(enum, key=eval(sorted_func)) + return enum + + +def dynamic_enum_apply(obj): + # get json schema enum obj + if 'enum' in obj and isinstance(obj['enum'], dict): + enum_setting = obj['enum'] + # check enum obj type + if enum_setting['type'] == 'dynamicEnum': + del enum_setting['type'] + # replace json schema obj enum field data + obj['enum'] = dynamic_enum(**enum_setting) + return obj + + +data = json.loads(scenario_json, object_hook=dynamic_enum_apply) +json.dumps(data) diff --git a/misc/config_tools/configurator/src/assets/schema/scenario.json b/misc/config_tools/configurator/src/assets/schema/scenario.json new file mode 100644 index 000000000..28526e926 --- /dev/null +++ b/misc/config_tools/configurator/src/assets/schema/scenario.json @@ -0,0 +1,2392 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "required": [ + "acrn-config" + ], + "properties": { + "acrn-config": { + "$ref": "#/definitions/ACRNConfigType" + } + }, + "additionalProperties": true, + "definitions": { + "Boolean": { + "type": "string", + "enum": [ + "y", + "n" + ] + }, + "EnablementType": { + "type": "string", + "enum": [ + "Enable", + "Disable" + ] + }, + "HexFormat": { + "type": "string", + "pattern": "^0[Xx][0-9A-Fa-f]+|0$" + }, + "None": { + "type": "string", + "pattern": "^[*]{0}$" + }, + "BuildType": { + "type": "string", + "enum": [ + "release", + "debug" + ] + }, + "KernLoadAddr": { + "anyOf": [ + { + "title": "None", + "type": "string", + "pattern": "^[*]{0}$" + }, + { + "title": "HexFormat", + "type": "string", + "pattern": "^0[Xx][0-9A-Fa-f]+|0$" + } + ] + }, + "KernEntryAddr": { + "anyOf": [ + { + "title": "None", + "type": "string", + "pattern": "^[*]{0}$" + }, + { + "title": "HexFormat", + "type": "string", + "pattern": "^0[Xx][0-9A-Fa-f]+|0$" + } + ] + }, + "MaxMsixTableNumType": { + "type": "integer", + "minimum": 1, + "maximum": 2048 + }, + "MaxMsixTableSizeType": { + "anyOf": [ + { + "title": "None", + "type": "string", + "pattern": "^[*]{0}$" + }, + { + "title": "MaxMsixTableNumType", + "type": "integer", + "minimum": 1, + "maximum": 2048 + } + ] + }, + "MemorySizeType": { + "anyOf": [ + { + "title": "HexFormat", + "type": "string", + "pattern": "^0[Xx][0-9A-Fa-f]+|0$" + } + ] + }, + "LogLevelType": { + "type": "string", + "enum": [ + "0", + "1", + "2", + "3", + "4", + "5" + ], + "enumNames": [ + "0: None", + "1: Critical", + "2: Error", + "3: Warning", + "4: Information", + "5: Debug" + ] + }, + "SchedulerType": { + "type": "string", + "enum": [ + "SCHED_NOOP", + "SCHED_IORR", + "SCHED_BVT", + "SCHED_PRIO" + ] + }, + "PriorityType": { + "type": "string", + "enum": [ + "PRIO_LOW", + "PRIO_HIGH" + ] + }, + "SerialConsoleType": { + "type": "string", + "pattern": "^.*ttyS[\\d]+$" + }, + "SerialConsoleOptions": { + "anyOf": [ + { + "title": "None", + "type": "string", + "pattern": "^[*]{0}$" + }, + { + "title": "SerialConsoleType", + "type": "string", + "pattern": "^.*ttyS[\\d]+$" + } + ] + }, + "VMNameType": { + "type": "string", + "pattern": "^([a-zA-Z0-9_\\-]){1,15}$" + }, + "VBDFType": { + "type": "string", + "pattern": "^[0-9A-Fa-f]{1,2}:[0-1][0-9A-Fa-f].[0-7]$" + }, + "ProviderType": { + "type": "string", + "enum": [ + "Hypervisor", + "Device Model" + ] + }, + "IVSHMEMSize": { + "type": "integer", + "enum": [ + 2, + 4, + 8, + 16, + 32, + 64, + 128, + 256, + 512 + ] + }, + "LoadOrderType": { + "type": "string", + "enum": [ + "SERVICE_VM", + "PRE_LAUNCHED_VM", + "POST_LAUNCHED_VM" + ] + }, + "VMType": { + "type": "string", + "enum": [ + "RTVM", + "STANDARD_VM", + "TEE_VM", + "REE_VM" + ] + }, + "VMKernelType": { + "type": "string", + "enum": [ + "KERNEL_BZIMAGE", + "KERNEL_RAWIMAGE", + "KERNEL_ELF" + ] + }, + "ConsoleVuartConfiguration": { + "type": "string", + "enum": [ + "None", + "COM Port 1", + "COM Port 2", + "COM Port 3", + "COM Port 4", + "PCI" + ] + }, + "VuartType": { + "type": "string", + "enum": [ + "legacy", + "pci" + ] + }, + "OSType": { + "type": "string", + "enum": [ + "Non-Windows OS", + "Windows OS" + ] + }, + "BasicVMType": { + "type": "string", + "enum": [ + "RTVM", + "STANDARD_VM" + ] + }, + "IVSHMEMVM": { + "type": "object", + "required": [ + "VM_NAME", + "VBDF" + ], + "properties": { + "VM_NAME": { + "$ref": "#/definitions/VMNameType", + "title": "Shared VMS", + "description": "
\n

\n Name of the VM which use this IVSHMEM.\n

\n
\n" + }, + "VBDF": { + "$ref": "#/definitions/VBDFType", + "title": "VBDF", + "description": "
\n

\n Bus, Device and function of the virtual\ndevice in VM . Set in hex.\n

\n
\n" + } + } + }, + "IVSHMEMVMS": { + "type": "object", + "required": [ + "IVSHMEM_VM" + ], + "properties": { + "IVSHMEM_VM": { + "items": { + "$ref": "#/definitions/IVSHMEMVM" + }, + "type": "array", + "title": "IVSHMEM_VM", + "description": "
\n

\n Set each VM which use this IVSHMEM.\n

\n
\n" + } + } + }, + "IVSHMEMRegionType": { + "type": "object", + "required": [ + "NAME", + "PROVIDED_BY", + "IVSHMEM_SIZE", + "IVSHMEM_VMS" + ], + "properties": { + "NAME": { + "type": "string", + "pattern": "^\\w+$", + "title": "Name", + "description": "
\n

\n Name of the shared memory region.\n

\n
\n" + }, + "PROVIDED_BY": { + "$ref": "#/definitions/ProviderType", + "default": "Hypervisor", + "title": "Emulated by", + "description": "
\n

\n Whether the shared memory region is emulated by the hypervisor or Device Model.\n

\n
\n" + }, + "IVSHMEM_SIZE": { + "$ref": "#/definitions/IVSHMEMSize", + "default": 2, + "title": "Size (MB)", + "description": "
\n

\n Select the size of the shared memory region\nin megabytes. The value should be a power of 2\nand no more than 512.\n

\n
\n" + }, + "IVSHMEM_VMS": { + "$ref": "#/definitions/IVSHMEMVMS", + "title": "Shared VMs", + "description": "
\n

\n Select all VMs that use the shared memory region.\n

\n
\n" + } + } + }, + "IVSHMEMInfo": { + "type": "object", + "properties": { + "IVSHMEM_REGION": { + "items": { + "$ref": "#/definitions/IVSHMEMRegionType" + }, + "type": "array", + "title": "IVSHMEM_REGION", + "description": "
\n

\n Set a inter-VM shared memory.\n

\n
\n" + } + } + }, + "RDTType": { + "type": "object", + "required": [ + "RDT_ENABLED", + "CDP_ENABLED", + "VCAT_ENABLED" + ], + "properties": { + "RDT_ENABLED": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Intel Resource Director Technology", + "description": "
\n

\n Enable the Intel Resource Director Technology (RDT)\nallocation feature. If the board hardware does not support\nRDT, setting this option to\n \n y\n \n is ignored.\n

\n
\n" + }, + "CDP_ENABLED": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Code and Data Prioritization", + "description": "
\n

\n Enable Code and Data Prioritization (CDP). CDP provides control over code and data placement in cache to improve an application's real-time performance.\n

\n
\n" + }, + "VCAT_ENABLED": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "VCAT_ENABLED", + "description": "
\n

\n Enable virtualization of the Cache Allocation Technology (CAT) feature in RDT. CAT enables you to allocate cache to VMs, providing isolation to avoid performance interference from other VMs.\n

\n
\n" + }, + "CLOS_MASK": { + "type": "array", + "items": { + "type": "string" + }, + "title": "CLOS_MASK", + "description": "
\n

\n Specify the cache capacity bitmask for the CLOS; only continuous '1' bits\nare allowed. The value will be ignored when hardware does not support RDT.\nThis option takes effect only if\n \n hv.FEATURES.RDT.RDT_ENABLED\n \n is set to\n \n y\n \n .\nAs\n \n vm.clos.vcpu_clos\n \n specifies the index of the CLOS to be associated with the given vCPU,\n \n hv.FEATURES.RDT.CLOS_MASK\n \n of that CLOS would impact the performance of the given vCPU.\n

\n
\n" + }, + "MBA_DELAY": { + "type": "array", + "items": { + "type": "string" + }, + "title": "MBA_DELAY", + "description": "
\n

\n Memory Bandwidth Allocation delay value.\n

\n
\n" + } + } + }, + "SSRAMInfo": { + "type": "object", + "required": [ + "SSRAM_ENABLED" + ], + "properties": { + "SSRAM_ENABLED": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Software SRAM (for real-time apps)", + "description": "
\n

\n Enable Software SRAM. This feature reserves memory buffers as always-cached memory to improve an application's real-time performance.\n

\n
\n" + } + } + }, + "CPUAffinityConfiguration": { + "type": "object", + "required": [ + "pcpu_id" + ], + "properties": { + "pcpu_id": { + "type": "array", + "items": { + "type": "integer", + "default": 2 + }, + "title": "pcpu_id", + "description": "
\n

\n A pCPU that this VM's vCPU is allowed to pin\nto.\n

\n
\n" + } + } + }, + "CLOSConfiguration": { + "type": "object", + "required": [ + "vcpu_clos" + ], + "properties": { + "vcpu_clos": { + "type": "array", + "items": { + "type": "integer", + "default": 0 + }, + "title": "vcpu_clos", + "description": "
\n

\n By default (\n \n virtual_cat_support\n \n is not specified):\nvcpu_clos is per-CPU and it configures each CPU in VMs to a desired CLOS ID in the\n \n VM\n \n section of the\nscenario file. Follow\n \n RDT Detection and Resource Capabilities\n \n to identify the maximum supported CLOS ID that can be used.\n

\n

\n If\n \n virtual_cat_support\n \n is specified:\nvcpu_clos is not per-CPU anymore, just a list of physical CLOSIDs (minimum 2) that are assigned to VMs\nfor vCAT use. Each vcpu_clos will be mapped to a virtual CLOSID, the first vcpu_clos is mapped to virtual\nCLOSID 0 and the second is mapped to virtual CLOSID 1, etc.\n

\n
\n" + } + } + }, + "EPCSection": { + "type": "object", + "required": [ + "base", + "size" + ], + "properties": { + "base": { + "$ref": "#/definitions/HexFormat", + "default": 0, + "title": "Intel Software Guard Extensions (SGX) EPC section base", + "description": "
\n

\n Specify the enclave page cache (EPC) section base for Intel Software Guard Extensions (SGX). Must be page aligned.\n

\n
\n" + }, + "size": { + "$ref": "#/definitions/HexFormat", + "default": 0, + "title": "Intel Software Guard Extensions (SGX) EPC section size (bytes)", + "description": "
\n

\n Specify the enclave page cache (EPC) section size in bytes for Intel Software Guard Extensions (SGX). Must be page aligned.\n

\n
\n" + } + } + }, + "MemoryInfo": { + "type": "object", + "required": [ + "whole", + "start_hpa" + ], + "properties": { + "whole": { + "type": "integer", + "default": 256, + "title": "VM physical memory allocation (MB)", + "description": "
\n

\n Specify the physical memory allocated to this VM in Megabytes.\n

\n
\n" + }, + "start_hpa": { + "$ref": "#/definitions/HexFormat", + "default": "0x100000000", + "title": "start_hpa", + "description": "
\n

\n The starting physical address in host for the VM.\n

\n
\n" + }, + "size": { + "$ref": "#/definitions/MemorySizeType", + "default": "0x20000000", + "title": "size", + "description": "
\n

\n The memory size in bytes for the VM. Default value is\n \n 0x200000000\n \n .\n

\n
\n" + }, + "start_hpa2": { + "$ref": "#/definitions/HexFormat", + "default": "0x0", + "title": "start_hpa2", + "description": "
\n

\n Start of second HPA for non-contiguous allocations in host for the VM.\n

\n
\n" + }, + "size_hpa2": { + "$ref": "#/definitions/MemorySizeType", + "default": "0x0", + "title": "size_hpa2", + "description": "
\n

\n Memory size of second HPA for non-contiguous allocations in Bytes for the VM.\n

\n
\n" + } + } + }, + "OSConfigurations": { + "type": "object", + "required": [ + "kern_type", + "kern_mod" + ], + "properties": { + "kern_type": { + "$ref": "#/definitions/VMKernelType", + "title": "Kernel image type", + "description": "
\n

\n Select the kernel image type so that the hypervisor can load it correctly.\n

\n
\n" + }, + "kern_mod": { + "type": "string", + "title": "Kernel module tag", + "description": "
\n

\n Specify the tag for the kernel image that is used as a multiboot module. The tag's spelling must exactly match the module tag in the GRUB multiboot cmdline.\n

\n
\n" + }, + "ramdisk_mod": { + "type": "string", + "title": "RAMdisk module tag", + "description": "
\n

\n Specify the tag for the RAMdisk image that is used as a multiboot module. The tag's spelling must exactly match the module tag in the GRUB multiboot cmdline.\n

\n
\n" + }, + "bootargs": { + "type": "string", + "title": "Kernel command-line parameters", + "description": "
\n

\n Specify the command-line parameters that will be used to boot the kernel for this VM. See\n \n Linux documentation\n \n for a list of parameters.\n

\n
\n" + }, + "kern_load_addr": { + "$ref": "#/definitions/KernLoadAddr", + "title": "kern_load_addr", + "description": "
\n

\n The loading address in host memory for the VM kernel.\n

\n
\n" + }, + "kern_entry_addr": { + "$ref": "#/definitions/KernEntryAddr", + "title": "kern_entry_addr", + "description": "
\n

\n The entry address in host memory for the VM kernel.\n

\n
\n" + } + } + }, + "VuartEndpointType": { + "type": "object", + "required": [ + "vm_name", + "io_port" + ], + "properties": { + "vm_name": { + "type": "string", + "title": "Virtual UART port", + "description": "
\n

\n Virtual UART port\n

\n
\n" + }, + "io_port": { + "$ref": "#/definitions/HexFormat", + "default": "0x3F", + "title": "Virtual I/O address", + "description": "
\n

\n Virtual I/O address\n

\n
\n" + }, + "vbdf": { + "items": { + "$ref": "#/definitions/VBDFType" + }, + "type": "array", + "maxItems": 1 + } + } + }, + "VuartConnectionType": { + "type": "object", + "required": [ + "name", + "type", + "endpoint" + ], + "properties": { + "name": { + "type": "string" + }, + "type": { + "$ref": "#/definitions/VuartType", + "default": "legacy" + }, + "endpoint": { + "minItems": 2, + "items": { + "$ref": "#/definitions/VuartEndpointType" + }, + "type": "array", + "maxItems": 2 + } + } + }, + "VuartConnectionsType": { + "type": "object", + "properties": { + "vuart_connection": { + "items": { + "$ref": "#/definitions/VuartConnectionType" + }, + "type": "array" + } + } + }, + "MMIOResourcesConfiguration": { + "type": "object", + "properties": { + "TPM2": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Trusted platform module (TPM2) passthrough", + "description": "
\n

\n Pass through the trusted platform module (TPM2) device to this VM.\n

\n
\n" + }, + "p2sb": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Primary-to-Sideband bridge passthrough", + "description": "
\n

\n Pass through the Primary-to-Sideband (P2SB) bridge register access BAR to this VM.\n

\n
\n" + } + } + }, + "PCIDevsConfiguration": { + "type": "object", + "properties": { + "pci_dev": { + "type": "array", + "items": { + "type": "string" + }, + "title": "PCI device assignment", + "description": "
\n

\n Select the PCI devices you want to assign to this virtual machine.\n

\n
\n", + "enum": { + "type": "dynamicEnum", + "function": "get_enum", + "source": "board_xml", + "selector": "//device[class]/@description", + "sorted": "lambda s: (s.split(' ', maxsplit=1)[-1].split(':')[0], s.split(' ')[0])" + } + } + } + }, + "DebugOptionsType": { + "type": "object", + "required": [ + "BUILD_TYPE", + "SERIAL_CONSOLE", + "MEM_LOGLEVEL", + "NPK_LOGLEVEL", + "CONSOLE_LOGLEVEL" + ], + "properties": { + "BUILD_TYPE": { + "$ref": "#/definitions/BuildType", + "default": "debug", + "title": "Build type", + "description": "
\n

\n Select the build type. Debug mode enables debug shell, prints, and logs. Release mode optimizes the ACRN binary for deployment and turns off all debug infrastructure. These settings can only be changed at build time.\n

\n
\n" + }, + "SERIAL_CONSOLE": { + "$ref": "#/definitions/SerialConsoleOptions", + "title": "Serial console port", + "description": "
\n

\n Select the host serial device used for hypervisor debugging.\n

\n
\n", + "enum": { + "type": "dynamicEnum", + "function": "get_enum", + "source": "board_xml", + "selector": "//ttys/serial[type != '0']/dev_path/text()", + "sorted": null + } + }, + "MEM_LOGLEVEL": { + "$ref": "#/definitions/LogLevelType", + "default": 0, + "title": "ACRN log level", + "description": "
\n

\n Select the default log level for log messages stored in memory. Value can be changed at runtime. Log messages with the selected value or lower are displayed.\n

\n
\n" + }, + "NPK_LOGLEVEL": { + "$ref": "#/definitions/LogLevelType", + "default": 0, + "title": "Intel Trace Hub log level", + "description": "
\n

\n Select the default log level for the hypervisor via Intel Trace Hub log. Use the Intel Trace Hub's memory to record log messages. Value can be changed at runtime. Log messages with the selected value or lower are displayed.\n

\n
\n" + }, + "CONSOLE_LOGLEVEL": { + "$ref": "#/definitions/LogLevelType", + "default": 0, + "title": "Serial console log level", + "description": "
\n

\n Select the default log level for log messages written to the serial console. Log messages with the selected value or lower are displayed.\n

\n
\n" + } + } + }, + "FeatureOptionsType": { + "type": "object", + "required": [ + "RELOC", + "SCHEDULER", + "MULTIBOOT2", + "ENFORCE_TURNOFF_AC", + "ENFORCE_TURNOFF_GP", + "SECURITY_VM_FIXUP", + "KEEP_IRQ_DISABLED", + "RDT", + "HYPERV_ENABLED", + "IOMMU_ENFORCE_SNP", + "ACPI_PARSE_ENABLED", + "L1D_VMENTRY_ENABLED", + "MCE_ON_PSC_DISABLED", + "IVSHMEM" + ], + "properties": { + "RELOC": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Hypervisor relocation in memory", + "description": "
\n

\n Enable hypervisor relocation in memory. The bootloader may need to change the location of the hypervisor because of other firmware.\n

\n
\n" + }, + "SCHEDULER": { + "$ref": "#/definitions/SchedulerType", + "default": "SCHED_BVT", + "title": "Virtual CPU scheduler", + "description": "
\n

\n Select the scheduling algorithm used to determine which User VM runs on a shared virtual CPU.\n

\n
\n" + }, + "MULTIBOOT2": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Multiboot2", + "description": "
\n

\n Enable multiboot2 protocol support and multiboot1 downward compatibility. Disable this feature if multiboot1 meets your requirements and to reduce lines of code.\n

\n
\n" + }, + "ENFORCE_TURNOFF_AC": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Split lock detection", + "description": "
\n

\n Enable detection of split locks, which can negatively affect an application's real-time performance. If a lock is detected, an alignment check exception #AC occurs.\n

\n
\n" + }, + "ENFORCE_TURNOFF_GP": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Uncacheable-memory lock detection", + "description": "
\n

\n Enable detection of uncacheable-memory locks, which can negatively affect an application's real-time performance. If a lock is detected, a general-protection exception #GP occurs.\n

\n
\n" + }, + "SECURITY_VM_FIXUP": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "SECURITY_VM_FIXUP", + "description": "
\n

\n Enable to do fixup for TPM2 and SMBIOS for Security VM. If no Security VM, setting this option to\n \n n\n \n

\n
\n" + }, + "KEEP_IRQ_DISABLED": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "KEEP_IRQ_DISABLED", + "description": "
\n

\n If\n \n y\n \n , permanently disables all interrupts in HV root mode.\n

\n
\n" + }, + "RDT": { + "$ref": "#/definitions/RDTType", + "title": "Intel Resource Director Technology (RDT)", + "description": "
\n

\n Intel Resource Director Technology (RDT) provides cache and memory bandwidth allocation features. The features can be used to improve an application's real-time performance.\n

\n
\n" + }, + "HYPERV_ENABLED": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Hyper-V virtualization technology", + "description": "
\n

\n Enable Microsoft Hyper-V Hypervisor Top-Level Functional Specification (TFLS) for Windows User VMs.\n

\n
\n" + }, + "IOMMU_ENFORCE_SNP": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "IOMMU_ENFORCE_SNP", + "description": "
\n

\n Specify if the IOMMU enforces snoop behavior of DMA operations.\n

\n
\n" + }, + "ACPI_PARSE_ENABLED": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Parse ACPI tables at runtime", + "description": "
\n

\n Enable ACPI runtime parsing to get DMAR (DMA remapping) configuration data from the APCI tables. Otherwise, use existing, static information from the associated board configuration file.\n

\n
\n" + }, + "L1D_VMENTRY_ENABLED": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Mitigate L1 terminal fault", + "description": "
\n

\n Enable L1 cache flush before VM entry to prevent L1 terminal fault. L1 terminal fault is a hardware vulnerability that allows unauthorized disclosure of information residing in the L1 data cache.\n

\n
\n" + }, + "MCE_ON_PSC_DISABLED": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Machine Check Error (MCE) workaround", + "description": "
\n

\n Enable the software workaround for Machine Check Error on Page Size Change (hardware bug in some processor families).\n

\n
\n" + }, + "IVSHMEM": { + "$ref": "#/definitions/IVSHMEMInfo", + "title": "Inter-VM shared memory", + "description": "" + }, + "SSRAM": { + "$ref": "#/definitions/SSRAMInfo", + "title": "Software SRAM (for real-time apps)", + "description": "" + } + } + }, + "MemoryOptionsType": { + "type": "object", + "required": [ + "STACK_SIZE", + "HV_RAM_START" + ], + "properties": { + "STACK_SIZE": { + "$ref": "#/definitions/HexFormat", + "default": "0x2000", + "title": "CPU memory stack size (bytes per CPU)", + "description": "
\n

\n Specify the size of the memory stack in bytes for each physical CPU. For example, if you specify 8 kilobytes, each CPU will get its own 8-kilobyte stack.\n

\n
\n" + }, + "HV_RAM_START": { + "$ref": "#/definitions/HexFormat", + "default": "0x00400000", + "title": "HV_RAM_START", + "description": "
\n

\n The 2MB-aligned starting physical address of the RAM region used by the hypervisor.\n

\n
\n" + } + } + }, + "CapacitiesOptionsType": { + "type": "object", + "required": [ + "MAX_VM_NUM", + "MAX_IOAPIC_NUM", + "MAX_PCI_DEV_NUM", + "MAX_IOAPIC_LINES", + "MAX_PT_IRQ_ENTRIES", + "MAX_MSIX_TABLE_NUM", + "MAX_EMULATED_MMIO" + ], + "properties": { + "MAX_VM_NUM": { + "type": "integer", + "default": 16, + "title": "MAX_VM_NUM", + "description": "
\n

\n Maximum number of User VMs allowed.\n

\n
\n" + }, + "MAX_IOAPIC_NUM": { + "type": "integer", + "minimum": 1, + "maximum": 10, + "default": 1, + "title": "MAX_IOAPIC_NUM", + "description": "
\n

\n Maximum number of IOAPICs.\n

\n
\n" + }, + "MAX_PCI_DEV_NUM": { + "type": "integer", + "minimum": 1, + "maximum": 1024, + "default": 96, + "title": "Maximum number of PCI devices", + "description": "
\n

\n Specify the maximum number of PCI devices. This impacts the amount of memory used to maintain information about these PCI devices. The default value is calculated from the board configuration file. If you have PCI devices that were not detected by the Board Inspector, you may need to change this maximum value.\n

\n
\n" + }, + "MAX_IOAPIC_LINES": { + "type": "integer", + "minimum": 1, + "maximum": 120, + "default": 120, + "title": "MAX_IOAPIC_LINES", + "description": "
\n

\n Maximum number of interrupt lines per IOAPIC.\n

\n
\n" + }, + "MAX_PT_IRQ_ENTRIES": { + "type": "integer", + "default": 256, + "title": "Maximum number of IRQ entries for passthrough devices", + "description": "
\n

\n Specify the maximum number of interrupt request (IRQ) entries from all passthrough devices.\n

\n
\n" + }, + "MAX_MSIX_TABLE_NUM": { + "type": "integer", + "minimum": 1, + "maximum": 2048, + "default": 64, + "title": "Maximum number of MSI-X tables per device", + "description": "
\n

\n Specify the maximum number of Message Signaled Interrupt MSI-X tables per device. The default value is calculated from the board configuration file.\n

\n
\n" + }, + "MAX_EMULATED_MMIO": { + "type": "integer", + "minimum": 1, + "maximum": 128, + "default": 16, + "title": "Maximum number of emulated MMIO regions", + "description": "
\n

\n Specify the maximum number of emulated MMIO regions for device virtualization. The default value is calculated from the board configuration file.\n

\n
\n" + } + } + }, + "MiscCfgOptionsType": { + "type": "object", + "required": [ + "GPU_SBDF" + ], + "properties": { + "GPU_SBDF": { + "$ref": "#/definitions/HexFormat", + "default": "0x00000010", + "title": "GPU_SBDF", + "description": "
\n

\n Segment, Bus, Device, and function of the GPU.\n

\n
\n" + } + } + }, + "HVConfigType": { + "type": "object", + "required": [ + "DEBUG_OPTIONS", + "FEATURES", + "MEMORY", + "CAPACITIES", + "MISC_CFG", + "vuart_connections" + ], + "properties": { + "DEBUG_OPTIONS": { + "$ref": "#/definitions/DebugOptionsType", + "title": "Debug options", + "description": "
\n

\n Configure the debug facilities.\n

\n
\n" + }, + "FEATURES": { + "$ref": "#/definitions/FeatureOptionsType", + "title": "Hypervisor features", + "description": "
\n

\n Enable hypervisor features.\n

\n
\n" + }, + "MEMORY": { + "$ref": "#/definitions/MemoryOptionsType", + "title": "Memory options", + "description": "
\n

\n Configure memory used by the hypervisor.\n

\n
\n" + }, + "CAPACITIES": { + "$ref": "#/definitions/CapacitiesOptionsType", + "title": "Hypervisor capacities", + "description": "
\n

\n Configure the capacities of the hypervisor.\n

\n
\n" + }, + "MISC_CFG": { + "$ref": "#/definitions/MiscCfgOptionsType", + "title": "MISC_CFG", + "description": "
\n

\n Miscellaneous options for workarounds.\n

\n
\n" + }, + "vuart_connections": { + "$ref": "#/definitions/VuartConnectionsType", + "title": "Virtual UART connection", + "description": "
\n

\n Specify the vUART connection settings.\nRefer to\n \n Enable vUART Configurations\n \n for detailed vUART settings.\n

\n
\n" + } + } + }, + "VMConfigType": { + "type": "object", + "required": [ + "load_order", + "vm_type", + "name", + "clos", + "memory", + "priority", + "companion_vmid", + "console_vuart", + "os_type", + "vbootloader", + "vuart0", + "virtio_devices" + ], + "properties": { + "load_order": { + "$ref": "#/definitions/LoadOrderType", + "title": "Load order", + "description": "
\n

\n Specify the load_order.\n

\n
\n" + }, + "vm_type": { + "$ref": "#/definitions/VMType", + "title": "VM type", + "description": "
\n

\n Select the VM type. A standard VM (\n \n STANDARD_VM\n \n ) is for general-purpose applications, such as human-machine interface (HMI). A real-time VM (\n \n RTVM\n \n ) offers special features for time-sensitive applications.\n

\n
\n" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 15, + "pattern": "^\\S+$", + "title": "VM name", + "description": "
\n

\n Specify the name used to identify this VM. The VM name will be shown in the hypervisor console vm_list command.\n

\n
\n" + }, + "lapic_passthrough": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "LAPIC passthrough", + "description": "
\n

\n Enable LAPIC passthrough for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "io_completion_polling": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "I/O completion polling", + "description": "
\n

\n Enable polling mode for I/O completion for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "nested_virtualization_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Nested virtualization", + "description": "
\n

\n Enable nested virtualization for KVM.\n

\n
\n" + }, + "virtual_cat_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Virtual Cache Allocation Technology (vCAT)", + "description": "
\n

\n Enable virtualization of the Cache Allocation Technology (CAT) feature in RDT. CAT enables you to allocate cache to VMs, providing isolation to avoid performance interference from other VMs.\n

\n
\n" + }, + "secure_world_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "secure_world_support", + "description": "
\n

\n Specify secure world support for trustry OS.\n

\n
\n" + }, + "hide_mtrr_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "hide_mtrr_support", + "description": "
\n

\n Specify MTRR capability to hide for VM.\n

\n
\n" + }, + "security_vm": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "security_vm", + "description": "
\n

\n Specify TPM2 FIXUP for VM.\n

\n
\n" + }, + "cpu_affinity": { + "$ref": "#/definitions/CPUAffinityConfiguration", + "title": "Physical CPU affinity", + "description": "
\n

\n Select a subset of physical CPUs that this VM can use. More than one can be selected.\n

\n
\n" + }, + "clos": { + "$ref": "#/definitions/CLOSConfiguration", + "title": "clos", + "description": "
\n

\n Class of Service for Cache Allocation Technology.\nRefer SDM 17.19.2 for details, and use with caution.\n

\n
\n" + }, + "epc_section": { + "$ref": "#/definitions/EPCSection", + "title": "epc_section", + "description": "
\n

\n Specify the Intel Software Guard Extensions (SGX) enclave page cache (EPC) section settings.\n

\n
\n" + }, + "memory": { + "$ref": "#/definitions/MemoryInfo", + "title": "memory", + "description": "
\n

\n Specify memory information for Service and User VMs.\n

\n
\n" + }, + "priority": { + "$ref": "#/definitions/PriorityType", + "default": "PRIO_LOW", + "title": "priority", + "description": "
\n

\n Specify the VM vCPU priority for scheduling.\n

\n
\n" + }, + "companion_vmid": { + "type": "integer", + "default": 65535, + "title": "companion_vmid", + "description": "
\n

\n Specify the companion VM id of this VM.\n

\n
\n" + }, + "os_config": { + "$ref": "#/definitions/OSConfigurations", + "title": "os_config", + "description": "
\n

\n General information for host kernel, boot\nargument and memory.\n

\n
\n" + }, + "console_vuart": { + "$ref": "#/definitions/ConsoleVuartConfiguration", + "default": "None", + "title": "Console virtual UART type", + "description": "
\n

\n Select the console virtual UART (vUART) type. Add the console settings to the kernel command line by typing them in the \"Linux kernel command-line parameters\" text box (for example, console=ttyS0 for COM port 1).\n

\n
\n" + }, + "mmio_resources": { + "$ref": "#/definitions/MMIOResourcesConfiguration", + "title": "mmio_resources", + "description": "
\n

\n MMIO resources to passthrough.\n

\n
\n" + }, + "pt_intx": { + "type": "string", + "title": "pt_intx", + "description": "
\n

\n Specify the pre-launched VM owned IOAPIC pins and the corresponding mapping between physical GSI and virtual GSI.\n

\n
\n" + }, + "pci_devs": { + "$ref": "#/definitions/PCIDevsConfiguration", + "title": "PCI device assignment", + "description": "" + }, + "PTM": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Precision Time Measurement", + "description": "
\n

\n Enable virtualization of PCIe Precision Time Measurement (PTM) mechanism for devices with PTM capability and for real-time application. The hypervisor provides PCIe root port emulation instead of host bridge emulation for the VM. PTM coordinates timing between the device and root port with the device's local timebases without relying on software.\n

\n
\n" + }, + "os_type": { + "$ref": "#/definitions/OSType", + "default": "Non-Windows OS", + "title": "OS type", + "description": "
\n

\n Select the OS type for this VM. This is required to run Windows in a User VM. See\n \n Device Model Parameters\n \n for how to include this in the Device Model arguments.\n

\n
\n" + }, + "vbootloader": { + "$ref": "#/definitions/EnablementType", + "default": "Enable", + "title": "OVMF (Open Virtual Machine Firmware)", + "description": "
\n

\n Use virtual bootloader OVMF (Open Virtual Machine Firmware) to boot this VM.\n

\n
\n" + }, + "vuart0": { + "$ref": "#/definitions/EnablementType", + "default": "Enable", + "title": "Emulate COM1 as stdio I/O in Device Model", + "description": "
\n

\n Enable the ACRN Device Model to emulate COM1 as a User VM stdio I/O. Hypervisor global emulation will take priority over this VM setting.\n

\n
\n" + }, + "usb_xhci": { + "type": "string", + "pattern": "^([\\d]+-[\\d]+){0,1}(:[\\d]+-[\\d]+)*$", + "title": "Virtual USB host controller interface", + "description": "
\n

\n Select the USB physical bus and port number that will be emulated by the ACRN Device Model for this VM. USB 3.0, 2.0, and 1.0 are supported.\n

\n
\n" + }, + "virtio_devices": { + "type": "object", + "properties": { + "console": { + "type": "string", + "title": "console", + "description": "
\n
\n
\n The virtio console device setting.Input format:\n
\n
\n

\n \n \n [@]stdio|tty|pty|sock:portname[=portpath][,[@]stdio|tty|pty:portname[=portpath]]\n \n \n

\n
\n
\n
\n" + }, + "network": { + "type": "string", + "title": "network", + "description": "
\n
\n
\n The virtio network device setting.\n
\n
\n

\n Input format:\n \n \n device_name[,vhost][,mac=XX:XX:XX:XX:XX:XX]\n \n \n .\nThe\n \n device_name\n \n is the name of the TAP (or MacVTap) device.\nIt must include the keyword\n \n tap\n \n .\n \n vhost\n \n specifies the\nvhost backend; otherwise, the VBSU backend is used. The\n \n mac\n \n address is optional.\n

\n
\n
\n
\n" + }, + "input": { + "type": "string", + "title": "input", + "description": "
\n

\n The virtio input device setting.\n

\n
\n" + }, + "block": { + "type": "string", + "title": "block", + "description": "
\n
\n
\n The virtio block device setting.\n
\n
\n

\n Format: [blk partition:][img path] e.g.: /dev/sda3:./a/b.img\n

\n
\n
\n
\n" + } + }, + "title": "Virt-IO devices", + "description": "
\n

\n Enable virt-IO devices in post-launched VMs.\n

\n
\n" + } + } + }, + "ACRNConfigType": { + "type": "object", + "required": [ + "hv" + ], + "properties": { + "hv": { + "$ref": "#/definitions/HVConfigType", + "title": "hv", + "description": "
\n

\n The hypervisor configuration defines a working scenario and target\nboard by configuring the hypervisor image features and capabilities such as\nsetting up the log and the serial port.\n

\n
\n" + } + } + }, + "PreLaunchedMemoryInfo": { + "type": "object", + "required": [ + "start_hpa" + ], + "properties": { + "start_hpa": { + "$ref": "#/definitions/HexFormat", + "default": "0x100000000", + "title": "start_hpa", + "description": "
\n

\n The starting physical address in host for the VM.\n

\n
\n" + }, + "size": { + "$ref": "#/definitions/MemorySizeType", + "default": "0x20000000", + "title": "size", + "description": "
\n

\n The memory size in bytes for the VM. Default value is\n \n 0x200000000\n \n .\n

\n
\n" + }, + "start_hpa2": { + "$ref": "#/definitions/HexFormat", + "default": "0x0", + "title": "start_hpa2", + "description": "
\n

\n Start of second HPA for non-contiguous allocations in host for the VM.\n

\n
\n" + }, + "size_hpa2": { + "$ref": "#/definitions/MemorySizeType", + "default": "0x0", + "title": "size_hpa2", + "description": "
\n

\n Memory size of second HPA for non-contiguous allocations in Bytes for the VM.\n

\n
\n" + } + } + }, + "PreLaunchedVMConfigType": { + "type": "object", + "required": [ + "load_order", + "vm_type", + "name", + "clos", + "memory", + "priority", + "companion_vmid", + "console_vuart" + ], + "properties": { + "load_order": { + "$ref": "#/definitions/LoadOrderType", + "title": "Load order", + "description": "
\n

\n Specify the load_order.\n

\n
\n" + }, + "vm_type": { + "$ref": "#/definitions/VMType", + "title": "VM type", + "description": "
\n

\n Select the VM type. A standard VM (\n \n STANDARD_VM\n \n ) is for general-purpose applications, such as human-machine interface (HMI). A real-time VM (\n \n RTVM\n \n ) offers special features for time-sensitive applications.\n

\n
\n" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 15, + "pattern": "^\\S+$", + "title": "VM name", + "description": "
\n

\n Specify the name used to identify this VM. The VM name will be shown in the hypervisor console vm_list command.\n

\n
\n" + }, + "lapic_passthrough": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "LAPIC passthrough", + "description": "
\n

\n Enable LAPIC passthrough for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "io_completion_polling": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "I/O completion polling", + "description": "
\n

\n Enable polling mode for I/O completion for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "nested_virtualization_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Nested virtualization", + "description": "
\n

\n Enable nested virtualization for KVM.\n

\n
\n" + }, + "virtual_cat_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Virtual Cache Allocation Technology (vCAT)", + "description": "
\n

\n Enable virtualization of the Cache Allocation Technology (CAT) feature in RDT. CAT enables you to allocate cache to VMs, providing isolation to avoid performance interference from other VMs.\n

\n
\n" + }, + "secure_world_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "secure_world_support", + "description": "
\n

\n Specify secure world support for trustry OS.\n

\n
\n" + }, + "hide_mtrr_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "hide_mtrr_support", + "description": "
\n

\n Specify MTRR capability to hide for VM.\n

\n
\n" + }, + "security_vm": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "security_vm", + "description": "
\n

\n Specify TPM2 FIXUP for VM.\n

\n
\n" + }, + "cpu_affinity": { + "$ref": "#/definitions/CPUAffinityConfiguration", + "title": "Physical CPU affinity", + "description": "
\n

\n Select a subset of physical CPUs that this VM can use. More than one can be selected.\n

\n
\n" + }, + "clos": { + "$ref": "#/definitions/CLOSConfiguration", + "title": "clos", + "description": "
\n

\n Class of Service for Cache Allocation Technology.\nRefer SDM 17.19.2 for details, and use with caution.\n

\n
\n" + }, + "epc_section": { + "$ref": "#/definitions/EPCSection", + "title": "epc_section", + "description": "
\n

\n Specify the Intel Software Guard Extensions (SGX) enclave page cache (EPC) section settings.\n

\n
\n" + }, + "memory": { + "$ref": "#/definitions/PreLaunchedMemoryInfo", + "title": "memory", + "description": "
\n

\n Specify memory information for Service and User VMs.\n

\n
\n" + }, + "priority": { + "$ref": "#/definitions/PriorityType", + "default": "PRIO_LOW", + "title": "priority", + "description": "
\n

\n Specify the VM vCPU priority for scheduling.\n

\n
\n" + }, + "companion_vmid": { + "type": "integer", + "default": 65535, + "title": "companion_vmid", + "description": "
\n

\n Specify the companion VM id of this VM.\n

\n
\n" + }, + "os_config": { + "$ref": "#/definitions/OSConfigurations", + "title": "os_config", + "description": "
\n

\n General information for host kernel, boot\nargument and memory.\n

\n
\n" + }, + "console_vuart": { + "$ref": "#/definitions/ConsoleVuartConfiguration", + "default": "None", + "title": "Console virtual UART type", + "description": "
\n

\n Select the console virtual UART (vUART) type. Add the console settings to the kernel command line by typing them in the \"Linux kernel command-line parameters\" text box (for example, console=ttyS0 for COM port 1).\n

\n
\n" + }, + "mmio_resources": { + "$ref": "#/definitions/MMIOResourcesConfiguration", + "title": "mmio_resources", + "description": "
\n

\n MMIO resources to passthrough.\n

\n
\n" + }, + "pt_intx": { + "type": "string", + "title": "pt_intx", + "description": "
\n

\n Specify the pre-launched VM owned IOAPIC pins and the corresponding mapping between physical GSI and virtual GSI.\n

\n
\n" + }, + "pci_devs": { + "$ref": "#/definitions/PCIDevsConfiguration", + "title": "PCI device assignment", + "description": "" + }, + "PTM": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Precision Time Measurement", + "description": "
\n

\n Enable virtualization of PCIe Precision Time Measurement (PTM) mechanism for devices with PTM capability and for real-time application. The hypervisor provides PCIe root port emulation instead of host bridge emulation for the VM. PTM coordinates timing between the device and root port with the device's local timebases without relying on software.\n

\n
\n" + } + } + }, + "ServiceMemoryInfo": { + "type": "object", + "required": [ + "start_hpa" + ], + "properties": { + "start_hpa": { + "$ref": "#/definitions/HexFormat", + "default": "0x100000000", + "title": "start_hpa", + "description": "
\n

\n The starting physical address in host for the VM.\n

\n
\n" + }, + "size": { + "$ref": "#/definitions/MemorySizeType", + "default": "0x20000000", + "title": "size", + "description": "
\n

\n The memory size in bytes for the VM. Default value is\n \n 0x200000000\n \n .\n

\n
\n" + }, + "start_hpa2": { + "$ref": "#/definitions/HexFormat", + "default": "0x0", + "title": "start_hpa2", + "description": "
\n

\n Start of second HPA for non-contiguous allocations in host for the VM.\n

\n
\n" + }, + "size_hpa2": { + "$ref": "#/definitions/MemorySizeType", + "default": "0x0", + "title": "size_hpa2", + "description": "
\n

\n Memory size of second HPA for non-contiguous allocations in Bytes for the VM.\n

\n
\n" + } + } + }, + "ServiceVMConfigType": { + "type": "object", + "required": [ + "load_order", + "vm_type", + "name", + "clos", + "memory", + "priority", + "companion_vmid", + "console_vuart" + ], + "properties": { + "load_order": { + "$ref": "#/definitions/LoadOrderType", + "title": "Load order", + "description": "
\n

\n Specify the load_order.\n

\n
\n" + }, + "vm_type": { + "$ref": "#/definitions/VMType", + "title": "VM type", + "description": "
\n

\n Select the VM type. A standard VM (\n \n STANDARD_VM\n \n ) is for general-purpose applications, such as human-machine interface (HMI). A real-time VM (\n \n RTVM\n \n ) offers special features for time-sensitive applications.\n

\n
\n" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 15, + "pattern": "^\\S+$", + "title": "VM name", + "description": "
\n

\n Specify the name used to identify this VM. The VM name will be shown in the hypervisor console vm_list command.\n

\n
\n" + }, + "lapic_passthrough": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "LAPIC passthrough", + "description": "
\n

\n Enable LAPIC passthrough for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "io_completion_polling": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "I/O completion polling", + "description": "
\n

\n Enable polling mode for I/O completion for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "nested_virtualization_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Nested virtualization", + "description": "
\n

\n Enable nested virtualization for KVM.\n

\n
\n" + }, + "virtual_cat_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Virtual Cache Allocation Technology (vCAT)", + "description": "
\n

\n Enable virtualization of the Cache Allocation Technology (CAT) feature in RDT. CAT enables you to allocate cache to VMs, providing isolation to avoid performance interference from other VMs.\n

\n
\n" + }, + "secure_world_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "secure_world_support", + "description": "
\n

\n Specify secure world support for trustry OS.\n

\n
\n" + }, + "hide_mtrr_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "hide_mtrr_support", + "description": "
\n

\n Specify MTRR capability to hide for VM.\n

\n
\n" + }, + "security_vm": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "security_vm", + "description": "
\n

\n Specify TPM2 FIXUP for VM.\n

\n
\n" + }, + "cpu_affinity": { + "$ref": "#/definitions/CPUAffinityConfiguration", + "title": "Physical CPU affinity", + "description": "
\n

\n Select a subset of physical CPUs that this VM can use. More than one can be selected.\n

\n
\n" + }, + "clos": { + "$ref": "#/definitions/CLOSConfiguration", + "title": "clos", + "description": "
\n

\n Class of Service for Cache Allocation Technology.\nRefer SDM 17.19.2 for details, and use with caution.\n

\n
\n" + }, + "memory": { + "$ref": "#/definitions/ServiceMemoryInfo", + "title": "memory", + "description": "
\n

\n Specify memory information for Service and User VMs.\n

\n
\n" + }, + "priority": { + "$ref": "#/definitions/PriorityType", + "default": "PRIO_LOW", + "title": "priority", + "description": "
\n

\n Specify the VM vCPU priority for scheduling.\n

\n
\n" + }, + "companion_vmid": { + "type": "integer", + "default": 65535, + "title": "companion_vmid", + "description": "
\n

\n Specify the companion VM id of this VM.\n

\n
\n" + }, + "os_config": { + "$ref": "#/definitions/OSConfigurations", + "title": "os_config", + "description": "
\n

\n General information for host kernel, boot\nargument and memory.\n

\n
\n" + }, + "console_vuart": { + "$ref": "#/definitions/ConsoleVuartConfiguration", + "default": "None", + "title": "Console virtual UART type", + "description": "
\n

\n Select the console virtual UART (vUART) type. Add the console settings to the kernel command line by typing them in the \"Linux kernel command-line parameters\" text box (for example, console=ttyS0 for COM port 1).\n

\n
\n" + } + } + }, + "PostLaunchedMemoryInfo": { + "type": "object", + "required": [ + "whole" + ], + "properties": { + "whole": { + "type": "integer", + "default": 256, + "title": "VM physical memory allocation (MB)", + "description": "
\n

\n Specify the physical memory allocated to this VM in Megabytes.\n

\n
\n" + } + } + }, + "PostLaunchedMMIOResourcesConfiguration": { + "type": "object", + "properties": { + "TPM2": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Trusted platform module (TPM2) passthrough", + "description": "
\n

\n Pass through the trusted platform module (TPM2) device to this VM.\n

\n
\n" + } + } + }, + "PostLaunchedVMConfigType": { + "type": "object", + "required": [ + "load_order", + "vm_type", + "name", + "clos", + "memory", + "priority", + "companion_vmid", + "console_vuart", + "os_type", + "vbootloader", + "vuart0", + "virtio_devices" + ], + "properties": { + "load_order": { + "$ref": "#/definitions/LoadOrderType", + "title": "Load order", + "description": "
\n

\n Specify the load_order.\n

\n
\n" + }, + "vm_type": { + "$ref": "#/definitions/VMType", + "title": "VM type", + "description": "
\n

\n Select the VM type. A standard VM (\n \n STANDARD_VM\n \n ) is for general-purpose applications, such as human-machine interface (HMI). A real-time VM (\n \n RTVM\n \n ) offers special features for time-sensitive applications.\n

\n
\n" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 15, + "pattern": "^\\S+$", + "title": "VM name", + "description": "
\n

\n Specify the name used to identify this VM. The VM name will be shown in the hypervisor console vm_list command.\n

\n
\n" + }, + "lapic_passthrough": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "LAPIC passthrough", + "description": "
\n

\n Enable LAPIC passthrough for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "io_completion_polling": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "I/O completion polling", + "description": "
\n

\n Enable polling mode for I/O completion for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "nested_virtualization_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Nested virtualization", + "description": "
\n

\n Enable nested virtualization for KVM.\n

\n
\n" + }, + "virtual_cat_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Virtual Cache Allocation Technology (vCAT)", + "description": "
\n

\n Enable virtualization of the Cache Allocation Technology (CAT) feature in RDT. CAT enables you to allocate cache to VMs, providing isolation to avoid performance interference from other VMs.\n

\n
\n" + }, + "secure_world_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "secure_world_support", + "description": "
\n

\n Specify secure world support for trustry OS.\n

\n
\n" + }, + "hide_mtrr_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "hide_mtrr_support", + "description": "
\n

\n Specify MTRR capability to hide for VM.\n

\n
\n" + }, + "security_vm": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "security_vm", + "description": "
\n

\n Specify TPM2 FIXUP for VM.\n

\n
\n" + }, + "cpu_affinity": { + "$ref": "#/definitions/CPUAffinityConfiguration", + "title": "Physical CPU affinity", + "description": "
\n

\n Select a subset of physical CPUs that this VM can use. More than one can be selected.\n

\n
\n" + }, + "clos": { + "$ref": "#/definitions/CLOSConfiguration", + "title": "clos", + "description": "
\n

\n Class of Service for Cache Allocation Technology.\nRefer SDM 17.19.2 for details, and use with caution.\n

\n
\n" + }, + "memory": { + "$ref": "#/definitions/PostLaunchedMemoryInfo", + "title": "memory", + "description": "
\n

\n Specify memory information for Service and User VMs.\n

\n
\n" + }, + "priority": { + "$ref": "#/definitions/PriorityType", + "default": "PRIO_LOW", + "title": "priority", + "description": "
\n

\n Specify the VM vCPU priority for scheduling.\n

\n
\n" + }, + "companion_vmid": { + "type": "integer", + "default": 65535, + "title": "companion_vmid", + "description": "
\n

\n Specify the companion VM id of this VM.\n

\n
\n" + }, + "console_vuart": { + "$ref": "#/definitions/ConsoleVuartConfiguration", + "default": "None", + "title": "Console virtual UART type", + "description": "
\n

\n Select the console virtual UART (vUART) type. Add the console settings to the kernel command line by typing them in the \"Linux kernel command-line parameters\" text box (for example, console=ttyS0 for COM port 1).\n

\n
\n" + }, + "mmio_resources": { + "$ref": "#/definitions/PostLaunchedMMIOResourcesConfiguration", + "title": "mmio_resources", + "description": "
\n

\n MMIO resources to passthrough.\n

\n
\n" + }, + "pci_devs": { + "$ref": "#/definitions/PCIDevsConfiguration", + "title": "PCI device assignment", + "description": "" + }, + "PTM": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Precision Time Measurement", + "description": "
\n

\n Enable virtualization of PCIe Precision Time Measurement (PTM) mechanism for devices with PTM capability and for real-time application. The hypervisor provides PCIe root port emulation instead of host bridge emulation for the VM. PTM coordinates timing between the device and root port with the device's local timebases without relying on software.\n

\n
\n" + }, + "os_type": { + "$ref": "#/definitions/OSType", + "default": "Non-Windows OS", + "title": "OS type", + "description": "
\n

\n Select the OS type for this VM. This is required to run Windows in a User VM. See\n \n Device Model Parameters\n \n for how to include this in the Device Model arguments.\n

\n
\n" + }, + "vbootloader": { + "$ref": "#/definitions/EnablementType", + "default": "Enable", + "title": "OVMF (Open Virtual Machine Firmware)", + "description": "
\n

\n Use virtual bootloader OVMF (Open Virtual Machine Firmware) to boot this VM.\n

\n
\n" + }, + "vuart0": { + "$ref": "#/definitions/EnablementType", + "default": "Enable", + "title": "Emulate COM1 as stdio I/O in Device Model", + "description": "
\n

\n Enable the ACRN Device Model to emulate COM1 as a User VM stdio I/O. Hypervisor global emulation will take priority over this VM setting.\n

\n
\n" + }, + "usb_xhci": { + "type": "string", + "pattern": "^([\\d]+-[\\d]+){0,1}(:[\\d]+-[\\d]+)*$", + "title": "Virtual USB host controller interface", + "description": "
\n

\n Select the USB physical bus and port number that will be emulated by the ACRN Device Model for this VM. USB 3.0, 2.0, and 1.0 are supported.\n

\n
\n" + }, + "virtio_devices": { + "type": "object", + "properties": { + "console": { + "type": "string", + "title": "console", + "description": "
\n
\n
\n The virtio console device setting.Input format:\n
\n
\n

\n \n \n [@]stdio|tty|pty|sock:portname[=portpath][,[@]stdio|tty|pty:portname[=portpath]]\n \n \n

\n
\n
\n
\n" + }, + "network": { + "type": "string", + "title": "network", + "description": "
\n
\n
\n The virtio network device setting.\n
\n
\n

\n Input format:\n \n \n device_name[,vhost][,mac=XX:XX:XX:XX:XX:XX]\n \n \n .\nThe\n \n device_name\n \n is the name of the TAP (or MacVTap) device.\nIt must include the keyword\n \n tap\n \n .\n \n vhost\n \n specifies the\nvhost backend; otherwise, the VBSU backend is used. The\n \n mac\n \n address is optional.\n

\n
\n
\n
\n" + }, + "input": { + "type": "string", + "title": "input", + "description": "
\n

\n The virtio input device setting.\n

\n
\n" + }, + "block": { + "type": "string", + "title": "block", + "description": "
\n
\n
\n The virtio block device setting.\n
\n
\n

\n Format: [blk partition:][img path] e.g.: /dev/sda3:./a/b.img\n

\n
\n
\n
\n" + } + }, + "title": "Virt-IO devices", + "description": "
\n

\n Enable virt-IO devices in post-launched VMs.\n

\n
\n" + } + } + }, + "BasicMemoryInfo": { + "type": "object", + "required": [ + "whole" + ], + "properties": { + "whole": { + "type": "integer", + "default": 256, + "title": "VM physical memory allocation (MB)", + "description": "
\n

\n Specify the physical memory allocated to this VM in Megabytes.\n

\n
\n" + } + } + }, + "VMBasicConfigType": { + "type": "object", + "required": [ + "vm_type", + "name", + "memory", + "console_vuart", + "os_type", + "vbootloader", + "vuart0", + "virtio_devices" + ], + "properties": { + "vm_type": { + "$ref": "#/definitions/BasicVMType", + "title": "VM type", + "description": "
\n

\n Select the VM type. A standard VM (\n \n STANDARD_VM\n \n ) is for general-purpose applications, such as human-machine interface (HMI). A real-time VM (\n \n RTVM\n \n ) offers special features for time-sensitive applications.\n

\n
\n" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 15, + "pattern": "^\\S+$", + "title": "VM name", + "description": "
\n

\n Specify the name used to identify this VM. The VM name will be shown in the hypervisor console vm_list command.\n

\n
\n" + }, + "cpu_affinity": { + "$ref": "#/definitions/CPUAffinityConfiguration", + "title": "Physical CPU affinity", + "description": "
\n

\n Select a subset of physical CPUs that this VM can use. More than one can be selected.\n

\n
\n" + }, + "memory": { + "$ref": "#/definitions/BasicMemoryInfo", + "title": "memory", + "description": "
\n

\n Specify memory information for Service and User VMs.\n

\n
\n" + }, + "os_config": { + "$ref": "#/definitions/OSConfigurations", + "title": "os_config", + "description": "
\n

\n General information for host kernel, boot\nargument and memory.\n

\n
\n" + }, + "console_vuart": { + "$ref": "#/definitions/ConsoleVuartConfiguration", + "default": "None", + "title": "Console virtual UART type", + "description": "
\n

\n Select the console virtual UART (vUART) type. Add the console settings to the kernel command line by typing them in the \"Linux kernel command-line parameters\" text box (for example, console=ttyS0 for COM port 1).\n

\n
\n" + }, + "mmio_resources": { + "$ref": "#/definitions/MMIOResourcesConfiguration", + "title": "mmio_resources", + "description": "
\n

\n MMIO resources to passthrough.\n

\n
\n" + }, + "pci_devs": { + "$ref": "#/definitions/PCIDevsConfiguration", + "title": "PCI device assignment", + "description": "" + }, + "os_type": { + "$ref": "#/definitions/OSType", + "default": "Non-Windows OS", + "title": "OS type", + "description": "
\n

\n Select the OS type for this VM. This is required to run Windows in a User VM. See\n \n Device Model Parameters\n \n for how to include this in the Device Model arguments.\n

\n
\n" + }, + "vbootloader": { + "$ref": "#/definitions/EnablementType", + "default": "Enable", + "title": "OVMF (Open Virtual Machine Firmware)", + "description": "
\n

\n Use virtual bootloader OVMF (Open Virtual Machine Firmware) to boot this VM.\n

\n
\n" + }, + "vuart0": { + "$ref": "#/definitions/EnablementType", + "default": "Enable", + "title": "Emulate COM1 as stdio I/O in Device Model", + "description": "
\n

\n Enable the ACRN Device Model to emulate COM1 as a User VM stdio I/O. Hypervisor global emulation will take priority over this VM setting.\n

\n
\n" + }, + "usb_xhci": { + "type": "string", + "pattern": "^([\\d]+-[\\d]+){0,1}(:[\\d]+-[\\d]+)*$", + "title": "Virtual USB host controller interface", + "description": "
\n

\n Select the USB physical bus and port number that will be emulated by the ACRN Device Model for this VM. USB 3.0, 2.0, and 1.0 are supported.\n

\n
\n" + }, + "virtio_devices": { + "type": "object", + "properties": { + "console": { + "type": "string", + "title": "console", + "description": "
\n
\n
\n The virtio console device setting.Input format:\n
\n
\n

\n \n \n [@]stdio|tty|pty|sock:portname[=portpath][,[@]stdio|tty|pty:portname[=portpath]]\n \n \n

\n
\n
\n
\n" + }, + "network": { + "type": "string", + "title": "network", + "description": "
\n
\n
\n The virtio network device setting.\n
\n
\n

\n Input format:\n \n \n device_name[,vhost][,mac=XX:XX:XX:XX:XX:XX]\n \n \n .\nThe\n \n device_name\n \n is the name of the TAP (or MacVTap) device.\nIt must include the keyword\n \n tap\n \n .\n \n vhost\n \n specifies the\nvhost backend; otherwise, the VBSU backend is used. The\n \n mac\n \n address is optional.\n

\n
\n
\n
\n" + }, + "input": { + "type": "string", + "title": "input", + "description": "
\n

\n The virtio input device setting.\n

\n
\n" + }, + "block": { + "type": "string", + "title": "block", + "description": "
\n
\n
\n The virtio block device setting.\n
\n
\n

\n Format: [blk partition:][img path] e.g.: /dev/sda3:./a/b.img\n

\n
\n
\n
\n" + } + }, + "title": "Virt-IO devices", + "description": "
\n

\n Enable virt-IO devices in post-launched VMs.\n

\n
\n" + } + } + }, + "PreLaunchedVMBasicConfigType": { + "type": "object", + "required": [ + "vm_type", + "name", + "console_vuart" + ], + "properties": { + "vm_type": { + "$ref": "#/definitions/BasicVMType", + "title": "VM type", + "description": "
\n

\n Select the VM type. A standard VM (\n \n STANDARD_VM\n \n ) is for general-purpose applications, such as human-machine interface (HMI). A real-time VM (\n \n RTVM\n \n ) offers special features for time-sensitive applications.\n

\n
\n" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 15, + "pattern": "^\\S+$", + "title": "VM name", + "description": "
\n

\n Specify the name used to identify this VM. The VM name will be shown in the hypervisor console vm_list command.\n

\n
\n" + }, + "cpu_affinity": { + "$ref": "#/definitions/CPUAffinityConfiguration", + "title": "Physical CPU affinity", + "description": "
\n

\n Select a subset of physical CPUs that this VM can use. More than one can be selected.\n

\n
\n" + }, + "os_config": { + "$ref": "#/definitions/OSConfigurations", + "title": "os_config", + "description": "
\n

\n General information for host kernel, boot\nargument and memory.\n

\n
\n" + }, + "console_vuart": { + "$ref": "#/definitions/ConsoleVuartConfiguration", + "default": "None", + "title": "Console virtual UART type", + "description": "
\n

\n Select the console virtual UART (vUART) type. Add the console settings to the kernel command line by typing them in the \"Linux kernel command-line parameters\" text box (for example, console=ttyS0 for COM port 1).\n

\n
\n" + }, + "mmio_resources": { + "$ref": "#/definitions/MMIOResourcesConfiguration", + "title": "mmio_resources", + "description": "
\n

\n MMIO resources to passthrough.\n

\n
\n" + }, + "pci_devs": { + "$ref": "#/definitions/PCIDevsConfiguration", + "title": "PCI device assignment", + "description": "" + } + } + }, + "ServiceVMBasicConfigType": { + "type": "object", + "required": [ + "vm_type", + "name", + "console_vuart" + ], + "properties": { + "vm_type": { + "$ref": "#/definitions/BasicVMType", + "title": "VM type", + "description": "
\n

\n Select the VM type. A standard VM (\n \n STANDARD_VM\n \n ) is for general-purpose applications, such as human-machine interface (HMI). A real-time VM (\n \n RTVM\n \n ) offers special features for time-sensitive applications.\n

\n
\n" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 15, + "pattern": "^\\S+$", + "title": "VM name", + "description": "
\n

\n Specify the name used to identify this VM. The VM name will be shown in the hypervisor console vm_list command.\n

\n
\n" + }, + "cpu_affinity": { + "$ref": "#/definitions/CPUAffinityConfiguration", + "title": "Physical CPU affinity", + "description": "
\n

\n Select a subset of physical CPUs that this VM can use. More than one can be selected.\n

\n
\n" + }, + "os_config": { + "$ref": "#/definitions/OSConfigurations", + "title": "os_config", + "description": "
\n

\n General information for host kernel, boot\nargument and memory.\n

\n
\n" + }, + "console_vuart": { + "$ref": "#/definitions/ConsoleVuartConfiguration", + "default": "None", + "title": "Console virtual UART type", + "description": "
\n

\n Select the console virtual UART (vUART) type. Add the console settings to the kernel command line by typing them in the \"Linux kernel command-line parameters\" text box (for example, console=ttyS0 for COM port 1).\n

\n
\n" + } + } + }, + "PostLaunchedVMBasicConfigType": { + "type": "object", + "required": [ + "vm_type", + "name", + "memory", + "console_vuart", + "os_type", + "vbootloader", + "vuart0", + "virtio_devices" + ], + "properties": { + "vm_type": { + "$ref": "#/definitions/BasicVMType", + "title": "VM type", + "description": "
\n

\n Select the VM type. A standard VM (\n \n STANDARD_VM\n \n ) is for general-purpose applications, such as human-machine interface (HMI). A real-time VM (\n \n RTVM\n \n ) offers special features for time-sensitive applications.\n

\n
\n" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 15, + "pattern": "^\\S+$", + "title": "VM name", + "description": "
\n

\n Specify the name used to identify this VM. The VM name will be shown in the hypervisor console vm_list command.\n

\n
\n" + }, + "cpu_affinity": { + "$ref": "#/definitions/CPUAffinityConfiguration", + "title": "Physical CPU affinity", + "description": "
\n

\n Select a subset of physical CPUs that this VM can use. More than one can be selected.\n

\n
\n" + }, + "memory": { + "$ref": "#/definitions/PostLaunchedMemoryInfo", + "title": "memory", + "description": "
\n

\n Specify memory information for Service and User VMs.\n

\n
\n" + }, + "console_vuart": { + "$ref": "#/definitions/ConsoleVuartConfiguration", + "default": "None", + "title": "Console virtual UART type", + "description": "
\n

\n Select the console virtual UART (vUART) type. Add the console settings to the kernel command line by typing them in the \"Linux kernel command-line parameters\" text box (for example, console=ttyS0 for COM port 1).\n

\n
\n" + }, + "mmio_resources": { + "$ref": "#/definitions/PostLaunchedMMIOResourcesConfiguration", + "title": "mmio_resources", + "description": "
\n

\n MMIO resources to passthrough.\n

\n
\n" + }, + "pci_devs": { + "$ref": "#/definitions/PCIDevsConfiguration", + "title": "PCI device assignment", + "description": "" + }, + "os_type": { + "$ref": "#/definitions/OSType", + "default": "Non-Windows OS", + "title": "OS type", + "description": "
\n

\n Select the OS type for this VM. This is required to run Windows in a User VM. See\n \n Device Model Parameters\n \n for how to include this in the Device Model arguments.\n

\n
\n" + }, + "vbootloader": { + "$ref": "#/definitions/EnablementType", + "default": "Enable", + "title": "OVMF (Open Virtual Machine Firmware)", + "description": "
\n

\n Use virtual bootloader OVMF (Open Virtual Machine Firmware) to boot this VM.\n

\n
\n" + }, + "vuart0": { + "$ref": "#/definitions/EnablementType", + "default": "Enable", + "title": "Emulate COM1 as stdio I/O in Device Model", + "description": "
\n

\n Enable the ACRN Device Model to emulate COM1 as a User VM stdio I/O. Hypervisor global emulation will take priority over this VM setting.\n

\n
\n" + }, + "usb_xhci": { + "type": "string", + "pattern": "^([\\d]+-[\\d]+){0,1}(:[\\d]+-[\\d]+)*$", + "title": "Virtual USB host controller interface", + "description": "
\n

\n Select the USB physical bus and port number that will be emulated by the ACRN Device Model for this VM. USB 3.0, 2.0, and 1.0 are supported.\n

\n
\n" + }, + "virtio_devices": { + "type": "object", + "properties": { + "console": { + "type": "string", + "title": "console", + "description": "
\n
\n
\n The virtio console device setting.Input format:\n
\n
\n

\n \n \n [@]stdio|tty|pty|sock:portname[=portpath][,[@]stdio|tty|pty:portname[=portpath]]\n \n \n

\n
\n
\n
\n" + }, + "network": { + "type": "string", + "title": "network", + "description": "
\n
\n
\n The virtio network device setting.\n
\n
\n

\n Input format:\n \n \n device_name[,vhost][,mac=XX:XX:XX:XX:XX:XX]\n \n \n .\nThe\n \n device_name\n \n is the name of the TAP (or MacVTap) device.\nIt must include the keyword\n \n tap\n \n .\n \n vhost\n \n specifies the\nvhost backend; otherwise, the VBSU backend is used. The\n \n mac\n \n address is optional.\n

\n
\n
\n
\n" + }, + "input": { + "type": "string", + "title": "input", + "description": "
\n

\n The virtio input device setting.\n

\n
\n" + }, + "block": { + "type": "string", + "title": "block", + "description": "
\n
\n
\n The virtio block device setting.\n
\n
\n

\n Format: [blk partition:][img path] e.g.: /dev/sda3:./a/b.img\n

\n
\n
\n
\n" + } + }, + "title": "Virt-IO devices", + "description": "
\n

\n Enable virt-IO devices in post-launched VMs.\n

\n
\n" + } + } + }, + "BasicFeatureOptionsType": { + "type": "object", + "required": [ + "IVSHMEM" + ], + "properties": { + "IVSHMEM": { + "$ref": "#/definitions/IVSHMEMInfo", + "title": "Inter-VM shared memory", + "description": "" + } + } + }, + "HVBasicConfigType": { + "type": "object", + "required": [ + "DEBUG_OPTIONS", + "FEATURES", + "vuart_connections" + ], + "properties": { + "DEBUG_OPTIONS": { + "$ref": "#/definitions/DebugOptionsType", + "title": "Debug options", + "description": "
\n

\n Configure the debug facilities.\n

\n
\n" + }, + "FEATURES": { + "$ref": "#/definitions/BasicFeatureOptionsType", + "title": "Hypervisor features", + "description": "
\n

\n Enable hypervisor features.\n

\n
\n" + }, + "vuart_connections": { + "$ref": "#/definitions/VuartConnectionsType", + "title": "Virtual UART connection", + "description": "
\n

\n Specify the vUART connection settings.\nRefer to\n \n Enable vUART Configurations\n \n for detailed vUART settings.\n

\n
\n" + } + } + }, + "AdvancedMemoryInfo": { + "type": "object", + "required": [ + "start_hpa" + ], + "properties": { + "start_hpa": { + "$ref": "#/definitions/HexFormat", + "default": "0x100000000", + "title": "start_hpa", + "description": "
\n

\n The starting physical address in host for the VM.\n

\n
\n" + }, + "size": { + "$ref": "#/definitions/MemorySizeType", + "default": "0x20000000", + "title": "size", + "description": "
\n

\n The memory size in bytes for the VM. Default value is\n \n 0x200000000\n \n .\n

\n
\n" + }, + "start_hpa2": { + "$ref": "#/definitions/HexFormat", + "default": "0x0", + "title": "start_hpa2", + "description": "
\n

\n Start of second HPA for non-contiguous allocations in host for the VM.\n

\n
\n" + }, + "size_hpa2": { + "$ref": "#/definitions/MemorySizeType", + "default": "0x0", + "title": "size_hpa2", + "description": "
\n

\n Memory size of second HPA for non-contiguous allocations in Bytes for the VM.\n

\n
\n" + } + } + }, + "VMAdvancedConfigType": { + "type": "object", + "required": [ + "clos", + "memory" + ], + "properties": { + "lapic_passthrough": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "LAPIC passthrough", + "description": "
\n

\n Enable LAPIC passthrough for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "io_completion_polling": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "I/O completion polling", + "description": "
\n

\n Enable polling mode for I/O completion for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "nested_virtualization_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Nested virtualization", + "description": "
\n

\n Enable nested virtualization for KVM.\n

\n
\n" + }, + "virtual_cat_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Virtual Cache Allocation Technology (vCAT)", + "description": "
\n

\n Enable virtualization of the Cache Allocation Technology (CAT) feature in RDT. CAT enables you to allocate cache to VMs, providing isolation to avoid performance interference from other VMs.\n

\n
\n" + }, + "clos": { + "$ref": "#/definitions/CLOSConfiguration", + "title": "clos", + "description": "
\n

\n Class of Service for Cache Allocation Technology.\nRefer SDM 17.19.2 for details, and use with caution.\n

\n
\n" + }, + "epc_section": { + "$ref": "#/definitions/EPCSection", + "title": "epc_section", + "description": "
\n

\n Specify the Intel Software Guard Extensions (SGX) enclave page cache (EPC) section settings.\n

\n
\n" + }, + "memory": { + "$ref": "#/definitions/AdvancedMemoryInfo", + "title": "memory", + "description": "
\n

\n Specify memory information for Service and User VMs.\n

\n
\n" + }, + "pt_intx": { + "type": "string", + "title": "pt_intx", + "description": "
\n

\n Specify the pre-launched VM owned IOAPIC pins and the corresponding mapping between physical GSI and virtual GSI.\n

\n
\n" + }, + "PTM": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Precision Time Measurement", + "description": "
\n

\n Enable virtualization of PCIe Precision Time Measurement (PTM) mechanism for devices with PTM capability and for real-time application. The hypervisor provides PCIe root port emulation instead of host bridge emulation for the VM. PTM coordinates timing between the device and root port with the device's local timebases without relying on software.\n

\n
\n" + } + } + }, + "PreLaunchedVMAdvancedConfigType": { + "type": "object", + "required": [ + "clos", + "memory" + ], + "properties": { + "lapic_passthrough": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "LAPIC passthrough", + "description": "
\n

\n Enable LAPIC passthrough for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "io_completion_polling": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "I/O completion polling", + "description": "
\n

\n Enable polling mode for I/O completion for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "nested_virtualization_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Nested virtualization", + "description": "
\n

\n Enable nested virtualization for KVM.\n

\n
\n" + }, + "virtual_cat_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Virtual Cache Allocation Technology (vCAT)", + "description": "
\n

\n Enable virtualization of the Cache Allocation Technology (CAT) feature in RDT. CAT enables you to allocate cache to VMs, providing isolation to avoid performance interference from other VMs.\n

\n
\n" + }, + "clos": { + "$ref": "#/definitions/CLOSConfiguration", + "title": "clos", + "description": "
\n

\n Class of Service for Cache Allocation Technology.\nRefer SDM 17.19.2 for details, and use with caution.\n

\n
\n" + }, + "epc_section": { + "$ref": "#/definitions/EPCSection", + "title": "epc_section", + "description": "
\n

\n Specify the Intel Software Guard Extensions (SGX) enclave page cache (EPC) section settings.\n

\n
\n" + }, + "memory": { + "$ref": "#/definitions/PreLaunchedMemoryInfo", + "title": "memory", + "description": "
\n

\n Specify memory information for Service and User VMs.\n

\n
\n" + }, + "pt_intx": { + "type": "string", + "title": "pt_intx", + "description": "
\n

\n Specify the pre-launched VM owned IOAPIC pins and the corresponding mapping between physical GSI and virtual GSI.\n

\n
\n" + }, + "PTM": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Precision Time Measurement", + "description": "
\n

\n Enable virtualization of PCIe Precision Time Measurement (PTM) mechanism for devices with PTM capability and for real-time application. The hypervisor provides PCIe root port emulation instead of host bridge emulation for the VM. PTM coordinates timing between the device and root port with the device's local timebases without relying on software.\n

\n
\n" + } + } + }, + "ServiceVMAdvancedConfigType": { + "type": "object", + "required": [ + "clos", + "memory" + ], + "properties": { + "lapic_passthrough": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "LAPIC passthrough", + "description": "
\n

\n Enable LAPIC passthrough for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "io_completion_polling": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "I/O completion polling", + "description": "
\n

\n Enable polling mode for I/O completion for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "nested_virtualization_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Nested virtualization", + "description": "
\n

\n Enable nested virtualization for KVM.\n

\n
\n" + }, + "virtual_cat_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Virtual Cache Allocation Technology (vCAT)", + "description": "
\n

\n Enable virtualization of the Cache Allocation Technology (CAT) feature in RDT. CAT enables you to allocate cache to VMs, providing isolation to avoid performance interference from other VMs.\n

\n
\n" + }, + "clos": { + "$ref": "#/definitions/CLOSConfiguration", + "title": "clos", + "description": "
\n

\n Class of Service for Cache Allocation Technology.\nRefer SDM 17.19.2 for details, and use with caution.\n

\n
\n" + }, + "memory": { + "$ref": "#/definitions/ServiceMemoryInfo", + "title": "memory", + "description": "
\n

\n Specify memory information for Service and User VMs.\n

\n
\n" + } + } + }, + "PostLaunchedVMAdvancedConfigType": { + "type": "object", + "required": [ + "clos" + ], + "properties": { + "lapic_passthrough": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "LAPIC passthrough", + "description": "
\n

\n Enable LAPIC passthrough for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "io_completion_polling": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "I/O completion polling", + "description": "
\n

\n Enable polling mode for I/O completion for this VM. This feature is required for VMs with stringent real-time performance needs.\n

\n
\n" + }, + "nested_virtualization_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Nested virtualization", + "description": "
\n

\n Enable nested virtualization for KVM.\n

\n
\n" + }, + "virtual_cat_support": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Virtual Cache Allocation Technology (vCAT)", + "description": "
\n

\n Enable virtualization of the Cache Allocation Technology (CAT) feature in RDT. CAT enables you to allocate cache to VMs, providing isolation to avoid performance interference from other VMs.\n

\n
\n" + }, + "clos": { + "$ref": "#/definitions/CLOSConfiguration", + "title": "clos", + "description": "
\n

\n Class of Service for Cache Allocation Technology.\nRefer SDM 17.19.2 for details, and use with caution.\n

\n
\n" + }, + "PTM": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Precision Time Measurement", + "description": "
\n

\n Enable virtualization of PCIe Precision Time Measurement (PTM) mechanism for devices with PTM capability and for real-time application. The hypervisor provides PCIe root port emulation instead of host bridge emulation for the VM. PTM coordinates timing between the device and root port with the device's local timebases without relying on software.\n

\n
\n" + } + } + }, + "AdvancedFeatureOptionsType": { + "type": "object", + "required": [ + "RELOC", + "SCHEDULER", + "MULTIBOOT2", + "ENFORCE_TURNOFF_AC", + "ENFORCE_TURNOFF_GP", + "RDT", + "HYPERV_ENABLED", + "ACPI_PARSE_ENABLED", + "L1D_VMENTRY_ENABLED", + "MCE_ON_PSC_DISABLED" + ], + "properties": { + "RELOC": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Hypervisor relocation in memory", + "description": "
\n

\n Enable hypervisor relocation in memory. The bootloader may need to change the location of the hypervisor because of other firmware.\n

\n
\n" + }, + "SCHEDULER": { + "$ref": "#/definitions/SchedulerType", + "default": "SCHED_BVT", + "title": "Virtual CPU scheduler", + "description": "
\n

\n Select the scheduling algorithm used to determine which User VM runs on a shared virtual CPU.\n

\n
\n" + }, + "MULTIBOOT2": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Multiboot2", + "description": "
\n

\n Enable multiboot2 protocol support and multiboot1 downward compatibility. Disable this feature if multiboot1 meets your requirements and to reduce lines of code.\n

\n
\n" + }, + "ENFORCE_TURNOFF_AC": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Split lock detection", + "description": "
\n

\n Enable detection of split locks, which can negatively affect an application's real-time performance. If a lock is detected, an alignment check exception #AC occurs.\n

\n
\n" + }, + "ENFORCE_TURNOFF_GP": { + "$ref": "#/definitions/Boolean", + "default": "n", + "title": "Uncacheable-memory lock detection", + "description": "
\n

\n Enable detection of uncacheable-memory locks, which can negatively affect an application's real-time performance. If a lock is detected, a general-protection exception #GP occurs.\n

\n
\n" + }, + "RDT": { + "$ref": "#/definitions/RDTType", + "title": "Intel Resource Director Technology (RDT)", + "description": "
\n

\n Intel Resource Director Technology (RDT) provides cache and memory bandwidth allocation features. The features can be used to improve an application's real-time performance.\n

\n
\n" + }, + "HYPERV_ENABLED": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Hyper-V virtualization technology", + "description": "
\n

\n Enable Microsoft Hyper-V Hypervisor Top-Level Functional Specification (TFLS) for Windows User VMs.\n

\n
\n" + }, + "ACPI_PARSE_ENABLED": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Parse ACPI tables at runtime", + "description": "
\n

\n Enable ACPI runtime parsing to get DMAR (DMA remapping) configuration data from the APCI tables. Otherwise, use existing, static information from the associated board configuration file.\n

\n
\n" + }, + "L1D_VMENTRY_ENABLED": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Mitigate L1 terminal fault", + "description": "
\n

\n Enable L1 cache flush before VM entry to prevent L1 terminal fault. L1 terminal fault is a hardware vulnerability that allows unauthorized disclosure of information residing in the L1 data cache.\n

\n
\n" + }, + "MCE_ON_PSC_DISABLED": { + "$ref": "#/definitions/Boolean", + "default": "y", + "title": "Machine Check Error (MCE) workaround", + "description": "
\n

\n Enable the software workaround for Machine Check Error on Page Size Change (hardware bug in some processor families).\n

\n
\n" + }, + "SSRAM": { + "$ref": "#/definitions/SSRAMInfo", + "title": "Software SRAM (for real-time apps)", + "description": "" + } + } + }, + "AdvancedMemoryOptionsType": { + "type": "object", + "required": [ + "STACK_SIZE" + ], + "properties": { + "STACK_SIZE": { + "$ref": "#/definitions/HexFormat", + "default": "0x2000", + "title": "CPU memory stack size (bytes per CPU)", + "description": "
\n

\n Specify the size of the memory stack in bytes for each physical CPU. For example, if you specify 8 kilobytes, each CPU will get its own 8-kilobyte stack.\n

\n
\n" + } + } + }, + "AdvancedCapacitiesOptionsType": { + "type": "object", + "required": [ + "MAX_PCI_DEV_NUM", + "MAX_PT_IRQ_ENTRIES", + "MAX_MSIX_TABLE_NUM", + "MAX_EMULATED_MMIO" + ], + "properties": { + "MAX_PCI_DEV_NUM": { + "type": "integer", + "minimum": 1, + "maximum": 1024, + "default": 96, + "title": "Maximum number of PCI devices", + "description": "
\n

\n Specify the maximum number of PCI devices. This impacts the amount of memory used to maintain information about these PCI devices. The default value is calculated from the board configuration file. If you have PCI devices that were not detected by the Board Inspector, you may need to change this maximum value.\n

\n
\n" + }, + "MAX_PT_IRQ_ENTRIES": { + "type": "integer", + "default": 256, + "title": "Maximum number of IRQ entries for passthrough devices", + "description": "
\n

\n Specify the maximum number of interrupt request (IRQ) entries from all passthrough devices.\n

\n
\n" + }, + "MAX_MSIX_TABLE_NUM": { + "type": "integer", + "minimum": 1, + "maximum": 2048, + "default": 64, + "title": "Maximum number of MSI-X tables per device", + "description": "
\n

\n Specify the maximum number of Message Signaled Interrupt MSI-X tables per device. The default value is calculated from the board configuration file.\n

\n
\n" + }, + "MAX_EMULATED_MMIO": { + "type": "integer", + "minimum": 1, + "maximum": 128, + "default": 16, + "title": "Maximum number of emulated MMIO regions", + "description": "
\n

\n Specify the maximum number of emulated MMIO regions for device virtualization. The default value is calculated from the board configuration file.\n

\n
\n" + } + } + }, + "HVAdvancedConfigType": { + "type": "object", + "required": [ + "FEATURES", + "MEMORY", + "CAPACITIES" + ], + "properties": { + "FEATURES": { + "$ref": "#/definitions/AdvancedFeatureOptionsType", + "title": "Hypervisor features", + "description": "
\n

\n Enable hypervisor features.\n

\n
\n" + }, + "MEMORY": { + "$ref": "#/definitions/AdvancedMemoryOptionsType", + "title": "Memory options", + "description": "
\n

\n Configure memory used by the hypervisor.\n

\n
\n" + }, + "CAPACITIES": { + "$ref": "#/definitions/AdvancedCapacitiesOptionsType", + "title": "Hypervisor capacities", + "description": "
\n

\n Configure the capacities of the hypervisor.\n

\n
\n" + } + } + } + } +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/components/Banner/Banner.css b/misc/config_tools/configurator/src/components/Banner/Banner.css new file mode 100644 index 000000000..c21fe9872 --- /dev/null +++ b/misc/config_tools/configurator/src/components/Banner/Banner.css @@ -0,0 +1,6 @@ +.banner { + min-height: 50px; + background-image: url("images/top_pattern.png"), linear-gradient(90.29deg, #242357 0.08%, #6ABFAE 85.19%, #69BFAD 99.72%); + background-repeat: no-repeat; + background-position: 50%; +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/components/Banner/Banner.jsx b/misc/config_tools/configurator/src/components/Banner/Banner.jsx new file mode 100644 index 000000000..1b7c1105b --- /dev/null +++ b/misc/config_tools/configurator/src/components/Banner/Banner.jsx @@ -0,0 +1,9 @@ +import React from "react"; + +export class Banner extends React.Component { + render() { + return ( +
{this.props.children}
+ ); + } +} diff --git a/misc/config_tools/configurator/src/components/Banner/images/top_pattern.png b/misc/config_tools/configurator/src/components/Banner/images/top_pattern.png new file mode 100644 index 000000000..4626e9173 Binary files /dev/null and b/misc/config_tools/configurator/src/components/Banner/images/top_pattern.png differ diff --git a/misc/config_tools/configurator/src/components/Banner/index.jsx b/misc/config_tools/configurator/src/components/Banner/index.jsx new file mode 100644 index 000000000..c698d227a --- /dev/null +++ b/misc/config_tools/configurator/src/components/Banner/index.jsx @@ -0,0 +1,5 @@ +import './Banner.css' +import {Banner} from "./Banner"; + + +export default Banner; \ No newline at end of file diff --git a/misc/config_tools/configurator/src/components/Confirm/Confirm.jsx b/misc/config_tools/configurator/src/components/Confirm/Confirm.jsx new file mode 100644 index 000000000..35af8d11e --- /dev/null +++ b/misc/config_tools/configurator/src/components/Confirm/Confirm.jsx @@ -0,0 +1,45 @@ +import {Button, Modal} from "react-bootstrap"; +import {useState} from "react"; + +export default function Confirm(props) { + const [show, setShow] = useState(false); + + const handleClose = (choice) => { + setShow(false); + props.callback(choice) + } + + const handleShow = (e) => { + setShow(true); + e.preventDefault() + } + + return ( + handleClose('cancel')} size="lg"> + + {props.title} + + +
+ {props.content} +
+
+ + + + + +
+ ); +} + diff --git a/misc/config_tools/configurator/src/components/Confirm/index.jsx b/misc/config_tools/configurator/src/components/Confirm/index.jsx new file mode 100644 index 000000000..8b5ecbaee --- /dev/null +++ b/misc/config_tools/configurator/src/components/Confirm/index.jsx @@ -0,0 +1,3 @@ +import Confirm from "./Confirm"; + +export default Confirm \ No newline at end of file diff --git a/misc/config_tools/configurator/src/components/Footer/footer.jsx b/misc/config_tools/configurator/src/components/Footer/footer.jsx new file mode 100644 index 000000000..0f6bac9bb --- /dev/null +++ b/misc/config_tools/configurator/src/components/Footer/footer.jsx @@ -0,0 +1,25 @@ +import {Component} from "react"; +import {getVersion} from "@tauri-apps/api/app"; + + +export default class Footer extends Component { + constructor(props) { + super(props); + this.state = { + version: "0.1.0" + } + } + + componentDidMount = () => { + getVersion().then((version) => { + this.setState({version: version}) + }) + } + + render = () => { + return
+

© Copyright Project ACRN™, a Series of LF Projects, LLC. + - Version {this.state.version}

+
+ } +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/components/Footer/index.jsx b/misc/config_tools/configurator/src/components/Footer/index.jsx new file mode 100644 index 000000000..c6c8f167f --- /dev/null +++ b/misc/config_tools/configurator/src/components/Footer/index.jsx @@ -0,0 +1,3 @@ +import Footer from "./footer"; + +export default Footer \ No newline at end of file diff --git a/misc/config_tools/configurator/src/components/Navbar/Navbar.css b/misc/config_tools/configurator/src/components/Navbar/Navbar.css new file mode 100644 index 000000000..8936059ac --- /dev/null +++ b/misc/config_tools/configurator/src/components/Navbar/Navbar.css @@ -0,0 +1,44 @@ +body { + -webkit-app-region: no-drag +} + +.bg-navbar { + height: 80px; + background: #007B81; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15); + -webkit-user-select: none; + -webkit-app-region: drag; +} + +.logo-text { + cursor: default; + font-family: Roboto, serif; + font-style: normal; + font-weight: bold; + font-size: 26px; + line-height: 30px; + letter-spacing: 0.04em; + text-transform: uppercase; + + color: #9ADFD1; +} + +.controlButtons { + margin-right: 30px; + width: 130px; + filter: drop-shadow(3px 3px 2px rgb(0 0 0 / 0.4)); +} + + +.wmb { + cursor: pointer; + -webkit-app-region: no-drag; +} + +.wmb:hover { + opacity: 0.7; +} + +.btn-close { + -webkit-app-region: no-drag; +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/components/Navbar/Navbar.jsx b/misc/config_tools/configurator/src/components/Navbar/Navbar.jsx new file mode 100644 index 000000000..8e19300fd --- /dev/null +++ b/misc/config_tools/configurator/src/components/Navbar/Navbar.jsx @@ -0,0 +1,39 @@ +import React from "react"; +import {Container} from "react-bootstrap"; +import {Navbar as BootstrapNavbar} from "react-bootstrap"; +import logo from "./images/ACRN_Logo.svg"; +import {faWindowMaximize} from "@fortawesome/free-regular-svg-icons"; +import {faClose, faMinus} from "@fortawesome/free-solid-svg-icons" +import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; + +import {windowHelper} from "../../lib/platform/tauri/tauri"; + + +export class Navbar extends React.Component { + render() { + return ( + + + + ACRN +
+ Configurator +
+
+
+ + + +
+
+
+ ); + } +} diff --git a/misc/config_tools/configurator/src/components/Navbar/images/ACRN_Logo.svg b/misc/config_tools/configurator/src/components/Navbar/images/ACRN_Logo.svg new file mode 100644 index 000000000..e52cd4bfa --- /dev/null +++ b/misc/config_tools/configurator/src/components/Navbar/images/ACRN_Logo.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/misc/config_tools/configurator/src/components/Navbar/index.jsx b/misc/config_tools/configurator/src/components/Navbar/index.jsx new file mode 100644 index 000000000..12075d91d --- /dev/null +++ b/misc/config_tools/configurator/src/components/Navbar/index.jsx @@ -0,0 +1,5 @@ +import './Navbar.css' +import {Navbar} from "./Navbar"; + + +export default Navbar; \ No newline at end of file diff --git a/misc/config_tools/configurator/src/favicon.svg b/misc/config_tools/configurator/src/favicon.svg new file mode 100644 index 000000000..de4aeddc1 --- /dev/null +++ b/misc/config_tools/configurator/src/favicon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/misc/config_tools/configurator/src/index.css b/misc/config_tools/configurator/src/index.css new file mode 100644 index 000000000..ec2585e8c --- /dev/null +++ b/misc/config_tools/configurator/src/index.css @@ -0,0 +1,13 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} diff --git a/misc/config_tools/configurator/src/index.scss b/misc/config_tools/configurator/src/index.scss new file mode 100644 index 000000000..b24d45b1c --- /dev/null +++ b/misc/config_tools/configurator/src/index.scss @@ -0,0 +1,36 @@ +// global +$primary: #007B81; + +// grid padding +$grid-gutter-width: 0; + +// a +$link-decoration: auto; +$link-shade-percentage: 39%; + +// text box fontsize +$input-font-size-lg: 1rem; + +@import "../node_modules/bootstrap/scss/bootstrap"; + +.text-pre-line { + white-space: pre-line; +} + +.btn.btn-outline-primary { + color: #007B81; + border-color: #007B81; + background-color: white; +} + +.btn-outline-primary:hover { + color: #004B50; + border-color: #004B50; + background-color: white; +} + +.btn-close-white { + opacity: 1; + filter: none; + background-image: url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11.5195 8.99331L17.4644 3.04835C18.1607 2.3521 18.1607 1.21845 17.4644 0.522192C16.7682 -0.174064 15.6345 -0.174064 14.9383 0.522192L8.99331 6.46715L3.04835 0.531118C2.3521 -0.165138 1.21845 -0.165138 0.522192 0.531118C-0.174064 1.22737 -0.174064 2.36102 0.522192 3.05728L6.46715 9.00223L0.522192 14.9472C-0.174064 15.6434 -0.174064 16.7771 0.522192 17.4733C0.87032 17.8215 1.32556 18 1.78081 18C2.23605 18 2.6913 17.8215 3.03942 17.4733L8.98438 11.5284L14.9293 17.4733C15.2775 17.8215 15.7327 18 16.1879 18C16.6432 18 17.0984 17.8215 17.4466 17.4733C18.1428 16.7771 18.1428 15.6434 17.4466 14.9472L11.5195 8.99331Z' fill='white'/%3E%3C/svg%3E%0A"); +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/lib/.gitignore b/misc/config_tools/configurator/src/lib/.gitignore new file mode 100644 index 000000000..b2a7018ad --- /dev/null +++ b/misc/config_tools/configurator/src/lib/.gitignore @@ -0,0 +1,2 @@ +pyodide +/pyodide.tar.bz2 diff --git a/misc/config_tools/configurator/src/lib/acrn.jsx b/misc/config_tools/configurator/src/lib/acrn.jsx new file mode 100644 index 000000000..e425e5532 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/acrn.jsx @@ -0,0 +1,476 @@ +import _ from "lodash"; + +import React, {Component} from "react"; +import {path} from "@tauri-apps/api"; +import scenario from '../assets/schema/scenario.json' +import {createSearchParams} from "react-router-dom"; +import queryString from 'query-string' +import {invoke} from "@tauri-apps/api/tauri"; +import {getNewSchema} from "./runpy"; + + +function ThrowError(errMsg) { + alert(errMsg) + throw new Error(errMsg) +} + +function NameTrans(name) { + return { + "recentlyWorkingFolders": "WorkingFolder", + "board": "Board", + "scenario": "Scenario", + }[name.replace("History", "")] +} + +class EventBase extends Component { + constructor(props) { + super(props) + this.funRegister = {} + this.funRegisterID = 0 + this.eventName = { + scenarioDataUpdate: 'scenarioDataUpdate' + } + } + + register = (eventName, fun) => { + if (this.funRegister.hasOwnProperty(eventName)) { + this.funRegisterID++ + this.funRegister[eventName][this.funRegisterID] = fun + return this.funRegisterID + } + } + + unregister = (eventName, funRegisterID) => { + if (this.funRegister.hasOwnProperty(eventName)) { + if (this.funRegister[eventName].hasOwnProperty(funRegisterID)) { + delete this.funRegister[eventName][funRegisterID] + } + } + } + +} + + +export class XMLLayer extends EventBase { + constructor(helper) { + super(); + this.helper = helper + this.funRegister = { + onScenarioLoad: [] + } + } + + #parseXML = (XMLText) => { + return (new DOMParser()).parseFromString(XMLText, "text/xml") + } + + #validateBoardXMLText = boardXMLText => { + // call inside + try { + let boardXML = this.#parseXML(boardXMLText, "text/xml"); + return !!boardXML.querySelector("BIOS_INFO") + } catch (e) { + return false + } + } + + #validateScenarioXMLText = (scenarioXMLText) => { + // call inside + try { + let scenarioXML = this.#parseXML(scenarioXMLText); + return !!scenarioXML.querySelector("acrn-config") + } catch (e) { + return false + } + } + + loadBoard = async (boardXMLPath) => { + // call by program + let boardXMLText = await this.helper.read(await this.helper.resolveHome(boardXMLPath)) + if (this.#validateBoardXMLText(boardXMLText)) { + let PCIDevices = this.getPCIDevice(boardXMLText) + return {boardXMLText, PCIDevices} + } else { + alert('Board XML Error!') + return false + } + } + + loadScenario = async (scenarioXMLPath) => { + // call by program + // load scenario data from xml file + let scenarioXMLText = await this.helper.read(await this.helper.resolveHome(scenarioXMLPath)) + if (!this.#validateScenarioXMLText(scenarioXMLText)) { + ThrowError('Scenario XML Error!') + } + + return this.helper.convertXMLTextToObj(scenarioXMLText)['acrn-config'] + } + + getPCIDevice = (boardXMLText) => { + let pci_devices = this.#parseXML(boardXMLText).querySelector("PCI_DEVICE").textContent + // Remove Region line + pci_devices = pci_devices.replace(/Region.+\s+/g, '\n') + // Remove Space + pci_devices = pci_devices.replace(/[\n\t]+/g, '\n') + // Split by \n + pci_devices = pci_devices.split('\n') + + return _.uniq(pci_devices) + } + + saveBoard = (boardFileWritePath, boardData) => { + this.helper.save(boardFileWritePath, boardData) + } + + saveScenario = (scenarioWritePath, scenarioData) => { + // call by program + console.log(scenarioData) + const scenarioXML = this.helper.convertObjToXML({'acrn-config': scenarioData}) + console.log(scenarioXML) + // debugger + this.helper.save(scenarioWritePath, scenarioXML) + } +} + + +export class ProgramLayer extends EventBase { + constructor(helper, instanceOfXMLLayer) { + super() + this.helper = helper + this.vmID = 0 + this.scenarioData = {} + this.initScenario() + this.xmlLayer = instanceOfXMLLayer + this.funRegister = { + scenarioDataUpdate: [] + } + } + + initScenario = () => { + this.vmID = 0 + this.scenarioData = { + hv: {}, + vm: { + PRE_LAUNCHED_VM: [], + SERVICE_VM: [], + POST_LAUNCHED_VM: [], + } + } + } + + onScenarioDataUpdateEvent() { + this.funRegister.scenarioDataUpdate.map((f) => f()) + } + + newScenario = (preLaunchedVM, serviceVM, postLaunchedVM) => { + // call by view + this.initScenario() + for (let i = 0; i < preLaunchedVM; i++) { + this.addVM('PRE_LAUNCHED_VM') + } + for (let i = 0; i < serviceVM; i++) { + this.addVM('SERVICE_VM') + } + for (let i = 0; i < postLaunchedVM; i++) { + this.addVM('POST_LAUNCHED_VM') + } + this.onScenarioDataUpdateEvent() + } + + + addVM = (VMType, vmData = {}) => { + // call by inside and view + // if provide VMType and vmData at same time + // function will set VMType to vmData + let vm = vmData + let usedVMID = false; + + // check VMType + let vmType = VMType; + if (!_.isString(vmType) || _.isEmpty(vmType)) { + // vmType is empty or not correct + if (vm.hasOwnProperty('load_order')) { + vmType = vm.load_order; + } else { + ThrowError('No VMType Set') + } + } else { + if (vm.hasOwnProperty('load_order') && vm.load_order !== vmType) { + console.warn("vmType and vmData provide load_order at same time, set vmData's load_order to vmType now") + } + vm.load_order = vmType + } + + + // check and validate vm name + if (!vm.hasOwnProperty('name') || !_.isString(vm.name) || _.isEmpty(vm.name)) { + vm.name = 'VM' + this.vmID + usedVMID = true + } + + vm['@id'] = this.vmID + this.vmID++ + + // add to config + this.scenarioData.vm[vmType].push(vm) + this.onScenarioDataUpdateEvent() + } + + deleteVM = (vmID) => { + // call by view + for (let vmType in this.scenarioData.vm) { + this.scenarioData.vm[vmType].map((vmConfig, vmIndex) => { + if (vmConfig['@id'] === vmID) { + this.scenarioData.vm[vmType].splice(vmIndex, 1) + } + }) + } + this.onScenarioDataUpdateEvent() + } + + loadBoard = async (WorkingFolder, boardXMLPath) => { + // call by view + let boardData = await this.xmlLayer.loadBoard(boardXMLPath) + if (boardData === false) { + return false + } + let {boardXMLText, PCIDevices} = boardData + + // get new board file name + let newBoardFileName = await path.basename(boardXMLPath) + let cut = 0 + if (_.endsWith(newBoardFileName.toLowerCase(), '.xml')) { + cut = '.xml'.length + } + if (_.endsWith(newBoardFileName.toLowerCase(), '.board.xml')) { + cut = '.board.xml'.length + } + newBoardFileName = newBoardFileName.slice(0, newBoardFileName.length - cut) + newBoardFileName = newBoardFileName + '.board.xml' + + // new board file save path + const boardFileWritePath = await path.join(await this.helper.resolveHome(WorkingFolder), newBoardFileName) + + // remove current working folder old Board File first + await this.removeOldBoardFile(WorkingFolder) + + // save board file to working director + this.xmlLayer.saveBoard(boardFileWritePath, boardXMLText) + // get shownName + let shownName = await path.join(WorkingFolder, newBoardFileName) + console.log({shownName, boardXMLText, PCIDevices}) + return {shownName, boardXMLText, PCIDevices} + } + + loadScenario = async (scenarioXMLPath) => { + // call by view + let scenarioConfig = await this.xmlLayer.loadScenario(scenarioXMLPath) + this.initScenario() + this.scenarioData.hv = scenarioConfig.hv; + scenarioConfig.vm.map((vmConfig, index) => { + let vmType = vmConfig.load_order + if (!this.scenarioData.vm.hasOwnProperty(vmType)) { + try { + ThrowError('VM @id=' + index + ' VMType Does Not Exist') + } catch (e) { + + } + } else { + //fix pci_devs is object issue + if (vmConfig.hasOwnProperty("pci_devs") && vmConfig.pci_devs.hasOwnProperty("pci_dev") && _.isString(vmConfig.pci_devs.pci_dev)) { + vmConfig.pci_devs.pci_dev = [vmConfig.pci_devs.pci_dev] + } + this.addVM(vmType, vmConfig) + } + }) + this.onScenarioDataUpdateEvent() + } + + getOriginScenarioData = () => { + // call by inside + let originScenario = _.cloneDeep(this.scenarioData) + originScenario.vm = originScenario.vm.PRE_LAUNCHED_VM.concat( + originScenario.vm.SERVICE_VM, + originScenario.vm.POST_LAUNCHED_VM + ) + return originScenario + } + + async removeOldBoardFile(WorkingFolder) { + let files = await this.helper.list(await this.helper.resolveHome(WorkingFolder)) + files.map((filename) => { + if (_.endsWith(filename, '.board.xml')) { + this.helper.remove(filename) + } + }) + } + + + saveScenario = async (WorkingFolder) => { + // call by view + let originScenarioData = this.getOriginScenarioData() + let filename = 'scenario.xml' + let scenarioWritePath = await path.join(await this.helper.resolveHome(WorkingFolder), filename) + this.xmlLayer.saveScenario(scenarioWritePath, originScenarioData) + // noinspection UnnecessaryLocalVariableJS + let shownPath = await path.join(WorkingFolder, filename) + return shownPath + } + +} + +export class Configurator extends EventBase { + // get data from Program + // convert it to view data + constructor(helper) { + super() + + this.WorkingFolder = this.#getURLParam('WorkingFolder') + + this.helper = helper + this.XMLLayer = new XMLLayer(this.helper) + this.programLayer = new ProgramLayer(this.helper, this.XMLLayer) + + this.vmSchemas = this.Schemas() + this.hvSchema = this.vmSchemas.HV + delete this.vmSchemas.HV + + this.updateSchema() + } + + #getURLParam(key) { + let hash = location.hash + let params = hash.substring(hash.indexOf('?')) + params = queryString.parse(params) + return params[key] + } + + #buildPageParams(url, queryParams = {}) { + let data = {pathname: url} + if (queryParams) { + data.search = createSearchParams(queryParams).toString() + } + return data; + } + + settingWorkingFolder = (WorkingFolder) => { + this.WorkingFolder = WorkingFolder + return this.#buildPageParams('./config', {WorkingFolder}) + } + + updateSchema = () => { + let listingFunctions = [this.ivshmemEnum] + listingFunctions.forEach((func) => { + func() + this.programLayer.register("scenarioDataUpdate", func) + }) + } + + ivshmemEnum = () => { + let odata = this.programLayer.getOriginScenarioData() + let vmNames = odata.vm.map((vmData) => { + return vmData.name + }) + if (vmNames.length === 0) { + vmNames = [''] + } + this.hvSchema.basic.definitions.VMNameType.enum = vmNames + } + + + loadBoard = async (boardXMLPath, callback) => { + let boardData = await this.programLayer.loadBoard(this.WorkingFolder, boardXMLPath) + if (boardData === false) { + await this.removeHistory('board', boardXMLPath) + return + } + let {shownName, boardXMLText, PCIDevices} = boardData + scenario.definitions.PCIDevsConfiguration.properties.pci_dev.items.enum = PCIDevices + Object.keys(this.vmSchemas).map((VMTypeKey) => { + Object.keys(this.vmSchemas[VMTypeKey]).map((configLevelKey) => { + this.vmSchemas[VMTypeKey][configLevelKey].definitions.PCIDevsConfiguration.properties.pci_dev.items.enum = PCIDevices + }) + }) + try { + let new_scenario = getNewSchema(boardXMLText) + scenario.definitions = new_scenario.definitions; + Object.keys(this.vmSchemas).map((VMTypeKey) => { + Object.keys(this.vmSchemas[VMTypeKey]).map((configLevelKey) => { + this.vmSchemas[VMTypeKey][configLevelKey].definitions = new_scenario.definitions + }) + }) + Object.keys(this.hvSchema).map((configLevelKey) => { + this.hvSchema[configLevelKey].definitions = new_scenario.definitions; + }) + } catch (e) { + + } + + callback(shownName, boardXMLText) + } + + async getHistory(key) { + let p = await invoke("get_history", {historyType: NameTrans(key)}) + console.log("p", p); + return JSON.parse(p) + } + + async addHistory(key, historyPath) { + await invoke("add_history", {historyType: NameTrans(key), path: historyPath}) + return Promise.resolve() + } + + async setHistory(key, history) { + return Promise.resolve() + } + + async removeHistory(key, historyPath) { + let history = await this.getHistory(key) + let index = history.indexOf(historyPath); + if (index > -1) { + history.splice(index, 1); + } + return this.setHistory(key, history) + } + + + saveScenario = async () => { + let shownPath = await this.programLayer.saveScenario(this.WorkingFolder) + return this.addHistory('scenario', shownPath) + } + + + static #getSchema(prefix) { + let bo = scenario.definitions[prefix + "BasicConfigType"] + let basic = _.cloneDeep(scenario); + basic.type = bo.type; + basic.required = bo.required; + basic.properties = bo.properties; + + let ao = scenario.definitions[prefix + "AdvancedConfigType"] + let advanced = _.cloneDeep(scenario); + advanced.type = ao.type; + advanced.required = ao.required; + advanced.properties = ao.properties; + + return {basic, advanced} + } + + Schemas() { + let prefixData = { + HV: 'HV', + PRE_LAUNCHED_VM: 'PreLaunchedVM', + SERVICE_VM: 'ServiceVM', + POST_LAUNCHED_VM: 'PostLaunchedVM' + } + for (let key in prefixData) { + prefixData[key] = Configurator.#getSchema(prefixData[key]) + } + return prefixData + } + + log() { + this.helper.log(...arguments) + } +} diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/.gitignore b/misc/config_tools/configurator/src/lib/bs4rjsf/.gitignore new file mode 100644 index 000000000..4e57eef88 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/.gitignore @@ -0,0 +1,2 @@ +*.js +*.js.map diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/AddButton/AddButton.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/AddButton/AddButton.tsx new file mode 100644 index 000000000..cc3ad1086 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/AddButton/AddButton.tsx @@ -0,0 +1,13 @@ +import React from "react"; + +import {AddButtonProps} from "@rjsf/core"; +import Button from "react-bootstrap/Button"; +import {BsPlus} from "react-icons/bs"; + +const AddButton: React.FC = props => ( + +); + +export default AddButton; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/AddButton/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/AddButton/index.ts new file mode 100644 index 000000000..d8452a62d --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/AddButton/index.ts @@ -0,0 +1,2 @@ +export {default} from "./AddButton"; +export * from "./AddButton"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/ArrayFieldTemplate/ArrayFieldTemplate.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/ArrayFieldTemplate/ArrayFieldTemplate.tsx new file mode 100644 index 000000000..fbe9b2ed7 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/ArrayFieldTemplate/ArrayFieldTemplate.tsx @@ -0,0 +1,210 @@ +import React from "react"; +import {utils} from "@rjsf/core"; +import Row from "react-bootstrap/Row"; +import Col from "react-bootstrap/Col"; +import Container from "react-bootstrap/Container"; +import {ArrayFieldTemplateProps, IdSchema} from "@rjsf/core"; + +import AddButton from "../AddButton/AddButton"; +import IconButton from "../IconButton/IconButton"; + +const {isMultiSelect, getDefaultRegistry} = utils; + +const ArrayFieldTemplate = (props: ArrayFieldTemplateProps) => { + const {schema, registry = getDefaultRegistry()} = props; + + if (isMultiSelect(schema, registry.rootSchema)) { + return ; + } else { + return ; + } +}; + +type ArrayFieldTitleProps = { + TitleField: any; + idSchema: IdSchema; + title: string; + required: boolean; +}; + +const ArrayFieldTitle = ({ + TitleField, + idSchema, + title, + required, + }: ArrayFieldTitleProps) => { + if (!title) { + return null; + } + + const id = `${idSchema.$id}__title`; + return ; +}; + +type ArrayFieldDescriptionProps = { + DescriptionField: any; + idSchema: IdSchema; + description: string; +}; + +const ArrayFieldDescription = ({ + DescriptionField, + idSchema, + description, + }: ArrayFieldDescriptionProps) => { + if (!description) { + return null; + } + + const id = `${idSchema.$id}__description`; + return ; +}; + +// Used in the two templates +const DefaultArrayItem = (props: any) => { + const btnStyle = { + flex: 1, + paddingLeft: 6, + paddingRight: 6, + fontWeight: "bold", + }; + return ( +
+ + {props.children} + + + {props.hasToolbar && ( +
+ {(props.hasMoveUp || props.hasMoveDown) && ( +
+ +
+ )} + + {(props.hasMoveUp || props.hasMoveDown) && ( +
+ +
+ )} + + {props.hasRemove && ( +
+ +
+ )} +
+ )} + +
+
+ ); +}; + +const DefaultFixedArrayFieldTemplate = (props: ArrayFieldTemplateProps) => { + return ( +
+ + + {(props.uiSchema["ui:description"] || props.schema.description) && ( +
+ {props.uiSchema["ui:description"] || props.schema.description} +
+ )} + +
+ {props.items && props.items.map(DefaultArrayItem)} +
+ + {props.canAdd && ( + + )} +
+ ); +}; + +const DefaultNormalArrayFieldTemplate = (props: ArrayFieldTemplateProps) => { + return ( +
+ + + + + {(props.uiSchema["ui:description"] || props.schema.description) && ( + + )} + + + {props.items && props.items.map(p => DefaultArrayItem(p))} + + {props.canAdd && ( + + + + + + + + )} + + + +
+ ); +}; + +export default ArrayFieldTemplate; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/ArrayFieldTemplate/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/ArrayFieldTemplate/index.ts new file mode 100644 index 000000000..a4dd3bbba --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/ArrayFieldTemplate/index.ts @@ -0,0 +1,2 @@ +export {default} from "./ArrayFieldTemplate"; +export * from "./ArrayFieldTemplate"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/CheckboxWidget/CheckboxWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/CheckboxWidget/CheckboxWidget.tsx new file mode 100644 index 000000000..aa79b1664 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/CheckboxWidget/CheckboxWidget.tsx @@ -0,0 +1,50 @@ +import React from "react"; + +import {WidgetProps} from "@rjsf/core"; +import Form from "react-bootstrap/Form"; + +const CheckboxWidget = (props: WidgetProps) => { + const { + id, + value, + required, + disabled, + readonly, + label, + schema, + autofocus, + onChange, + onBlur, + onFocus, + } = props; + + const _onChange = ({ + target: {checked}, + }: React.FocusEvent) => onChange(checked); + const _onBlur = ({ + target: {checked}, + }: React.FocusEvent) => onBlur(id, checked); + const _onFocus = ({ + target: {checked}, + }: React.FocusEvent) => onFocus(id, checked); + + const desc = label || schema.description; + return ( + + + + ); +}; + +export default CheckboxWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/CheckboxWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/CheckboxWidget/index.ts new file mode 100644 index 000000000..1090bf22c --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/CheckboxWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./CheckboxWidget"; +export * from "./CheckboxWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/CheckboxesWidget/CheckboxesWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/CheckboxesWidget/CheckboxesWidget.tsx new file mode 100644 index 000000000..2b34bf3f8 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/CheckboxesWidget/CheckboxesWidget.tsx @@ -0,0 +1,103 @@ +import React from "react"; +import Form from "react-bootstrap/Form"; +import {WidgetProps} from "@rjsf/core"; + +const selectValue = (value: any, selected: any, all: any) => { + const at = all.indexOf(value); + const updated = selected.slice(0, at).concat(value, selected.slice(at)); + + // As inserting values at predefined index positions doesn't work with empty + // arrays, we need to reorder the updated selection to match the initial order + return updated.sort((a: any, b: any) => all.indexOf(a) > all.indexOf(b)); +}; + +const deselectValue = (value: any, selected: any) => { + return selected.filter((v: any) => v !== value); +}; + +const CheckboxesWidget = ({ + schema, + label, + id, + disabled, + options, + value, + autofocus, + readonly, + required, + onChange, + onBlur, + onFocus, + }: WidgetProps) => { + const {enumOptions, enumDisabled, inline} = options; + + const _onChange = (option: any) => ({ + target: {checked}, + }: React.ChangeEvent) => { + const all = (enumOptions as any).map(({value}: any) => value); + + if (checked) { + onChange(selectValue(option.value, value, all)); + } else { + onChange(deselectValue(option.value, value)); + } + }; + + const _onBlur = ({target: {value}}: React.FocusEvent) => + onBlur(id, value); + const _onFocus = ({ + target: {value}, + }: React.FocusEvent) => onFocus(id, value); + + return ( + <> + {label || schema.title} + + {(enumOptions as any).map((option: any, index: number) => { + const checked = value.indexOf(option.value) !== -1; + const itemDisabled = + enumDisabled && (enumDisabled as any).indexOf(option.value) != -1; + + return inline ? ( +
+ + + ) : ( +
+ + + ); + })} +
+ + ); +}; + +export default CheckboxesWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/CheckboxesWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/CheckboxesWidget/index.ts new file mode 100644 index 000000000..0a330f7ce --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/CheckboxesWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./CheckboxesWidget"; +export * from "./CheckboxesWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/ColorWidget/ColorWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/ColorWidget/ColorWidget.tsx new file mode 100644 index 000000000..3cca6122e --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/ColorWidget/ColorWidget.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import {WidgetProps} from "@rjsf/core"; + +const ColorWidget = (props: WidgetProps) => { + const {registry} = props; + const {TextWidget} = registry.widgets; + return ; +}; + +export default ColorWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/ColorWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/ColorWidget/index.ts new file mode 100644 index 000000000..eecf91373 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/ColorWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./ColorWidget"; +export * from "./ColorWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/DateTimeWidget/DateTimeWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/DateTimeWidget/DateTimeWidget.tsx new file mode 100644 index 000000000..74087e299 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/DateTimeWidget/DateTimeWidget.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import {utils, WidgetProps} from "@rjsf/core"; + +const {localToUTC, utcToLocal} = utils; + +const DateTimeWidget = (props: WidgetProps) => { + const {registry} = props; + const {TextWidget} = registry.widgets; + const value = utcToLocal(props.value); + const onChange = (value: any) => { + props.onChange(localToUTC(value)); + }; + + return ( + + ); +}; + +export default DateTimeWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/DateTimeWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/DateTimeWidget/index.ts new file mode 100644 index 000000000..f412f0cb8 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/DateTimeWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./DateTimeWidget"; +export * from "./DateTimeWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/DateWidget/DateWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/DateWidget/DateWidget.tsx new file mode 100644 index 000000000..d8b99a62c --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/DateWidget/DateWidget.tsx @@ -0,0 +1,15 @@ +import React from "react"; +import {WidgetProps} from "@rjsf/core"; + +const DateWidget = (props: WidgetProps) => { + const {registry} = props; + const {TextWidget} = registry.widgets; + return ( + + ); +}; + +export default DateWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/DateWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/DateWidget/index.ts new file mode 100644 index 000000000..3260f890b --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/DateWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./DateWidget"; +export * from "./DateWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/DescriptionField/DescriptionField.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/DescriptionField/DescriptionField.tsx new file mode 100644 index 000000000..1fca34ecf --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/DescriptionField/DescriptionField.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import {FieldProps} from "@rjsf/core"; + +export interface DescriptionFieldProps extends Partial { + description?: string; +} + +const DescriptionField = ({description}: Partial) => { + if (description) { + return
+
+
; + } + + return null; +}; + +export default DescriptionField; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/DescriptionField/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/DescriptionField/index.ts new file mode 100644 index 000000000..e12b66a3b --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/DescriptionField/index.ts @@ -0,0 +1,2 @@ +export {default} from "./DescriptionField"; +export * from "./DescriptionField"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/EmailWidget/EmailWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/EmailWidget/EmailWidget.tsx new file mode 100644 index 000000000..581ce00c3 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/EmailWidget/EmailWidget.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import {WidgetProps} from "@rjsf/core"; + +const EmailWidget = (props: WidgetProps) => { + const {registry} = props; + const {TextWidget} = registry.widgets; + return ; +}; + +export default EmailWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/EmailWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/EmailWidget/index.ts new file mode 100644 index 000000000..4537a21aa --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/EmailWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./EmailWidget"; +export * from "./EmailWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/ErrorList/ErrorList.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/ErrorList/ErrorList.tsx new file mode 100644 index 000000000..6a9a1bf04 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/ErrorList/ErrorList.tsx @@ -0,0 +1,25 @@ +import React from "react"; + +import Card from "react-bootstrap/Card"; +import ListGroup from "react-bootstrap/ListGroup"; + +import {ErrorListProps} from "@rjsf/core"; + +const ErrorList = ({errors}: ErrorListProps) => ( + + Errors + + + {errors.map((error, i: number) => { + return ( + + {error.stack} + + ); + })} + + + +); + +export default ErrorList; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/ErrorList/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/ErrorList/index.ts new file mode 100644 index 000000000..7626610c6 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/ErrorList/index.ts @@ -0,0 +1,2 @@ +export {default} from "./ErrorList"; +export * from "./ErrorList"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/FieldTemplate/FieldTemplate.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/FieldTemplate/FieldTemplate.tsx new file mode 100644 index 000000000..bd318d9f6 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/FieldTemplate/FieldTemplate.tsx @@ -0,0 +1,171 @@ +import React from "react"; + +import {FieldTemplateProps} from "@rjsf/core"; + +import Form from "react-bootstrap/Form"; +import ListGroup from "react-bootstrap/ListGroup"; + +import WrapIfAdditional from "./WrapIfAdditional"; + +import {OverlayTrigger, Popover} from "react-bootstrap"; +import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; +import {faCircleInfo, faCircleExclamation} from "@fortawesome/free-solid-svg-icons"; +import _ from "lodash"; + +const FieldTemplate = ( + { + id, + children, + displayLabel, + rawErrors = [], + rawHelp, + rawDescription, + classNames, + disabled, + label, + onDropPropertyClick, + onKeyChange, + readonly, + required, + schema, + uiSchema + }: FieldTemplateProps) => { + + let descLabel = (uiSchema.hasOwnProperty("ui:descLabel") && uiSchema["ui:descLabel"] === true) + let descWithChildren + let showLabel = _.endsWith(id, 'IVSHMEM_VM_0_VBDF') || _.endsWith(id, 'IVSHMEM_VM_0_VM_NAME') || ( + id.indexOf('vuart_connection') > 0 && (_.endsWith(id, 'vm_name') || _.endsWith(id, 'io_port')) + ) + let dlva = uiSchema.hasOwnProperty("ui:descLabelAli") && uiSchema["ui:descLabelAli"] === 'V' + if (displayLabel && rawDescription) { + let desc + const icon = rawErrors.length > 0 ? faCircleExclamation : faCircleInfo; + if (descLabel) { + if (dlva) { + desc = + + 0 ? "text-danger" : "text-muted"} + dangerouslySetInnerHTML={{__html: rawDescription}}/> + + + }> +
+ 0 ? "text-danger" : "")}> + {uiSchema["ui:title"] || schema.title || label} + {(label || uiSchema["ui:title"] || schema.title) && required ? "*" : null} + +
+
+ descWithChildren =
+ {desc} +
+ {children} +
+
+ } else { + desc = + + 0 ? "text-danger" : "text-muted"} + dangerouslySetInnerHTML={{__html: rawDescription}}/> + + + }> +
+ 0 ? "text-danger" : "")}> + {uiSchema["ui:title"] || schema.title || label} + {(label || uiSchema["ui:title"] || schema.title) && required ? "*" : null} + +
+
+ descWithChildren =
+ {desc} +
+ {children} +
+
+ } + } else { + desc = + + 0 ? "text-danger" : "text-muted"} + dangerouslySetInnerHTML={{__html: rawDescription}}/> + + + }> +
+ 0 ? "red" : ""} + /> +
+
+ descWithChildren =
+ {desc} +
+ {children} +
+
+ } + + + } else { + descWithChildren = children + } + return ( + + + {descWithChildren} + {rawErrors.length > 0 && ( + + {rawErrors.map((error: string) => { + return ( + + + {error} + + + ); + })} + + )} + {rawHelp && ( + 0 ? "text-danger" : "text-muted"} + id={id}> + {rawHelp} + + )} + + + ); +}; + +export default FieldTemplate; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/FieldTemplate/WrapIfAdditional.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/FieldTemplate/WrapIfAdditional.tsx new file mode 100644 index 000000000..fb2310da9 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/FieldTemplate/WrapIfAdditional.tsx @@ -0,0 +1,83 @@ +import React from "react"; + +import {utils} from "@rjsf/core"; +import {JSONSchema7} from "json-schema"; + +import Row from "react-bootstrap/Row"; +import Col from "react-bootstrap/Col"; +import Form from "react-bootstrap/Form"; + +import IconButton from "../IconButton/IconButton"; + +const {ADDITIONAL_PROPERTY_FLAG} = utils; + +type WrapIfAdditionalProps = { + children: React.ReactElement; + classNames: string; + disabled: boolean; + id: string; + label: string; + onDropPropertyClick: (index: string) => (event?: any) => void; + onKeyChange: (index: string) => (event?: any) => void; + readonly: boolean; + required: boolean; + schema: JSONSchema7; +}; + +const WrapIfAdditional = ({ + children, + disabled, + id, + label, + onDropPropertyClick, + onKeyChange, + readonly, + required, + schema, + }: WrapIfAdditionalProps) => { + const keyLabel = `${label} Key`; // i18n ? + const additional = schema.hasOwnProperty(ADDITIONAL_PROPERTY_FLAG); + + if (!additional) { + return children; + } + + const handleBlur = ({target}: React.FocusEvent) => + onKeyChange(target.value); + + return ( + + + + {keyLabel} + + + + + {children} + + + + + + ); +}; + +export default WrapIfAdditional; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/FieldTemplate/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/FieldTemplate/index.ts new file mode 100644 index 000000000..8d6d06eb6 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/FieldTemplate/index.ts @@ -0,0 +1,2 @@ +export {default} from "./FieldTemplate"; +export * from "./FieldTemplate"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/Fields/Fields.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/Fields/Fields.ts new file mode 100644 index 000000000..adb32d9f2 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/Fields/Fields.ts @@ -0,0 +1,7 @@ +import DescriptionField from "../DescriptionField/DescriptionField"; +import TitleField from "../TitleField/TitleField"; + +export default { + DescriptionField, + TitleField, +}; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/Fields/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/Fields/index.ts new file mode 100644 index 000000000..faa3dcbc3 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/Fields/index.ts @@ -0,0 +1,2 @@ +export {default} from "./Fields"; +export * from "./Fields"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/FileWidget/FileWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/FileWidget/FileWidget.tsx new file mode 100644 index 000000000..511c28e44 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/FileWidget/FileWidget.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import {WidgetProps} from "@rjsf/core"; + +const FileWidget = (props: WidgetProps) => { + const {registry} = props; + const {TextWidget} = registry.widgets; + return ; +}; + +export default FileWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/FileWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/FileWidget/index.ts new file mode 100644 index 000000000..558890e80 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/FileWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./FileWidget"; +export * from "./FileWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/Form/Form.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/Form/Form.tsx new file mode 100644 index 000000000..971c6b565 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/Form/Form.tsx @@ -0,0 +1,10 @@ +import {withTheme, FormProps} from "@rjsf/core"; + +import Theme from "../Theme"; +import {StatelessComponent} from "react"; + +const Form: + | React.ComponentClass> + | StatelessComponent> = withTheme(Theme); + +export default Form; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/Form/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/Form/index.ts new file mode 100644 index 000000000..243aa7b6d --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/Form/index.ts @@ -0,0 +1,2 @@ +export {default} from "./Form"; +export * from "./Form"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/IconButton/IconButton.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/IconButton/IconButton.tsx new file mode 100644 index 000000000..062708166 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/IconButton/IconButton.tsx @@ -0,0 +1,33 @@ +import React from "react"; +import Button, {ButtonProps} from "react-bootstrap/Button"; +import {IoIosRemove} from "react-icons/io"; +import {GrAdd} from "react-icons/gr"; +import {AiOutlineArrowUp, AiOutlineArrowDown} from "react-icons/ai"; + +const mappings: any = { + remove: , + plus: , + "arrow-up": , + "arrow-down": , +}; + +type IconButtonProps = ButtonProps & { + icon: string; + variant?: ButtonProps["variant"]; + className?: string; + tabIndex?: number; + style?: any; + disabled?: any; + onClick?: any; +}; + +const IconButton = (props: IconButtonProps) => { + const {icon, className, ...otherProps} = props; + return ( + + ); +}; + +export default IconButton; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/IconButton/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/IconButton/index.ts new file mode 100644 index 000000000..36cd49eb5 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/IconButton/index.ts @@ -0,0 +1,2 @@ +export {default} from "./IconButton"; +export * from "./IconButton"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/ObjectFieldTemplate/ObjectFieldTemplate.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/ObjectFieldTemplate/ObjectFieldTemplate.tsx new file mode 100644 index 000000000..8f99c2465 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/ObjectFieldTemplate/ObjectFieldTemplate.tsx @@ -0,0 +1,81 @@ +import React from "react"; + +import Row from "react-bootstrap/Row"; +import Col from "react-bootstrap/Col"; +import Container from "react-bootstrap/Container"; + +import {ObjectFieldTemplateProps} from "@rjsf/core"; +import {utils} from "@rjsf/core"; + +import AddButton from "../AddButton/AddButton"; + +const {canExpand} = utils; + +const ObjectFieldTemplate = ( + { + DescriptionField, + description, + TitleField, + title, + properties, + required, + uiSchema, + idSchema, + schema, + formData, + onAddClick, + disabled, + readonly, + }: ObjectFieldTemplateProps) => { + let content = properties.map((element: any, index: number) => { + return ( + + {element.content} + + ); + }) + let expand = canExpand(schema, uiSchema, formData) ? ( + + + + + + ) : null + + let container = + {content} + {expand} + + + return ( + <> + {(uiSchema["ui:title"] || title) && ( + + )} + {description && ( + + )} + {container} + + ); +}; + +export default ObjectFieldTemplate; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/ObjectFieldTemplate/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/ObjectFieldTemplate/index.ts new file mode 100644 index 000000000..1c56e5023 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/ObjectFieldTemplate/index.ts @@ -0,0 +1,2 @@ +export {default} from "./ObjectFieldTemplate"; +export * from "./ObjectFieldTemplate"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/PasswordWidget/PasswordWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/PasswordWidget/PasswordWidget.tsx new file mode 100644 index 000000000..ad187fb55 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/PasswordWidget/PasswordWidget.tsx @@ -0,0 +1,55 @@ +import React from "react"; + +import Form from "react-bootstrap/Form"; + +import {WidgetProps} from "@rjsf/core"; + +const PasswordWidget = ({ + id, + required, + readonly, + disabled, + value, + label, + onFocus, + onBlur, + onChange, + options, + autofocus, + schema, + rawErrors = [], + }: WidgetProps) => { + const _onChange = ({ + target: {value}, + }: React.ChangeEvent) => + onChange(value === "" ? options.emptyValue : value); + const _onBlur = ({target: {value}}: React.FocusEvent) => + onBlur(id, value); + const _onFocus = ({ + target: {value}, + }: React.FocusEvent) => onFocus(id, value); + + return ( + + 0 ? "text-danger" : ""}> + {label || schema.title} + {(label || schema.title) && required ? "*" : null} + + 0 ? "is-invalid" : ""} + required={required} + disabled={disabled} + readOnly={readonly} + type="password" + value={value ? value : ""} + onFocus={_onFocus} + onBlur={_onBlur} + onChange={_onChange} + /> + + ); +}; + +export default PasswordWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/PasswordWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/PasswordWidget/index.ts new file mode 100644 index 000000000..ad9455bc9 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/PasswordWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./PasswordWidget"; +export * from "./PasswordWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/RadioWidget/RadioWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/RadioWidget/RadioWidget.tsx new file mode 100644 index 000000000..80fa2594e --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/RadioWidget/RadioWidget.tsx @@ -0,0 +1,70 @@ +import React from "react"; + +import Form from "react-bootstrap/Form"; + +import {WidgetProps} from "@rjsf/core"; + +const RadioWidget = ( + { + id, + schema, + options, + value, + required, + disabled, + readonly, + label, + onChange, + onBlur, + onFocus, + uiSchema, + }: WidgetProps) => { + const {enumOptions, enumDisabled} = options; + + const _onChange = ({target: {value},}: React.ChangeEvent) => + onChange(schema.type == "boolean" ? value !== "false" : value); + const _onBlur = ({target: {value}}: React.FocusEvent) => + onBlur(id, value); + const _onFocus = ({target: {value},}: React.FocusEvent) => onFocus(id, value); + + const inline = Boolean(options && options.inline); + + return ( + + + {uiSchema["ui:title"] || schema.title || label} + {(label || uiSchema["ui:title"] || schema.title) && required ? "*" : null} + +
+ {(enumOptions as any).map((option: any, i: number) => { + const itemDisabled = + Array.isArray(enumDisabled) && + enumDisabled.indexOf(option.value) !== -1; + const checked = option.value == value; + + // @ts-ignore + const radio = ( + + ); + return radio; + })} +
+
+ ); +}; + +export default RadioWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/RadioWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/RadioWidget/index.ts new file mode 100644 index 000000000..d461a901c --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/RadioWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./RadioWidget"; +export * from "./RadioWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/RangeWidget/RangeWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/RangeWidget/RangeWidget.tsx new file mode 100644 index 000000000..9eeb38122 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/RangeWidget/RangeWidget.tsx @@ -0,0 +1,57 @@ +import React from "react"; + +import Form from "react-bootstrap/Form"; + +import {utils} from "@rjsf/core"; +import {WidgetProps} from "@rjsf/core"; + +const {rangeSpec} = utils; + +const RangeWidget = ({ + value, + readonly, + disabled, + onBlur, + onFocus, + options, + schema, + onChange, + required, + label, + id, + uiSchema, + }: WidgetProps) => { + let sliderProps = {value, label, id, ...rangeSpec(schema)}; + + const _onChange = ({ + target: {value}, + }: React.ChangeEvent) => + onChange(value === "" ? options.emptyValue : value); + const _onBlur = ({target: {value}}: React.FocusEvent) => + onBlur(id, value); + const _onFocus = ({ + target: {value}, + }: React.FocusEvent) => onFocus(id, value); + + return ( + + + {uiSchema["ui:title"] || schema.title || label} + {(label || uiSchema["ui:title"] || schema.title) && required ? "*" : null} + + + {value} + + ); +}; + +export default RangeWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/RangeWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/RangeWidget/index.ts new file mode 100644 index 000000000..f43ff7464 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/RangeWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./RangeWidget"; +export * from "./RangeWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/SelectWidget/SelectWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/SelectWidget/SelectWidget.tsx new file mode 100644 index 000000000..5a9c7b813 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/SelectWidget/SelectWidget.tsx @@ -0,0 +1,132 @@ +import React from "react"; + +import Form from "react-bootstrap/Form"; + +import {WidgetProps} from "@rjsf/core"; +import {utils} from "@rjsf/core"; + +const {asNumber, guessType} = utils; + +const nums = new Set(["number", "integer"]); + +/** + * This is a silly limitation in the DOM where option change event values are + * always retrieved as strings. + */ +const processValue = (schema: any, value: any) => { + // "enum" is a reserved word, so only "type" and "items" can be destructured + const {type, items} = schema; + if (value === "") { + return undefined; + } else if (type === "array" && items && nums.has(items.type)) { + return value.map(asNumber); + } else if (type === "boolean") { + return value === "true"; + } else if (type === "number") { + return asNumber(value); + } + + // If type is undefined, but an enum is present, try and infer the type from + // the enum values + if (schema.enum) { + if (schema.enum.every((x: any) => guessType(x) === "number")) { + return asNumber(value); + } else if (schema.enum.every((x: any) => guessType(x) === "boolean")) { + return value === "true"; + } + } + + return value; +}; + +const SelectWidget = ( + { + schema, + id, + options, + label, + required, + disabled, + readonly, + value, + multiple, + autofocus, + onChange, + onBlur, + onFocus, + placeholder, + rawErrors = [], + }: WidgetProps) => { + const {enumOptions, enumDisabled} = options; + + const emptyValue = multiple ? [] : ""; + + function getValue( + event: React.FocusEvent | React.ChangeEvent | any, + multiple: Boolean, + ) { + if (multiple) { + return [].slice + .call(event.target.options as any) + .filter((o: any) => o.selected) + .map((o: any) => o.value); + } else { + return event.target.value; + } + } + + return ( + + 0 ? "text-danger" : "")}> + {label || schema.title} + {(label || schema.title) && required ? "*" : null} + +
+ 0 ? "is-invalid" : "")} + onBlur={ + onBlur && + ((event: React.FocusEvent) => { + const newValue = getValue(event, multiple); + onBlur(id, processValue(schema, newValue)); + }) + } + onFocus={ + onFocus && + ((event: React.FocusEvent) => { + const newValue = getValue(event, multiple); + onFocus(id, processValue(schema, newValue)); + }) + } + onChange={(event: React.ChangeEvent) => { + const newValue = getValue(event, multiple); + onChange(processValue(schema, newValue)); + }}> + {!multiple && schema.default === undefined && ( + + )} + {(enumOptions as any).map(({value, label}: any, i: number) => { + const disabled: any = + Array.isArray(enumDisabled) && + (enumDisabled as any).indexOf(value) != -1; + return ( + + ); + })} + +
+
+ ); +}; + +export default SelectWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/SelectWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/SelectWidget/index.ts new file mode 100644 index 000000000..6e104f2ea --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/SelectWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./SelectWidget"; +export * from "./SelectWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/TextWidget/TextWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/TextWidget/TextWidget.tsx new file mode 100644 index 000000000..ea491c296 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/TextWidget/TextWidget.tsx @@ -0,0 +1,74 @@ +import React from "react"; + +import Form from "react-bootstrap/Form"; + +import {WidgetProps} from "@rjsf/core"; + +const TextWidget = ( + { + id, + placeholder, + required, + readonly, + disabled, + type, + label, + value, + onChange, + onBlur, + onFocus, + autofocus, + options, + schema, + rawErrors = [], + uiSchema, + }: WidgetProps) => { + const _onChange = ({ + target: {value}, + }: React.ChangeEvent) => + onChange(value === "" ? options.emptyValue : value); + const _onBlur = ({target: {value}}: React.FocusEvent) => + onBlur(id, value); + const _onFocus = ({ + target: {value}, + }: React.FocusEvent) => onFocus(id, value); + const inputType = (type || schema.type) === "string" ? "text" : `${type || schema.type}`; + + // const classNames = [rawErrors.length > 0 ? "is-invalid" : "", type === 'file' ? 'custom-file-label': ""] + return ( + + 0 ? "text-danger" : "")}> + {uiSchema["ui:title"] || schema.title || label} + {(label || uiSchema["ui:title"] || schema.title) && required ? "*" : null} + +
+ 0 ? "is-invalid" : ""} + list={schema.examples ? `examples_${id}` : undefined} + type={inputType} + value={value || value === 0 ? value : ""} + onChange={_onChange} + onBlur={_onBlur} + onFocus={_onFocus} + /> +
+ {schema.examples ? ( + + {(schema.examples as string[]) + .concat(schema.default ? ([schema.default] as string[]) : []) + .map((example: any) => { + return + ) : null} +
+ ); +}; + +export default TextWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/TextWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/TextWidget/index.ts new file mode 100644 index 000000000..e7e838908 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/TextWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./TextWidget"; +export * from "./TextWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/TextareaWidget/TextareaWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/TextareaWidget/TextareaWidget.tsx new file mode 100644 index 000000000..763efb975 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/TextareaWidget/TextareaWidget.tsx @@ -0,0 +1,71 @@ +import React from "react"; + +import {WidgetProps} from "@rjsf/core"; +import FormControl from "react-bootstrap/FormControl"; +import InputGroup from "react-bootstrap/InputGroup"; + +type CustomWidgetProps = WidgetProps & { + options: any; +}; + +const TextareaWidget = ({ + id, + placeholder, + value, + required, + disabled, + autofocus, + label, + readonly, + onBlur, + onFocus, + onChange, + options, + schema, + rawErrors = [], + uiSchema, + }: CustomWidgetProps) => { + const _onChange = ({ + target: {value}, + }: React.ChangeEvent) => + onChange(value === "" ? options.emptyValue : value); + const _onBlur = ({ + target: {value}, + }: React.FocusEvent) => onBlur(id, value); + const _onFocus = ({ + target: {value}, + }: React.FocusEvent) => onFocus(id, value); + + return ( + <> + + + + + + ); +}; + +export default TextareaWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/TextareaWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/TextareaWidget/index.ts new file mode 100644 index 000000000..cbcf0b8f3 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/TextareaWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./TextareaWidget"; +export * from "./TextareaWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/Theme/Theme.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/Theme/Theme.tsx new file mode 100644 index 000000000..b3b0fc179 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/Theme/Theme.tsx @@ -0,0 +1,37 @@ +import React from "react"; + +import Button from "react-bootstrap/Button"; + +import ArrayFieldTemplate from "../ArrayFieldTemplate"; +import ErrorList from "../ErrorList"; +import Fields from "../Fields"; +import FieldTemplate from "../FieldTemplate"; +import ObjectFieldTemplate from "../ObjectFieldTemplate"; +import Widgets from "../Widgets"; + +import {ThemeProps} from "@rjsf/core"; +import {utils} from "@rjsf/core"; + +const {getDefaultRegistry} = utils; + +const {fields, widgets} = getDefaultRegistry(); + +const DefaultChildren = () => ( +
+ +
+); + +const Theme: ThemeProps = { + children: , + ArrayFieldTemplate, + fields: {...fields, ...Fields}, + FieldTemplate, + ObjectFieldTemplate, + widgets: {...widgets, ...Widgets}, + ErrorList, +}; + +export default Theme; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/Theme/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/Theme/index.ts new file mode 100644 index 000000000..2398c7502 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/Theme/index.ts @@ -0,0 +1,2 @@ +export {default} from "./Theme"; +export * from "./Theme"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/TitleField/TitleField.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/TitleField/TitleField.tsx new file mode 100644 index 000000000..ee6067da2 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/TitleField/TitleField.tsx @@ -0,0 +1,17 @@ +import React from "react"; +import {FieldProps} from "@rjsf/core"; + +export interface TitleFieldProps extends Partial { + title: string; +} + +const TitleField = ({title, uiSchema}: Partial) => ( + <> +
+
{(uiSchema && uiSchema["ui:title"]) || title}
+
+
+ +); + +export default TitleField; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/TitleField/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/TitleField/index.ts new file mode 100644 index 000000000..51ee5dd17 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/TitleField/index.ts @@ -0,0 +1,2 @@ +export {default} from "./TitleField"; +export * from "./TitleField"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/URLWidget/URLWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/URLWidget/URLWidget.tsx new file mode 100644 index 000000000..ff7972a63 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/URLWidget/URLWidget.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import {WidgetProps} from "@rjsf/core"; + +const URLWidget = (props: WidgetProps) => { + const {registry} = props; + const {TextWidget} = registry.widgets; + return ; +}; + +export default URLWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/URLWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/URLWidget/index.ts new file mode 100644 index 000000000..6aaa0378e --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/URLWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./URLWidget"; +export * from "./URLWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/UpDownWidget/UpDownWidget.tsx b/misc/config_tools/configurator/src/lib/bs4rjsf/UpDownWidget/UpDownWidget.tsx new file mode 100644 index 000000000..8a732e1c2 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/UpDownWidget/UpDownWidget.tsx @@ -0,0 +1,52 @@ +import React from "react"; + +import Form from "react-bootstrap/Form"; + +import {WidgetProps} from "@rjsf/core"; + +const UpDownWidget = ({ + id, + required, + readonly, + disabled, + label, + value, + onChange, + onBlur, + onFocus, + autofocus, + schema, + uiSchema, + }: WidgetProps) => { + const _onChange = ({ + target: {value}, + }: React.ChangeEvent) => onChange(value); + const _onBlur = ({target: {value}}: React.FocusEvent) => + onBlur(id, value); + const _onFocus = ({ + target: {value}, + }: React.FocusEvent) => onFocus(id, value); + + return ( + + + {uiSchema["ui:title"] || schema.title || label} + {(label || uiSchema["ui:title"] || schema.title) && required ? "*" : null} + + + + ); +}; + +export default UpDownWidget; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/UpDownWidget/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/UpDownWidget/index.ts new file mode 100644 index 000000000..4097027b7 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/UpDownWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./UpDownWidget"; +export * from "./UpDownWidget"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/Widgets/Widgets.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/Widgets/Widgets.ts new file mode 100644 index 000000000..cfd1a5b54 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/Widgets/Widgets.ts @@ -0,0 +1,33 @@ +import CheckboxWidget from "../CheckboxWidget/CheckboxWidget"; +import CheckboxesWidget from "../CheckboxesWidget/CheckboxesWidget"; +import ColorWidget from "../ColorWidget/ColorWidget"; +import DateWidget from "../DateWidget/DateWidget"; +import DateTimeWidget from "../DateTimeWidget/DateTimeWidget"; +import EmailWidget from "../EmailWidget/EmailWidget"; +import PasswordWidget from "../PasswordWidget/PasswordWidget"; +import RadioWidget from "../RadioWidget/RadioWidget"; +import RangeWidget from "../RangeWidget/RangeWidget"; +import SelectWidget from "../SelectWidget/SelectWidget"; +import TextareaWidget from "../TextareaWidget/TextareaWidget"; +import TextWidget from "../TextWidget/TextWidget"; +import UpDownWidget from "../UpDownWidget/UpDownWidget"; +import URLWidget from "../URLWidget/URLWidget"; +import FileWidget from "../FileWidget/FileWidget"; + +export default { + CheckboxWidget, + CheckboxesWidget, + ColorWidget, + DateWidget, + DateTimeWidget, + EmailWidget, + PasswordWidget, + RadioWidget, + RangeWidget, + SelectWidget, + TextareaWidget, + TextWidget, + UpDownWidget, + URLWidget, + FileWidget, +}; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/Widgets/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/Widgets/index.ts new file mode 100644 index 000000000..91b5756bc --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/Widgets/index.ts @@ -0,0 +1,2 @@ +export {default} from "./Widgets"; +export * from "./Widgets"; diff --git a/misc/config_tools/configurator/src/lib/bs4rjsf/index.ts b/misc/config_tools/configurator/src/lib/bs4rjsf/index.ts new file mode 100644 index 000000000..2e1e8faf8 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/bs4rjsf/index.ts @@ -0,0 +1,10 @@ +import Form from "./Form/Form"; + +export {default as Fields} from "./Fields"; +export {default as FieldTemplate} from "./FieldTemplate"; +export {default as Form} from "./Form"; +export {default as ObjectFieldTemplate} from "./ObjectFieldTemplate"; +export {default as Theme} from "./Theme"; +export {default as Widgets} from "./Widgets"; + +export default Form; diff --git a/misc/config_tools/configurator/src/lib/common.js b/misc/config_tools/configurator/src/lib/common.js new file mode 100644 index 000000000..e69de29bb diff --git a/misc/config_tools/configurator/src/lib/helper.jsx b/misc/config_tools/configurator/src/lib/helper.jsx new file mode 100644 index 000000000..65e507862 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/helper.jsx @@ -0,0 +1,221 @@ +import _ from "lodash"; +import xml2json, {parseXml} from "./xml2json"; +import JSON2XML from "./json2xml"; + +import {fs, path} from "@tauri-apps/api" + + +// noinspection JSUnresolvedFunction,JSUnresolvedVariable +class BackendBase { + listConfig = async () => { + await this.init + + let config = await this.read(this.configPath) + if (config == null) { + return {} + } + try { + config = JSON.parse(config) + } catch (e) { + return {} + } + return config + } + + getConfig = async (key, defaultValue) => { + let config = await this.listConfig() + console.log(key, config, defaultValue) + if (config.hasOwnProperty(key)) { + return config[key] + } + return defaultValue + } + + setConfig = async (key, value) => { + let config = await this.listConfig() + config[key] = value + config = JSON.stringify(config) + await this.write(this.configPath, config) + } + + read = async () => { + throw new Error('Not Impl') + } + write = async () => { + throw new Error('Not Impl') + } + list = async () => { + throw new Error('Not Impl') + } + remove = async () => { + throw new Error('Not Impl') + } +} + +export class LocalStorageBackend extends BackendBase { + constructor() { + super() + this.rootFSName = 'acrn-configurator' + this.configPath = 'config.json' + } + + _readRootFS = () => { + let localStorageFS = localStorage.getItem(this.rootFSName) + if (localStorageFS == null) { + return {} + } + localStorageFS = JSON.parse(localStorageFS) + return localStorageFS + } + + _writeRootFS = (fs) => { + localStorage.setItem(this.rootFSName, JSON.stringify(fs)) + } + + read = async (filePath) => { + let localStorageFS = this._readRootFS() + if (localStorageFS.hasOwnProperty(filePath)) { + return localStorageFS[filePath] + } + return null + } + + write = async (filePath, value) => { + let localStorageFS = this._readRootFS() + localStorageFS[filePath] = value + this._writeRootFS(localStorageFS) + } + list = async (dirPath) => { + let localStorageFS = this._readRootFS() + let dirFiles = [] + for (let filepath in localStorageFS) { + if (_.startsWith(filepath, dirPath)) { + dirFiles.push(filepath) + } + } + return dirFiles + } + remove = async (filename) => { + let localStorageFS = this._readRootFS() + if (localStorageFS.hasOwnProperty(filename)) { + delete localStorageFS[filename] + } + } +} + +export class TauriLocalFSBackend extends BackendBase { + constructor() { + super() + this.init = path.homeDir() + .then(async (dirPath) => { + this.configDir = await path.join(dirPath, '.acrn-configurator') + this.configPath = await path.join(this.configDir, 'config.json') + return fs.readDir(this.configDir) + .catch(async () => { + fs.createDir(this.configDir, {recursive: true}) + .then(() => this.write(this.configPath, "{}")) + .catch((reason) => { + alert("Create config dir failed. Error:" + reason) + }) + }) + }) + } + + + read = async (filePath) => { + await this.init + return await fs.readTextFile(filePath) + .catch(reason => { + // Todo: add isFile function to check perm + // alert("Read file error! Error: " + reason); + return null + }) + } + + write = async (filePath, value) => { + await this.init + return await fs.writeFile({ + path: filePath, + contents: value + }).catch((reason => alert("Write file error! Error: " + reason))) + } + + list = async (dirPath) => { + await this.init + return (await fs.readDir(dirPath)) + .filter((file) => file.children == null) + .map((file) => file.path) + } + + remove = async (filePath) => { + await this.init + return await fs.removeFile(filePath) + } + +} + +export class Helper { + constructor(configBackend, fsBackend) { + this.configBackend = configBackend + this.fsBackend = fsBackend + this.color = { + blue: "#1475b2", + green: "#42c02e", + deepGray: "#606060" + } + } + + log(title, content, backgroundColor = this.color.green) { + console.log( + "%c ".concat(title, " %c ").concat(content, " "), + "padding: 1px; border-radius: 3px 0 0 3px; color: #fff; background: ".concat(this.color.deepGray, ";"), + "padding: 1px; border-radius: 0 3px 3px 0; color: #fff; background: ".concat(backgroundColor, ";") + ) + } + + resolveHome = async (filepath) => { + if (filepath[0] === '~') { + return await path.join(await path.homeDir(), filepath.slice(1)) + } + return filepath; + } + + convertXMLTextToObj = (XMLText) => { + let jsonText = xml2json(parseXml(XMLText)) + // console.log(scenarioData) + return JSON.parse(jsonText) + } + + convertObjToXML = (o) => { + // convert our js object to xml + let json2xml = new JSON2XML() + // noinspection UnnecessaryLocalVariableJS + let xml = json2xml.convert(o) + return xml + } + + read = async filePath => { + return await this.fsBackend.read(filePath) + } + + save = async (filePath, text) => { + await this.fsBackend.write(filePath, text) + }; + + list = async dirPath => { + return await this.fsBackend.list(dirPath) + }; + + remove = async filePath => { + await this.fsBackend.remove(filePath).catch((reason => alert("Remove file failed! Error:" + reason))) + } + + getConfig = async (configKeyName, defaultValue) => { + return await this.configBackend.getConfig(configKeyName, defaultValue) + } + + setConfig = async (configKeyName, value) => { + return await this.configBackend.setConfig(configKeyName, value) + }; + +} diff --git a/misc/config_tools/configurator/src/lib/json2xml.jsx b/misc/config_tools/configurator/src/lib/json2xml.jsx new file mode 100644 index 000000000..526ed5b84 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/json2xml.jsx @@ -0,0 +1,88 @@ +import _ from 'lodash' + +export default class JSON2XML { + constructor(indent = ' ', newline = '\n') { + this.xml = '' + this.indent = indent + this.newline = newline + } + + convert = (jsObject) => { + return this.handleConvert(jsObject) + } + + handleConvert(jsObject) { + if (!(_.isObject(jsObject) || _.isArray(jsObject))) { + throw new Error('Not js object') + } + this.xml = '' + for (const jsObjectKey in jsObject) { + this.#convertObject(0, jsObjectKey, jsObject[jsObjectKey]) + } + return this.xml + } + + #getAttrText(jso) { + let attrs = {} + Object.keys(jso).map((childKey) => { + if (_.startsWith(childKey, '@')) { + attrs[childKey.substr(1)] = jso[childKey] + delete jso[childKey] + } + } + ) + let attrText = '' + for (const attrsKey in attrs) { + attrText += ` ${attrsKey}="${attrs[attrsKey]}"` + } + return attrText + } + + addNewlineAndIndent(deepth) { + this.xml += this.newline + _.repeat(this.indent, deepth) + } + + #convertObject(deepth, selfName, jsObjectElement) { + // this.#convertObject('acrn-config',jso['acrn-config']) + // let example = { + // 'acrn-config': { + // '@board': 'whl-ipc-i7', + // hv: {}, + // vm: [ + // {'@id': 1}, + // {'@id': 2}, + // {'@id': 3} + // ] + // } + // } + + if (_.isString(jsObjectElement) || _.isNumber(jsObjectElement)) { + // this.#convertObject('boot_args', 'default') + this.addNewlineAndIndent(deepth) + let val = _.escape(`${jsObjectElement}`) + this.xml += `<${selfName}>${val}` + } else if (_.isArray(jsObjectElement)) { + // this.#convertObject('cpuid', [1,2,3]) + // this.#convertObject('vm', [{},{},{}]) + for (const index in jsObjectElement) { + this.#convertObject(deepth, selfName, jsObjectElement[index]) + } + } else if (_.isObject(jsObjectElement)) { + // this.#convertObject('acrn-config',jso['acrn-config']) + let attrText = this.#getAttrText(jsObjectElement) + this.addNewlineAndIndent(deepth) + this.xml += `<${selfName}${attrText}>` + for (const key in jsObjectElement) { + this.#convertObject(deepth + 1, key, jsObjectElement[key]) + } + this.addNewlineAndIndent(deepth) + this.xml += `` + } else if (jsObjectElement == null) { + //pass + } else { + console.log(jsObjectElement) + debugger; + throw new Error("Unknown Object") + } + } +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/lib/platform/tauri/tauri.jsx b/misc/config_tools/configurator/src/lib/platform/tauri/tauri.jsx new file mode 100644 index 000000000..51895534a --- /dev/null +++ b/misc/config_tools/configurator/src/lib/platform/tauri/tauri.jsx @@ -0,0 +1,22 @@ +import {appWindow} from "@tauri-apps/api/window"; + +class WindowHelper { + minimal = (cb = null) => { + appWindow.minimize().then(() => { + cb ? cb() : false + }) + } + + maxmal = (cb = null) => { + appWindow.toggleMaximize().then(() => { + cb ? cb() : false + }) + } + + close = () => { + appWindow.close().then() + } +} + + +export const windowHelper = new WindowHelper() \ No newline at end of file diff --git a/misc/config_tools/configurator/src/lib/runpy.jsx b/misc/config_tools/configurator/src/lib/runpy.jsx new file mode 100644 index 000000000..e568764b9 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/runpy.jsx @@ -0,0 +1,58 @@ +import dynamicScenario from "../assets/schema/dynamicScenario.py" +import scenario_json from "../assets/schema/scenario.json" +import {Base64} from 'js-base64'; + + +function toJSONString(obj) { + if (_.isString(obj)) { + return JSON.stringify(obj) + } + return JSON.stringify(JSON.stringify(obj)) +} + + +async function initPyodide() { + await pyodide.runPythonAsync( + `import micropip +await micropip.install(['elementpath', 'xmlschema']) +`) + return pyodide +} + +initPyodide() + +function runPyCode(pythonCode) { + pyodide.loadPackagesFromImports(pythonCode) + return pyodide.runPython(pythonCode) +} + +function writeFile(filename, content) { + let file_content = JSON.stringify(content) + return runPyCode( + `import json; open(${toJSONString(filename)},'w',encoding='utf-8').write(json.loads(${toJSONString(file_content)}))` + ) +} + +function readFile(filename) { + return runPyCode( + `open(${toJSONString(filename)},'r',encoding='utf-8').read()` + ) +} + +function loadLibrary(libraryName, content) { + return writeFile(`/lib/python3.9/${libraryName}.py`, content) +} + +function getNewSchema(boardXMLText) { + let params = JSON.stringify({board_xml: boardXMLText, scenario_json: JSON.stringify(scenario_json)}) + params = Base64.encode(params); + let scenario_text = runPyCode(` +params="${params}" +${dynamicScenario} +`) + let new_scenario_json = JSON.parse(scenario_text) + console.log(new_scenario_json) + return new_scenario_json +} + +export {runPyCode, readFile, writeFile, getNewSchema} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/lib/xml2json.js b/misc/config_tools/configurator/src/lib/xml2json.js new file mode 100644 index 000000000..f7f933cc6 --- /dev/null +++ b/misc/config_tools/configurator/src/lib/xml2json.js @@ -0,0 +1,191 @@ +export function parseXml(xml) { + let dom = null; + if (window.DOMParser) { + try { + dom = (new DOMParser()).parseFromString(xml, "text/xml"); + } catch (e) { + dom = null; + } + } else if (window.ActiveXObject) { + try { + dom = new ActiveXObject('Microsoft.XMLDOM'); + dom.async = false; + if (!dom.loadXML(xml)) { + // parse error .. + window.alert(dom.parseError.reason + dom.parseError.srcText); + } + } catch (e) { + dom = null; + } + } else { + alert("cannot parse xml string!"); + } + return dom; +} + +export default function xml2json(xml, tab = "\t") { + let X = { + toObj: function (xml) { + let o = {}; + if (xml.nodeType === 1) { + // element node .. + if (xml.attributes.length) { + // element with attributes .. + for (let i = 0; i < xml.attributes.length; i++) { + o["@" + xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue || "").toString(); + } + } + if (xml.firstChild) { + // element has child nodes .. + let textChild = 0, cdataChild = 0, hasElementChild = false; + for (let n = xml.firstChild; n; n = n.nextSibling) { + if (n.nodeType === 1) { + hasElementChild = true; + } else if (n.nodeType === 3 && n.nodeValue.match(/[^ \f\n\r\t\v]/)) { + // non-whitespace text + textChild++; + } else if (n.nodeType === 4) { + // cdata section node + cdataChild++; + } + } + if (hasElementChild) { + if (textChild < 2 && cdataChild < 2) { + // structured element with evtl. a single text or/and cdata node .. + X.removeWhite(xml); + for (let n = xml.firstChild; n; n = n.nextSibling) { + if (n.nodeType === 3) { + // text node + o["#text"] = X.escape(n.nodeValue); + } else if (n.nodeType === 4) { + // cdata node + o["#cdata"] = X.escape(n.nodeValue); + } else if (o[n.nodeName]) { + // multiple occurence of element .. + if (o[n.nodeName] instanceof Array) { + o[n.nodeName][o[n.nodeName].length] = X.toObj(n); + } else { + o[n.nodeName] = [o[n.nodeName], X.toObj(n)]; + } + + } else { + // first occurence of element.. + o[n.nodeName] = X.toObj(n); + } + } + } else { + // mixed content + if (!xml.attributes.length) { + o = X.escape(X.innerXml(xml)); + } else { + o["#text"] = X.escape(X.innerXml(xml)); + } + } + } else if (textChild) { + // pure text + if (!xml.attributes.length) + o = X.escape(X.innerXml(xml)); + else + o["#text"] = X.escape(X.innerXml(xml)); + } else if (cdataChild) { + // cdata + if (cdataChild > 1) + o = X.escape(X.innerXml(xml)); + else { + for (let n = xml.firstChild; n; n = n.nextSibling) + o["#cdata"] = X.escape(n.nodeValue); + } + } + } + if (!xml.attributes.length && !xml.firstChild) o = null; + } else if (xml.nodeType === 9) { + // document.node + o = X.toObj(xml.documentElement); + } else + alert("unhandled node type: " + xml.nodeType); + return o; + }, + toJson: function (o, name, ind) { + let json = name ? ("\"" + name + "\"") : ""; + if (o instanceof Array) { + for (let i = 0, n = o.length; i < n; i++) + o[i] = X.toJson(o[i], "", ind + "\t"); + json += (name ? ":[" : "[") + (o.length > 1 ? ("\n" + ind + "\t" + o.join(",\n" + ind + "\t") + "\n" + ind) : o.join("")) + "]"; + } else if (o == null) + json += (name && ":") + "null"; + else if (typeof (o) == "object") { + let arr = []; + for (let m in o) + arr[arr.length] = X.toJson(o[m], m, ind + "\t"); + json += (name ? ":{" : "{") + (arr.length > 1 ? ("\n" + ind + "\t" + arr.join(",\n" + ind + "\t") + "\n" + ind) : arr.join("")) + "}"; + } else if (typeof (o) == "string") + json += (name && ":") + "\"" + o.toString() + "\""; + else + json += (name && ":") + o.toString(); + return json; + }, + innerXml: function (node) { + let s = "" + if ("innerHTML" in node) + s = node.innerHTML; + else { + let asXml = function (n) { + let s = ""; + if (n.nodeType === 1) { + s += "<" + n.nodeName; + for (let i = 0; i < n.attributes.length; i++) + s += " " + n.attributes[i].nodeName + "=\"" + (n.attributes[i].nodeValue || "").toString() + "\""; + if (n.firstChild) { + s += ">"; + for (let c = n.firstChild; c; c = c.nextSibling) + s += asXml(c); + s += ""; + } else + s += "/>"; + } else if (n.nodeType === 3) + s += n.nodeValue; + else if (n.nodeType === 4) + s += ""; + return s; + }; + for (let c = node.firstChild; c; c = c.nextSibling) + s += asXml(c); + } + return s; + }, + escape: function (txt) { + return txt.replace(/[\\]/g, "\\\\") + .replace(/["]/g, '\\"') + .replace(/[\n]/g, '\\n') + .replace(/[\r]/g, '\\r'); + }, + removeWhite: function (e) { + e.normalize(); + for (let n = e.firstChild; n;) { + if (n.nodeType === 3) { // text node + if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) { + // pure whitespace text node + let nxt = n.nextSibling; + e.removeChild(n); + n = nxt; + } else + n = n.nextSibling; + } else if (n.nodeType === 1) { + // element node + X.removeWhite(n); + n = n.nextSibling; + } else { + // any other node + n = n.nextSibling; + } + } + return e; + } + }; + if (xml.nodeType === 9) { + // document node + xml = xml.documentElement; + } + let json = X.toJson(X.toObj(X.removeWhite(xml)), xml.nodeName, "\t"); + return "{\n" + tab + (tab ? json.replace(/\t/g, tab) : json.replace(/[\t\n]/g, "")) + "\n}"; +} diff --git a/misc/config_tools/configurator/src/logo.svg b/misc/config_tools/configurator/src/logo.svg new file mode 100644 index 000000000..6b60c1042 --- /dev/null +++ b/misc/config_tools/configurator/src/logo.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/misc/config_tools/configurator/src/main.jsx b/misc/config_tools/configurator/src/main.jsx new file mode 100644 index 000000000..e878a4b86 --- /dev/null +++ b/misc/config_tools/configurator/src/main.jsx @@ -0,0 +1,25 @@ +import VConsole from 'vconsole'; + +const vConsole = new VConsole(); +import React from 'react' +import ReactDOM from 'react-dom' + +import './index.scss' +import './assets/fonts/Roboto.css' + +import App from './App' +import Navbar from "./components/Navbar"; +import MyErrorBoundary from "./pages/Error/MyErrorBoundary"; +import {Container} from "react-bootstrap"; + +ReactDOM.render( + + + + + + + + , + document.getElementById('root') +) diff --git a/misc/config_tools/configurator/src/pages/Config/Config.css b/misc/config_tools/configurator/src/pages/Config/Config.css new file mode 100644 index 000000000..52c3dbd87 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/Config.css @@ -0,0 +1,8 @@ +.card, .card-header { + background-color: #F5F5F5; +} + +.configBody { + height: calc(100vh - 80px); + overflow: auto; +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/Config.jsx b/misc/config_tools/configurator/src/pages/Config/Config.jsx new file mode 100644 index 000000000..106fdea36 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/Config.jsx @@ -0,0 +1,67 @@ +import React from "react"; +import {Accordion, Container} from "react-bootstrap"; + +import "./Config.css" + +import Banner from "../../components/Banner"; + +import backArrow from '../../assets/images/back_arrow_icon.svg' + + +// import ExitACRNConfigurationModal from "./ExitACRNConfigurationModal/ExitACRNConfigurationModal"; +import ImportABoardConfigurationFile from "./ImportABoardConfigurationFile"; +import CreateNewOrImportAnExistingScenario from "./CreateNewOrImportAnExistingScenario"; +import ConfigureSettingsForScenario from "./ConfigureSettingsForScenario"; + +import Footer from "../../components/Footer"; +import {ACRNContext} from "../../ACRNContext"; + +class Config extends React.Component { + constructor(props, context) { + super(props); + let {configurator} = context + this.state = { + WorkingFolder: configurator.WorkingFolder + } + } + + render = () => { + return (
+ + +
+ back to welcome page { + document.location.href = '#' + }}/> Working folder: {this.state.WorkingFolder} +
+
+ + + + + {/**/} + + + + + {/*/!**!/*/} + + + + + {/**/} + + + +
+ +
) + }; + + +} + +Config.contextType = ACRNContext + +export default Config diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/ConfigForm.css b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/ConfigForm.css new file mode 100644 index 000000000..bd8a5eab6 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/ConfigForm.css @@ -0,0 +1,10 @@ +.form-area { + mix-blend-mode: normal; + border: 1px solid #373A77; + box-sizing: border-box; + border-radius: 5px; +} + +.object-property-expand { + display: none; +} diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/ConfigForm.jsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/ConfigForm.jsx new file mode 100644 index 000000000..96e7532f9 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/ConfigForm.jsx @@ -0,0 +1,150 @@ +import React, {Component} from "react" +import Form from "../../../../lib/bs4rjsf" +import {ACRNContext} from "../../../../ACRNContext"; +import SelectWidget from "./IVSHMEM_VM/SelectWidget"; +import TextWidget from "./IVSHMEM_VM/TextWidget"; + +// import CustomTemplateField from "./CustomTemplateField/CustomTemplateField"; + +export class ConfigForm extends Component { + constructor(props) { + super(props); + } + + setFormData = (data) => { + let {configurator} = this.context + let VMID = data['@id'] + + if (VMID == null) { + configurator.programLayer.scenarioData.hv = data + return + } + + let load_order = data['load_order'] + for (let index = 0; index < configurator.programLayer.scenarioData.vm[load_order].length; index++) { + if (configurator.programLayer.scenarioData.vm[load_order][index]['@id'] === VMID) { + configurator.programLayer.scenarioData.vm[load_order][index] = data + } + } + + } + + + getParams = (VMID, mode) => { + let {configurator} = this.context + let schema, formData; + if (VMID === -1) { + schema = configurator.hvSchema[mode] + formData = configurator.programLayer.scenarioData.hv + } else { + let VMData = null; + configurator.programLayer.getOriginScenarioData().vm.map((vmConfig) => { + if (vmConfig['@id'] === VMID) { + VMData = vmConfig + } + }) + schema = configurator.vmSchemas[VMData.load_order][mode] + formData = VMData + } + + return {schema, formData} + } + + + render = () => { + let VMID = this.props.VMID + let mode = this.props.mode + + let params = this.getParams(VMID, mode) + let uiSchema = { + basic: { + DEBUG_OPTIONS: { + BUILD_TYPE: { + "ui:widget": "radio" + } + }, + FEATURES: { + IVSHMEM: { + IVSHMEM_REGION: { + items: { + IVSHMEM_VMS: { + IVSHMEM_VM: { + "ui:style": { + border: "1px solid gray", + padding: "1rem", + borderRadius: "7px" + }, + items: { + VM_NAME: { + "ui:grid": 7, + "ui:widget": 'VM_NAME', + "ui:descLabel": true, + "ui:descLabelAli": 'H', + "ui:descLabelMT": true + }, + VBDF: { + "ui:grid": 5, + "ui:widget": 'VBDF', + "ui:descLabel": true, + "ui:descLabelAli": 'V', + } + } + } + } + } + } + } + }, + vuart_connections: { + vuart_connection: { + items: { + endpoint: { + items: { + vm_name: { + "ui:grid": 6, + "ui:widget": 'VBDF', + "ui:descLabel": true, + "ui:descLabelAli": 'V', + }, + io_port: { + "ui:grid": 6, + "ui:widget": 'VBDF', + "ui:descLabel": true, + "ui:descLabelAli": 'V', + }, + } + } + } + } + } + }, + additionalProperties: { + "ui:widget": "hidden" + } + } + + let widgets = { + VM_NAME: SelectWidget, + VBDF: TextWidget + } + + + return
+

* are required fields

+
{ + let data = e.formData + this.setFormData(data) + }} + /> +
+ } +} + +ConfigForm.contextType = ACRNContext \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/CustomTemplateField.js b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/CustomTemplateField.js new file mode 100644 index 000000000..5eea0cd9f --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/CustomTemplateField.js @@ -0,0 +1,30 @@ +import React from "react"; +import Form from "react-bootstrap/Form"; +import ListGroup from "react-bootstrap/ListGroup"; +import WrapIfAdditional from "./WrapIfAdditional"; +// @ts-ignore +import rst2html from "rst2html"; +import { OverlayTrigger, Popover } from "react-bootstrap"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faCircleExclamation } from "@fortawesome/free-solid-svg-icons"; +const CustomTemplateField = ({ id, children, displayLabel, rawErrors = [], rawHelp, rawDescription, classNames, disabled, label, onDropPropertyClick, onKeyChange, readonly, required, schema }) => { + let descHtml = ""; + if (rawDescription) { + descHtml = rst2html(rawDescription); + } + return (React.createElement(WrapIfAdditional, { classNames: classNames, disabled: disabled, id: id, label: label, onDropPropertyClick: onDropPropertyClick, onKeyChange: onKeyChange, readonly: readonly, required: required, schema: schema }, + React.createElement(Form.Group, null, + displayLabel && rawDescription && (React.createElement(OverlayTrigger, { trigger: ["hover", "focus"], key: "top", placement: "top", overlay: React.createElement(Popover, { id: `popover-positioned-top` }, + React.createElement(Popover.Body, null, + React.createElement(Form.Text, { className: rawErrors.length > 0 ? "text-danger" : "text-muted", dangerouslySetInnerHTML: { __html: descHtml } }))) }, + React.createElement("span", null, + React.createElement(FontAwesomeIcon, { icon: faCircleExclamation, color: rawErrors.length > 0 ? "red" : "gray" })))), + children, + rawErrors.length > 0 && (React.createElement(ListGroup, { as: "ul" }, rawErrors.map((error) => { + return (React.createElement(ListGroup.Item, { as: "li", key: error, className: "border-0 m-0 p-0" }, + React.createElement("small", { className: "m-0 text-danger" }, error))); + }))), + rawHelp && (React.createElement(Form.Text, { className: rawErrors.length > 0 ? "text-danger" : "text-muted", id: id }, rawHelp))))); +}; +export default CustomTemplateField; +//# sourceMappingURL=CustomTemplateField.js.map \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/CustomTemplateField.js.map b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/CustomTemplateField.js.map new file mode 100644 index 000000000..dc6dce9de --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/CustomTemplateField.js.map @@ -0,0 +1 @@ +{"version":3,"file":"CustomTemplateField.js","sourceRoot":"","sources":["CustomTemplateField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,IAAI,MAAM,sBAAsB,CAAC;AACxC,OAAO,SAAS,MAAM,2BAA2B,CAAC;AAClD,OAAO,gBAAgB,MAAM,oBAAoB,CAAA;AACjD,aAAa;AACb,OAAO,QAAQ,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAC,cAAc,EAAE,OAAO,EAAC,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAC,eAAe,EAAC,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAC,mBAAmB,EAAC,MAAM,mCAAmC,CAAC;AAEtE,MAAM,mBAAmB,GAAG,CACxB,EACI,EAAE,EACF,QAAQ,EACR,YAAY,EACZ,SAAS,GAAG,EAAE,EACd,OAAO,EACP,cAAc,EACd,UAAU,EACV,QAAQ,EACR,KAAK,EACL,mBAAmB,EACnB,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,MAAM,EACW,EAAE,EAAE;IAEzB,IAAI,QAAQ,GAAG,EAAE,CAAA;IACjB,IAAI,cAAc,EAAE;QAChB,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;KACvC;IAED,OAAO,CACH,oBAAC,gBAAgB,IACb,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,QAAQ,EAClB,EAAE,EAAE,EAAE,EACN,KAAK,EAAE,KAAK,EACZ,mBAAmB,EAAE,mBAAmB,EACxC,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM;QAEd,oBAAC,IAAI,CAAC,KAAK;YACN,YAAY,IAAI,cAAc,IAAI,CAC/B,oBAAC,cAAc,IACX,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAC3B,GAAG,EAAC,KAAK,EACT,SAAS,EAAC,KAAK,EACf,OAAO,EACH,oBAAC,OAAO,IAAC,EAAE,EAAE,wBAAwB;oBACjC,oBAAC,OAAO,CAAC,IAAI;wBACT,oBAAC,IAAI,CAAC,IAAI,IAAC,SAAS,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,EAC9D,uBAAuB,EAAE,EAAC,MAAM,EAAE,QAAQ,EAAC,GAAG,CAC9C,CACT;gBAEd;oBACI,oBAAC,eAAe,IACZ,IAAI,EAAE,mBAAmB,EACzB,KAAK,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,GAC9C,CACC,CACM,CACpB;YACA,QAAQ;YACR,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CACrB,oBAAC,SAAS,IAAC,EAAE,EAAC,IAAI,IACb,SAAS,CAAC,GAAG,CAAC,CAAC,KAAa,EAAE,EAAE;gBAC7B,OAAO,CACH,oBAAC,SAAS,CAAC,IAAI,IAAC,EAAE,EAAC,IAAI,EAAC,GAAG,EAAE,KAAK,EAAE,SAAS,EAAC,kBAAkB;oBAC5D,+BAAO,SAAS,EAAC,iBAAiB,IAC7B,KAAK,CACF,CACK,CACpB,CAAC;YACN,CAAC,CAAC,CACM,CACf;YACA,OAAO,IAAI,CACR,oBAAC,IAAI,CAAC,IAAI,IACN,SAAS,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,EAC9D,EAAE,EAAE,EAAE,IACL,OAAO,CACA,CACf,CACQ,CACE,CACtB,CAAC;AACN,CAAC,CAAC;AAEF,eAAe,mBAAmB,CAAC"} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/CustomTemplateField.tsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/CustomTemplateField.tsx new file mode 100644 index 000000000..dc404e39c --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/CustomTemplateField.tsx @@ -0,0 +1,97 @@ +import React from "react"; + +import {FieldTemplateProps} from "@rjsf/core"; + +import Form from "react-bootstrap/Form"; +import ListGroup from "react-bootstrap/ListGroup"; +import WrapIfAdditional from "./WrapIfAdditional" +// @ts-ignore +import rst2html from "rst2html" +import {OverlayTrigger, Popover} from "react-bootstrap"; +import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; +import {faCircleExclamation} from "@fortawesome/free-solid-svg-icons"; + +const CustomTemplateField = ( + { + id, + children, + displayLabel, + rawErrors = [], + rawHelp, + rawDescription, + classNames, + disabled, + label, + onDropPropertyClick, + onKeyChange, + readonly, + required, + schema + }: FieldTemplateProps) => { + + let descHtml = "" + if (rawDescription) { + descHtml = rst2html(rawDescription); + } + + return ( + + + {displayLabel && rawDescription && ( + + + 0 ? "text-danger" : "text-muted"} + dangerouslySetInnerHTML={{__html: descHtml}}/> + + + }> + + 0 ? "red" : "gray"} + /> + + + )} + {children} + {rawErrors.length > 0 && ( + + {rawErrors.map((error: string) => { + return ( + + + {error} + + + ); + })} + + )} + {rawHelp && ( + 0 ? "text-danger" : "text-muted"} + id={id}> + {rawHelp} + + )} + + + ); +}; + +export default CustomTemplateField; diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/WrapIfAdditional.js b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/WrapIfAdditional.js new file mode 100644 index 000000000..1845c5985 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/WrapIfAdditional.js @@ -0,0 +1,30 @@ +import React from "react"; +import { utils } from "@rjsf/core"; +import Row from "react-bootstrap/Row"; +import Col from "react-bootstrap/Col"; +import Form from "react-bootstrap/Form"; +import IconButton from "@rjsf/bootstrap-4"; +const { ADDITIONAL_PROPERTY_FLAG } = utils; +const WrapIfAdditional = ({ children, disabled, id, label, onDropPropertyClick, onKeyChange, readonly, required, schema, }) => { + const keyLabel = `${label} Key`; // i18n ? + const additional = schema.hasOwnProperty(ADDITIONAL_PROPERTY_FLAG); + if (!additional) { + return children; + } + const handleBlur = ({ target }) => onKeyChange(target.value); + // @ts-ignore + return (React.createElement(Row, { key: `${id}-key` }, + React.createElement(Col, { xs: 5 }, + React.createElement(Form.Group, null, + React.createElement(Form.Label, null, keyLabel), + React.createElement(Form.Control, { required: required, defaultValue: label, disabled: disabled || readonly, id: `${id}-key`, name: `${id}-key`, onBlur: !readonly ? handleBlur : undefined, type: "text" }))), + React.createElement(Col, { xs: 5 }, children), + React.createElement(Col, { xs: 2, className: "py-4" }, + React.createElement(IconButton + // @ts-ignore + , { + // @ts-ignore + block: true, className: "w-100", variant: "danger", icon: "remove", tabIndex: -1, disabled: disabled || readonly, onClick: onDropPropertyClick(label) })))); +}; +export default WrapIfAdditional; +//# sourceMappingURL=WrapIfAdditional.js.map \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/WrapIfAdditional.js.map b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/WrapIfAdditional.js.map new file mode 100644 index 000000000..cd823ef9d --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/WrapIfAdditional.js.map @@ -0,0 +1 @@ +{"version":3,"file":"WrapIfAdditional.js","sourceRoot":"","sources":["WrapIfAdditional.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAGjC,OAAO,GAAG,MAAM,qBAAqB,CAAC;AACtC,OAAO,GAAG,MAAM,qBAAqB,CAAC;AACtC,OAAO,IAAI,MAAM,sBAAsB,CAAC;AAExC,OAAO,UAAU,MAAM,mBAAmB,CAAC;AAE3C,MAAM,EAAC,wBAAwB,EAAC,GAAG,KAAK,CAAC;AAezC,MAAM,gBAAgB,GAAG,CAAC,EACI,QAAQ,EACR,QAAQ,EACR,EAAE,EACF,KAAK,EACL,mBAAmB,EACnB,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,MAAM,GACc,EAAE,EAAE;IAClD,MAAM,QAAQ,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC,SAAS;IAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;IAEnE,IAAI,CAAC,UAAU,EAAE;QACb,OAAO,QAAQ,CAAC;KACnB;IAED,MAAM,UAAU,GAAG,CAAC,EAAC,MAAM,EAAqC,EAAE,EAAE,CAChE,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAG9B,aAAa;IACb,OAAO,CACH,oBAAC,GAAG,IAAC,GAAG,EAAE,GAAG,EAAE,MAAM;QACjB,oBAAC,GAAG,IAAC,EAAE,EAAE,CAAC;YACN,oBAAC,IAAI,CAAC,KAAK;gBACP,oBAAC,IAAI,CAAC,KAAK,QAAE,QAAQ,CAAc;gBACnC,oBAAC,IAAI,CAAC,OAAO,IACT,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAE,KAAK,EACnB,QAAQ,EAAE,QAAQ,IAAI,QAAQ,EAC9B,EAAE,EAAE,GAAG,EAAE,MAAM,EACf,IAAI,EAAE,GAAG,EAAE,MAAM,EACjB,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EAC1C,IAAI,EAAC,MAAM,GACb,CACO,CACX;QACN,oBAAC,GAAG,IAAC,EAAE,EAAE,CAAC,IACL,QAAQ,CACP;QACN,oBAAC,GAAG,IAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAC,MAAM;YACxB,oBAAC,UAAU;YACP,aAAa;;gBAAb,aAAa;gBACb,KAAK,EAAE,IAAI,EACX,SAAS,EAAC,OAAO,EACjB,OAAO,EAAC,QAAQ,EAChB,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,CAAC,CAAC,EACZ,QAAQ,EAAE,QAAQ,IAAI,QAAQ,EAC9B,OAAO,EAAE,mBAAmB,CAAC,KAAK,CAAC,GACrC,CACA,CACJ,CACT,CAAC;AACN,CAAC,CAAC;AAEF,eAAe,gBAAgB,CAAC"} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/WrapIfAdditional.tsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/WrapIfAdditional.tsx new file mode 100644 index 000000000..56b606bd2 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/CustomTemplateField/WrapIfAdditional.tsx @@ -0,0 +1,85 @@ +import React from "react"; + +import {utils} from "@rjsf/core"; +import {JSONSchema7} from "json-schema"; + +import Row from "react-bootstrap/Row"; +import Col from "react-bootstrap/Col"; +import Form from "react-bootstrap/Form"; + +import IconButton from "@rjsf/bootstrap-4"; + +const {ADDITIONAL_PROPERTY_FLAG} = utils; + +type WrapIfAdditionalProps = { + children: React.ReactElement; + classNames: string; + disabled: boolean; + id: string; + label: string; + onDropPropertyClick: (index: string) => (event?: any) => void; + onKeyChange: (index: string) => (event?: any) => void; + readonly: boolean; + required: boolean; + schema: JSONSchema7; +}; + +const WrapIfAdditional = ({ + children, + disabled, + id, + label, + onDropPropertyClick, + onKeyChange, + readonly, + required, + schema, + }: WrapIfAdditionalProps) => { + const keyLabel = `${label} Key`; // i18n ? + const additional = schema.hasOwnProperty(ADDITIONAL_PROPERTY_FLAG); + + if (!additional) { + return children; + } + + const handleBlur = ({target}: React.FocusEvent) => + onKeyChange(target.value); + + + // @ts-ignore + return ( + + + + {keyLabel} + + + + + {children} + + + + + + ); +}; + +export default WrapIfAdditional; diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/IVSHMEM_VM/SelectWidget/SelectWidget.tsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/IVSHMEM_VM/SelectWidget/SelectWidget.tsx new file mode 100644 index 000000000..0c5eef43a --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/IVSHMEM_VM/SelectWidget/SelectWidget.tsx @@ -0,0 +1,130 @@ +import React from "react"; + +import Form from "react-bootstrap/Form"; + +import {WidgetProps} from "@rjsf/core"; +import {utils} from "@rjsf/core"; +import _ from "lodash"; + +const {asNumber, guessType} = utils; + +const nums = new Set(["number", "integer"]); + +/** + * This is a silly limitation in the DOM where option change event values are + * always retrieved as strings. + */ +const processValue = (schema: any, value: any) => { + // "enum" is a reserved word, so only "type" and "items" can be destructured + const {type, items} = schema; + if (value === "") { + return undefined; + } else if (type === "array" && items && nums.has(items.type)) { + return value.map(asNumber); + } else if (type === "boolean") { + return value === "true"; + } else if (type === "number") { + return asNumber(value); + } + + // If type is undefined, but an enum is present, try and infer the type from + // the enum values + if (schema.enum) { + if (schema.enum.every((x: any) => guessType(x) === "number")) { + return asNumber(value); + } else if (schema.enum.every((x: any) => guessType(x) === "boolean")) { + return value === "true"; + } + } + + return value; +}; + +const SelectWidget = ( + { + schema, + id, + options, + label, + required, + disabled, + readonly, + value, + multiple, + autofocus, + onChange, + onBlur, + onFocus, + placeholder, + rawErrors = [], + }: WidgetProps) => { + const {enumOptions, enumDisabled} = options; + + const emptyValue = multiple ? [] : ""; + + function getValue( + event: React.FocusEvent | React.ChangeEvent | any, + multiple: Boolean, + ) { + if (multiple) { + return [].slice + .call(event.target.options as any) + .filter((o: any) => o.selected) + .map((o: any) => o.value); + } else { + return event.target.value; + } + } + + let isFirst = _.endsWith(id, 'IVSHMEM_VM_0_VM_NAME') + return ( + +
+ 0 ? "is-invalid" : "")} + onBlur={ + onBlur && + ((event: React.FocusEvent) => { + const newValue = getValue(event, multiple); + onBlur(id, processValue(schema, newValue)); + }) + } + onFocus={ + onFocus && + ((event: React.FocusEvent) => { + const newValue = getValue(event, multiple); + onFocus(id, processValue(schema, newValue)); + }) + } + onChange={(event: React.ChangeEvent) => { + const newValue = getValue(event, multiple); + onChange(processValue(schema, newValue)); + }}> + {!multiple && schema.default === undefined && ( + + )} + {(enumOptions as any).map(({value, label}: any, i: number) => { + const disabled: any = + Array.isArray(enumDisabled) && + (enumDisabled as any).indexOf(value) != -1; + return ( + + ); + })} + +
+
+ ); +}; + +export default SelectWidget; diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/IVSHMEM_VM/SelectWidget/index.ts b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/IVSHMEM_VM/SelectWidget/index.ts new file mode 100644 index 000000000..6e104f2ea --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/IVSHMEM_VM/SelectWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./SelectWidget"; +export * from "./SelectWidget"; diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/IVSHMEM_VM/TextWidget/TextWidget.tsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/IVSHMEM_VM/TextWidget/TextWidget.tsx new file mode 100644 index 000000000..23e0ca0e5 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/IVSHMEM_VM/TextWidget/TextWidget.tsx @@ -0,0 +1,72 @@ +import React from "react"; + +import Form from "react-bootstrap/Form"; + +import {WidgetProps} from "@rjsf/core"; +import _ from "lodash"; + +const TextWidget = ( + { + id, + placeholder, + required, + readonly, + disabled, + type, + label, + value, + onChange, + onBlur, + onFocus, + autofocus, + options, + schema, + rawErrors = [], + uiSchema, + }: WidgetProps) => { + const _onChange = ({ + target: {value}, + }: React.ChangeEvent) => + onChange(value === "" ? options.emptyValue : value); + const _onBlur = ({target: {value}}: React.FocusEvent) => + onBlur(id, value); + const _onFocus = ({ + target: {value}, + }: React.FocusEvent) => onFocus(id, value); + const inputType = (type || schema.type) === "string" ? "text" : `${type || schema.type}`; + + // const classNames = [rawErrors.length > 0 ? "is-invalid" : "", type === 'file' ? 'custom-file-label': ""] + // let isFirst = _.endsWith(id, 'IVSHMEM_VM_0_VBDF') + return ( + +
+ 0 ? "is-invalid" : ""} + list={schema.examples ? `examples_${id}` : undefined} + type={inputType} + value={value || value === 0 ? value : ""} + onChange={_onChange} + onBlur={_onBlur} + onFocus={_onFocus} + /> +
+ {schema.examples ? ( + + {(schema.examples as string[]) + .concat(schema.default ? ([schema.default] as string[]) : []) + .map((example: any) => { + return + ) : null} +
+ ); +}; + +export default TextWidget; diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/IVSHMEM_VM/TextWidget/index.ts b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/IVSHMEM_VM/TextWidget/index.ts new file mode 100644 index 000000000..e7e838908 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/IVSHMEM_VM/TextWidget/index.ts @@ -0,0 +1,2 @@ +export {default} from "./TextWidget"; +export * from "./TextWidget"; diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/index.jsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/index.jsx new file mode 100644 index 000000000..d3ebf86f2 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigForm/index.jsx @@ -0,0 +1,5 @@ +import './ConfigForm.css' +import {ConfigForm} from "./ConfigForm"; + + +export default ConfigForm; \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/ConfigTabBar.css b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/ConfigTabBar.css new file mode 100644 index 000000000..b59ad88c4 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/ConfigTabBar.css @@ -0,0 +1,12 @@ +.TabBox { + display: flex; + user-select: none; + border: 1px solid #007B81; + box-sizing: border-box; + border-radius: 5px; +} + +.rjsf button[type='submit'] { + display: none; +} + diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/ConfigTabBar.jsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/ConfigTabBar.jsx new file mode 100644 index 000000000..5ac542d10 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/ConfigTabBar.jsx @@ -0,0 +1,84 @@ +import React, {Component} from "react"; +import "./ConfigTabBar.css" +import Tab from "./Tab"; +import TabSplitter from "./TabSplitter"; +import TabAdd from "./TabAdd"; +import {ACRNContext} from "../../../../ACRNContext"; + +export default class ConfigTabBar extends Component { + constructor(props) { + super(props); + this.state = { + activeVMID: -1 + } + } + + componentDidMount = () => { + let {configurator} = this.context + this.funRegisterID = configurator.programLayer.register( + configurator.eventName.scenarioDataUpdate, () => { + this.forceUpdate() + } + ) + } + + componentWillUnmount = () => { + let {configurator} = this.context + configurator.programLayer.unregister(this.funRegisterID) + } + + active = (activeVMID = null) => { + if (activeVMID == null) { + return this.state.activeVMID + } + this.props.callback ? this.props.callback(activeVMID) : null; + return this.setState({activeVMID: activeVMID}) + } + + tab = (vmConfig, desc) => { + console.log(vmConfig) + return + } + + + render = () => { + let {configurator} = this.context + let scenarioData = configurator.programLayer.scenarioData + + let PRE_LAUNCHED_VM = scenarioData.vm.PRE_LAUNCHED_VM.map((vmConfig) => { + return this.tab(vmConfig, 'Pre-Launched') + }) + let SERVICE_VM = scenarioData.vm.SERVICE_VM.map((vmConfig) => { + return this.tab(vmConfig, 'ServiceVM') + }) + let POST_LAUNCHED_VM = scenarioData.vm.POST_LAUNCHED_VM.map((vmConfig) => { + return this.tab(vmConfig, 'Post-Launched') + }) + + return ( +
+ + + {PRE_LAUNCHED_VM} + { + configurator.programLayer.addVM('PRE_LAUNCHED_VM') + }}/> + {SERVICE_VM} + {POST_LAUNCHED_VM} + { + if (scenarioData.vm.SERVICE_VM.length === 0) { + configurator.programLayer.addVM('SERVICE_VM') + } + configurator.programLayer.addVM('POST_LAUNCHED_VM') + }}/> +
+ ) + } +} +ConfigTabBar.contextType = ACRNContext \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/Tab/Tab.css b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/Tab/Tab.css new file mode 100644 index 000000000..e22c4815b --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/Tab/Tab.css @@ -0,0 +1,17 @@ +div.TabBox{ + overflow-x: auto; +} +.TabBox .Tab { + background: #E1F2EF; + border-radius: 5px; + color: #007B81; + border: 1px solid #007B81; + margin: 0 0.5rem 0 0; + cursor: pointer; + white-space: nowrap; +} + +.TabBox .Tab.Active { + background: #373A77; + color: white; +} diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/Tab/Tab.jsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/Tab/Tab.jsx new file mode 100644 index 000000000..58ee1a84e --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/Tab/Tab.jsx @@ -0,0 +1,22 @@ +import React, {Component} from "react"; +import './Tab.css' + +export default class Tab extends Component { + constructor(props) { + super(props); + } + + setActive = () => { + this.props.active(this.props.VMID) + } + + render() { + let active = this.props.active() === this.props.VMID ? "Active" : '' + return ( +
+
{this.props.title}
+
{this.props.desc}
+
+ ) + } +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/Tab/index.jsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/Tab/index.jsx new file mode 100644 index 000000000..d559af4d7 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/Tab/index.jsx @@ -0,0 +1,3 @@ +import Tab from "./Tab"; + +export default Tab \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabAdd/TabAdd.css b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabAdd/TabAdd.css new file mode 100644 index 000000000..0fbb5a74c --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabAdd/TabAdd.css @@ -0,0 +1,4 @@ +.TabAdd { + cursor: pointer; + white-space: nowrap; +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabAdd/TabAdd.jsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabAdd/TabAdd.jsx new file mode 100644 index 000000000..5d6a18b40 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabAdd/TabAdd.jsx @@ -0,0 +1,12 @@ +import React, {Component} from "react"; +import addIcon from './assets/Plus.svg' +import './TabAdd.css' + +export default class TabAdd extends Component { + render() { + return (
+
{"Add
+
{this.props.desc}
+
) + } +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabAdd/assets/Plus.svg b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabAdd/assets/Plus.svg new file mode 100644 index 000000000..a3c91700f --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabAdd/assets/Plus.svg @@ -0,0 +1,4 @@ + + + + diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabAdd/index.jsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabAdd/index.jsx new file mode 100644 index 000000000..17a69f7d8 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabAdd/index.jsx @@ -0,0 +1,3 @@ +import TabAdd from "./TabAdd"; + +export default TabAdd \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabSplitter/TabSplitter.css b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabSplitter/TabSplitter.css new file mode 100644 index 000000000..a64298309 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabSplitter/TabSplitter.css @@ -0,0 +1,6 @@ +.TabSplitter { + height: 74px; + width: 0; + border-right: 1px solid #C4C4C4; + margin: 0 0.5rem; +} diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabSplitter/TabSplitter.jsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabSplitter/TabSplitter.jsx new file mode 100644 index 000000000..6751502a8 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabSplitter/TabSplitter.jsx @@ -0,0 +1,10 @@ +import {Component} from "react"; +import './TabSplitter.css' + +export default class TabSplitter extends Component { + render() { + return ( +
{" "}
+ ) + } +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabSplitter/index.jsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabSplitter/index.jsx new file mode 100644 index 000000000..bfc0be382 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/TabSplitter/index.jsx @@ -0,0 +1,3 @@ +import TabSplitter from "./TabSplitter"; + +export default TabSplitter \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/index.jsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigTabBar/index.jsx new file mode 100644 index 000000000..e69de29bb diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigureSettingsForScenario.css b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigureSettingsForScenario.css new file mode 100644 index 000000000..5abc12ca6 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigureSettingsForScenario.css @@ -0,0 +1,55 @@ +.nav-tabs .nav-link { + font-family: Roboto, serif; + font-style: normal; + font-weight: 500; + font-size: 22px; + line-height: 26px; + + background: #E1F2EF; + border: 1px solid #007B81; + box-sizing: border-box; + box-shadow: inset 0 -1px 0 #D7D7D7; + border-radius: 5px 5px 0 0; + border-bottom: none; + + color: #007B81; + margin-right: 4px; + padding: 1rem 1.5rem; +} + +.nav-tabs .nav-link.active { + mix-blend-mode: normal; + border: 1px solid #373A77; + border-bottom: none; + box-sizing: border-box; + border-radius: 5px 5px 0 0; + + + font-weight: 600; + + color: #373A77; +} + +.nav-tabs .nav-link.active:after { + display: block; + content: ""; + height: 3px; + background: white; + position: relative; + top: calc(1rem + 1px); + left: -1.5rem; + width: calc(100% + 3rem + 1px); +} + +.tab-content { + margin-top: -2px; +} +.nav-tabs{ + border-bottom: none; +} + +.deleteVM { + height: 52px; + max-width: 210px; + width: 100%; +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigureSettingsForScenario.jsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigureSettingsForScenario.jsx new file mode 100644 index 000000000..214c91f10 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/ConfigureSettingsForScenario.jsx @@ -0,0 +1,93 @@ +import React, {Component} from "react"; +import "./ConfigureSettingsForScenario.css" +import {Accordion, Button} from "react-bootstrap"; +import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; +import {faMinus} from "@fortawesome/free-solid-svg-icons"; +import ConfigTabBar from "./ConfigTabBar/ConfigTabBar"; +import ConfigForm from "./ConfigForm"; +import {ACRNContext} from "../../../ACRNContext"; + +export default class ConfigureSettingsForScenario extends Component { + constructor(props) { + super(props); + // VMID possible value + // [-1 0 1 2 3] + this.state = { + VMID: -1, + tabMode: 'basic' + } + } + + tabSwitch = (VMID) => { + this.setState({VMID: VMID}) + document.querySelector('#BasicFormTab').click() + this.forceUpdate() + } + + tab = (tabID, title, isActive) => { + let active = isActive ? 'active' : '' + return ( +
  • + +
  • + ) + } + + tabsContent = (mode, VMID) => { + let tabID = mode + 'Form' + + return (
    + +
    ) + } + + render = () => { + let {configurator} = this.context + return ( + +
    +
    3. Configure settings for scenario and launch scripts
    + +
    +
    + + +
    + +
    +
    +
    +
      + {this.tab('BasicForm', 'Basic Parameters', true)} + {this.tab('AdvancedForm', 'Advanced Parameters', false)} +
    + +
    +
    + {this.tabsContent('Basic', this.state.VMID)} + {this.tabsContent('Advanced', this.state.VMID)} +
    + +
    +
    +
    ) + } +} +ConfigureSettingsForScenario.contextType = ACRNContext \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/index.jsx b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/index.jsx new file mode 100644 index 000000000..42a2b4174 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ConfigureSettingsForScenario/index.jsx @@ -0,0 +1,3 @@ +import ConfigureSettingsForScenario from "./ConfigureSettingsForScenario"; + +export default ConfigureSettingsForScenario \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/CreateNewOrImportAnExistingScenario.jsx b/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/CreateNewOrImportAnExistingScenario.jsx new file mode 100644 index 000000000..5698f939b --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/CreateNewOrImportAnExistingScenario.jsx @@ -0,0 +1,126 @@ +import React, {Component} from "react"; +import {Accordion, Button, Col, Form, Row} from "react-bootstrap"; + +import CreateScenarioModal from "./CreateScenarioModal/CreateScenarioModal"; +import Banner from "../../../components/Banner"; +import {dialog} from "@tauri-apps/api"; +import {ACRNContext} from "../../../ACRNContext"; + +export default class CreateNewOrImportAnExistingScenario extends Component { + constructor(props) { + super(props); + this.scenarioXMLSelect = React.createRef() + this.scenarioXMLFileInput = React.createRef() + this.state = { + scenarioConfigFiles: [], + stage: props.stage, + scenarioName: '', + scenarioConfig: {}, + selected: null + } + } + + componentDidMount() { + this.scenarioHistoryUpdate() + } + + scenarioHistoryUpdate() { + let {configurator} = this.context + return configurator.getHistory('scenario').then((scenarioHistory) => { + this.setState({scenarioConfigFiles: scenarioHistory}) + }) + } + + + openFileDialog = () => { + dialog.open({directory: false, multiple: false}).then(this.scenarioChange) + } + + scenarioChange = (filepath) => { + console.log(filepath) + let {configurator} = this.context + configurator.addHistory('scenario', filepath).then(() => { + this.scenarioHistoryUpdate().then(() => { + this.scenarioXMLSelect.current.value = filepath + }) + }) + } + + importScenario = () => { + let {configurator} = this.context + configurator.programLayer.loadScenario(this.scenarioXMLSelect.current.value) + .then(() => { + this.setState({selected: configurator.WorkingFolder + '/scenario.xml'}) + }) + .catch((reason) => { + console.log(reason) + alert(reason) + }) + }; + + render = () => { + let {configurator} = this.context + let scenarioHistorySelect = this.state.scenarioConfigFiles.map((optionValue, index) => { + return () + }) + return ( + + +
    + 2. Create new or import an existing scenario +
    +
    + + + +

    Current scenario: + {this.state.selected ? this.state.selected : "none selected"}

    +
    + { + this.setState({selected: configurator.WorkingFolder + '/scenario.xml'}) + }}/> +
    + + + + + + Recently used scenarios: + + + + + + + + + + + +
    + + {scenarioHistorySelect} + + + + + Browse for scenario file… + +
    +
    + +
    +
    +
    + + +
    +
    +
    + ) + } +} +CreateNewOrImportAnExistingScenario.contextType = ACRNContext \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/CreateScenarioModal/CreateScenarioModal.css b/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/CreateScenarioModal/CreateScenarioModal.css new file mode 100644 index 000000000..27786294e --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/CreateScenarioModal/CreateScenarioModal.css @@ -0,0 +1,17 @@ +.vmNum input[type="number"] { + max-width: 69px; + text-align: center; +} +.vmNum b{ + padding: 0 0; +} + +.vmNum b, .vmNum input { + flex: 0 1 50%; +} + +.modal-header .btn-close{ + margin-right: 15px; + color: white; + font-weight: bolder; +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/CreateScenarioModal/CreateScenarioModal.jsx b/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/CreateScenarioModal/CreateScenarioModal.jsx new file mode 100644 index 000000000..bd9438fc7 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/CreateScenarioModal/CreateScenarioModal.jsx @@ -0,0 +1,128 @@ +import {Button, Form, Modal} from "react-bootstrap"; +import {Component} from "react"; +import "./CreateScenarioModal.css" +import {ACRNContext} from "../../../../ACRNContext"; + +export default class CreateScenarioModal extends Component { + constructor(props) { + super(props); + this.state = { + show: false, + mode: 'POST_LAUNCHED_VM' + } + } + + + handelScenarioCreateEvent = () => { + function getVal(id) { + // @ts-ignore + return document.querySelector('#' + id + 'Inp').value + } + + function getInt(id) { + return parseInt(getVal(id)) + } + + const vmNum = { + PRE_LAUNCHED_VM: this.state.mode === 'POST_LAUNCHED_VM' ? 0 : getInt('PRE_LAUNCHED_VM'), + SERVICE_VM: this.state.mode === 'PRE_LAUNCHED_VM' ? 0 : getInt('SERVICE_VM'), + POST_LAUNCHED_VM: this.state.mode === 'PRE_LAUNCHED_VM' ? 0 : getInt('POST_LAUNCHED_VM'), + } + let {configurator} = this.context + + configurator.programLayer.newScenario(vmNum.PRE_LAUNCHED_VM, vmNum.SERVICE_VM, vmNum.POST_LAUNCHED_VM) + this.props.cb() + this.setState({show: false}) + } + + + render = () => { + + const handleClose = () => this.setState({show: false}); + const handleShow = () => this.setState({show: true}); + const handleScenarioModeChange = (event) => this.setState({mode: event.target.id}) + + return ( + <> + + + + + Create a new Scenario + + +
    +
    +
    +

    + Choose a scenario type: + + Learn about scenarios + +

    + Shared (Post-launched VMs only)} + defaultChecked={this.state.mode === 'POST_LAUNCHED_VM'} + /> + + Partitioned (Pre-launched VMs only)} + defaultChecked={this.state.mode === 'PRE_LAUNCHED_VM'} + /> + + Hybrid (Both pre-launched and post-launched VMs)} + defaultChecked={this.state.mode === 'hybrid'} + /> +
    + VM Configuration +

    This system’s board supports a maximum of 8 VMs.

    +

    How many of each VM type do you want in your scenario? (You can change these + later.)

    +
    + Pre-launch + VMs: + + Service VM: + + Post-launch + VMs: + +
    +
    +
    +
    + + + + +
    + + ) + } +} + +CreateScenarioModal.contextType = ACRNContext \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/CreateScenarioModal/index.jsx b/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/CreateScenarioModal/index.jsx new file mode 100644 index 000000000..f70751faf --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/CreateScenarioModal/index.jsx @@ -0,0 +1,3 @@ +import CreateScenarioModal from "./CreateScenarioModal"; + +export default CreateScenarioModal \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/index.jsx b/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/index.jsx new file mode 100644 index 000000000..9a5af579d --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/CreateNewOrImportAnExistingScenario/index.jsx @@ -0,0 +1,3 @@ +import CreateNewOrImportAnExistingScenario from "./CreateNewOrImportAnExistingScenario"; + +export default CreateNewOrImportAnExistingScenario \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ExitACRNConfigurationModal/ExitACRNConfigurationModal.jsx b/misc/config_tools/configurator/src/pages/Config/ExitACRNConfigurationModal/ExitACRNConfigurationModal.jsx new file mode 100644 index 000000000..84792f416 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ExitACRNConfigurationModal/ExitACRNConfigurationModal.jsx @@ -0,0 +1,63 @@ +import {CloseButton, Button, Modal} from "react-bootstrap"; +import {Component, useState} from "react"; +import {ACRNContext} from "../../../ACRNContext"; + +export default class ExitACRNConfigurationModal extends Component { + constructor(props) { + super(props); + this.state = { + show: false + } + } + + render() { + let {configurator} = this.context + + const handleClose = () => this.setState({show: false}); + const handleShow = (e) => { + this.setState({show: true}) + e.preventDefault() + } + + return ( + <> + + + + + Exit ACRN Configuration + + +
    + ACRN Configuration files will be saved in the working folder: +

    + {configurator.WorkingFolder} +

    +
    +
    + + + + + +
    + + ); + } +} +ExitACRNConfigurationModal.contextType = ACRNContext diff --git a/misc/config_tools/configurator/src/pages/Config/ImportABoardConfigurationFile/ImportABoardConfigurationFile.jsx b/misc/config_tools/configurator/src/pages/Config/ImportABoardConfigurationFile/ImportABoardConfigurationFile.jsx new file mode 100644 index 000000000..27f45d9bd --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ImportABoardConfigurationFile/ImportABoardConfigurationFile.jsx @@ -0,0 +1,165 @@ +import React, {Component} from "react"; +import {Accordion, Button, Col, Form, Row} from "react-bootstrap"; +import Banner from "../../../components/Banner"; +import {dialog} from "@tauri-apps/api"; +import {ACRNContext} from "../../../ACRNContext"; + +export default class ImportABoardConfigurationFile extends Component { + constructor(props) { + super(props); + this.boardXMLSelect = React.createRef() + this.boardXMLFileInput = React.createRef() + this.state = { + disableImport: true, + boardFiles: [], + boardName: '', + boardXML: '', + BIOS_INFO: '', + BASE_BOARD_INFO: '' + } + } + + componentDidMount() { + let {configurator} = this.context + configurator.getHistory('board').then((boardFiles) => { + let disableImport = boardFiles.length === 0 + this.setState({boardFiles, disableImport}) + }) + } + + + openFileDialog = () => { + //this.boardXMLFileInput.current.click() + dialog.open({directory: false, multiple: false}).then((filepath) => { + this.boardChange(filepath) + }) + }; + + boardChange = (filepath) => { + let {configurator} = this.context + configurator.addHistory('board', filepath).then(() => { + return configurator.getHistory('board') + }).then((boardFiles) => { + console.log(boardFiles) + this.setState({ + disableImport: false, + boardFiles + }) + }).then(() => { + this.boardXMLSelect.current.value = filepath + }) + } + + importBoard = () => { + let {configurator} = this.context + + if (!this.state.boardXML) { + configurator.loadBoard(this.boardXMLSelect.current.value, this.updateBoardInfo) + } else { + this.openFileDialog() + } + } + + getNodeTextContent(boardXML, nodeSelector) { + return boardXML.querySelector(nodeSelector).textContent; + } + + updateBoardInfo = (boardName, boardXMLText) => { + const boardXML = (new DOMParser()).parseFromString(boardXMLText, 'text/xml') + let BIOS_INFO = this.getNodeTextContent(boardXML, "BIOS_INFO").replace(/\s+BIOS Information\s+/, '') + let BASE_BOARD_INFO = this.getNodeTextContent(boardXML, "BASE_BOARD_INFO").replace(/\s+Base Board Information\s+/, '') + this.setState({ + boardName: boardName, + boardXML: boardXML, + BIOS_INFO: BIOS_INFO, + BASE_BOARD_INFO: BASE_BOARD_INFO + }) + this.boardXMLSelect.current.disabled = true + } + + render() { + let boardHistorySelect = this.state.boardFiles.map((optionValue, index) => { + return ( + + ) + }) + return ( + + +
    + 1. Import a board configuration file +
    +
    + + + + + +
    + + {this.state.boardXML ? 'Current board file:' : 'Recently used board files:'} + + + + + + + + + + + +
    + + {boardHistorySelect} + + + + + Browse for file… + +
    +
    + +
    +
    +
    + + +
    + + + + +
    +
    + {this.state.boardXML ? "Current Board: " + this.state.boardName : "No board information has been imported yet."} +
    +
    +
    + + + {this.state.BASE_BOARD_INFO} + + + {this.state.BIOS_INFO} + + +
    +
    +
    + +
    +
    +
    + ) + } +} +ImportABoardConfigurationFile.contextType = ACRNContext \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Config/ImportABoardConfigurationFile/index.jsx b/misc/config_tools/configurator/src/pages/Config/ImportABoardConfigurationFile/index.jsx new file mode 100644 index 000000000..57c43eeea --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Config/ImportABoardConfigurationFile/index.jsx @@ -0,0 +1,3 @@ +import ImportABoardConfigurationFile from "./ImportABoardConfigurationFile"; + +export default ImportABoardConfigurationFile \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Error/Error.jsx b/misc/config_tools/configurator/src/pages/Error/Error.jsx new file mode 100644 index 000000000..19763d6f4 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Error/Error.jsx @@ -0,0 +1,15 @@ +import React from 'react'; + +export class Error extends React.Component { + render() { + return ( +
    + There's nothing here!
    + Your URL: {document.location.href} +
    + ); + } +} + + +export default Error; \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Error/MyErrorBoundary.jsx b/misc/config_tools/configurator/src/pages/Error/MyErrorBoundary.jsx new file mode 100644 index 000000000..e0bf6c260 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Error/MyErrorBoundary.jsx @@ -0,0 +1,23 @@ +import {Component} from "react"; + +export default class MyErrorBoundary extends Component { + state = { + hasError: false, + }; + + static getDerivedStateFromError(error) { + return {hasError: true}; + }; + + componentDidCatch(error, errorInfo) { + // A custom error logging function + console.log(error, errorInfo); + }; + + render() { + return this.state.hasError ? <> + Error detect, you can see error log in vconsole at right bottom. + Please report error log to me, https://github.com/Weiyi-Feng/acrn-hypervisor/issue . + : this.props.children; + } +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Welcome/ExitACRNConfigurationModal/ExitACRNConfigurationModal.jsx b/misc/config_tools/configurator/src/pages/Welcome/ExitACRNConfigurationModal/ExitACRNConfigurationModal.jsx new file mode 100644 index 000000000..25ceb1654 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Welcome/ExitACRNConfigurationModal/ExitACRNConfigurationModal.jsx @@ -0,0 +1,41 @@ +import {CloseButton, Button, Modal} from "react-bootstrap"; +import {useState} from "react"; + +export default function ExitACRNConfigurationModal(props) { + const [show, setShow] = useState(false); + + const handleClose = () => setShow(false); + const handleShow = (e) => { + setShow(true); + e.preventDefault() + } + + return ( + <> + + + + + Exit ACRN Configuration + + +
    + Do you want exit ACRN Configuration? +
    +
    + + + + +
    + + ); +} + diff --git a/misc/config_tools/configurator/src/pages/Welcome/StartNewConfigurationPanel/StartNewConfigurationPanel.jsx b/misc/config_tools/configurator/src/pages/Welcome/StartNewConfigurationPanel/StartNewConfigurationPanel.jsx new file mode 100644 index 000000000..f50b6618d --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Welcome/StartNewConfigurationPanel/StartNewConfigurationPanel.jsx @@ -0,0 +1,138 @@ +import React from "react"; +import {useNavigate} from "react-router"; +import {Button, Form} from "react-bootstrap"; + +import Confirm from "../../../components/Confirm/Confirm"; +import {dialog, fs} from "@tauri-apps/api"; +import {ACRNContext} from "../../../ACRNContext"; +import {invoke} from "@tauri-apps/api/tauri"; + +class StartNewConfigurationPanel extends React.Component { + constructor(props, context) { + super(props); + const {navigate} = this.props; + this.navigate = navigate + this.pathInput = React.createRef() + + this.state = {defaultPath: ""} + } + + componentDidMount = () => { + invoke("get_home",).then( + (path) => { + let ps = "/"; + if (path.indexOf("\\") > 0) { + ps = "\\" + } + path = [path, "acrn-work", "MyConfiguration"].join(ps) + ps + console.log(path) + this.setState({defaultPath: path}) + + } + ) + } + + addRecentDir = async (dirPath) => { + let {configurator} = this.context; + await configurator.addHistory("recentlyWorkingFolders", dirPath); + } + + nextPage = (WorkingFolder) => { + this.addRecentDir(WorkingFolder) + .then(() => { + let {configurator} = this.context; + let params = configurator.settingWorkingFolder(WorkingFolder) + this.navigate(params); + }) + } + + openDir = () => { + dialog.open({ + title: "Start new configurator", + directory: true, + multiple: false + }).then((filePath) => { + this.pathInput.current.value = filePath + }).catch() + } + + useFolder = async () => { + let {helper} = this.context + let folderPath = this.pathInput.current.value ? this.pathInput.current.value : this.pathInput.current.placeholder; + helper.resolveHome(folderPath).then((homeResolvePath) => { + fs.readDir(homeResolvePath) + .then((files) => { + console.log("Directory exists.", files) + if (files.length > 0) { + confirm("Directory exists, overwrite it?") + .then((r) => { + if (r) this.nextPage(folderPath) + }) + } else { + this.nextPage(folderPath) + } + }) + .catch(() => { + fs.createDir(homeResolvePath, {recursive: true}) + .then(() => { + console.log('Directory created successfully!'); + this.nextPage(folderPath) + }).catch((err) => { + return console.error(err); + }) + }) + }) + } + + + handleConfirm = (params) => { + console.log(params) + } + + + render = () => { + return (
    + Start a new + configuration +

    + ACRN Configurator saves your scenario and configuration files into a working + folder. +

    + + + + + + + + + + + +
    + + + Browse for folder… +
    +
    + + +
    +
    +
    +
    ) + } +} + +StartNewConfigurationPanel.contextType = ACRNContext; + +export default function (props) { + const navigate = useNavigate(); + + return ; +} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Welcome/StartNewConfigurationPanel/index.jsx b/misc/config_tools/configurator/src/pages/Welcome/StartNewConfigurationPanel/index.jsx new file mode 100644 index 000000000..02eed6cdb --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Welcome/StartNewConfigurationPanel/index.jsx @@ -0,0 +1,3 @@ +import StartNewConfigurationPanel from "./StartNewConfigurationPanel"; + +export default StartNewConfigurationPanel \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Welcome/UseAnExistingConfigurationPanel/UseAnExistingConfigurationPanel.jsx b/misc/config_tools/configurator/src/pages/Welcome/UseAnExistingConfigurationPanel/UseAnExistingConfigurationPanel.jsx new file mode 100644 index 000000000..1e2217bf0 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Welcome/UseAnExistingConfigurationPanel/UseAnExistingConfigurationPanel.jsx @@ -0,0 +1,123 @@ +import {useNavigate} from "react-router"; +import React from "react"; +import {Button, Form} from "react-bootstrap"; +import {dialog} from "@tauri-apps/api"; +import {ACRNContext} from "../../../ACRNContext"; + + +class UseAnExistingConfigurationPanel extends React.Component { + constructor(props) { + super(props); + const {navigate} = this.props; + this.navigate = navigate + this.pathSelect = React.createRef() + this.state = { + recentDirs: [] + } + } + + componentDidMount() { + this.updateHistory() + } + + updateHistory = () => { + let {configurator} = this.context + return configurator.getHistory("recentlyWorkingFolders") + .then((recentDirs) => { + this.setState({recentDirs}) + }) + } + + recentDir = () => { + let recent = this.state.recentDirs; + let result = [] + for (let i = 0; i < recent.length; i++) { + let dirPath = recent[i]; + result.push() + } + + return result; + } + + addRecentDir = (dirPath) => { + let {config, configurator} = this.context + return configurator.addHistory("recentlyWorkingFolders", dirPath) + } + + nextPage = (WorkingFolder) => { + let {configurator} = this.context + this.addRecentDir(WorkingFolder).then(() => { + let params = configurator.settingWorkingFolder(WorkingFolder) + this.navigate(params); + }) + } + + openDir = async () => { + await dialog.open({ + title: 'Open Working Folder', + directory: true, + multiple: false + }).then(async (existDir) => { + await this.addRecentDir(existDir) + await this.updateHistory() + this.pathSelect.current.value = existDir + }).catch() + } + + useFolder = () => { + let folderPath = this.pathSelect.current.value; + if (!folderPath) { + alert("Please select existing configuration folder!") + return + } + this.nextPage(folderPath) + } + + render() { + let recent_dir = this.recentDir(); + return ( +
    + Use an existing configuration +

    + Open a working folder to retrieve an existing configuration. +

    + + + + + + + + + + + +
    + + {recent_dir} + + + Browse for folder… +
    +
    + +
    +
    +
    + +
    + ) + } +} + +UseAnExistingConfigurationPanel.contextType = ACRNContext + +export default function (props) { + const navigate = useNavigate(); + + return ; +} diff --git a/misc/config_tools/configurator/src/pages/Welcome/UseAnExistingConfigurationPanel/index.jsx b/misc/config_tools/configurator/src/pages/Welcome/UseAnExistingConfigurationPanel/index.jsx new file mode 100644 index 000000000..8a1258bda --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Welcome/UseAnExistingConfigurationPanel/index.jsx @@ -0,0 +1,3 @@ +import UseAnExistingConfigurationPanel from "./UseAnExistingConfigurationPanel"; + +export default UseAnExistingConfigurationPanel \ No newline at end of file diff --git a/misc/config_tools/configurator/src/pages/Welcome/Welcome.css b/misc/config_tools/configurator/src/pages/Welcome/Welcome.css new file mode 100644 index 000000000..8f25f2239 --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Welcome/Welcome.css @@ -0,0 +1,8 @@ +.wel-btn { + max-width: 221px; + width: 100%; +} + +.banner.welcome { + min-height: 164px; +} diff --git a/misc/config_tools/configurator/src/pages/Welcome/Welcome.jsx b/misc/config_tools/configurator/src/pages/Welcome/Welcome.jsx new file mode 100644 index 000000000..61c49c1cd --- /dev/null +++ b/misc/config_tools/configurator/src/pages/Welcome/Welcome.jsx @@ -0,0 +1,53 @@ +import React from "react"; +import {Col, Container, Row} from "react-bootstrap"; + +import './Welcome.css' + +import Banner from "../../components/Banner"; + +import StartNewConfigurationPanel from "./StartNewConfigurationPanel"; +import UseAnExistingConfigurationPanel from "./UseAnExistingConfigurationPanel"; +import Footer from "../../components/Footer"; + +class Welcome extends React.Component { + render() { + return ( +
    + + +
    + ACRN Configurator helps you set up and customize your ACRN hypervisor and VMs. +
    +
    +

    +

    This is a preview version, please be careful.
    + If you find a bug, please report it to   + + https://github.com/Weiyi-Feng/acrn-hypervisor + . +

    + + + +
    + +
    + + + +
    + +
    + + +
    + +
    +
    + +
    + ) + } +} + +export default Welcome diff --git a/misc/config_tools/configurator/src/plugin/tauri-plugin.ts b/misc/config_tools/configurator/src/plugin/tauri-plugin.ts new file mode 100644 index 000000000..4cb4ce9e7 --- /dev/null +++ b/misc/config_tools/configurator/src/plugin/tauri-plugin.ts @@ -0,0 +1,71 @@ +const fs = require('fs') +const path = require('path') + +import type {ConfigEnv, Plugin, ResolvedConfig} from "vite"; +import replace from "@rollup/plugin-replace"; + +import cli from "@tauri-apps/cli" +import Config from "../../src-tauri/types/config" + +import tauriConf from "../../src-tauri/tauri.json"; + + +interface Options { + config?: (c: Config, e: ConfigEnv) => Config; +} + + +export default (options?: Options): Plugin => { + let tauriConfig: Config = {...tauriConf}; + let viteConfig: ResolvedConfig; + + const tauri = (mode: "dev" | "build"): Promise => { + // Generate `tauri.conf.json` by `tauri.json`. + console.log("Generate `tauri.conf.json` by `tauri.json`.") + let filePath = path.resolve(__dirname, '..', '..', 'src-tauri', 'tauri.conf.json') + let config = JSON.stringify(tauriConfig) + try { + fs.writeFileSync(filePath, config) + return cli.run([mode], 'tauri') + } catch (err) { + console.error(err) + return Promise.reject(err) + } + } + + return { + ...replace({ + "process.env.IS_TAURI": "true", + preventAssignment: false + }), + name: "tauri-plugin", + configureServer(server) { + server?.httpServer?.on("listening", () => { + if (!process.env.TAURI_SERVE) { + process.env.TAURI_SERVE = "true"; + delete tauriConfig["$schema"] + tauri('dev').finally() + } + }); + }, + closeBundle() { + if (!process.env.TAURI_BUILD) { + process.env.TAURI_BUILD = "true"; + delete tauriConfig["$schema"] + tauri('build').finally() + } + }, + config(viteConfig, env) { + process.env.IS_TAURI = "true"; + if (options && options.config) { + options.config(tauriConfig, env); + } + if (env.command === "build") { + viteConfig.base = "/"; + } + }, + configResolved(resolvedConfig) { + viteConfig = resolvedConfig; + }, + }; +}; \ No newline at end of file diff --git a/misc/config_tools/configurator/src/plugin/text-plugin.js b/misc/config_tools/configurator/src/plugin/text-plugin.js new file mode 100644 index 000000000..2ebdfa92e --- /dev/null +++ b/misc/config_tools/configurator/src/plugin/text-plugin.js @@ -0,0 +1,17 @@ +export default function textFileResolver(fileRegex) { + function compileFileToJS(src) { + return src; + } + return { + name: 'transform-xsd-file', + transform(src, id) { + if (fileRegex.test(id)) { + return { + code: compileFileToJS(src), + map: null // 如果可行将提供 source map + }; + } + } + }; +} +//# sourceMappingURL=text-plugin.js.map \ No newline at end of file diff --git a/misc/config_tools/configurator/src/plugin/text-plugin.js.map b/misc/config_tools/configurator/src/plugin/text-plugin.js.map new file mode 100644 index 000000000..53d2a40a1 --- /dev/null +++ b/misc/config_tools/configurator/src/plugin/text-plugin.js.map @@ -0,0 +1 @@ +{"version":3,"file":"text-plugin.js","sourceRoot":"","sources":["text-plugin.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,SAAiB;IACtD,SAAS,eAAe,CAAC,GAAW;QAChC,OAAO,GAAG,CAAA;IACd,CAAC;IAED,OAAO;QACH,IAAI,EAAE,oBAAoB;QAC1B,SAAS,CAAC,GAAW,EAAE,EAAU;YAC7B,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;gBACpB,OAAO;oBACH,IAAI,EAAE,eAAe,CAAC,GAAG,CAAC;oBAC1B,GAAG,EAAE,IAAI,CAAC,qBAAqB;iBAClC,CAAA;aACJ;QACL,CAAC;KACJ,CAAA;AACL,CAAC"} \ No newline at end of file diff --git a/misc/config_tools/configurator/src/plugin/text-plugin.ts b/misc/config_tools/configurator/src/plugin/text-plugin.ts new file mode 100644 index 000000000..eab74d1e8 --- /dev/null +++ b/misc/config_tools/configurator/src/plugin/text-plugin.ts @@ -0,0 +1,24 @@ +import _ from "lodash"; +import * as fs from "fs"; + +export default function textFileResolver(fileRegex: RegExp) { + function compileFileToJS(id: string, src: string) { + if (_.endsWith(id, '.txt')) { + let src = fs.readFileSync(id, {encoding: "utf-8"}) + return "export default " + JSON.stringify(src) + } + return "export default " + JSON.stringify(src) + } + + return { + name: 'text-file-resolver', + transform(src: string, id: string) { + if (fileRegex.test(id)) { + return { + code: compileFileToJS(id, src), + map: null // 如果可行将提供 source map + } + } + } + } +} \ No newline at end of file diff --git a/misc/config_tools/configurator/tsconfig.json b/misc/config_tools/configurator/tsconfig.json new file mode 100644 index 000000000..9450bff21 --- /dev/null +++ b/misc/config_tools/configurator/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "strict": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "sourceMap": true, + "esModuleInterop": true, + "lib": [ + "esnext", + "dom" + ], + "types": [ + "vite/client" + ], + "jsx": "react" + } +} \ No newline at end of file diff --git a/misc/config_tools/configurator/vite.config.js b/misc/config_tools/configurator/vite.config.js new file mode 100644 index 000000000..5435694b0 --- /dev/null +++ b/misc/config_tools/configurator/vite.config.js @@ -0,0 +1,17 @@ +import path from "path"; + +import {defineConfig} from 'vite' + +import react from '@vitejs/plugin-react' +import tauri from './src/plugin/tauri-plugin' +import textFileResolver from './src/plugin/text-plugin' + + +// https://vitejs.dev/config/ +export default defineConfig({ + base: './', + plugins: [react(), tauri(), textFileResolver(/\.(xsd|py|txt)$/)], + build: { + outDir: path.resolve(__dirname, 'build') + } +}) diff --git a/misc/config_tools/configurator/yarn.lock b/misc/config_tools/configurator/yarn.lock new file mode 100644 index 000000000..5616c8184 --- /dev/null +++ b/misc/config_tools/configurator/yarn.lock @@ -0,0 +1,1399 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.1.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" + integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.0" + +"@babel/code-frame@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + +"@babel/compat-data@^7.16.4": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" + integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== + +"@babel/core@^7.16.12": + version "7.17.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.5.tgz#6cd2e836058c28f06a4ca8ee7ed955bbf37c8225" + integrity sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.17.2" + "@babel/parser" "^7.17.3" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.3" + "@babel/types" "^7.17.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + +"@babel/generator@^7.17.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" + integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== + dependencies: + "@babel/types" "^7.17.0" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" + integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-compilation-targets@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" + integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== + dependencies: + "@babel/compat-data" "^7.16.4" + "@babel/helper-validator-option" "^7.16.7" + browserslist "^4.17.5" + semver "^6.3.0" + +"@babel/helper-environment-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" + integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" + integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== + dependencies: + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-get-function-arity@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" + integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-hoist-variables@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" + integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-imports@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" + integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-transforms@^7.16.7": + version "7.17.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz#3c3b03cc6617e33d68ef5a27a67419ac5199ccd0" + integrity sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.3" + "@babel/types" "^7.17.0" + +"@babel/helper-plugin-utils@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" + integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== + +"@babel/helper-simple-access@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" + integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-split-export-declaration@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" + integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + +"@babel/helper-validator-option@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" + integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== + +"@babel/helpers@^7.17.2": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417" + integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.0" + "@babel/types" "^7.17.0" + +"@babel/highlight@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.16.7", "@babel/parser@^7.17.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" + integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== + +"@babel/plugin-syntax-jsx@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz#50b6571d13f764266a113d77c82b4a6508bbe665" + integrity sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-react-jsx-development@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz#43a00724a3ed2557ed3f276a01a929e6686ac7b8" + integrity sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.16.7" + +"@babel/plugin-transform-react-jsx-self@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.16.7.tgz#f432ad0cba14c4a1faf44f0076c69e42a4d4479e" + integrity sha512-oe5VuWs7J9ilH3BCCApGoYjHoSO48vkjX2CbA5bFVhIuO2HKxA3vyF7rleA4o6/4rTDbk6r8hBW7Ul8E+UZrpA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-react-jsx-source@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.16.7.tgz#1879c3f23629d287cc6186a6c683154509ec70c0" + integrity sha512-rONFiQz9vgbsnaMtQlZCjIRwhJvlrPET8TabIUK2hzlXw9B9s2Ieaxte1SCOOXMbWRHodbKixNf3BLcWVOQ8Bw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-react-jsx@^7.16.7": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz#eac1565da176ccb1a715dae0b4609858808008c1" + integrity sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-jsx" "^7.16.7" + "@babel/types" "^7.17.0" + +"@babel/runtime@^7.13.16", "@babel/runtime@^7.14.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.7": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" + integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.17.2": + version "7.17.8" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.8.tgz#3e56e4aff81befa55ac3ac6a0967349fd1c5bca2" + integrity sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/template@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" + integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" + integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.17.3" + "@babel/types" "^7.17.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.16.7", "@babel/types@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" + integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + +"@fortawesome/fontawesome-common-types@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.3.0.tgz#949995a05c0d8801be7e0a594f775f1dbaa0d893" + integrity sha512-CA3MAZBTxVsF6SkfkHXDerkhcQs0QPofy43eFdbWJJkZiq3SfiaH1msOkac59rQaqto5EqWnASboY1dBuKen5w== + +"@fortawesome/fontawesome-svg-core@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.3.0.tgz#343fac91fa87daa630d26420bfedfba560f85885" + integrity sha512-UIL6crBWhjTNQcONt96ExjUnKt1D68foe3xjEensLDclqQ6YagwCRYVQdrp/hW0ALRp/5Fv/VKw+MqTUWYYvPg== + dependencies: + "@fortawesome/fontawesome-common-types" "^0.3.0" + +"@fortawesome/free-regular-svg-icons@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.0.0.tgz#f3cb91dac643472fe8138024b93fbfbdf05675cc" + integrity sha512-lYK6oyQL8HwZUAVWGqF7TGuwQBVfphNBVTdvPSD3h4gmQfGazm/xcwg3kmtcRycu3y6QspOC7hPXSoJbVqSYCw== + dependencies: + "@fortawesome/fontawesome-common-types" "^0.3.0" + +"@fortawesome/free-solid-svg-icons@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.0.0.tgz#bed4a501b631c6cfa35c09830f7cb63ffca1589d" + integrity sha512-o4FZ1XbndcgeWNb8Wh0y+Hgf73CjmyOQowUSaqQCtgIIdS+XliSBSOwCl330wER+I6CGYE96hT27bHBPmzX2Gg== + dependencies: + "@fortawesome/fontawesome-common-types" "^0.3.0" + +"@fortawesome/react-fontawesome@^0.1.17": + version "0.1.17" + resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.17.tgz#06fc06cb1a721e38e5b50b4a1cb851e9b9c77d7a" + integrity sha512-dX43Z5IvMaW7fwzU8farosYjKNGfRb2HB/DgjVBHeJZ/NSnuuaujPPx0YOdcAq+n3mqn70tyCde2HM1mqbhiuw== + dependencies: + prop-types "^15.8.1" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" + integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.11" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" + integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== + +"@jridgewell/trace-mapping@^0.3.0": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" + integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@popperjs/core@^2.10.1", "@popperjs/core@^2.11.2": + version "2.11.2" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.2.tgz#830beaec4b4091a9e9398ac50f865ddea52186b9" + integrity sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA== + +"@react-aria/ssr@^3.0.1": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@react-aria/ssr/-/ssr-3.1.2.tgz#665a6fd56385068c7417922af2d0d71b0618e52d" + integrity sha512-amXY11ImpokvkTMeKRHjsSsG7v1yzzs6yeqArCyBIk60J3Yhgxwx9Cah+Uu/804ATFwqzN22AXIo7SdtIaMP+g== + dependencies: + "@babel/runtime" "^7.6.2" + +"@restart/hooks@^0.4.0", "@restart/hooks@^0.4.5": + version "0.4.5" + resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.4.5.tgz#e7acbea237bfc9e479970500cf87538b41a1ed02" + integrity sha512-tLGtY0aHeIfT7aPwUkvQuhIy3+q3w4iqmUzFLPlOAf/vNUacLaBt1j/S//jv/dQhenRh8jvswyMojCwmLvJw8A== + dependencies: + dequal "^2.0.2" + +"@restart/ui@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@restart/ui/-/ui-1.0.1.tgz#379f8340ab14adc18522731a1be6e32eaa10ef92" + integrity sha512-hLAqltcAjQYtjGuHBHKyPpR3ScTxzdkSYNvniwBfN7rUDbYiHu/UZiI1hvV2idJeUvktRnz29l7W9BnNLHrG6Q== + dependencies: + "@babel/runtime" "^7.13.16" + "@popperjs/core" "^2.10.1" + "@react-aria/ssr" "^3.0.1" + "@restart/hooks" "^0.4.0" + "@types/warning" "^3.0.0" + dequal "^2.0.2" + dom-helpers "^5.2.0" + prop-types "^15.7.2" + uncontrollable "^7.2.1" + warning "^4.0.3" + +"@rjsf/core@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@rjsf/core/-/core-4.0.1.tgz#3363aadbaf40f7086f8669c4a645ed0cddd6c2da" + integrity sha512-3HZ5Udy/Yvtixjn/dOcVm4IBoF/HM/LmUAPZt98elSAISga3vhzGc3zv7Fi3IbDNrvL6ZdJbfIj+BtR0q4Rnrg== + dependencies: + "@types/json-schema" "^7.0.7" + ajv "^6.7.0" + core-js-pure "^3.6.5" + json-schema-merge-allof "^0.6.0" + jsonpointer "^5.0.0" + lodash "^4.17.15" + nanoid "^3.1.23" + prop-types "^15.7.2" + react-is "^16.9.0" + +"@rollup/plugin-replace@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-4.0.0.tgz#e34c457d6a285f0213359740b43f39d969b38a67" + integrity sha512-+rumQFiaNac9y64OHtkHGmdjm7us9bo1PlbgQfdihQtuNxzjpaB064HbRnewUOggLQxVCCyINfStkgmBeQpv1g== + dependencies: + "@rollup/pluginutils" "^3.1.0" + magic-string "^0.25.7" + +"@rollup/pluginutils@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== + dependencies: + "@types/estree" "0.0.39" + estree-walker "^1.0.1" + picomatch "^2.2.2" + +"@rollup/pluginutils@^4.1.2": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.2.tgz#ed5821c15e5e05e32816f5fb9ec607cdf5a75751" + integrity sha512-ROn4qvkxP9SyPeHaf7uQC/GPFY6L/OWy9+bd9AwcjOAWQwxRscoEyAUD8qCY5o5iL4jqQwoLk2kaTKJPb/HwzQ== + dependencies: + estree-walker "^2.0.1" + picomatch "^2.2.2" + +"@tauri-apps/api@^1.0.0-rc.1": + version "1.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@tauri-apps/api/-/api-1.0.0-rc.1.tgz#ce26a0fe30d8980a4682d50015eec28ed4a23c1e" + integrity sha512-VBUOmfT8ea02JB/Qr+FHeaLnug5BRA7ro2pX47q0GZCbZsU9b+iPnOXl0ShJwT0melR7B6iamyhDwkHStMVfQA== + dependencies: + type-fest "2.11.2" + +"@tauri-apps/cli-darwin-arm64@1.0.0-rc.5": + version "1.0.0-rc.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.0.0-rc.5.tgz#9374be8c96afa1cf77b5647bc81fe1a05006757d" + integrity sha512-X+3EIAUGfoL8uE6PBADZC8FcUISe4JPQCxXgaVv6ehoZGoCh/pFJF7AvBGTQxbnvngqM7Xce4Lmh63Io2/5ggw== + +"@tauri-apps/cli-darwin-x64@1.0.0-rc.5": + version "1.0.0-rc.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.0.0-rc.5.tgz#4db1dd56a228bfafe5b3f64c7661abbe5606e804" + integrity sha512-fEpgOdAvKdq9C5/yip8RnwP1VS+nRrtKdzzplu4jY6njDVH/Vom8mg+EfXkCY5RveCaoskJMFgUvt10IGeZHBA== + +"@tauri-apps/cli-linux-arm-gnueabihf@1.0.0-rc.5": + version "1.0.0-rc.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.0.0-rc.5.tgz#0f1ff84c534908a54fbe63b45004abc6d4f03f4d" + integrity sha512-V7sWSBrpLyvkQxpkHIM8JltYqQhiTpThySDjO8POtrTqkRwM5BXORcCYhxTAKCedecfYK/RNUJ6Q0t7+3jS6DQ== + +"@tauri-apps/cli-linux-arm64-gnu@1.0.0-rc.5": + version "1.0.0-rc.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.0.0-rc.5.tgz#c5d2f1dd962d80a1958261229778b410b86254d4" + integrity sha512-HhM+2FInxtUAI/41LF4fDEzmhLQUq6DOoo7fLN94vgWlhsPyWZoDGP9pA043XbO86+4OX5JZUW1SnTVXMwEaMA== + +"@tauri-apps/cli-linux-arm64-musl@1.0.0-rc.5": + version "1.0.0-rc.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.0.0-rc.5.tgz#f485db9ca5402f5d2c4585801a3aaa4519bd67e8" + integrity sha512-DhHdKOhf3+peA/sM0c9CpxK89cp8GVwOB5osFW55fxBZbD0mJFeL2SzjkgfGFqFu6Ci/ZiibQGfEp8XTC8OsYA== + +"@tauri-apps/cli-linux-x64-gnu@1.0.0-rc.5": + version "1.0.0-rc.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.0.0-rc.5.tgz#e468939585bc98e80ec827d0a3d8ba06a7cc38e8" + integrity sha512-pZzsOHRGG/mdcn7fF/yOIOdeVzGxZUtZqvlGSd90ZM9Ps3//uYGCBHoNTbeSwp/V6+D0KVDaSCbm9lYlHoXcdA== + +"@tauri-apps/cli-linux-x64-musl@1.0.0-rc.5": + version "1.0.0-rc.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.0.0-rc.5.tgz#a1308e93850555f2b6c97b5d7cdbbb9afaa803e2" + integrity sha512-COwWCbOhEjBlzGRGTa0ESO4/AiC0cBZ2UEPExRn++S+kWSPJ2vsyMdCLu3hiMy1ABSIRcQ4Vc68M1iVkLhOHHw== + +"@tauri-apps/cli-win32-x64-msvc@1.0.0-rc.5": + version "1.0.0-rc.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.0.0-rc.5.tgz#d15c95143d9123d10c510e28ba90df5349b68ecd" + integrity sha512-zzizUmPWvnWjj+IUCk36kVjS9j1Bg5JmnwOW5QdX26+a64q5vocmVimCgrfZ5STw3sDFXE++S55ghpzhhH5o+g== + +"@tauri-apps/cli@^1.0.0-rc.5": + version "1.0.0-rc.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli/-/cli-1.0.0-rc.5.tgz#db8ca22c9f55f5400d1c6addd78ee1df5dc15a29" + integrity sha512-Q3D0R5YdZRA5EcL206hwwKCyXpet2mRDcfaRTU/IXwF73bS4AMja+JdAGfO2cyHuSvXd+b//Cgbei2zCG8M6hw== + optionalDependencies: + "@tauri-apps/cli-darwin-arm64" "1.0.0-rc.5" + "@tauri-apps/cli-darwin-x64" "1.0.0-rc.5" + "@tauri-apps/cli-linux-arm-gnueabihf" "1.0.0-rc.5" + "@tauri-apps/cli-linux-arm64-gnu" "1.0.0-rc.5" + "@tauri-apps/cli-linux-arm64-musl" "1.0.0-rc.5" + "@tauri-apps/cli-linux-x64-gnu" "1.0.0-rc.5" + "@tauri-apps/cli-linux-x64-musl" "1.0.0-rc.5" + "@tauri-apps/cli-win32-x64-msvc" "1.0.0-rc.5" + +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + +"@types/invariant@^2.2.33": + version "2.2.35" + resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.35.tgz#cd3ebf581a6557452735688d8daba6cf0bd5a3be" + integrity sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg== + +"@types/json-schema@^7.0.7": + version "7.0.9" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" + integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + +"@types/lodash@^4.14.179": + version "4.14.179" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.179.tgz#490ec3288088c91295780237d2497a3aa9dfb5c5" + integrity sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w== + +"@types/node@^17.0.21": + version "17.0.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644" + integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ== + +"@types/prop-types@*", "@types/prop-types@^15.7.3": + version "15.7.4" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" + integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== + +"@types/react-transition-group@^4.4.1": + version "4.4.4" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.4.tgz#acd4cceaa2be6b757db61ed7b432e103242d163e" + integrity sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@>=16.14.8", "@types/react@>=16.9.11": + version "17.0.39" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.39.tgz#d0f4cde092502a6db00a1cded6e6bf2abb7633ce" + integrity sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + +"@types/warning@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52" + integrity sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI= + +"@vitejs/plugin-react@^1.0.7": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-1.2.0.tgz#4cfb4c0475e93885e56d66ff15e12ef4c34b0af0" + integrity sha512-Rywwt0IXXg6yQ0hv3cMT3mtdDcGIw31mGaa+MMMAT651LhoXLF2yFy4LrakiTs7UKs7RPBo9eNgaS8pgl2A6Qw== + dependencies: + "@babel/core" "^7.16.12" + "@babel/plugin-transform-react-jsx" "^7.16.7" + "@babel/plugin-transform-react-jsx-development" "^7.16.7" + "@babel/plugin-transform-react-jsx-self" "^7.16.7" + "@babel/plugin-transform-react-jsx-source" "^7.16.7" + "@rollup/pluginutils" "^4.1.2" + react-refresh "^0.11.0" + resolve "^1.22.0" + +ajv@^6.7.0: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + 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" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bootstrap@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.1.3.tgz#ba081b0c130f810fa70900acbc1c6d3c28fa8f34" + integrity sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q== + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.17.5: + version "4.19.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.3.tgz#29b7caad327ecf2859485f696f9604214bedd383" + integrity sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg== + dependencies: + caniuse-lite "^1.0.30001312" + electron-to-chromium "^1.4.71" + escalade "^3.1.1" + node-releases "^2.0.2" + picocolors "^1.0.0" + +caniuse-lite@^1.0.30001312: + version "1.0.30001312" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" + integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== + +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +"chokidar@>=3.0.0 <4.0.0": + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +classnames@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" + integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +compute-gcd@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/compute-gcd/-/compute-gcd-1.2.1.tgz#34d639f3825625e1357ce81f0e456a6249d8c77f" + integrity sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg== + dependencies: + validate.io-array "^1.0.3" + validate.io-function "^1.0.2" + validate.io-integer-array "^1.0.0" + +compute-lcm@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/compute-lcm/-/compute-lcm-1.1.2.tgz#9107c66b9dca28cefb22b4ab4545caac4034af23" + integrity sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ== + dependencies: + compute-gcd "^1.2.1" + validate.io-array "^1.0.3" + validate.io-function "^1.0.2" + validate.io-integer-array "^1.0.0" + +convert-source-map@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== + dependencies: + safe-buffer "~5.1.1" + +copy-text-to-clipboard@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" + integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== + +core-js-pure@^3.6.5: + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" + integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== + +core-js@^3.11.0: + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94" + integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig== + +csstype@^3.0.2: + version "3.0.10" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5" + integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA== + +debug@^4.1.0: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +dequal@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.2.tgz#85ca22025e3a87e65ef75a7a437b35284a7e319d" + integrity sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug== + +dom-helpers@^5.0.1, dom-helpers@^5.2.0, dom-helpers@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + +electron-to-chromium@^1.4.71: + version "1.4.73" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.73.tgz#422f6f514315bcace9615903e4a9b6b9fa283137" + integrity sha512-RlCffXkE/LliqfA5m29+dVDPB2r72y2D2egMMfIy3Le8ODrxjuZNVo4NIC2yPL01N4xb4nZQLwzi6Z5tGIGLnA== + +esbuild-android-64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.24.tgz#d826ac29a9b983dc200a0ca407c34c64d2480b38" + integrity sha512-mbhO8NepmUZ84cP/axGR8IzH1Trth+uknEJzz36cZl8FfMA3ooaiBsMyzJ35s70QEAreiEt1XzltZ4pcfOsVUA== + +esbuild-android-arm64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.24.tgz#f8aaf28dbd4d7b80d30b0323c7a645e3a12b5de9" + integrity sha512-wM3iuLZjaA9BhlMOH6mWvTGXwPJsLOuAbMkGiczSY+NLeG2WF1ouCcuhFz2jZCbnw9lnI30QWgzebNBQi9K8SA== + +esbuild-darwin-64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.24.tgz#9f6e4b94066e9c5e521b19176a85edd7f94ac074" + integrity sha512-GDaCV5e9mdrJkrGT91W8WCqQ/+fvB/nsULIu4l7Ik7dlQd5uB4qeKRcFFl5Vz5ODK/C/UWZmKmMQWokZsLNWLQ== + +esbuild-darwin-arm64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.24.tgz#6b8ce7f2a3e1210cc672c73d658669e5f88b8efb" + integrity sha512-reU7/vEdXsg+zZWxKL/gaHsJkGMCC49Y4pqbsaBmx0YAF00K0+V7w5BHBF+iY5jvtJ1ZCYRHTN/iAbYVOnoV0w== + +esbuild-freebsd-64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.24.tgz#b586d8aa290bfcdf0aa73fdfcf64c092d49795f2" + integrity sha512-Mp35Rz/XoixG7Uka6l54hU/XUxAEwQozgKoHPusJzX+Fu1vANil0Ypos0RJkidu7skSkd0xisNIT+gtD36BxpA== + +esbuild-freebsd-arm64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.24.tgz#4e7098de07791089b6ef6b4f17a8ce6124da7bec" + integrity sha512-+tf4a4zYaHP1XXPt286mxOc2bmj13K57GZYjqYz/G3c3sgNXa0JBkcPlUATIj96WfXhWM115n3nHe9wF88+ZGQ== + +esbuild-linux-32@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.24.tgz#afe7345f3e8ee58eede36c0254e128924680b305" + integrity sha512-8jMZErn5aLnlSQqzK365yoWRr67ZkGNcoTmk1CK5Bk1EB9g7uwCfdZsmWcclLWPGkIhMbdk4OvzQ+Wp0popwWA== + +esbuild-linux-64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.24.tgz#ce7b95e8ed96076dcb329d1d34e4b9ef084e02cf" + integrity sha512-D/JCsk9OY2IZj+fkU74pKD4rD2pjeiYUbze1cS5D6+U0pz8j71GjZY5UkfwHhBBbNyPe6DPCyex97txQUlHwWw== + +esbuild-linux-arm64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.24.tgz#f8aee4eb78309fd3c064e86393a698e33908e8ec" + integrity sha512-DypWEDQLE+PoHGMa4FLcmKvS+yQLsYlsN03R496rTpDOiVQGrRdo0LbYtf+uHpDxa1KRrHZsQim6n8m3VBHP6g== + +esbuild-linux-arm@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.24.tgz#eaccc0a4d7d17e7290e5b20c383e6969c6769bf7" + integrity sha512-N+vvGpJAUWv3j+YZGOMEtrHwrrSG582TuAThBwoRE7d2N4zFE2WQBCiSYaAVckMQhvMOPqnCdqeTDUse5nlKTw== + +esbuild-linux-mips64le@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.24.tgz#9db94b62bbcbaad6229087ea27a6d7dc3fc878d6" + integrity sha512-eMk9pEHba1yd5bOuPZUJfFucigvysdcE2d/wV4M0eUdb/VjyH9fcGqz8byvSjmYSOt3WCn/V4jLVI+pwDSHWYw== + +esbuild-linux-ppc64le@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.24.tgz#194d59a5ebfcdbfc7e710d13893e6c62216baa77" + integrity sha512-4vQ/Y6EV5Z2BjO7RdpEyTCv702WmOPc95d2CbUcFvg78FpGQAmrbIrHXu/yX4+rdUU6vMNBn3M+7M7/lxmxjjg== + +esbuild-linux-riscv64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.24.tgz#0d8cbbcd2f3b7cc4365ebc8fac8d00fdc95691d2" + integrity sha512-pAN9/+NZ487Wo9PmlOM6Ra95SrhG8JQw7fCgi3z7dUufwTApTNTPGs5UOMD4Bmorju+DeGb0f0GddLaeabvqDg== + +esbuild-linux-s390x@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.24.tgz#460e726f5d827f1171f9eac8c9bbcad8e6574ec5" + integrity sha512-ZR+VMHP2WS3022x2sK/85cBfKGgPalIZzpquDWjra9nUb+WdEzuK9i9bRsstLmjIPs3uIkGfe6xXUh/7PNLllw== + +esbuild-netbsd-64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.24.tgz#8f6f4c68b8e84e1e011330096f118013cc275601" + integrity sha512-1PzXU++e0PEaSuGpkhrVb+fDUw9mSp4laY9KRsjJkAuXPDj0rHz7KxK7CAbzY/ucufeIR9Ca8/oMpdVyWdaOGw== + +esbuild-openbsd-64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.24.tgz#6fbfc089103d154d74d4ea5a3aefc2844189094a" + integrity sha512-PvXh7JJAFM1kR87XDWbRrUkaOGVMS6Dq/IRXE2E02maio21JELk/jNRijTe81ztr8v+8K9osB3rG9zKqIdTxhQ== + +esbuild-sunos-64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.24.tgz#09931dbbc610f88feda1c071f2844e7d8867f46e" + integrity sha512-5iYi76kGQdyCqvSUknqjTZ0T19KvQD6hiklPAY6kVoQ1YoDUGCGILRI9eM/3zLNLG1bUFgcdJ2ktaBxwyXuHyA== + +esbuild-windows-32@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.24.tgz#3c8dddffaec6dce9a3ac8ef2bec939ec5af17e68" + integrity sha512-oDxcNu4P1FWTk2ompKB0uKHfxYw1QuubH189+PlfrrWT9tVu+mxT9dSwJu2erfUDz5dnr6h8rgkg95NGboeJxg== + +esbuild-windows-64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.24.tgz#e97081ee16d51c5a210cd1de15454689ac09fc8b" + integrity sha512-0uxXF1yLcGEM2es0OMDgQYQGZXQEEIdq8cG3IWhY2GGfFRLXpMgic1iUE+SKCh+b82t1ftUVoyG0zIFRn5NOIA== + +esbuild-windows-arm64@0.14.24: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.24.tgz#0fcff2b58c772874f8dc52638557f817609ed699" + integrity sha512-unwaYRaIK/4OaZm0jnM3pLKMPEjaQqmT5teTciSZ86VYaiYZF27Ki7BW7R5ngk27gIw0ovIfUcn9DhJgp7qAlw== + +esbuild@^0.14.14: + version "0.14.24" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.24.tgz#543899cf9ff0ebe206dc3de2ac18b9122d9f5697" + integrity sha512-NjfmycVQqY0+iKXoHXsvMAKx4XF/bD/dDm8pK6C/3aJO/i/uby+7AR4z8vu0qkiihkB5Y43+9BjdY2MGnswC/A== + optionalDependencies: + esbuild-android-64 "0.14.24" + esbuild-android-arm64 "0.14.24" + esbuild-darwin-64 "0.14.24" + esbuild-darwin-arm64 "0.14.24" + esbuild-freebsd-64 "0.14.24" + esbuild-freebsd-arm64 "0.14.24" + esbuild-linux-32 "0.14.24" + esbuild-linux-64 "0.14.24" + esbuild-linux-arm "0.14.24" + esbuild-linux-arm64 "0.14.24" + esbuild-linux-mips64le "0.14.24" + esbuild-linux-ppc64le "0.14.24" + esbuild-linux-riscv64 "0.14.24" + esbuild-linux-s390x "0.14.24" + esbuild-netbsd-64 "0.14.24" + esbuild-openbsd-64 "0.14.24" + esbuild-sunos-64 "0.14.24" + esbuild-windows-32 "0.14.24" + esbuild-windows-64 "0.14.24" + esbuild-windows-arm64 "0.14.24" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +estree-walker@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== + +estree-walker@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +filter-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" + integrity sha1-mzERErxsYSehbgFsbF1/GeCAXFs= + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +history@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b" + integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ== + dependencies: + "@babel/runtime" "^7.7.6" + +immutable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" + integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== + +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== + dependencies: + has "^1.0.3" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +js-base64@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.2.tgz#816d11d81a8aff241603d19ce5761e13e41d7745" + integrity sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-schema-compare@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/json-schema-compare/-/json-schema-compare-0.2.2.tgz#dd601508335a90c7f4cfadb6b2e397225c908e56" + integrity sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ== + dependencies: + lodash "^4.17.4" + +json-schema-merge-allof@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/json-schema-merge-allof/-/json-schema-merge-allof-0.6.0.tgz#64d48820fec26b228db837475ce3338936bf59a5" + integrity sha512-LEw4VMQVRceOPLuGRWcxW5orTTiR9ZAtqTAe4rQUjNADTeR81bezBVFa0MqIwp0YmHIM1KkhSjZM7o+IQhaPbQ== + dependencies: + compute-lcm "^1.1.0" + json-schema-compare "^0.2.2" + lodash "^4.17.4" + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json5@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== + dependencies: + minimist "^1.2.5" + +jsonpointer@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.0.tgz#f802669a524ec4805fa7389eadbc9921d5dc8072" + integrity sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg== + +lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.4: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +magic-string@^0.25.7: + version "0.25.7" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" + integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== + dependencies: + sourcemap-codec "^1.4.4" + +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +mutation-observer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/mutation-observer/-/mutation-observer-1.0.3.tgz#42e9222b101bca82e5ba9d5a7acf4a14c0f263d0" + integrity sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA== + +nanoid@^3.1.23, nanoid@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" + integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== + +node-fetch@2: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-releases@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" + integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +postcss@^8.4.6: + version "8.4.7" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.7.tgz#f99862069ec4541de386bf57f5660a6c7a0875a8" + integrity sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A== + dependencies: + nanoid "^3.3.1" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +prop-types-extra@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b" + integrity sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew== + dependencies: + react-is "^16.3.2" + warning "^4.0.0" + +prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +query-string@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.1.tgz#754620669db978625a90f635f12617c271a088e1" + integrity sha512-MplouLRDHBZSG9z7fpuAAcI7aAYjDLhtsiVZsevsfaHWDS2IDdORKbSd1kWUA+V4zyva/HZoSfpwnYMMQDhb0w== + dependencies: + decode-uri-component "^0.2.0" + filter-obj "^1.1.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + +react-bootstrap@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-2.1.2.tgz#a81161821c351d5e0eaed5bb85d50659736f2aa4" + integrity sha512-E7PR13cVsEW70gw08BWplENwn6PHTshskOsQygZqyc65jQlsnr9MsmuW/lgzAN2OiMBnc0KaNpuZ/FohL7dchw== + dependencies: + "@babel/runtime" "^7.14.0" + "@restart/hooks" "^0.4.5" + "@restart/ui" "^1.0.1" + "@types/invariant" "^2.2.33" + "@types/prop-types" "^15.7.3" + "@types/react" ">=16.14.8" + "@types/react-transition-group" "^4.4.1" + "@types/warning" "^3.0.0" + classnames "^2.3.1" + dom-helpers "^5.2.1" + invariant "^2.2.4" + prop-types "^15.7.2" + prop-types-extra "^1.1.0" + react-transition-group "^4.4.1" + uncontrollable "^7.2.1" + warning "^4.0.3" + +react-dom@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" + integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + scheduler "^0.20.2" + +react-icons@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.3.1.tgz#2fa92aebbbc71f43d2db2ed1aed07361124e91ca" + integrity sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ== + +react-is@^16.13.1, react-is@^16.3.2, react-is@^16.9.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-lifecycles-compat@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== + +react-refresh@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" + integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A== + +react-router-dom@^6.2.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.2.2.tgz#f1a2c88365593c76b9612ae80154a13fcb72e442" + integrity sha512-AtYEsAST7bDD4dLSQHDnk/qxWLJdad5t1HFa1qJyUrCeGgEuCSw0VB/27ARbF9Fi/W5598ujvJOm3ujUCVzuYQ== + dependencies: + history "^5.2.0" + react-router "6.2.2" + +react-router@6.2.2, react-router@^6.2.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.2.2.tgz#495e683a0c04461eeb3d705fe445d6cf42f0c249" + integrity sha512-/MbxyLzd7Q7amp4gDOGaYvXwhEojkJD5BtExkuKmj39VEE0m3l/zipf6h2WIB2jyAO0lI6NGETh4RDcktRm4AQ== + dependencies: + history "^5.2.0" + +react-transition-group@^4.4.1: + version "4.4.2" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470" + integrity sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + +react@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" + integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +regenerator-runtime@^0.13.4: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + +resolve@^1.22.0: + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +rollup@^2.59.0: + version "2.69.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.69.0.tgz#82aa86682a45e9760146b736c1643bf435506156" + integrity sha512-kjER91tHyek8gAkuz7+558vSnTQ+pITEok1P0aNOS45ZXyngaqPsXJmSel4QPQnJo7EJMjXUU1/GErWkWiKORg== + optionalDependencies: + fsevents "~2.3.2" + +safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +sass@^1.49.9: + version "1.49.9" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.49.9.tgz#b15a189ecb0ca9e24634bae5d1ebc191809712f9" + integrity sha512-YlYWkkHP9fbwaFRZQRXgDi3mXZShslVmmo+FVK3kHLUELHHEYrCmL1x6IUjC7wLS6VuJSAFXRQS/DxdsC4xL1A== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + +scheduler@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" + integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map@^0.5.0: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +sourcemap-codec@^1.4.4: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + +split-on-first@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" + integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== + +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +type-fest@2.11.2: + version "2.11.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.11.2.tgz#5534a919858bc517492cd3a53a673835a76d2e71" + integrity sha512-reW2Y2Mpn0QNA/5fvtm5doROLwDPu2zOm5RtY7xQQS05Q7xgC8MOZ3yPNaP9m/s/sNjjFQtHo7VCNqYW2iI+Ig== + +uncontrollable@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-7.2.1.tgz#1fa70ba0c57a14d5f78905d533cf63916dc75738" + integrity sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ== + dependencies: + "@babel/runtime" "^7.6.3" + "@types/react" ">=16.9.11" + invariant "^2.2.4" + react-lifecycles-compat "^3.0.4" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +validate.io-array@^1.0.3: + version "1.0.6" + resolved "https://registry.yarnpkg.com/validate.io-array/-/validate.io-array-1.0.6.tgz#5b5a2cafd8f8b85abb2f886ba153f2d93a27774d" + integrity sha1-W1osr9j4uFq7L4hroVPy2Tond00= + +validate.io-function@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/validate.io-function/-/validate.io-function-1.0.2.tgz#343a19802ed3b1968269c780e558e93411c0bad7" + integrity sha1-NDoZgC7TsZaCaceA5VjpNBHAutc= + +validate.io-integer-array@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz#2cabde033293a6bcbe063feafe91eaf46b13a089" + integrity sha1-LKveAzKTpry+Bj/q/pHq9GsToIk= + dependencies: + validate.io-array "^1.0.3" + validate.io-integer "^1.0.4" + +validate.io-integer@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/validate.io-integer/-/validate.io-integer-1.0.5.tgz#168496480b95be2247ec443f2233de4f89878068" + integrity sha1-FoSWSAuVviJH7EQ/IjPeT4mHgGg= + dependencies: + validate.io-number "^1.0.3" + +validate.io-number@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/validate.io-number/-/validate.io-number-1.0.3.tgz#f63ffeda248bf28a67a8d48e0e3b461a1665baf8" + integrity sha1-9j/+2iSL8opnqNSODjtGGhZluvg= + +vconsole@^3.14.3: + version "3.14.3" + resolved "https://registry.yarnpkg.com/vconsole/-/vconsole-3.14.3.tgz#a452867f03b2eb1f57a3ce4b8ff2b0e067e92040" + integrity sha512-Je26lm4AzS8uGRVLvHRmCK2MoSDviM/z/kpM4RLGrbDzDB36stlMjmtOa3Vh9IQDQG/aw/gqQGtpSHIGEP7/og== + dependencies: + "@babel/runtime" "^7.17.2" + copy-text-to-clipboard "^3.0.1" + core-js "^3.11.0" + mutation-observer "^1.0.3" + +vite@^2.8.0: + version "2.8.6" + resolved "https://registry.yarnpkg.com/vite/-/vite-2.8.6.tgz#32d50e23c99ca31b26b8ccdc78b1d72d4d7323d3" + integrity sha512-e4H0QpludOVKkmOsRyqQ7LTcMUDF3mcgyNU4lmi0B5JUbe0ZxeBBl8VoZ8Y6Rfn9eFKYtdXNPcYK97ZwH+K2ug== + dependencies: + esbuild "^0.14.14" + postcss "^8.4.6" + resolve "^1.22.0" + rollup "^2.59.0" + optionalDependencies: + fsevents "~2.3.2" + +warning@^4.0.0, warning@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" + integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== + dependencies: + loose-envify "^1.0.0" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" diff --git a/misc/config_tools/scenario_config/jsonschema/__init__.py b/misc/config_tools/scenario_config/jsonschema/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/misc/config_tools/scenario_config/jsonschema/converter.py b/misc/config_tools/scenario_config/jsonschema/converter.py new file mode 100644 index 000000000..ed8c999cf --- /dev/null +++ b/misc/config_tools/scenario_config/jsonschema/converter.py @@ -0,0 +1,350 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2022 Intel Corporation. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +""" +# XS2JS + +Convert XML Schema To JSON Schema. + +# Example Code + +```python +import os +import json +from xs2js import XS2JS + +schema_file = os.path.join('schema', 'config.xsd') +json_schema = XS2JS(schema_file).get_json_schema() +json_schema = json.dumps(json_schema, indent='\t') +output_file = 'schema.json' +open(output_file, 'w', encoding='utf-8').write(json_schema) +``` + +""" +import os +import json + +from collections import OrderedDict +from pathlib import Path + +import xmltodict + +try: + from .document import ACRNDocumentStringConvertor +except ImportError: + from document import ACRNDocumentStringConvertor + + +class XSTypes: + def __init__(self, schema_dict): + self.simple = self.load_type(schema_dict.get('xs:simpleType', [])) + self.complex = self.load_type(schema_dict.get('xs:complexType', [])) + + @staticmethod + def load_type(type_list): + return {type_info['@name']: type_info for type_info in type_list} + + def get_type(self, type_name): + if type_name in self.simple: + return self.simple[type_name] + elif type_name in self.complex: + return self.complex[type_name] + print(type_name) + raise NotImplementedError + + +class XS: + def __init__(self, schema_filename): + self.schema = self.load_file(schema_filename) + self.types = XSTypes(self.schema) + + @staticmethod + def load_file(schema_filename): + """load xml schema file and convert it to json dict""" + schema = open(schema_filename, encoding='utf-8').read() + + # load schema_content + schema_content = xmltodict.parse(schema) + schema_content = schema_content['xs:schema'] + + # handle xinclude element + XS._handle_include(schema_filename, schema_content) + + return schema_content + + @staticmethod + def _handle_include(schema_filename, schema_content): + """parse xsd document xi:include tag and inject their content to origin document content""" + if 'xi:include' in schema_content: + for include in reversed(schema_content['xi:include']): + source_path = os.path.join(os.path.dirname(schema_filename), include['@href']) + include_content = XS.load_file(source_path) + + # marge data + for attr in ['xs:simpleType', 'xs:complexType']: + if attr in include_content: + if attr not in schema_content: + schema_content[attr] = [] + + schema_content[attr] = [ + *include_content[attr], + *schema_content[attr] + ] + + +class XS2JS: + xst2jst_mapping = { + 'xs:string': 'string', + 'xs:integer': 'integer' + } + xsa2jsa_mapping = { + 'xs:minLength': ('minLength', int), + 'xs:maxLength': ('maxLength', int), + 'xs:pattern': ('pattern', lambda x: f"^{x}$"), + 'xs:minInclusive': ('minimum', int), + 'xs:maxInclusive': ('maximum', int), + } + + def __init__(self, schema_filename): + self.xs = XS(schema_filename) + self.desc_conv = ACRNDocumentStringConvertor() + + def _get_definitions(self): + """convert xml schema types to json schema definitions""" + definitions = OrderedDict() + + # simple types + for type_name, simple_type in self.xs.types.simple.items(): + definitions[type_name] = self.xso2jso(simple_type) + + # complex types + for type_name, complex_type in self.xs.types.complex.items(): + definitions[type_name] = self.xse2jse(complex_type) + + return definitions + + def get_json_schema(self): + json_schema = self.xse2jse(self.xs.schema) + json_schema["additionalProperties"] = True + json_schema['$schema'] = "http://json-schema.org/draft-07/schema" + json_schema.move_to_end('$schema', False) + json_schema["definitions"] = self._get_definitions() + return json_schema + + def xst2jst(self, type_name) -> str: + """convert xml schema type name to json schema type name""" + if type_name in self.xst2jst_mapping: + return self.xst2jst_mapping[type_name] + print(type_name) + raise NotImplementedError + + def xsa2jsa(self, restriction): + """convert xml schema object attrs to json schema object attrs""" + result = {} + for key in restriction: + if key in self.xsa2jsa_mapping: + js_key, js_type = self.xsa2jsa_mapping[key] + result[js_key] = js_type(restriction[key]['@value']) + return result + + def xso2jso(self, obj, show_type_name=False) -> OrderedDict: + """convert xml schema object to json schema object""" + if 'xs:restriction' in obj: + restriction = obj['xs:restriction'] + js_st = OrderedDict({"type": self.xst2jst(restriction['@base'])}) + if show_type_name: + js_st['title'] = obj['@name'] + js_st.move_to_end('title', False) + if 'xs:enumeration' in restriction: + type_func = {"string": str, "integer": int}.get(js_st['type'], str) + # enum + enum = [] + for enum_element in restriction['xs:enumeration']: + enum.append(type_func(enum_element['@value'])) + js_st["enum"] = enum + + # enumNames + if enum and '@acrn:title' in restriction['xs:enumeration'][0].get('xs:annotation', {}): + enum_names = [] + for enum_element in restriction['xs:enumeration']: + enum_names.append(enum_element['xs:annotation']['@acrn:title']) + js_st["enumNames"] = enum_names + + js_st.update(self.xsa2jsa(restriction)) + return js_st + elif 'xs:union' in obj: + member_types = obj['xs:union']['@memberTypes'].split(' ') + member_js_objects = [] + for type_name in member_types: + member_type = self.xs.types.get_type(type_name) + member_js_objects.append(self.xso2jso(member_type, True)) + # Todo: union type refactor + return OrderedDict({"anyOf": member_js_objects}) + print(obj) + raise NotImplementedError + + def get_element_define(self, element): + basic_define = {} + if 'xs:simpleType' in element: + basic_define = self.xso2jso(element['xs:simpleType']) + elif '@type' in element: + element_type = element['@type'] + if element_type in self.xst2jst_mapping: + basic_define['type'] = self.xst2jst_mapping[element_type] + else: + basic_define["$ref"] = "#/definitions/%s" % element_type + elif 'xs:complexType' in element: + basic_define = self.xse2jse(element['xs:complexType']) + else: + print(json.dumps(element, indent=2)) + raise NotImplementedError + return basic_define + + def xse2jse(self, obj) -> OrderedDict: + """convert xml schema elements to json schema elements""" + properties = OrderedDict() + required = [] + + # get elements + all_elements = self.get_elements(obj) + + for element in all_elements: + name = element['@name'] + + # get element basic define (basic/simple type? $ref?) + try: + basic_define = self.get_element_define(element) + except NotImplementedError: + print(f"{name} not translated") + continue + + # build element json schema + js_ele = OrderedDict(basic_define) + + # get default + if '@default' in element: + default = element['@default'] + if default.isdigit(): + default = int(default) + + js_ele['default'] = default + + # is this element is required ? + if '@minOccurs' in element: + min_items = int(element['@minOccurs']) + if min_items > 0: + required.append(name) + if min_items > 1: + js_ele['minItems'] = min_items + else: + # by default, field is required + required.append(name) + + if '@maxOccurs' in element: + if 'type' in js_ele: + js_ele['items'] = {'type': js_ele['type']} + elif '$ref' in js_ele: + js_ele['items'] = {'$ref': js_ele['$ref']} + del js_ele['$ref'] + else: + raise NotImplementedError + + if element['@maxOccurs'] == "unbounded": + # unlimited, only set type = array + js_ele['type'] = 'array' + else: + js_ele['type'] = 'array' + js_ele['maxItems'] = int(element['@maxOccurs']) + + if 'default' in js_ele: + js_ele['items']['default'] = js_ele['default'] + del js_ele['default'] + + # get description + if 'xs:annotation' in element: + # title + js_ele['title'] = element['xs:annotation'].get('@acrn:title', name) + + # documentation + documentation: str = element['xs:annotation'].get('xs:documentation', None) + if documentation is None or documentation.strip() == '': + documentation = '' + if documentation: + documentation = self.desc_conv.convert(documentation) + js_ele['description'] = documentation + + # dynamic enum + if '@acrn:options' in element['xs:annotation']: + dynamic_enum = { + 'type': 'dynamicEnum', + 'function': 'get_enum', + 'source': 'board_xml', + 'selector': element['xs:annotation']['@acrn:options'], + 'sorted': element['xs:annotation'].get('@acrn:options-sorted-by', None) + } + js_ele['enum'] = dynamic_enum + + properties[name] = js_ele + + # build result + result = OrderedDict({"type": "object"}) + + if required: + result['required'] = required + + if properties: + result["properties"] = properties + + return result + + @staticmethod + def get_elements(obj): + """get elements from xml schema object""" + all_elements = [] + if 'xs:element' in obj: + elements = obj['xs:element'] + if not isinstance(elements, list): + elements = [elements] + all_elements.extend(elements) + for attr in ['xs:sequence', 'xs:all']: + if attr in obj: + elements = obj[attr]['xs:element'] + if not isinstance(elements, list): + elements = [elements] + all_elements.extend(elements) + return all_elements + + +def main(manual_call=False): + """ + if you call this function in your + module must set params `manual_call=True` + else this function will not run + """ + # for pyodide run check. + if __name__ != '__main__' and not manual_call: + return + + # find acrn-hypervisor/misc/config_tools folder + config_tools = Path(__file__).absolute() + while config_tools.name != "config_tools": + config_tools = config_tools.parent + + schema_file = config_tools / 'configurator' / 'build' / 'sliced.xsd' + json_schema_file = config_tools / 'configurator' / 'src' / 'assets' / 'schema' / 'scenario.json' + + # Convert XSD to JSON Schema + json_schema = XS2JS(schema_file).get_json_schema() + json_schema = json.dumps(json_schema, indent='\t') + + # Write file and print successful message + open(json_schema_file, 'w', encoding='utf-8').write(json_schema) + print("File %s Convert Success. JSON Schema Write To: %s" % (repr(schema_file), repr(json_schema_file))) + + +# for pyodide +main() diff --git a/misc/config_tools/scenario_config/jsonschema/document.py b/misc/config_tools/scenario_config/jsonschema/document.py new file mode 100644 index 000000000..2218777c5 --- /dev/null +++ b/misc/config_tools/scenario_config/jsonschema/document.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2022 Intel Corporation. +# +# SPDX-License-Identifier: BSD-3-Clause +# +""" +This program support run in pyodide env. +In js side you can pass params by add follow code before this script. +```js +params = "${Base64.encode(params)}" +``` +""" + +import re +import sys +import json +import base64 + +from urllib.parse import urljoin +from subprocess import check_output + +from typing import Optional + +try: + import locale # module missing in Jython + + locale.setlocale(locale.LC_ALL, '') +except locale.Error: + pass + +from docutils.core import publish_string +from sphinx.ext.intersphinx import fetch_inventory +from bs4 import BeautifulSoup + + +class RSTNormalizer: + def __init__(self, url_base, objects_inv: [dict, str]): + self.url_base = url_base + + if isinstance(objects_inv, dict): + # parsed data + self.data = objects_inv + elif isinstance(objects_inv, str): + self.data = self.__convert_inv(objects_inv) + else: + raise NotImplementedError + + self.fake_roles = [ + self.fake_role('option', 'std:cmdoption'), + self.fake_role('ref', 'std:label') + ] + + @staticmethod + def __convert_inv(url): + try: + inv_data = RSTNormalizer.__prase_inv_file(url) + except Exception as e: + print(e) + print('Download inv data failed, document link will link to search page.') + inv_data = None + return inv_data + + @staticmethod + def __prase_inv_file(filename): + class MockConfig: + intersphinx_timeout: int = None + tls_verify = False + user_agent = None + + class MockApp: + srcdir = '' + config = MockConfig() + + def warn(self, msg: str) -> None: + print(msg, file=sys.stderr) + + invdata = fetch_inventory(MockApp(), '', filename) # type: ignore + result = {} + for key in sorted(invdata or {}): + result[key] = {} + data = result[key] + for entry, einfo in sorted(invdata[key].items()): + data[entry] = {"title": einfo[3] if einfo[3] != '-' else '', "link": einfo[2]} + return result + + def normalize(self, rest_text): + result = re.sub(r'\.\. option::[ \t]+(\S+)', lambda x: x.group(1) + f'\n{len(x.group(1)) * "-"}', rest_text) + for fake_role_handle in self.fake_roles: + result = fake_role_handle(result) + + return result + + def url(self, key, data): + title = data["title"] if data["title"] else key + url = urljoin(self.url_base, data['link']) + return f'`{title} <{url}>`_' + + def fake_role(self, rest_key, json_key): + def handel_role(rest_text): + def re_sub(match): + key = match.group(1) + if self.data is None or json_key not in self.data or key not in self.data[json_key]: + return self.url(key, {'title': '', 'link': f'search.html?q={key}&check_keywords=yes&area=default'}) + return self.url(key, self.data[json_key][key]) + + return re.sub(f':{rest_key}:' + r'`(.+?)`', re_sub, rest_text) + + return handel_role + + +class ACRNDocumentStringConvertor: + def __init__(self, objects_inv: Optional[dict] = None): + self.version = self.get_acrn_document_version() + self.url_base = 'https://projectacrn.github.io/{}/'.format(self.version) + + self.objects_inv = objects_inv + if self.objects_inv is None: + self.objects_inv = urljoin(self.url_base, 'objects.inv') + + self.rst_normalizer = RSTNormalizer(self.url_base, self.objects_inv) + + @staticmethod + def get_acrn_document_version(default_version='latest'): + version = default_version + try: + branch_name = check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).decode() + version = re.match(r"^release_(\d\.\d)$", branch_name).group(1) + except: + print("Can't detect current acrn-hypervisor version, document string will link to latest") + + return version + + def convert(self, docstring): + rst = self.rst_normalizer.normalize(docstring) + html = publish_string(rst, writer_name='html5').decode('utf-8') + soup = BeautifulSoup(html, 'lxml') + for link in soup.select('a'): + link['target'] = '_blank' + try: + fragment = soup.select_one('div.document').prettify() + except: + fragment = '\n'.join([str(x) for x in soup.select_one('main').children]).strip() + return fragment + + +doc_html = '' +if __name__ == '__main__': + WEB = False + if 'params' in globals(): + WEB = True + # noinspection PyUnboundLocalVariable,PyUnresolvedReferences + params_data = base64.b64decode(params) + params = json.loads(params_data) + else: + params = { + "text": open('configdoc.txt').read(), + "objectsInv": None + } + + print(params) + doc_html = ACRNDocumentStringConvertor(params['objectsInv']).convert(params['text']) + if not WEB: + print(doc_html) + +# for pyodide +(lambda x: x)(doc_html) diff --git a/misc/config_tools/scenario_config/schema_slicer.py b/misc/config_tools/scenario_config/schema_slicer.py index e0a6a84e6..e0572c097 100755 --- a/misc/config_tools/scenario_config/schema_slicer.py +++ b/misc/config_tools/scenario_config/schema_slicer.py @@ -236,12 +236,17 @@ def main(args): print(f"Sliced schema written to {args.out}") + if __name__ == "__main__": - config_tools_dir = os.path.join(os.path.dirname(__file__), "..") + # abs __file__ path to ignore `__file__ == 'schema_slicer.py'` issue + config_tools_dir = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")) schema_dir = os.path.join(config_tools_dir, "schema") + configurator_build_dir = os.path.join(config_tools_dir, 'configurator', 'build') + if not os.path.isdir(configurator_build_dir): + os.mkdir(configurator_build_dir) parser = argparse.ArgumentParser(description="Slice a given scenario schema by VM types and views") - parser.add_argument("out", nargs="?", default=os.path.join(schema_dir, "sliced.xsd"), help="Path where the output is placed") + parser.add_argument("out", nargs="?", default=os.path.join(configurator_build_dir, "sliced.xsd"), help="Path where the output is placed") parser.add_argument("--schema", default=os.path.join(schema_dir, "config.xsd"), help="the XML schema that defines the syntax of scenario XMLs") args = parser.parse_args() diff --git a/misc/config_tools/schema/VMtypes.xsd b/misc/config_tools/schema/VMtypes.xsd index 16d83d74d..db9a40cbb 100644 --- a/misc/config_tools/schema/VMtypes.xsd +++ b/misc/config_tools/schema/VMtypes.xsd @@ -184,8 +184,16 @@ CLOSID 0 and the second is mapped to virtual CLOSID 1, etc. - - + + + Virtual UART port + + + + + Virtual I/O address + + diff --git a/misc/config_tools/schema/types.xsd b/misc/config_tools/schema/types.xsd index b40424b35..e6f612862 100644 --- a/misc/config_tools/schema/types.xsd +++ b/misc/config_tools/schema/types.xsd @@ -196,7 +196,7 @@ Read more about the available scheduling options in :ref:`cpu_sharing`. - + Name of the VM which use this IVSHMEM. diff --git a/misc/packaging/gen_acrn_deb.py b/misc/packaging/gen_acrn_deb.py index 788d08ee2..649792c48 100644 --- a/misc/packaging/gen_acrn_deb.py +++ b/misc/packaging/gen_acrn_deb.py @@ -1,40 +1,58 @@ +#!/usr/bin/env python3 # -*- coding: utf-8 -*- -#* Copyright (c) 2020 Intel Corporation -import os,sys,copy,json -import subprocess -import datetime -import time +# +# Copyright (C) 2022 Intel Corporation. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import sys +import os +import json import shlex -import glob +import shutil +import subprocess import argparse -import multiprocessing + +from pathlib import Path + +DEBUG = False + def run_command(cmd, path): - ret_code = 0 - #print("cmd = %s, path = %s" % (cmd, path)) - cmd_proc = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd = path, universal_newlines=True) - while True: - output = cmd_proc.stdout.readline() - #print(output.strip()) - ret_code = cmd_proc.poll() - if ret_code is not None: - break - return ret_code + if DEBUG: + print("cmd = %s, path = %s" % (cmd, path)) + cmd_proc = subprocess.Popen( + shlex.split(cmd), + cwd=path, + stdout=sys.stdout, + stderr=sys.stderr, + universal_newlines=True + ) + while True: + ret_code = cmd_proc.poll() + if ret_code is not None: + break + return ret_code + def add_cmd_list(cmd_list, cmd_str, dir_str): - cmd = {} - cmd['cmd'] = cmd_str - cmd['dir'] = dir_str + cmd = { + 'cmd': cmd_str, + 'dir': dir_str + } cmd_list.append(cmd) + def run_cmd_list(cmd_list): - for i, cmd in enumerate(cmd_list): + for cmd in cmd_list: ret = run_command(cmd['cmd'], cmd['dir']) if ret != 0: print("cmd(%s) run in dir(%s) failed and exit" % (cmd['cmd'], cmd['dir'])) exit(-1) return + def create_acrn_deb(board, scenario, version, build_dir): cur_dir = build_dir + '/../' deb_dir = build_dir + '/acrn_release_deb/' @@ -45,43 +63,45 @@ def create_acrn_deb(board, scenario, version, build_dir): add_cmd_list(cmd_list, 'mkdir -p acrn_release_deb/boot', build_dir) add_cmd_list(cmd_list, 'mkdir DEBIAN', deb_dir) add_cmd_list(cmd_list, 'touch DEBIAN/control', deb_dir) - deb_bin_name ='acrn.%s.%s.bin' % (scenario,board) - deb_out_name ='acrn.%s.%s.32.out' % (scenario,board) + deb_bin_name = 'acrn.%s.%s.bin' % (scenario, board) + deb_out_name = 'acrn.%s.%s.32.out' % (scenario, board) build_bin_name = build_dir + '/hypervisor/acrn.bin' build_out_name = build_dir + '/hypervisor/acrn.32.out' - add_cmd_list(cmd_list, 'cp %s acrn_release_deb/boot/%s' %(build_bin_name, deb_bin_name), build_dir) - add_cmd_list(cmd_list, 'cp %s acrn_release_deb/boot/%s' %(build_out_name, deb_out_name), build_dir) + add_cmd_list(cmd_list, 'cp %s acrn_release_deb/boot/%s' % (build_bin_name, deb_bin_name), build_dir) + add_cmd_list(cmd_list, 'cp %s acrn_release_deb/boot/%s' % (build_out_name, deb_out_name), build_dir) run_cmd_list(cmd_list) - lines=[] - f=open(cur_dir + "/misc/packaging/acrn-hypervisor.postinst",'r') + lines = [] + f = open(cur_dir + "/misc/packaging/acrn-hypervisor.postinst", 'r') for line in f: lines.append(line) f.close() start = lines.index('#Build info Start\n') end = lines.index('#Build info End\n') - del lines[(start+1):(end-1)] - lines.insert(start+1,"\nSCENARIO=(%s)\n"%scenario) - lines.insert(start+2,"\nBOARD=(%s)\n"%board) + del lines[(start + 1):(end - 1)] + lines.insert(start + 1, "\nSCENARIO=(%s)\n" % scenario) + lines.insert(start + 2, "\nBOARD=(%s)\n" % board) with open(cur_dir + "/misc/packaging/acrn-hypervisor.postinst", "w") as f: for line in lines: f.write(line) f.close() - listcontrol=['Package: acrn-hypervisor\n', - 'version: %s \n'% version, - 'Depends: libcjson1\n', - 'Section: free \n', - 'Priority: optional \n', - 'Architecture: amd64 \n', - 'Maintainer: acrn-dev@lists.projectacrn.org \n', - 'Description: ACRN Hypervisor for IoT \n', - '\n'] - with open(deb_dir + '/DEBIAN/control','w',encoding='utf-8') as fr: - fr.writelines(listcontrol) + listcontrol = [ + 'Package: acrn-hypervisor\n', + 'version: %s \n' % version, + 'Depends: libcjson1\n', + 'Section: free \n', + 'Priority: optional \n', + 'Architecture: amd64 \n', + 'Maintainer: acrn-dev@lists.projectacrn.org \n', + 'Description: ACRN Hypervisor for IoT \n', + '\n' + ] + with open(deb_dir + '/DEBIAN/control', 'w', encoding='utf-8') as fr: + fr.writelines(listcontrol) - #design in acrn_data - with open(cur_dir + "/.deb.conf","r") as load_deb: + # design in acrn_data + with open(cur_dir + "/.deb.conf", "r") as load_deb: deb_info = json.load(load_deb) load_deb.close() @@ -108,14 +128,17 @@ def create_acrn_deb(board, scenario, version, build_dir): run_command('chmod +x ./build/acrn_release_deb/DEBIAN/preinst', cur_dir) run_command('sed -i \'s/\r//\' ./build/acrn_release_deb/DEBIAN/preinst', cur_dir) - ret = run_command('dpkg -b acrn_release_deb acrn-%s-%s-%s.deb' %(board, scenario, version), build_dir) + ret = run_command('dpkg -b acrn_release_deb acrn-%s-%s-%s.deb' % (board, scenario, version), build_dir) if ret != 0: print("ERROR : generate ACRN debian package acrn-{}-{}-{}.deb failed! \ Please check all the files in {}/acrn_release_deb".format(board, scenario, version, build_dir)) else: - print("ACRN debian package acrn-{}-{}-{}.deb was successfully created in the {}.".format(board, scenario, version, build_dir)) + print( + "ACRN debian package acrn-{}-{}-{}.deb was successfully created in the {}.".format(board, scenario, version, + build_dir)) return + def create_acrn_board_inspector_deb(version, build_dir): cur_dir = build_dir + '/../' deb_dir = build_dir + '/acrn_board_inspector_deb/' @@ -127,34 +150,74 @@ def create_acrn_board_inspector_deb(version, build_dir): add_cmd_list(cmd_list, 'touch DEBIAN/control', deb_dir) run_cmd_list(cmd_list) - #control file description - listcontrol=['Package: acrn-board-inspector\n', - 'version: %s \n'% version, - 'Section: free \n', - 'Priority: optional \n', - 'Architecture: amd64 \n', - 'Maintainer: acrn-dev@lists.projectacrn.org \n', - 'Description: ACRN board inspector tools \n', - 'Depends: cpuid, msr-tools, pciutils, dmidecode, python3, python3-pip, python3-lxml \n', - '\n'] - with open(deb_dir + '/DEBIAN/control','w',encoding='utf-8') as fr: - fr.writelines(listcontrol) + # control file description + listcontrol = [ + 'Package: acrn-board-inspector\n', + 'version: %s \n' % version, + 'Section: free \n', + 'Priority: optional \n', + 'Architecture: amd64 \n', + 'Maintainer: acrn-dev@lists.projectacrn.org \n', + 'Description: ACRN board inspector tools \n', + 'Depends: cpuid, msr-tools, pciutils, dmidecode, python3, python3-pip, python3-lxml \n', + '\n' + ] + with open(deb_dir + '/DEBIAN/control', 'w', encoding='utf-8') as fr: + fr.writelines(listcontrol) run_command('cp -r ./misc/config_tools/board_inspector/ ./build/acrn_board_inspector_deb/bin/', cur_dir) - run_command('cp ./misc/packaging/acrn-board-inspector.postinst ./build/acrn_board_inspector_deb/DEBIAN/postinst', cur_dir) + run_command('cp ./misc/packaging/acrn-board-inspector.postinst ./build/acrn_board_inspector_deb/DEBIAN/postinst', + cur_dir) run_command('chmod +x ./build/acrn_board_inspector_deb/DEBIAN/postinst', cur_dir) run_command('sed -i \'s/\r//\' ./build/acrn_board_inspector_deb/DEBIAN/postinst', cur_dir) run_command('cp ./misc/packaging/acrn-board-inspector.prerm ./build/acrn_board_inspector_deb/DEBIAN/prerm', cur_dir) run_command('chmod +x ./build/acrn_board_inspector_deb/DEBIAN/prerm', cur_dir) run_command('sed -i \'s/\r//\' ./build/acrn_board_inspector_deb/DEBIAN/prerm', cur_dir) - ret = run_command('dpkg -b acrn_board_inspector_deb acrn-board-inspector-%s.deb' %(version), build_dir) + ret = run_command('dpkg -b acrn_board_inspector_deb acrn-board-inspector-%s.deb' % version, build_dir) if ret != 0: - print("ERROR : generate board_inspector debian package acrn-board-inspector-{}.deb failed! \ -Please check all the files in {}/acrn_board_inspector_deb".format(version, build_dir)) + print( + "ERROR : generate board_inspector debian package acrn-board-inspector-{}.deb failed! " + "Please check all the files in {}/acrn_board_inspector_deb".format(version, build_dir) + ) else: - print("board_inspector debian package acrn-board-inspector-{}.deb was successfully created in the {}.".format(version, build_dir)) + print( + "board_inspector debian package acrn-board-inspector-{}.deb" + " was successfully created in the {}.".format(version, build_dir) + ) return + +def create_configurator_deb(build_dir): + cmd_list = [] + + # get folder path + project_base = Path(__file__).parent.parent.parent + configurator_path = Path(__file__).parent.parent / 'config_tools' / 'configurator' + scenario_config_path = project_base / "misc" / "config_tools" / "scenario_config" + deb_dir = configurator_path / 'src-tauri' / 'target' / 'release' / 'bundle' / 'deb' + + # clean old directory + if os.path.isdir(deb_dir): + shutil.rmtree(deb_dir) + + # build command, if you update this, please update misc/config_tools/configurator/README.md#L55 + add_cmd_list(cmd_list, 'python3 schema_slicer.py', scenario_config_path) + add_cmd_list(cmd_list, 'python3 converter.py', scenario_config_path / "jsonschema") + add_cmd_list(cmd_list, 'yarn', configurator_path) + add_cmd_list(cmd_list, 'yarn build', configurator_path) + run_cmd_list(cmd_list) + + deb_name = [x for x in os.listdir(deb_dir) if x.endswith('.deb')] + if not deb_name: + print('ERROR! No acrn-configurator deb found!') + return + deb_name = deb_name[0] + with open(deb_dir / deb_name, 'rb') as src: + with open(os.path.join(build_dir, deb_name), 'wb') as dest: + dest.write(src.read()) + return + + if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("deb_mode", help="choose deb mode, e.g. acrn_all or board_inspector") @@ -162,11 +225,16 @@ if __name__ == "__main__": parser.add_argument("--version", default="1.0", help="the acrn-hypervisor version") parser.add_argument("--board_name", default="board", help="the name of the board that runs the ACRN hypervisor") parser.add_argument("--scenario", default="scenario", help="the acrn hypervisor scenario setting") + parser.add_argument("--debug", default=False, help="debug mode") args = parser.parse_args() + DEBUG = args.debug + if args.deb_mode == 'board_inspector': create_acrn_board_inspector_deb(args.version, args.build_dir) elif args.deb_mode == 'acrn_all': create_acrn_deb(args.board_name, args.scenario, args.version, args.build_dir) + elif args.deb_mode == 'configurator': + create_configurator_deb(args.build_dir) else: print("ERROR: Please check the value of deb_mode: the value shall be acrn_all or board_inspector.")