diff --git a/.eslintrc b/.eslintrc
index ce5c8035..c186e3ad 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -55,7 +55,8 @@
{
"singleQuote": true,
"parser": "typescript",
- "printWidth": 120
+ "printWidth": 120,
+ "endOfLine": "auto"
}
],
diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-target.yml
similarity index 89%
rename from .github/workflows/pr-title.yml
rename to .github/workflows/pr-target.yml
index 29789c7d..9d7dbe52 100644
--- a/.github/workflows/pr-title.yml
+++ b/.github/workflows/pr-target.yml
@@ -1,16 +1,17 @@
-name: PR
-on:
- pull_request_target:
- types:
- - opened
- - synchronize
- - reopened
- - ready_for_review
-
-jobs:
- title:
- runs-on: ubuntu-latest
- steps:
- - uses: amannn/action-semantic-pull-request@v3.1.0
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+name: PR
+on:
+ pull_request_target:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ - ready_for_review
+
+jobs:
+ title:
+ name: Validate title semantics
+ runs-on: ubuntu-latest
+ steps:
+ - uses: amannn/action-semantic-pull-request@v3.1.0
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
new file mode 100644
index 00000000..1d63eb7c
--- /dev/null
+++ b/.github/workflows/pr.yml
@@ -0,0 +1,61 @@
+name: PR
+on:
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ - ready_for_review
+
+jobs:
+ lint:
+ name: Lint
+ runs-on: windows-latest
+ steps:
+ - name: Checkout source
+ uses: actions/checkout@v4
+ - name: set Node version
+ uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ - name: Install dependencies
+ run: |
+ npm install
+ cd apps/remote/
+ npm install
+ - name: npm run lint
+ run: |
+ npm run lint
+ build:
+ name: Build and upload SimBridge
+ runs-on: windows-latest
+ env:
+ RELEASE_ZIP_NAME: fbw-simbridge.zip
+ BUILD_DIR_NAME: pr
+ steps:
+ - name: Checkout source
+ uses: actions/checkout@v4
+ - name: set Node version
+ uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ - name: Install dependencies
+ run: |
+ npm install
+ cd apps/remote/
+ npm install
+ - name: Build SimBridge
+ run: |
+ npm run typecheck
+ npm run build:exec
+ - name: Build ZIP File
+ run: |
+ node .\scripts\fragment.js
+ mkdir .\${{env.BUILD_DIR_NAME}}
+ Compress-Archive -Path .\build\* .\${{env.BUILD_DIR_NAME }}\${{ env.RELEASE_ZIP_NAME }}
+ - name: Upload PR artifact
+ uses: actions/upload-artifact@v4
+ if: github.event.pull_request.auto_merge == false
+ with:
+ name: flybywire-external-simbridge
+ path: .\${{env.BUILD_DIR_NAME }}\${{ env.RELEASE_ZIP_NAME }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 852c03ac..8181c3e4 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -24,6 +24,7 @@ jobs:
- name: Build Local API
run: |
npm install
+ npm run typecheck
npm run build:exec
- name: Build ZIP File
run: |
diff --git a/apps/remote/.eslintrc.cjs b/apps/remote/.eslintrc.cjs
new file mode 100644
index 00000000..2cf25747
--- /dev/null
+++ b/apps/remote/.eslintrc.cjs
@@ -0,0 +1,28 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: [
+ '../../.eslintrc',
+ 'plugin:react-hooks/recommended',
+ ],
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
+ parser: '@typescript-eslint/parser',
+ plugins: ['react-refresh'],
+ rules: {
+ // Since we are shimming MSFS APIs that truly take `any` as a type, we need it
+ '@typescript-eslint/no-explicit-any': 'off',
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ // Configure prettier
+ "prettier/prettier": [
+ "error",
+ {
+ "singleQuote": true,
+ "parser": "typescript",
+ "printWidth": 120
+ }
+ ]
+ }
+}
diff --git a/apps/remote/.gitignore b/apps/remote/.gitignore
new file mode 100644
index 00000000..ec871c17
--- /dev/null
+++ b/apps/remote/.gitignore
@@ -0,0 +1,28 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+vite.config.ts.js
+
+# Fonts should be pulled locally
+./public/Fonts/fbw-a32nx/*
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/apps/remote/README.md b/apps/remote/README.md
new file mode 100644
index 00000000..0d6babed
--- /dev/null
+++ b/apps/remote/README.md
@@ -0,0 +1,30 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
+
+- Configure the top-level `parserOptions` property like this:
+
+```js
+export default {
+ // other rules...
+ parserOptions: {
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ project: ['./tsconfig.json', './tsconfig.node.json'],
+ tsconfigRootDir: __dirname,
+ },
+}
+```
+
+- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
+- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
+- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
diff --git a/apps/remote/index.html b/apps/remote/index.html
new file mode 100644
index 00000000..e7192fa3
--- /dev/null
+++ b/apps/remote/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ FBW Remote
+
+
+
+
+
+
diff --git a/apps/remote/package-lock.json b/apps/remote/package-lock.json
new file mode 100644
index 00000000..9c771e0f
--- /dev/null
+++ b/apps/remote/package-lock.json
@@ -0,0 +1,5649 @@
+{
+ "name": "remote-web-client",
+ "version": "0.1.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "remote-web-client",
+ "version": "0.1.0",
+ "dependencies": {
+ "@reduxjs/toolkit": "^1.9.7",
+ "react": "^18.2.0",
+ "react-bootstrap-icons": "^1.10.3",
+ "react-dom": "^18.2.0",
+ "react-redux": "^8.1.3",
+ "react-use": "^17.4.2",
+ "redux": "^4.2.1",
+ "uuid": "^9.0.1"
+ },
+ "devDependencies": {
+ "@types/react": "^18.2.37",
+ "@types/react-dom": "^18.2.15",
+ "@types/uuid": "^9.0.7",
+ "@vitejs/plugin-react": "^4.2.0",
+ "autoprefixer": "^10.4.16",
+ "eslint": "^8.53.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-prettier": "^5.0.1",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.4",
+ "postcss": "^8.4.32",
+ "prettier": "^3.1.0",
+ "sass": "^1.69.5",
+ "tailwindcss": "^3.3.5",
+ "typescript": "^5.2.2",
+ "vite": "^5.0.0"
+ }
+ },
+ "node_modules/@aashutoshrathi/word-wrap": {
+ "version": "1.2.6",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.2.1",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.23.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/highlight": "^7.23.4",
+ "chalk": "^2.4.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.23.5",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.23.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.23.5",
+ "@babel/generator": "^7.23.5",
+ "@babel/helper-compilation-targets": "^7.22.15",
+ "@babel/helper-module-transforms": "^7.23.3",
+ "@babel/helpers": "^7.23.5",
+ "@babel/parser": "^7.23.5",
+ "@babel/template": "^7.22.15",
+ "@babel/traverse": "^7.23.5",
+ "@babel/types": "^7.23.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.23.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.23.5",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.22.15",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.22.9",
+ "@babel/helper-validator-option": "^7.22.15",
+ "browserslist": "^4.21.9",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.22.20",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.23.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.22.15",
+ "@babel/types": "^7.23.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.22.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.22.15",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.22.15"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.23.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-module-imports": "^7.22.15",
+ "@babel/helper-simple-access": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/helper-validator-identifier": "^7.22.20"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.22.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.22.6",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.23.4",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.22.20",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.23.5",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.23.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.22.15",
+ "@babel/traverse": "^7.23.5",
+ "@babel/types": "^7.23.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.23.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.23.5",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.23.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.23.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.23.5",
+ "license": "MIT",
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.22.15",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.23.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.23.5",
+ "@babel/generator": "^7.23.5",
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-function-name": "^7.23.0",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/parser": "^7.23.5",
+ "@babel/types": "^7.23.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.23.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.23.4",
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.19.8",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.10.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "13.23.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.54.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.13",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.1",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.1.2",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.20",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@pkgr/utils": {
+ "version": "2.4.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "fast-glob": "^3.3.0",
+ "is-glob": "^4.0.3",
+ "open": "^9.1.0",
+ "picocolors": "^1.0.0",
+ "tslib": "^2.6.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "node_modules/@reduxjs/toolkit": {
+ "version": "1.9.7",
+ "license": "MIT",
+ "dependencies": {
+ "immer": "^9.0.21",
+ "redux": "^4.2.1",
+ "redux-thunk": "^2.4.2",
+ "reselect": "^4.1.8"
+ },
+ "peerDependencies": {
+ "react": "^16.9.0 || ^17.0.0 || ^18",
+ "react-redux": "^7.2.1 || ^8.0.2"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-redux": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.6.1",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.6.7",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "node_modules/@types/hoist-non-react-statics": {
+ "version": "3.3.5",
+ "license": "MIT",
+ "dependencies": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
+ "node_modules/@types/js-cookie": {
+ "version": "2.2.7",
+ "license": "MIT"
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.11",
+ "license": "MIT"
+ },
+ "node_modules/@types/react": {
+ "version": "18.2.39",
+ "license": "MIT",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.2.17",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/scheduler": {
+ "version": "0.16.8",
+ "license": "MIT"
+ },
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.3",
+ "license": "MIT"
+ },
+ "node_modules/@types/uuid": {
+ "version": "9.0.7",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.2.0",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "4.2.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.23.3",
+ "@babel/plugin-transform-react-jsx-self": "^7.23.3",
+ "@babel/plugin-transform-react-jsx-source": "^7.23.3",
+ "@types/babel__core": "^7.20.4",
+ "react-refresh": "^0.14.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0"
+ }
+ },
+ "node_modules/@xobotyi/scrollbar-width": {
+ "version": "1.9.5",
+ "license": "MIT"
+ },
+ "node_modules/acorn": {
+ "version": "8.11.2",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arg": {
+ "version": "5.0.2",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.16",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.21.10",
+ "caniuse-lite": "^1.0.30001538",
+ "fraction.js": "^4.3.6",
+ "normalize-range": "^0.1.2",
+ "picocolors": "^1.0.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/big-integer": {
+ "version": "1.6.52",
+ "dev": true,
+ "license": "Unlicense",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/bplist-parser": {
+ "version": "0.2.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "big-integer": "^1.6.44"
+ },
+ "engines": {
+ "node": ">= 5.10.0"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.22.1",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001541",
+ "electron-to-chromium": "^1.4.535",
+ "node-releases": "^2.0.13",
+ "update-browserslist-db": "^1.0.13"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bundle-name": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "run-applescript": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase-css": {
+ "version": "2.0.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001565",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/commander": {
+ "version": "4.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/copy-to-clipboard": {
+ "version": "3.3.3",
+ "license": "MIT",
+ "dependencies": {
+ "toggle-selection": "^1.0.6"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/css-in-js-utils": {
+ "version": "3.1.0",
+ "license": "MIT",
+ "dependencies": {
+ "hyphenate-style-name": "^1.0.3"
+ }
+ },
+ "node_modules/css-tree": {
+ "version": "1.1.3",
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.0.14",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.2",
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/default-browser": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bundle-name": "^3.0.0",
+ "default-browser-id": "^3.0.0",
+ "execa": "^7.1.1",
+ "titleize": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser-id": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bplist-parser": "^0.2.0",
+ "untildify": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/define-lazy-prop": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/didyoumean": {
+ "version": "1.2.2",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.601",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/error-stack-parser": {
+ "version": "2.1.4",
+ "license": "MIT",
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.19.8",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.19.8",
+ "@esbuild/android-arm64": "0.19.8",
+ "@esbuild/android-x64": "0.19.8",
+ "@esbuild/darwin-arm64": "0.19.8",
+ "@esbuild/darwin-x64": "0.19.8",
+ "@esbuild/freebsd-arm64": "0.19.8",
+ "@esbuild/freebsd-x64": "0.19.8",
+ "@esbuild/linux-arm": "0.19.8",
+ "@esbuild/linux-arm64": "0.19.8",
+ "@esbuild/linux-ia32": "0.19.8",
+ "@esbuild/linux-loong64": "0.19.8",
+ "@esbuild/linux-mips64el": "0.19.8",
+ "@esbuild/linux-ppc64": "0.19.8",
+ "@esbuild/linux-riscv64": "0.19.8",
+ "@esbuild/linux-s390x": "0.19.8",
+ "@esbuild/linux-x64": "0.19.8",
+ "@esbuild/netbsd-x64": "0.19.8",
+ "@esbuild/openbsd-x64": "0.19.8",
+ "@esbuild/sunos-x64": "0.19.8",
+ "@esbuild/win32-arm64": "0.19.8",
+ "@esbuild/win32-ia32": "0.19.8",
+ "@esbuild/win32-x64": "0.19.8"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.54.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.3",
+ "@eslint/js": "8.54.0",
+ "@humanwhocodes/config-array": "^0.11.13",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "9.1.0",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.8.5"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "4.6.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.4.4",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "eslint": ">=7"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/eslint/node_modules/chalk": {
+ "version": "4.1.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/eslint/node_modules/color-convert": {
+ "version": "2.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint/node_modules/color-name": {
+ "version": "1.1.4",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/eslint/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/globals": {
+ "version": "13.23.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/has-flag": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/eslint/node_modules/supports-color": {
+ "version": "7.2.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/execa": {
+ "version": "7.2.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.1",
+ "human-signals": "^4.3.0",
+ "is-stream": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^5.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^3.0.7",
+ "strip-final-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || ^16.14.0 || >=18.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "license": "MIT"
+ },
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-loops": {
+ "version": "1.1.3",
+ "license": "MIT"
+ },
+ "node_modules/fast-shallow-equal": {
+ "version": "1.0.0"
+ },
+ "node_modules/fastest-stable-stringify": {
+ "version": "2.0.2",
+ "license": "MIT"
+ },
+ "node_modules/fastq": {
+ "version": "1.15.0",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.2.9",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fraction.js": {
+ "version": "4.3.7",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://github.com/sponsors/rawify"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "11.12.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/hoist-non-react-statics/node_modules/react-is": {
+ "version": "16.13.1",
+ "license": "MIT"
+ },
+ "node_modules/human-signals": {
+ "version": "4.3.1",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/hyphenate-style-name": {
+ "version": "1.0.4",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/ignore": {
+ "version": "5.3.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/immer": {
+ "version": "9.0.21",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/immer"
+ }
+ },
+ "node_modules/immutable": {
+ "version": "4.3.4",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/inline-style-prefixer": {
+ "version": "7.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "css-in-js-utils": "^3.1.0",
+ "fast-loops": "^1.1.3"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.13.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-inside-container": {
+ "version": "1.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^3.0.0"
+ },
+ "bin": {
+ "is-inside-container": "cli.js"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-wsl/node_modules/is-docker": {
+ "version": "2.2.1",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/jiti": {
+ "version": "1.21.0",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
+ "node_modules/js-cookie": {
+ "version": "2.2.1",
+ "license": "MIT"
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "2.5.2",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lilconfig": {
+ "version": "2.1.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/mdn-data": {
+ "version": "2.0.14",
+ "license": "CC0-1.0"
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
+ "node_modules/nano-css": {
+ "version": "5.6.1",
+ "license": "Unlicense",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.4.15",
+ "css-tree": "^1.1.2",
+ "csstype": "^3.1.2",
+ "fastest-stable-stringify": "^2.0.2",
+ "inline-style-prefixer": "^7.0.0",
+ "rtl-css-js": "^1.16.1",
+ "stacktrace-js": "^2.0.2",
+ "stylis": "^4.3.0"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-dom": "*"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.7",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.14",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-range": {
+ "version": "0.1.2",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "5.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/npm-run-path/node_modules/path-key": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-hash": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "6.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/open": {
+ "version": "9.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "default-browser": "^4.0.0",
+ "define-lazy-prop": "^3.0.0",
+ "is-inside-container": "^1.0.0",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@aashutoshrathi/word-wrap": "^1.2.3",
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.6",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.32",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-import": {
+ "version": "15.1.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-js": {
+ "version": "4.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "camelcase-css": "^2.0.1"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
+ }
+ },
+ "node_modules/postcss-load-config": {
+ "version": "4.0.2",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "lilconfig": "^3.0.0",
+ "yaml": "^2.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ },
+ "peerDependencies": {
+ "postcss": ">=8.0.9",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "postcss": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/postcss-load-config/node_modules/lilconfig": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/postcss-nested": {
+ "version": "6.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.11"
+ },
+ "engines": {
+ "node": ">=12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.0.13",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.1.1",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/prop-types/node_modules/react-is": {
+ "version": "16.13.1",
+ "license": "MIT"
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/react": {
+ "version": "18.2.0",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-bootstrap-icons": {
+ "version": "1.10.3",
+ "license": "MIT",
+ "dependencies": {
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.6"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.2.0",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "18.2.0",
+ "license": "MIT"
+ },
+ "node_modules/react-redux": {
+ "version": "8.1.3",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.12.1",
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "@types/use-sync-external-store": "^0.0.3",
+ "hoist-non-react-statics": "^3.3.2",
+ "react-is": "^18.0.0",
+ "use-sync-external-store": "^1.0.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.8 || ^17.0 || ^18.0",
+ "@types/react-dom": "^16.8 || ^17.0 || ^18.0",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0",
+ "react-native": ">=0.59",
+ "redux": "^4 || ^5.0.0-beta.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ },
+ "redux": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.14.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-universal-interface": {
+ "version": "0.6.2",
+ "peerDependencies": {
+ "react": "*",
+ "tslib": "*"
+ }
+ },
+ "node_modules/react-use": {
+ "version": "17.4.2",
+ "license": "Unlicense",
+ "dependencies": {
+ "@types/js-cookie": "^2.2.6",
+ "@xobotyi/scrollbar-width": "^1.9.5",
+ "copy-to-clipboard": "^3.3.1",
+ "fast-deep-equal": "^3.1.3",
+ "fast-shallow-equal": "^1.0.0",
+ "js-cookie": "^2.2.1",
+ "nano-css": "^5.6.1",
+ "react-universal-interface": "^0.6.2",
+ "resize-observer-polyfill": "^1.5.1",
+ "screenfull": "^5.1.0",
+ "set-harmonic-interval": "^1.0.1",
+ "throttle-debounce": "^3.0.1",
+ "ts-easing": "^0.2.0",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-dom": "*"
+ }
+ },
+ "node_modules/read-cache": {
+ "version": "1.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pify": "^2.3.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/redux": {
+ "version": "4.2.1",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.9.2"
+ }
+ },
+ "node_modules/redux-thunk": {
+ "version": "2.4.2",
+ "license": "MIT",
+ "peerDependencies": {
+ "redux": "^4"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.14.0",
+ "license": "MIT"
+ },
+ "node_modules/reselect": {
+ "version": "4.1.8",
+ "license": "MIT"
+ },
+ "node_modules/resize-observer-polyfill": {
+ "version": "1.5.1",
+ "license": "MIT"
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.6.1",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.6.1",
+ "@rollup/rollup-android-arm64": "4.6.1",
+ "@rollup/rollup-darwin-arm64": "4.6.1",
+ "@rollup/rollup-darwin-x64": "4.6.1",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.6.1",
+ "@rollup/rollup-linux-arm64-gnu": "4.6.1",
+ "@rollup/rollup-linux-arm64-musl": "4.6.1",
+ "@rollup/rollup-linux-x64-gnu": "4.6.1",
+ "@rollup/rollup-linux-x64-musl": "4.6.1",
+ "@rollup/rollup-win32-arm64-msvc": "4.6.1",
+ "@rollup/rollup-win32-ia32-msvc": "4.6.1",
+ "@rollup/rollup-win32-x64-msvc": "4.6.1",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/rtl-css-js": {
+ "version": "1.16.1",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.1.2"
+ }
+ },
+ "node_modules/run-applescript": {
+ "version": "5.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/run-applescript/node_modules/execa": {
+ "version": "5.1.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/run-applescript/node_modules/human-signals": {
+ "version": "2.1.0",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/run-applescript/node_modules/is-stream": {
+ "version": "2.0.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/run-applescript/node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/run-applescript/node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/run-applescript/node_modules/onetime": {
+ "version": "5.1.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/run-applescript/node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/sass": {
+ "version": "1.69.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chokidar": ">=3.0.0 <4.0.0",
+ "immutable": "^4.0.0",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.0",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/screenfull": {
+ "version": "5.2.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/set-harmonic-interval": {
+ "version": "1.0.1",
+ "license": "Unlicense",
+ "engines": {
+ "node": ">=6.9"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.0.2",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stack-generator": {
+ "version": "2.0.10",
+ "license": "MIT",
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/stackframe": {
+ "version": "1.3.4",
+ "license": "MIT"
+ },
+ "node_modules/stacktrace-gps": {
+ "version": "3.1.2",
+ "license": "MIT",
+ "dependencies": {
+ "source-map": "0.5.6",
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/stacktrace-gps/node_modules/source-map": {
+ "version": "0.5.6",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stacktrace-js": {
+ "version": "2.0.2",
+ "license": "MIT",
+ "dependencies": {
+ "error-stack-parser": "^2.0.6",
+ "stack-generator": "^2.0.5",
+ "stacktrace-gps": "^3.0.4"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/stylis": {
+ "version": "4.3.0",
+ "license": "MIT"
+ },
+ "node_modules/sucrase": {
+ "version": "3.34.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "glob": "7.1.6",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/sucrase/node_modules/glob": {
+ "version": "7.1.6",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/synckit": {
+ "version": "0.8.6",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@pkgr/utils": "^2.4.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "node_modules/tailwindcss": {
+ "version": "3.3.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.5.3",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.0",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.19.1",
+ "lilconfig": "^2.1.0",
+ "micromatch": "^4.0.5",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.0.0",
+ "postcss": "^8.4.23",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.1",
+ "postcss-nested": "^6.0.1",
+ "postcss-selector-parser": "^6.0.11",
+ "resolve": "^1.22.2",
+ "sucrase": "^3.32.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/throttle-debounce": {
+ "version": "3.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/titleize": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/to-fast-properties": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toggle-selection": {
+ "version": "1.0.6",
+ "license": "MIT"
+ },
+ "node_modules/ts-easing": {
+ "version": "0.2.0",
+ "license": "Unlicense"
+ },
+ "node_modules/ts-interface-checker": {
+ "version": "0.1.13",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/tslib": {
+ "version": "2.6.2",
+ "license": "0BSD"
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.3.2",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/untildify": {
+ "version": "4.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.13",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.2.0",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/uuid": {
+ "version": "9.0.1",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/vite": {
+ "version": "5.0.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.19.3",
+ "postcss": "^8.4.31",
+ "rollup": "^4.2.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yaml": {
+ "version": "2.3.4",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ },
+ "dependencies": {
+ "@aashutoshrathi/word-wrap": {
+ "version": "1.2.6",
+ "dev": true
+ },
+ "@alloc/quick-lru": {
+ "version": "5.2.0",
+ "dev": true
+ },
+ "@ampproject/remapping": {
+ "version": "2.2.1",
+ "dev": true,
+ "requires": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "@babel/code-frame": {
+ "version": "7.23.5",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.23.4",
+ "chalk": "^2.4.2"
+ }
+ },
+ "@babel/compat-data": {
+ "version": "7.23.5",
+ "dev": true
+ },
+ "@babel/core": {
+ "version": "7.23.5",
+ "dev": true,
+ "requires": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.23.5",
+ "@babel/generator": "^7.23.5",
+ "@babel/helper-compilation-targets": "^7.22.15",
+ "@babel/helper-module-transforms": "^7.23.3",
+ "@babel/helpers": "^7.23.5",
+ "@babel/parser": "^7.23.5",
+ "@babel/template": "^7.22.15",
+ "@babel/traverse": "^7.23.5",
+ "@babel/types": "^7.23.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.1",
+ "dev": true
+ }
+ }
+ },
+ "@babel/generator": {
+ "version": "7.23.5",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.23.5",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
+ "jsesc": "^2.5.1"
+ }
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.22.15",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.22.9",
+ "@babel/helper-validator-option": "^7.22.15",
+ "browserslist": "^4.21.9",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.1",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-environment-visitor": {
+ "version": "7.22.20",
+ "dev": true
+ },
+ "@babel/helper-function-name": {
+ "version": "7.23.0",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.22.15",
+ "@babel/types": "^7.23.0"
+ }
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.22.5",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.22.15",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.23.3",
+ "dev": true,
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-module-imports": "^7.22.15",
+ "@babel/helper-simple-access": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/helper-validator-identifier": "^7.22.20"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "dev": true
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.22.5",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.22.6",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-string-parser": {
+ "version": "7.23.4",
+ "dev": true
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.20",
+ "dev": true
+ },
+ "@babel/helper-validator-option": {
+ "version": "7.23.5",
+ "dev": true
+ },
+ "@babel/helpers": {
+ "version": "7.23.5",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.22.15",
+ "@babel/traverse": "^7.23.5",
+ "@babel/types": "^7.23.5"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.23.4",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.23.5",
+ "dev": true
+ },
+ "@babel/plugin-transform-react-jsx-self": {
+ "version": "7.23.3",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ }
+ },
+ "@babel/plugin-transform-react-jsx-source": {
+ "version": "7.23.3",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ }
+ },
+ "@babel/runtime": {
+ "version": "7.23.5",
+ "requires": {
+ "regenerator-runtime": "^0.14.0"
+ }
+ },
+ "@babel/template": {
+ "version": "7.22.15",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.23.5",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.23.5",
+ "@babel/generator": "^7.23.5",
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-function-name": "^7.23.0",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/parser": "^7.23.5",
+ "@babel/types": "^7.23.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ }
+ },
+ "@babel/types": {
+ "version": "7.23.5",
+ "dev": true,
+ "requires": {
+ "@babel/helper-string-parser": "^7.23.4",
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@esbuild/win32-x64": {
+ "version": "0.19.8",
+ "dev": true,
+ "optional": true
+ },
+ "@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "@eslint-community/regexpp": {
+ "version": "4.10.0",
+ "dev": true
+ },
+ "@eslint/eslintrc": {
+ "version": "2.1.3",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "dependencies": {
+ "globals": {
+ "version": "13.23.0",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ }
+ }
+ },
+ "@eslint/js": {
+ "version": "8.54.0",
+ "dev": true
+ },
+ "@humanwhocodes/config-array": {
+ "version": "0.11.13",
+ "dev": true,
+ "requires": {
+ "@humanwhocodes/object-schema": "^2.0.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.5"
+ }
+ },
+ "@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "dev": true
+ },
+ "@humanwhocodes/object-schema": {
+ "version": "2.0.1",
+ "dev": true
+ },
+ "@jridgewell/gen-mapping": {
+ "version": "0.3.3",
+ "dev": true,
+ "requires": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "@jridgewell/resolve-uri": {
+ "version": "3.1.1",
+ "dev": true
+ },
+ "@jridgewell/set-array": {
+ "version": "1.1.2",
+ "dev": true
+ },
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.4.15"
+ },
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.20",
+ "dev": true,
+ "requires": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@pkgr/utils": {
+ "version": "2.4.2",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.3",
+ "fast-glob": "^3.3.0",
+ "is-glob": "^4.0.3",
+ "open": "^9.1.0",
+ "picocolors": "^1.0.0",
+ "tslib": "^2.6.0"
+ }
+ },
+ "@reduxjs/toolkit": {
+ "version": "1.9.7",
+ "requires": {
+ "immer": "^9.0.21",
+ "redux": "^4.2.1",
+ "redux-thunk": "^2.4.2",
+ "reselect": "^4.1.8"
+ }
+ },
+ "@rollup/rollup-win32-x64-msvc": {
+ "version": "4.6.1",
+ "dev": true,
+ "optional": true
+ },
+ "@types/babel__core": {
+ "version": "7.20.5",
+ "dev": true,
+ "requires": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "@types/babel__generator": {
+ "version": "7.6.7",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@types/babel__template": {
+ "version": "7.4.4",
+ "dev": true,
+ "requires": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@types/babel__traverse": {
+ "version": "7.20.4",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "@types/hoist-non-react-statics": {
+ "version": "3.3.5",
+ "requires": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
+ "@types/js-cookie": {
+ "version": "2.2.7"
+ },
+ "@types/prop-types": {
+ "version": "15.7.11"
+ },
+ "@types/react": {
+ "version": "18.2.39",
+ "requires": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "@types/react-dom": {
+ "version": "18.2.17",
+ "devOptional": true,
+ "requires": {
+ "@types/react": "*"
+ }
+ },
+ "@types/scheduler": {
+ "version": "0.16.8"
+ },
+ "@types/use-sync-external-store": {
+ "version": "0.0.3"
+ },
+ "@types/uuid": {
+ "version": "9.0.7",
+ "dev": true
+ },
+ "@ungap/structured-clone": {
+ "version": "1.2.0",
+ "dev": true
+ },
+ "@vitejs/plugin-react": {
+ "version": "4.2.0",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.23.3",
+ "@babel/plugin-transform-react-jsx-self": "^7.23.3",
+ "@babel/plugin-transform-react-jsx-source": "^7.23.3",
+ "@types/babel__core": "^7.20.4",
+ "react-refresh": "^0.14.0"
+ }
+ },
+ "@xobotyi/scrollbar-width": {
+ "version": "1.9.5"
+ },
+ "acorn": {
+ "version": "8.11.2",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "5.3.2",
+ "dev": true,
+ "requires": {}
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "dev": true,
+ "requires": {
+ "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-regex": {
+ "version": "5.0.1",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "any-promise": {
+ "version": "1.3.0",
+ "dev": true
+ },
+ "anymatch": {
+ "version": "3.1.3",
+ "dev": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "arg": {
+ "version": "5.0.2",
+ "dev": true
+ },
+ "argparse": {
+ "version": "2.0.1",
+ "dev": true
+ },
+ "autoprefixer": {
+ "version": "10.4.16",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.21.10",
+ "caniuse-lite": "^1.0.30001538",
+ "fraction.js": "^4.3.6",
+ "normalize-range": "^0.1.2",
+ "picocolors": "^1.0.0",
+ "postcss-value-parser": "^4.2.0"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "dev": true
+ },
+ "big-integer": {
+ "version": "1.6.52",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "2.2.0",
+ "dev": true
+ },
+ "bplist-parser": {
+ "version": "0.2.0",
+ "dev": true,
+ "requires": {
+ "big-integer": "^1.6.44"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "browserslist": {
+ "version": "4.22.1",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30001541",
+ "electron-to-chromium": "^1.4.535",
+ "node-releases": "^2.0.13",
+ "update-browserslist-db": "^1.0.13"
+ }
+ },
+ "bundle-name": {
+ "version": "3.0.0",
+ "dev": true,
+ "requires": {
+ "run-applescript": "^5.0.0"
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "dev": true
+ },
+ "camelcase-css": {
+ "version": "2.0.1",
+ "dev": true
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001565",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "chokidar": {
+ "version": "3.5.3",
+ "dev": true,
+ "requires": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "fsevents": "~2.3.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"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "5.1.2",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "dev": true
+ },
+ "commander": {
+ "version": "4.1.1",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "2.0.0",
+ "dev": true
+ },
+ "copy-to-clipboard": {
+ "version": "3.3.3",
+ "requires": {
+ "toggle-selection": "^1.0.6"
+ }
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "css-in-js-utils": {
+ "version": "3.1.0",
+ "requires": {
+ "hyphenate-style-name": "^1.0.3"
+ }
+ },
+ "css-tree": {
+ "version": "1.1.3",
+ "requires": {
+ "mdn-data": "2.0.14",
+ "source-map": "^0.6.1"
+ }
+ },
+ "cssesc": {
+ "version": "3.0.0",
+ "dev": true
+ },
+ "csstype": {
+ "version": "3.1.2"
+ },
+ "debug": {
+ "version": "4.3.4",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.4",
+ "dev": true
+ },
+ "default-browser": {
+ "version": "4.0.0",
+ "dev": true,
+ "requires": {
+ "bundle-name": "^3.0.0",
+ "default-browser-id": "^3.0.0",
+ "execa": "^7.1.1",
+ "titleize": "^3.0.0"
+ }
+ },
+ "default-browser-id": {
+ "version": "3.0.0",
+ "dev": true,
+ "requires": {
+ "bplist-parser": "^0.2.0",
+ "untildify": "^4.0.0"
+ }
+ },
+ "define-lazy-prop": {
+ "version": "3.0.0",
+ "dev": true
+ },
+ "didyoumean": {
+ "version": "1.2.2",
+ "dev": true
+ },
+ "dlv": {
+ "version": "1.1.3",
+ "dev": true
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "electron-to-chromium": {
+ "version": "1.4.601",
+ "dev": true
+ },
+ "error-stack-parser": {
+ "version": "2.1.4",
+ "requires": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "esbuild": {
+ "version": "0.19.8",
+ "dev": true,
+ "requires": {
+ "@esbuild/android-arm": "0.19.8",
+ "@esbuild/android-arm64": "0.19.8",
+ "@esbuild/android-x64": "0.19.8",
+ "@esbuild/darwin-arm64": "0.19.8",
+ "@esbuild/darwin-x64": "0.19.8",
+ "@esbuild/freebsd-arm64": "0.19.8",
+ "@esbuild/freebsd-x64": "0.19.8",
+ "@esbuild/linux-arm": "0.19.8",
+ "@esbuild/linux-arm64": "0.19.8",
+ "@esbuild/linux-ia32": "0.19.8",
+ "@esbuild/linux-loong64": "0.19.8",
+ "@esbuild/linux-mips64el": "0.19.8",
+ "@esbuild/linux-ppc64": "0.19.8",
+ "@esbuild/linux-riscv64": "0.19.8",
+ "@esbuild/linux-s390x": "0.19.8",
+ "@esbuild/linux-x64": "0.19.8",
+ "@esbuild/netbsd-x64": "0.19.8",
+ "@esbuild/openbsd-x64": "0.19.8",
+ "@esbuild/sunos-x64": "0.19.8",
+ "@esbuild/win32-arm64": "0.19.8",
+ "@esbuild/win32-ia32": "0.19.8",
+ "@esbuild/win32-x64": "0.19.8"
+ }
+ },
+ "escalade": {
+ "version": "3.1.1",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "dev": true
+ },
+ "eslint": {
+ "version": "8.54.0",
+ "dev": true,
+ "requires": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.3",
+ "@eslint/js": "8.54.0",
+ "@humanwhocodes/config-array": "^0.11.13",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "dev": true
+ },
+ "globals": {
+ "version": "13.23.0",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "eslint-config-prettier": {
+ "version": "9.1.0",
+ "dev": true,
+ "requires": {}
+ },
+ "eslint-plugin-prettier": {
+ "version": "5.0.1",
+ "dev": true,
+ "requires": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.8.5"
+ }
+ },
+ "eslint-plugin-react-hooks": {
+ "version": "4.6.0",
+ "dev": true,
+ "requires": {}
+ },
+ "eslint-plugin-react-refresh": {
+ "version": "0.4.4",
+ "dev": true,
+ "requires": {}
+ },
+ "eslint-scope": {
+ "version": "7.2.2",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "3.4.3",
+ "dev": true
+ },
+ "espree": {
+ "version": "9.6.1",
+ "dev": true,
+ "requires": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ }
+ },
+ "esquery": {
+ "version": "1.5.0",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ }
+ },
+ "estraverse": {
+ "version": "5.3.0",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "dev": true
+ },
+ "execa": {
+ "version": "7.2.0",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.1",
+ "human-signals": "^4.3.0",
+ "is-stream": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^5.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^3.0.7",
+ "strip-final-newline": "^3.0.0"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3"
+ },
+ "fast-diff": {
+ "version": "1.3.0",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.3.2",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "5.1.2",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "dev": true
+ },
+ "fast-loops": {
+ "version": "1.1.3"
+ },
+ "fast-shallow-equal": {
+ "version": "1.0.0"
+ },
+ "fastest-stable-stringify": {
+ "version": "2.0.2"
+ },
+ "fastq": {
+ "version": "1.15.0",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "find-up": {
+ "version": "5.0.0",
+ "dev": true,
+ "requires": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "flat-cache": {
+ "version": "3.2.0",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.2.9",
+ "dev": true
+ },
+ "fraction.js": {
+ "version": "4.3.7",
+ "dev": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "dev": true
+ },
+ "function-bind": {
+ "version": "1.1.2",
+ "dev": true
+ },
+ "gensync": {
+ "version": "1.0.0-beta.2",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "6.0.1",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.2.3",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "6.0.2",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.3"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "dev": true
+ },
+ "graphemer": {
+ "version": "1.4.0",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "dev": true
+ },
+ "hasown": {
+ "version": "2.0.0",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.2"
+ }
+ },
+ "hoist-non-react-statics": {
+ "version": "3.3.2",
+ "requires": {
+ "react-is": "^16.7.0"
+ },
+ "dependencies": {
+ "react-is": {
+ "version": "16.13.1"
+ }
+ }
+ },
+ "human-signals": {
+ "version": "4.3.1",
+ "dev": true
+ },
+ "hyphenate-style-name": {
+ "version": "1.0.4"
+ },
+ "ignore": {
+ "version": "5.3.0",
+ "dev": true
+ },
+ "immer": {
+ "version": "9.0.21"
+ },
+ "immutable": {
+ "version": "4.3.4",
+ "dev": true
+ },
+ "import-fresh": {
+ "version": "3.3.0",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "dev": true
+ },
+ "inline-style-prefixer": {
+ "version": "7.0.0",
+ "requires": {
+ "css-in-js-utils": "^3.1.0",
+ "fast-loops": "^1.1.3"
+ }
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-core-module": {
+ "version": "2.13.1",
+ "dev": true,
+ "requires": {
+ "hasown": "^2.0.0"
+ }
+ },
+ "is-docker": {
+ "version": "3.0.0",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-inside-container": {
+ "version": "1.0.0",
+ "dev": true,
+ "requires": {
+ "is-docker": "^3.0.0"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "dev": true
+ },
+ "is-path-inside": {
+ "version": "3.0.3",
+ "dev": true
+ },
+ "is-stream": {
+ "version": "3.0.0",
+ "dev": true
+ },
+ "is-wsl": {
+ "version": "2.2.0",
+ "dev": true,
+ "requires": {
+ "is-docker": "^2.0.0"
+ },
+ "dependencies": {
+ "is-docker": {
+ "version": "2.2.1",
+ "dev": true
+ }
+ }
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "dev": true
+ },
+ "jiti": {
+ "version": "1.21.0",
+ "dev": true
+ },
+ "js-cookie": {
+ "version": "2.2.1"
+ },
+ "js-tokens": {
+ "version": "4.0.0"
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "dev": true
+ },
+ "json-buffer": {
+ "version": "3.0.1",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "dev": true
+ },
+ "json5": {
+ "version": "2.2.3",
+ "dev": true
+ },
+ "keyv": {
+ "version": "4.5.4",
+ "dev": true,
+ "requires": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "levn": {
+ "version": "0.4.1",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "lilconfig": {
+ "version": "2.1.0",
+ "dev": true
+ },
+ "lines-and-columns": {
+ "version": "1.2.4",
+ "dev": true
+ },
+ "locate-path": {
+ "version": "6.0.0",
+ "dev": true,
+ "requires": {
+ "p-locate": "^5.0.0"
+ }
+ },
+ "lodash.merge": {
+ "version": "4.6.2",
+ "dev": true
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "dev": true,
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "mdn-data": {
+ "version": "2.0.14"
+ },
+ "merge-stream": {
+ "version": "2.0.0",
+ "dev": true
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.5",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
+ "mimic-fn": {
+ "version": "4.0.0",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "dev": true
+ },
+ "mz": {
+ "version": "2.7.0",
+ "dev": true,
+ "requires": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
+ "nano-css": {
+ "version": "5.6.1",
+ "requires": {
+ "@jridgewell/sourcemap-codec": "^1.4.15",
+ "css-tree": "^1.1.2",
+ "csstype": "^3.1.2",
+ "fastest-stable-stringify": "^2.0.2",
+ "inline-style-prefixer": "^7.0.0",
+ "rtl-css-js": "^1.16.1",
+ "stacktrace-js": "^2.0.2",
+ "stylis": "^4.3.0"
+ }
+ },
+ "nanoid": {
+ "version": "3.3.7",
+ "dev": true
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "dev": true
+ },
+ "node-releases": {
+ "version": "2.0.14",
+ "dev": true
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "dev": true
+ },
+ "normalize-range": {
+ "version": "0.1.2",
+ "dev": true
+ },
+ "npm-run-path": {
+ "version": "5.1.0",
+ "dev": true,
+ "requires": {
+ "path-key": "^4.0.0"
+ },
+ "dependencies": {
+ "path-key": {
+ "version": "4.0.0",
+ "dev": true
+ }
+ }
+ },
+ "object-assign": {
+ "version": "4.1.1"
+ },
+ "object-hash": {
+ "version": "3.0.0",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "6.0.0",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^4.0.0"
+ }
+ },
+ "open": {
+ "version": "9.1.0",
+ "dev": true,
+ "requires": {
+ "default-browser": "^4.0.0",
+ "define-lazy-prop": "^3.0.0",
+ "is-inside-container": "^1.0.0",
+ "is-wsl": "^2.2.0"
+ }
+ },
+ "optionator": {
+ "version": "0.9.3",
+ "dev": true,
+ "requires": {
+ "@aashutoshrathi/word-wrap": "^1.2.3",
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0"
+ }
+ },
+ "p-limit": {
+ "version": "3.1.0",
+ "dev": true,
+ "requires": {
+ "yocto-queue": "^0.1.0"
+ }
+ },
+ "p-locate": {
+ "version": "5.0.0",
+ "dev": true,
+ "requires": {
+ "p-limit": "^3.0.2"
+ }
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "dev": true
+ },
+ "picocolors": {
+ "version": "1.0.0",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "dev": true
+ },
+ "pify": {
+ "version": "2.3.0",
+ "dev": true
+ },
+ "pirates": {
+ "version": "4.0.6",
+ "dev": true
+ },
+ "postcss": {
+ "version": "8.4.32",
+ "dev": true,
+ "requires": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ }
+ },
+ "postcss-import": {
+ "version": "15.1.0",
+ "dev": true,
+ "requires": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ }
+ },
+ "postcss-js": {
+ "version": "4.0.1",
+ "dev": true,
+ "requires": {
+ "camelcase-css": "^2.0.1"
+ }
+ },
+ "postcss-load-config": {
+ "version": "4.0.2",
+ "dev": true,
+ "requires": {
+ "lilconfig": "^3.0.0",
+ "yaml": "^2.3.4"
+ },
+ "dependencies": {
+ "lilconfig": {
+ "version": "3.0.0",
+ "dev": true
+ }
+ }
+ },
+ "postcss-nested": {
+ "version": "6.0.1",
+ "dev": true,
+ "requires": {
+ "postcss-selector-parser": "^6.0.11"
+ }
+ },
+ "postcss-selector-parser": {
+ "version": "6.0.13",
+ "dev": true,
+ "requires": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "4.2.0",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "dev": true
+ },
+ "prettier": {
+ "version": "3.1.1",
+ "dev": true
+ },
+ "prettier-linter-helpers": {
+ "version": "1.0.0",
+ "dev": true,
+ "requires": {
+ "fast-diff": "^1.1.2"
+ }
+ },
+ "prop-types": {
+ "version": "15.8.1",
+ "requires": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ },
+ "dependencies": {
+ "react-is": {
+ "version": "16.13.1"
+ }
+ }
+ },
+ "punycode": {
+ "version": "2.3.1",
+ "dev": true
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "dev": true
+ },
+ "react": {
+ "version": "18.2.0",
+ "requires": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "react-bootstrap-icons": {
+ "version": "1.10.3",
+ "requires": {
+ "prop-types": "^15.7.2"
+ }
+ },
+ "react-dom": {
+ "version": "18.2.0",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.0"
+ }
+ },
+ "react-is": {
+ "version": "18.2.0"
+ },
+ "react-redux": {
+ "version": "8.1.3",
+ "requires": {
+ "@babel/runtime": "^7.12.1",
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "@types/use-sync-external-store": "^0.0.3",
+ "hoist-non-react-statics": "^3.3.2",
+ "react-is": "^18.0.0",
+ "use-sync-external-store": "^1.0.0"
+ }
+ },
+ "react-refresh": {
+ "version": "0.14.0",
+ "dev": true
+ },
+ "react-universal-interface": {
+ "version": "0.6.2",
+ "requires": {}
+ },
+ "react-use": {
+ "version": "17.4.2",
+ "requires": {
+ "@types/js-cookie": "^2.2.6",
+ "@xobotyi/scrollbar-width": "^1.9.5",
+ "copy-to-clipboard": "^3.3.1",
+ "fast-deep-equal": "^3.1.3",
+ "fast-shallow-equal": "^1.0.0",
+ "js-cookie": "^2.2.1",
+ "nano-css": "^5.6.1",
+ "react-universal-interface": "^0.6.2",
+ "resize-observer-polyfill": "^1.5.1",
+ "screenfull": "^5.1.0",
+ "set-harmonic-interval": "^1.0.1",
+ "throttle-debounce": "^3.0.1",
+ "ts-easing": "^0.2.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "read-cache": {
+ "version": "1.0.0",
+ "dev": true,
+ "requires": {
+ "pify": "^2.3.0"
+ }
+ },
+ "readdirp": {
+ "version": "3.6.0",
+ "dev": true,
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "redux": {
+ "version": "4.2.1",
+ "requires": {
+ "@babel/runtime": "^7.9.2"
+ }
+ },
+ "redux-thunk": {
+ "version": "2.4.2",
+ "requires": {}
+ },
+ "regenerator-runtime": {
+ "version": "0.14.0"
+ },
+ "reselect": {
+ "version": "4.1.8"
+ },
+ "resize-observer-polyfill": {
+ "version": "1.5.1"
+ },
+ "resolve": {
+ "version": "1.22.8",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "dev": true
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "rollup": {
+ "version": "4.6.1",
+ "dev": true,
+ "requires": {
+ "@rollup/rollup-android-arm-eabi": "4.6.1",
+ "@rollup/rollup-android-arm64": "4.6.1",
+ "@rollup/rollup-darwin-arm64": "4.6.1",
+ "@rollup/rollup-darwin-x64": "4.6.1",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.6.1",
+ "@rollup/rollup-linux-arm64-gnu": "4.6.1",
+ "@rollup/rollup-linux-arm64-musl": "4.6.1",
+ "@rollup/rollup-linux-x64-gnu": "4.6.1",
+ "@rollup/rollup-linux-x64-musl": "4.6.1",
+ "@rollup/rollup-win32-arm64-msvc": "4.6.1",
+ "@rollup/rollup-win32-ia32-msvc": "4.6.1",
+ "@rollup/rollup-win32-x64-msvc": "4.6.1",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "rtl-css-js": {
+ "version": "1.16.1",
+ "requires": {
+ "@babel/runtime": "^7.1.2"
+ }
+ },
+ "run-applescript": {
+ "version": "5.0.0",
+ "dev": true,
+ "requires": {
+ "execa": "^5.0.0"
+ },
+ "dependencies": {
+ "execa": {
+ "version": "5.1.1",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ }
+ },
+ "human-signals": {
+ "version": "2.1.0",
+ "dev": true
+ },
+ "is-stream": {
+ "version": "2.0.1",
+ "dev": true
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "dev": true
+ },
+ "npm-run-path": {
+ "version": "4.0.1",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "onetime": {
+ "version": "5.1.2",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
+ "strip-final-newline": {
+ "version": "2.0.0",
+ "dev": true
+ }
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "sass": {
+ "version": "1.69.5",
+ "dev": true,
+ "requires": {
+ "chokidar": ">=3.0.0 <4.0.0",
+ "immutable": "^4.0.0",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ }
+ },
+ "scheduler": {
+ "version": "0.23.0",
+ "requires": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "screenfull": {
+ "version": "5.2.0"
+ },
+ "set-harmonic-interval": {
+ "version": "1.0.1"
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.7",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1"
+ },
+ "source-map-js": {
+ "version": "1.0.2",
+ "dev": true
+ },
+ "stack-generator": {
+ "version": "2.0.10",
+ "requires": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "stackframe": {
+ "version": "1.3.4"
+ },
+ "stacktrace-gps": {
+ "version": "3.1.2",
+ "requires": {
+ "source-map": "0.5.6",
+ "stackframe": "^1.3.4"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.6"
+ }
+ }
+ },
+ "stacktrace-js": {
+ "version": "2.0.2",
+ "requires": {
+ "error-stack-parser": "^2.0.6",
+ "stack-generator": "^2.0.5",
+ "stacktrace-gps": "^3.0.4"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "strip-final-newline": {
+ "version": "3.0.0",
+ "dev": true
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "dev": true
+ },
+ "stylis": {
+ "version": "4.3.0"
+ },
+ "sucrase": {
+ "version": "3.34.0",
+ "dev": true,
+ "requires": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "glob": "7.1.6",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.1.6",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "dev": true
+ },
+ "synckit": {
+ "version": "0.8.6",
+ "dev": true,
+ "requires": {
+ "@pkgr/utils": "^2.4.2",
+ "tslib": "^2.6.2"
+ }
+ },
+ "tailwindcss": {
+ "version": "3.3.5",
+ "dev": true,
+ "requires": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.5.3",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.0",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.19.1",
+ "lilconfig": "^2.1.0",
+ "micromatch": "^4.0.5",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.0.0",
+ "postcss": "^8.4.23",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.1",
+ "postcss-nested": "^6.0.1",
+ "postcss-selector-parser": "^6.0.11",
+ "resolve": "^1.22.2",
+ "sucrase": "^3.32.0"
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "dev": true
+ },
+ "thenify": {
+ "version": "3.3.1",
+ "dev": true,
+ "requires": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "thenify-all": {
+ "version": "1.6.0",
+ "dev": true,
+ "requires": {
+ "thenify": ">= 3.1.0 < 4"
+ }
+ },
+ "throttle-debounce": {
+ "version": "3.0.1"
+ },
+ "titleize": {
+ "version": "3.0.0",
+ "dev": true
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "toggle-selection": {
+ "version": "1.0.6"
+ },
+ "ts-easing": {
+ "version": "0.2.0"
+ },
+ "ts-interface-checker": {
+ "version": "0.1.13",
+ "dev": true
+ },
+ "tslib": {
+ "version": "2.6.2"
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.20.2",
+ "dev": true
+ },
+ "typescript": {
+ "version": "5.3.2",
+ "dev": true
+ },
+ "untildify": {
+ "version": "4.0.0",
+ "dev": true
+ },
+ "update-browserslist-db": {
+ "version": "1.0.13",
+ "dev": true,
+ "requires": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ }
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "use-sync-external-store": {
+ "version": "1.2.0",
+ "requires": {}
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "dev": true
+ },
+ "uuid": {
+ "version": "9.0.1"
+ },
+ "vite": {
+ "version": "5.0.4",
+ "dev": true,
+ "requires": {
+ "esbuild": "^0.19.3",
+ "fsevents": "~2.3.3",
+ "postcss": "^8.4.31",
+ "rollup": "^4.2.0"
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "dev": true
+ },
+ "yaml": {
+ "version": "2.3.4",
+ "dev": true
+ },
+ "yocto-queue": {
+ "version": "0.1.0",
+ "dev": true
+ }
+ }
+}
diff --git a/apps/remote/package.json b/apps/remote/package.json
new file mode 100644
index 00000000..56e8c3f8
--- /dev/null
+++ b/apps/remote/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "remote-web-client",
+ "private": true,
+ "version": "0.1.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@reduxjs/toolkit": "^1.9.7",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-redux": "^8.1.3",
+ "redux": "^4.2.1",
+ "uuid": "^9.0.1",
+ "react-bootstrap-icons": "^1.10.3",
+ "react-use": "^17.4.2"
+ },
+ "devDependencies": {
+ "@types/react": "^18.2.37",
+ "@types/react-dom": "^18.2.15",
+ "@types/uuid": "^9.0.7",
+ "@vitejs/plugin-react": "^4.2.0",
+ "autoprefixer": "^10.4.16",
+ "eslint": "^8.53.0",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.4",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-prettier": "^5.0.1",
+ "prettier": "^3.1.0",
+ "postcss": "^8.4.32",
+ "sass": "^1.69.5",
+ "tailwindcss": "^3.3.5",
+ "typescript": "^5.2.2",
+ "vite": "^5.0.0"
+ }
+}
diff --git a/apps/remote/postcss.config.js b/apps/remote/postcss.config.js
new file mode 100644
index 00000000..2aa7205d
--- /dev/null
+++ b/apps/remote/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/apps/remote/public/Fonts/fbw-a32nx/ECAMFontRegular.ttf b/apps/remote/public/Fonts/fbw-a32nx/ECAMFontRegular.ttf
new file mode 100644
index 00000000..a206331f
Binary files /dev/null and b/apps/remote/public/Fonts/fbw-a32nx/ECAMFontRegular.ttf differ
diff --git a/apps/remote/public/favicon.ico b/apps/remote/public/favicon.ico
new file mode 100644
index 00000000..28ce4252
Binary files /dev/null and b/apps/remote/public/favicon.ico differ
diff --git a/apps/remote/src/App.css b/apps/remote/src/App.css
new file mode 100644
index 00000000..e69de29b
diff --git a/apps/remote/src/Application.tsx b/apps/remote/src/Application.tsx
new file mode 100644
index 00000000..6294a53d
--- /dev/null
+++ b/apps/remote/src/Application.tsx
@@ -0,0 +1,31 @@
+import React, { useEffect, useState } from 'react';
+import { RemoteClient } from './RemoteClient';
+import MainView from './MainView';
+import { ModalWrapper } from './modals/ModalWrapper';
+
+let remoteClient: RemoteClient | undefined;
+function initializeClient() {
+ if (!remoteClient) {
+ remoteClient = new RemoteClient(`ws://${window.location.hostname}:8380/interfaces/v1/remote-app`);
+ }
+}
+
+export const Application: React.FC = () => {
+ const [client, setClient] = useState(null);
+
+ useEffect(() => {
+ initializeClient();
+ setClient(remoteClient!);
+ }, []);
+
+ if (!client) {
+ return null;
+ }
+
+ return (
+ <>
+
+
+ >
+ );
+};
diff --git a/apps/remote/src/FlightStatusBar.tsx b/apps/remote/src/FlightStatusBar.tsx
new file mode 100644
index 00000000..307d5012
--- /dev/null
+++ b/apps/remote/src/FlightStatusBar.tsx
@@ -0,0 +1,53 @@
+import React from 'react';
+import { useAppSelector } from './store';
+import { ChevronDown, Wifi2, WifiOff } from 'react-bootstrap-icons';
+import { ConnectionPhase } from './store/connection';
+
+export interface FlightStatusProps {
+ dropdownOpen: boolean;
+ onToggleDropdown: () => void;
+}
+
+export const FlightStatusBar: React.FC = ({ dropdownOpen, onToggleDropdown }) => {
+ const connectionState = useAppSelector((state) => state.connectionState);
+
+ const flightStatus = useAppSelector((state) => state.flightStatus);
+
+ return (
+
+
+ {connectionState.connected === ConnectionPhase.ConnectedToAircraft && }
+ {connectionState.connected === ConnectionPhase.ConnectedToBridge && }
+ {connectionState.connected === ConnectionPhase.ConnectedToAircraft
+ ? `Connected (${connectionState.clientName})`
+ : connectionState.connected === ConnectionPhase.ConnectedToBridge
+ ? 'Waiting on aircraft'
+ : 'Not connected'}
+
+
+
+
+
+
+
+ {flightStatus.airframe.name}
+ {flightStatus.airframe.livery}
+
+
+ );
+};
diff --git a/apps/remote/src/FlightStatusPanel.tsx b/apps/remote/src/FlightStatusPanel.tsx
new file mode 100644
index 00000000..c55dc992
--- /dev/null
+++ b/apps/remote/src/FlightStatusPanel.tsx
@@ -0,0 +1,83 @@
+import React from 'react';
+import { ChevronDown } from 'react-bootstrap-icons';
+
+export interface FlightStatusPanelProps {
+ shown: boolean;
+ onToggleDropdown: () => void;
+}
+
+export const FlightStatusPanel: React.FC = ({ shown, onToggleDropdown }) => {
+ return (
+
+
+
+
+
+ KLAX
+ KLAX
+
+
+
+ KJFK
+ JFK
+
+
+
+
+ KLAX/21R CLEEE PKE DRK J96 SLN J24 MCI J80 SPI
+ KOLTS WWODD RINTE KLYNE Q29WWSHR JHW J70 LVZ LENDY8{' '}
+ KJFK/04R
+
+
+
+
+
+
A320-251N
+ FBW397
+
+
+
+
+
+ 157
+ HDG
+
+
+ 33 000
+ ALT
+
+
+ 350
+ TAS
+
+
+
+
+
+ 157
+ HDG
+
+
+ LAXJFK1
+ CO RTE
+
+
+ 350
+ TAS
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/apps/remote/src/InstrumentsPanel.tsx b/apps/remote/src/InstrumentsPanel.tsx
new file mode 100644
index 00000000..fbf96e50
--- /dev/null
+++ b/apps/remote/src/InstrumentsPanel.tsx
@@ -0,0 +1,64 @@
+import React from 'react';
+import { protocolV0 } from '@flybywiresim/remote-bridge-types';
+import { useAppSelector } from './store';
+import { ArrowRight } from 'react-bootstrap-icons';
+import { useModals } from './modals/ModalHook';
+import { ValueModal } from './modals/ValueModal';
+
+export interface InstrumentsPanelProps {
+ onInstrumentClicked: (instrument: protocolV0.InstrumentMetadata) => void;
+}
+
+export const InstrumentsPanel: React.FC = ({ onInstrumentClicked }) => {
+ const instruments = useAppSelector((state) => state.instruments.availableInstruments);
+
+ const { showValueModal } = useModals();
+
+ const handleSelectInstrument = async () =>
+ showValueModal(
+
+ title="Choose an instrument"
+ render={(pickValueAndClose) => (
+
+ {instruments.map((it) => (
+ pickValueAndClose(it)} />
+ ))}
+
+ )}
+ onValuePicked={(value) => onInstrumentClicked(value)}
+ />,
+ );
+
+ return (
+
+ {instruments.length === 0 ? (
+ No instruments available
+ ) : (
+
+
+
+ )}
+
+ );
+};
+
+interface InstrumentButtonProps {
+ instrument: protocolV0.InstrumentMetadata;
+ onClick: () => void;
+}
+
+const InstrumentButton: React.FC = ({ instrument, onClick }) => {
+ return (
+
+ );
+};
diff --git a/apps/remote/src/MainView.tsx b/apps/remote/src/MainView.tsx
new file mode 100644
index 00000000..eebca02d
--- /dev/null
+++ b/apps/remote/src/MainView.tsx
@@ -0,0 +1,492 @@
+import React, { forwardRef, useCallback, useEffect, useRef, useState } from 'react';
+
+import {
+ DataStorageSetCallback,
+ RegisterViewListenerCallback,
+ RemoteClient,
+ SimVarSetCallback,
+ SimVarSubscribeCallback,
+ ViewListenerOffCallback,
+ ViewListenerOnCallback,
+} from './RemoteClient';
+import { installShims } from './shims';
+import { FlightStatusBar } from './FlightStatusBar';
+import { InstrumentsPanel } from './InstrumentsPanel';
+import { applicationStore, useAppDispatch, useAppSelector } from './store';
+import { addAvailableInstrument, clearAvailableInstruments, setLoadedInstrument } from './store/instruments';
+import { v4 } from 'uuid';
+import { ConnectionPhase, setCurrentSubscriptionGroupID } from './store/connection';
+import { clearSimVars } from './store/simVars';
+import { CloudSlashFill, Fullscreen, XLg } from 'react-bootstrap-icons';
+import { FlightStatusPanel } from './FlightStatusPanel';
+import { protocolV0 } from '@flybywiresim/remote-bridge-types';
+
+interface MainViewProps {
+ client: RemoteClient;
+}
+
+const MainView: React.FC = ({ client }) => {
+ const iframeRef = useRef(null);
+
+ const isConnected = useAppSelector((state) => state.connectionState.connected);
+ const loadedInstrument = useAppSelector((state) => state.instruments.loadedInstrument);
+
+ const [flightStatusDropdownOpened, setFlightStatusDropdownOpened] = useState(false);
+ const [fullScreenOpened, setFullScreenOpened] = useState(false);
+
+ const dispatch = useAppDispatch();
+
+ const simVarSubscribeCallback: SimVarSubscribeCallback = (type, name, unit) => {
+ const id = Math.floor(Math.random() * 100_000);
+
+ client.subscribeToSimVar(
+ type,
+ name,
+ unit,
+ id,
+ applicationStore.getState().connectionState.currentSubscriptionGroupID,
+ );
+
+ return id;
+ };
+
+ const simVarSetCallback: SimVarSetCallback = (name, unit, value) => {
+ return client.setSimVarValue(name, unit, value);
+ };
+
+ const dataStorageSetCallback: DataStorageSetCallback = (key, value) => {
+ client.setDataStorageKey(key, value);
+ };
+
+ const registerViewListenerCallback: RegisterViewListenerCallback = (name) => {
+ const listenerID = v4();
+
+ return [listenerID, client.registerViewListener(name, listenerID)];
+ };
+
+ const viewListenerOnCallback: ViewListenerOnCallback = (listenerID, event, callback): string => {
+ const subscriptionID = v4();
+
+ client.viewListenerOn(
+ listenerID,
+ event,
+ callback,
+ subscriptionID,
+ applicationStore.getState().connectionState.currentSubscriptionGroupID!,
+ );
+
+ return subscriptionID;
+ };
+
+ const viewListenerOffCallback: ViewListenerOffCallback = (subscriptionID): void => {
+ client.viewListenerOff(subscriptionID);
+ };
+
+ const resizeIframe = useCallback(() => {
+ if (fullScreenOpened || !iframeRef.current || !iframeRef.current.contentDocument || !loadedInstrument) {
+ return;
+ }
+
+ const wrapperWidth = iframeRef.current.parentElement!.parentElement!.clientWidth;
+
+ const scale = wrapperWidth / loadedInstrument.dimensions.width;
+ iframeRef.current.style.transform = `scale(${scale})`;
+ iframeRef.current.style.transformOrigin = 'top left';
+ }, [fullScreenOpened, loadedInstrument]);
+
+ const resetIframe = async () => {
+ const updateInterval = (window as unknown as { FBW_REMOTE_INTERVAL: number | null }).FBW_REMOTE_INTERVAL;
+ if (updateInterval !== null) {
+ window.clearInterval(updateInterval);
+ }
+
+ if (!iframeRef.current || !iframeRef.current.contentDocument) {
+ return;
+ }
+
+ iframeRef.current.style.width = '0px';
+ iframeRef.current.style.height = '0px';
+
+ const iframeWindow = iframeRef.current.contentWindow!;
+
+ iframeWindow.location.reload();
+
+ // Wait just to be careful
+ await new Promise((resolve) => setTimeout(resolve, 100));
+ };
+
+ const runCodeInIframe = (jsVfsUrl: string, cssVfsUrl: string, width: number, height: number) => {
+ if (!iframeRef.current || !iframeRef.current.contentDocument) {
+ return;
+ }
+
+ const iframeWindow = iframeRef.current.contentWindow! as Window & { lastUpdate: number | undefined };
+ const iframeDocument = iframeRef.current.contentWindow!.document;
+
+ if (!iframeWindow || !iframeDocument) {
+ return;
+ }
+
+ iframeRef.current.style.width = `${width}px`;
+ iframeRef.current.style.height = `${height}px`;
+
+ (iframeWindow as unknown as { FBW_REMOTE: boolean })['FBW_REMOTE'] = true;
+
+ iframeDocument.head.innerHTML = '';
+ iframeDocument.body.innerHTML = '';
+
+ const baseTag = iframeDocument.createElement('base');
+ baseTag.setAttribute('href', `http://localhost:8380/api/v1/remote-app/vfs-proxy/`);
+
+ iframeDocument.head.appendChild(baseTag);
+
+ const baseStyleTag = iframeDocument.createElement('style');
+ baseStyleTag.textContent = `
+ html, body {
+ padding: 0;
+ margin: 0;
+ overflow: hidden;
+ }
+ `;
+ iframeDocument.head.appendChild(baseStyleTag);
+
+ const panelTag = iframeDocument.createElement('vcockpit-panel');
+ iframeDocument.body.appendChild(panelTag);
+
+ const instrumentTag = iframeDocument.createElement('fbw-remote-instrument');
+ instrumentTag.setAttribute('Index', '1');
+ panelTag.appendChild(instrumentTag);
+
+ const contentTag = iframeDocument.createElement('div');
+ contentTag.id = 'INSTRUMENT_CONTENT';
+ instrumentTag.appendChild(contentTag);
+
+ const titleTag = iframeDocument.createElement('h1');
+ titleTag.textContent = '';
+ contentTag.appendChild(titleTag);
+
+ const contentTag2 = iframeDocument.createElement('div');
+ contentTag2.id = 'MSFS_REACT_MOUNT';
+ instrumentTag.appendChild(contentTag2);
+
+ const titleTag2 = iframeDocument.createElement('h1');
+ titleTag2.textContent = '';
+ contentTag2.appendChild(titleTag2);
+
+ installShims(
+ iframeWindow,
+ simVarSubscribeCallback,
+ simVarSetCallback,
+ dataStorageSetCallback,
+ registerViewListenerCallback,
+ viewListenerOnCallback,
+ viewListenerOffCallback,
+ );
+
+ const scriptTag = iframeDocument.createElement('script');
+ scriptTag.setAttribute('src', `.${jsVfsUrl}`);
+
+ iframeDocument.head.appendChild(scriptTag);
+
+ iframeWindow.setInterval(() => {
+ const now = Date.now();
+
+ iframeDocument
+ ?.getElementById('INSTRUMENT_CONTENT')
+ ?.parentElement?.dispatchEvent(new CustomEvent('update', { detail: now - (iframeWindow.lastUpdate ?? now) }));
+
+ iframeWindow.lastUpdate = now;
+ });
+
+ setTimeout(() => {
+ const cssTag = iframeDocument.createElement('link');
+ cssTag.setAttribute('href', `.${cssVfsUrl}`);
+ cssTag.setAttribute('rel', 'stylesheet');
+ cssTag.setAttribute('type', 'text/css');
+
+ iframeDocument.head.appendChild(cssTag);
+
+ iframeDocument.body.style.backgroundColor = 'black';
+ }, 1_000);
+ };
+
+ useEffect(() => {
+ if (isConnected !== ConnectionPhase.ConnectedToAircraft) {
+ return;
+ }
+
+ client.enumerateInstruments().then((instruments) => {
+ dispatch(clearAvailableInstruments());
+
+ for (const instrument of instruments) {
+ dispatch(addAvailableInstrument(instrument));
+ }
+ });
+ }, [client, dispatch, isConnected]);
+
+ useEffect(() => {
+ window.addEventListener('resize', resizeIframe);
+
+ return () => window.removeEventListener('resize', resizeIframe);
+ }, [resizeIframe]);
+
+ useEffect(() => {
+ resizeIframe();
+ }, [resizeIframe, loadedInstrument]);
+
+ const handleLoadInstrument = useCallback(
+ async (instrument: protocolV0.InstrumentMetadata | null) => {
+ await resetIframe();
+
+ dispatch(clearSimVars());
+
+ const currentSubscriptionGroupID = applicationStore.getState().connectionState.currentSubscriptionGroupID;
+
+ if (currentSubscriptionGroupID !== null) {
+ client.cancelSubscriptionGroup(currentSubscriptionGroupID);
+ }
+
+ if (instrument) {
+ dispatch(setLoadedInstrument(instrument));
+ dispatch(setCurrentSubscriptionGroupID(v4()));
+
+ runCodeInIframe(
+ instrument.gauges[0].bundles.js,
+ instrument.gauges[0].bundles.css,
+ instrument.dimensions.width,
+ instrument.dimensions.height,
+ );
+ } else {
+ dispatch(setLoadedInstrument(null));
+ dispatch(setCurrentSubscriptionGroupID(null));
+ }
+ },
+ [client, dispatch, runCodeInIframe],
+ );
+
+ useEffect(() => {
+ const subscription = client.on('connectionRegained', async () => {
+ await resetIframe();
+
+ const currentInstrument = applicationStore.getState().instruments.loadedInstrument;
+
+ if (currentInstrument) {
+ await handleLoadInstrument(currentInstrument);
+ }
+ });
+
+ return () => subscription.cancel();
+ }, [client, handleLoadInstrument]);
+
+ return (
+
+
+
setFlightStatusDropdownOpened((old) => !old)} />
+
+
+
+ setFlightStatusDropdownOpened((old) => !old)}
+ />
+
+
+
setFlightStatusDropdownOpened((old) => !old)}
+ />
+
+ setFullScreenOpened((old) => !old)}
+ handleLoadInstrument={handleLoadInstrument}
+ />
+
+ );
+};
+
+const ConnectionLostOverlay: React.FC = () => (
+
+
+
+
+
+
Connection Lost
+
+
+ Instruments can only be used while the simulator is running and connected to the gateway server
+
+
+);
+
+export interface NoInstrumentLoadedOverlayProps {
+ onInstrumentClicked: (instrument: protocolV0.InstrumentMetadata) => void;
+}
+
+const NoInstrumentLoadedOverlay: React.FC
= ({ onInstrumentClicked }) => (
+
+
+
+);
+
+interface InstrumentFrameProps {
+ onFullScreenToggled: () => void;
+ handleLoadInstrument: (instrument: protocolV0.InstrumentMetadata | null) => void;
+}
+
+const InstrumentFrame = forwardRef(
+ ({ onFullScreenToggled, handleLoadInstrument }, ref) => {
+ const wrapperRef = useRef(null);
+ const rootRef = useRef(null);
+
+ const [isFullScreen, setIsFullScreen] = useState(false);
+
+ const connectionState = useAppSelector((state) => state.connectionState.connected);
+ const loadedInstrument = useAppSelector((state) => state.instruments.loadedInstrument);
+
+ const instrumentAspectRatio = loadedInstrument
+ ? loadedInstrument.dimensions.width / loadedInstrument.dimensions.height
+ : 1;
+
+ useEffect(() => {
+ const handler = () => {
+ const wrapper = wrapperRef.current;
+
+ if (!wrapper) {
+ return;
+ }
+
+ const wrapperParent = wrapper.parentElement;
+ const wrapperParentHeight = wrapperParent!.clientHeight;
+ const wrapperHeight = wrapper.clientHeight;
+ const marginTop = wrapperParentHeight / 2 - wrapperHeight / 2;
+
+ wrapper.style.marginTop = `${marginTop}px`;
+ };
+
+ window.addEventListener('resize', handler);
+
+ return () => window.removeEventListener('resize', handler);
+ });
+
+ useEffect(() => {
+ const handleElementFullscreen = () => {
+ onFullScreenToggled();
+
+ const goingIntoFullScreen = document.fullscreenElement !== null;
+
+ setIsFullScreen(goingIntoFullScreen);
+
+ if (!ref || !('current' in ref) || !ref.current) {
+ return;
+ }
+
+ if (goingIntoFullScreen) {
+ ref.current.style.transform = `scale(${
+ 1 / Math.max(ref.current.clientWidth / window.innerWidth, ref.current.clientHeight / window.innerHeight)
+ })`;
+
+ // Evaluate this the next frame so that we get the fullscreen dimensions
+ setTimeout(() => {
+ if (!ref.current) {
+ return;
+ }
+
+ ref.current.style.marginLeft = `${
+ window.innerWidth / 2 - ref.current?.getBoundingClientRect().width / 2
+ }px`;
+ });
+ } else {
+ ref.current.style.transform = '';
+ ref.current.style.margin = '';
+ }
+ };
+
+ const elm = rootRef.current;
+
+ if (!elm) {
+ return;
+ }
+
+ elm.addEventListener('fullscreenchange', handleElementFullscreen);
+
+ return () => elm.removeEventListener('fullscreenchange', handleElementFullscreen);
+ }, [onFullScreenToggled, ref]);
+
+ const handleFullScreen = () => {
+ const elm = rootRef.current;
+
+ if (!elm) {
+ return;
+ }
+
+ elm?.requestFullscreen();
+ };
+
+ const handleClearInstrument = () => {
+ handleLoadInstrument(null);
+ };
+
+ const connectionLost = connectionState === ConnectionPhase.ConnectedToBridge;
+
+ return (
+
+
+ {!loadedInstrument &&
}
+
+
+
+ {loadedInstrument?.instrumentID ?? '-----'}
+
+
+
+
+
+
+
+
+
+
+ {loadedInstrument && connectionLost && }
+
+
+
+
+
+ );
+ },
+);
+
+export default MainView;
diff --git a/apps/remote/src/MessagesPanel.tsx b/apps/remote/src/MessagesPanel.tsx
new file mode 100644
index 00000000..58911b09
--- /dev/null
+++ b/apps/remote/src/MessagesPanel.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { useAppSelector } from './store';
+
+export const MessagesPanel: React.FC = () => {
+ const messages = useAppSelector((state) => state.messages);
+
+ return (
+
+ {messages.slice(Math.max(0, messages.length - 10), messages.length - 1).map((it, i) => {
+ const arrow = it.direction === 'up' ? ' ↑' : ' ↓';
+
+ return (
+
+ {arrow} {it.contents}
+
+ );
+ })}
+
+ );
+};
diff --git a/apps/remote/src/RemoteClient.ts b/apps/remote/src/RemoteClient.ts
new file mode 100644
index 00000000..54c80e83
--- /dev/null
+++ b/apps/remote/src/RemoteClient.ts
@@ -0,0 +1,527 @@
+import { v4 } from 'uuid';
+import { applicationStore } from './store';
+import { clearFlightState, setFlightState } from './store/flightState';
+import { appendMessage } from './store/messages';
+import { updateSimVarValue } from './store/simVars';
+import { ConnectionPhase, updateConnectionState } from './store/connection';
+import { protocolV0 } from '@flybywiresim/remote-bridge-types';
+import { updateDataStorageKey } from './store/dataStorage';
+
+const MAX_CONNECTION_ATTEMPTS = 10;
+
+export type SimVarSubscribeCallback = (type: 'simVar' | 'globalVar', name: string, unit: string) => number;
+
+export type SimVarSetCallback = (name: string, unit: string, value: unknown) => Promise;
+
+export type DataStorageSetCallback = (key: string, value: string) => void;
+
+export type RegisterViewListenerCallback = (
+ name: string,
+) => [listenerID: string, listenerRegisteredPromise: Promise];
+
+export type ViewListenerOnCallback = (
+ listenerID: string,
+ event: string,
+ callback: (...args: unknown[]) => void,
+) => string;
+
+export type ViewListenerOffCallback = (subscriptionID: string) => void;
+
+interface PendingViewListenerOnCall {
+ event: string;
+ subscriptionID: string;
+ subscriptionGroupID: string;
+}
+
+export interface RemoteClientEvents {
+ connectionRegained: void;
+}
+
+export interface RemoteClientEventSubscription {
+ cancel: () => void;
+}
+
+export class RemoteClient {
+ private static readonly PROTOCOL_VERSION = 0;
+
+ private ws: WebSocket | null = null;
+
+ private clientID = v4();
+
+ private connectionAttemptCount = 0;
+
+ private successfulConnectionCount = 0;
+
+ private heartbeatTimeout: number | null = null;
+
+ private enumerateInstrumentsPromiseResolveFn: ((value: protocolV0.InstrumentMetadata[]) => void) | undefined =
+ undefined;
+
+ private firstFrameViewListenerOnCalls: Record = {};
+
+ private awaitedMessagesTypesToKeys = new Map();
+
+ private awaitedMessagesPromiseFns: Record void, (arg: any) => void][]> = {};
+
+ private queuedUnhandledMessages: protocolV0.Messages[] = [];
+
+ private asyncOperationPromiseFns = new Map void, (arg: any) => void]>();
+
+ private eventSubscriptionCallbacks = new Map void>();
+
+ private readonly eventSubscriptions: Record void)[]> = {
+ connectionRegained: [],
+ };
+
+ constructor(private readonly url: string) {
+ this.attemptConnect();
+ }
+
+ public on(event: keyof RemoteClientEvents & string, handler: () => void): RemoteClientEventSubscription {
+ this.eventSubscriptions[event].push(handler);
+
+ return {
+ cancel: () => {
+ this.eventSubscriptions[event].splice(this.eventSubscriptions[event].indexOf(handler), 1);
+ },
+ };
+ }
+
+ private emitEvent(event: keyof RemoteClientEvents & string): void {
+ for (const handler of this.eventSubscriptions[event]) {
+ handler();
+ }
+ }
+
+ public enumerateInstruments(): Promise {
+ this.sendMessage({ type: 'remoteEnumerateInstruments', fromClientID: this.clientID });
+
+ return new Promise((resolve) => {
+ this.enumerateInstrumentsPromiseResolveFn = resolve;
+ });
+ }
+
+ public async downloadFile(fileVfsPath: string): Promise {
+ const requestID = v4();
+
+ try {
+ this.sendMessage({
+ type: 'remoteDownloadFile',
+ requestID,
+ fileVfsPath,
+ fromClientID: this.clientID,
+ });
+
+ const chunks: Uint8Array[] = [];
+
+ let doneDownloading = false;
+ while (!doneDownloading) {
+ const nextChunk = await this.awaitMessageOfType(
+ 'aircraftSendFileChunk',
+ requestID,
+ );
+
+ if (nextChunk.requestID !== requestID) {
+ continue;
+ }
+
+ console.log(
+ `[RemoteClient](downloadFile) Received chunk #${nextChunk.chunkIndex + 1} / ${
+ nextChunk.chunkCount
+ } for request ${requestID}`,
+ );
+
+ const chunk = await (await fetch(`data:application/octet-stream;base64,${nextChunk.data}`))
+ .arrayBuffer()
+ .then((it) => new Uint8Array(it));
+
+ chunks.push(chunk);
+
+ if (nextChunk.chunkIndex === nextChunk.chunkCount - 1) {
+ console.log(`[RemoteClient](downloadFile) Done downloading for request ${requestID}`);
+ this.stopAwaitingMessages('aircraftSendFileChunk', requestID);
+ doneDownloading = true;
+ }
+ }
+
+ const totalLength = chunks.reduce((acc, chunk) => acc + chunk.byteLength, 0);
+ const mergedArray = new Uint8Array(totalLength);
+
+ let offset = 0;
+ for (const item of chunks) {
+ mergedArray.set(item, offset);
+ offset += item.length;
+ }
+
+ return mergedArray;
+ } catch (e) {
+ this.stopAwaitingMessages('aircraftSendFileChunk', requestID);
+ throw e;
+ }
+ }
+
+ public subscribeToSimVar(
+ type: 'simVar' | 'globalVar',
+ name: string,
+ unit: string,
+ id: number,
+ subscriptionGroupID: string | null,
+ ): void {
+ if (!subscriptionGroupID) {
+ return;
+ }
+
+ this.sendMessage({
+ type: 'remoteSubscribeToSimVar',
+ simVarType: type,
+ simVar: name,
+ unit,
+ id,
+ subscriptionGroupID,
+ fromClientID: this.clientID,
+ });
+ }
+
+ public setDataStorageKey(key: string, value: string): void {
+ this.sendMessage({
+ type: 'remoteSetDataStorageKey',
+ key,
+ value,
+ fromClientID: this.clientID,
+ });
+ }
+
+ public setSimVarValue(name: string, unit: string, value: unknown): Promise {
+ const requestID = v4();
+
+ this.sendMessage({
+ type: 'remoteSetSimVarValue',
+ name,
+ unit,
+ value,
+ requestID,
+ fromClientID: this.clientID,
+ });
+
+ return new Promise((resolve, reject) => {
+ this.asyncOperationPromiseFns.set(requestID, [resolve, reject]);
+ });
+ }
+
+ public registerViewListener(name: string, listenerID: string): Promise {
+ const requestID = v4();
+
+ this.firstFrameViewListenerOnCalls[listenerID] = [];
+
+ // We wait 100ms to let .on() calls be collected and sent along with the remoteRegisterViewListener message.
+ // This ensures any events that are emitted the moment the ViewListener is registered are captured, if need be.
+ setTimeout(() => {
+ this.sendMessage({
+ type: 'remoteRegisterViewListener',
+ listenerName: name,
+ listenerID,
+ firstFrameCalls: this.firstFrameViewListenerOnCalls[listenerID]!,
+ requestID,
+ fromClientID: this.clientID,
+ });
+
+ this.firstFrameViewListenerOnCalls[listenerID] = undefined;
+ }, 100);
+
+ return new Promise((resolve, reject) => {
+ this.asyncOperationPromiseFns.set(requestID, [resolve, reject]);
+ });
+ }
+
+ public viewListenerOn(
+ listenerID: string,
+ event: string,
+ callback: (...data: unknown[]) => void,
+ subscriptionID: string,
+ subscriptionGroupID: string,
+ ): void {
+ if (this.firstFrameViewListenerOnCalls[listenerID]) {
+ this.firstFrameViewListenerOnCalls[listenerID]?.push({ event, subscriptionID, subscriptionGroupID });
+ } else {
+ this.sendMessage({
+ type: 'remoteViewListenerOn',
+ listenerID,
+ event,
+ subscriptionID,
+ subscriptionGroupID,
+ fromClientID: this.clientID,
+ });
+ }
+
+ this.eventSubscriptionCallbacks.set(subscriptionID, (data) => callback(...data));
+ }
+
+ public viewListenerOff(subscriptionID: string): void {
+ this.eventSubscriptionCallbacks.delete(subscriptionID);
+
+ this.sendMessage({
+ type: 'remoteSubscriptionCancel',
+ subscriptionID,
+ fromClientID: this.clientID,
+ });
+ }
+
+ public cancelSubscriptionGroup(subscriptionGroupID: string): void {
+ this.sendMessage({
+ type: 'remoteSubscriptionGroupCancel',
+ subscriptionGroupID,
+ fromClientID: this.clientID,
+ });
+ }
+
+ private attemptConnect(): void {
+ this.connectionAttemptCount++;
+ try {
+ this.ws = new WebSocket(this.url);
+ this.ws.addEventListener('error', () => this.onConnectFailed());
+ this.ws.addEventListener('open', () => this.onOpened());
+ this.ws.addEventListener('message', (msg) => this.onMessage(msg.data));
+ this.ws.addEventListener('close', () => this.onClosed());
+ } catch (e: any) {
+ console.error(`[RemoteClient](attemptConnect) Could not create WebSocket: ${e.message}`);
+ this.onConnectFailed();
+ }
+ }
+
+ private onConnectFailed(): void {
+ if (this.ws) {
+ this.ws.close();
+ }
+ this.ws = null;
+
+ if (this.connectionAttemptCount < MAX_CONNECTION_ATTEMPTS) {
+ this.scheduleConnectionAttempt();
+ } else {
+ console.error(
+ `[RemoteClient](onConnectFailed) Reached max connection attempts (${MAX_CONNECTION_ATTEMPTS}), not trying again`,
+ );
+ }
+ }
+
+ private onOpened(): void {
+ if (!this.ws) {
+ return;
+ }
+
+ // applicationStore.dispatch(updateConnectionState({ connected: ConnectionPhase.ConnectedToBridge }));
+ //
+ // this.sendMessage({ type: 'remoteSignin', clientName: 'remote', fromClientID: this.clientID });
+ // this.sendMessage({ type: 'remoteRequestAircraftSignin', fromClientID: this.clientID });
+ //
+ // this.heartbeatTimeout = setInterval(() => {
+ // this.sendMessage({ type: 'protocolHeartbeat', fromClientID: this.clientID });
+ // }, 1_000) as unknown as number;
+ }
+
+ private onMessage(message: string): void {
+ const msg: protocolV0.Messages = JSON.parse(message);
+
+ applicationStore.dispatch(appendMessage({ direction: 'down', contents: message }));
+
+ let messageHandled = false;
+ if (this.awaitedMessagesPromiseFns[msg.type]) {
+ while (this.awaitedMessagesPromiseFns[msg.type].length > 0) {
+ const [resolve] = this.awaitedMessagesPromiseFns[msg.type][0];
+
+ messageHandled = true;
+ resolve(msg);
+
+ this.awaitedMessagesPromiseFns[msg.type].shift();
+ }
+ }
+
+ switch (msg.type) {
+ case 'protocolGatewayIntroductionMessage':
+ if (msg.minProtocolVersion > RemoteClient.PROTOCOL_VERSION) {
+ console.error(
+ `[RemoteClient](onMessage) Gateway server minProtocolVersion is too high (${msg.minProtocolVersion}). Disconnecting`,
+ );
+ this.ws?.close();
+ return;
+ }
+
+ if (msg.maxProtocolVersion < RemoteClient.PROTOCOL_VERSION) {
+ console.error(
+ `[RemoteClient](onMessage) Gateway server maxProtocolVersion is too low (${msg.minProtocolVersion}). Disconnecting`,
+ );
+ this.ws?.close();
+ return;
+ }
+
+ console.log(`[RemoteClient] Connected to server '${msg.server}'. Logging in...`);
+
+ applicationStore.dispatch(updateConnectionState({ connected: ConnectionPhase.ConnectedToBridge }));
+
+ this.sendMessage({ type: 'remoteSignin', clientName: 'remote', fromClientID: this.clientID });
+ this.sendMessage({ type: 'remoteRequestAircraftSignin', fromClientID: this.clientID });
+
+ this.heartbeatTimeout = setInterval(() => {
+ this.sendMessage({ type: 'protocolHeartbeat', fromClientID: this.clientID });
+ }, msg.heartbeatMaxInterval) as unknown as number;
+ return;
+ case 'aircraftSignin':
+ applicationStore.dispatch(
+ updateConnectionState({ connected: ConnectionPhase.ConnectedToAircraft, clientName: msg.clientName }),
+ );
+
+ this.sendMessage({ type: 'remoteRequestDataStorage', fromClientID: this.clientID });
+
+ // TODO If we were attempting to reconnect after losing connection, we need to recall everything we subscribed to and
+ // re-subscribe to it. For now though, we should just reload the gauge.
+ // We should also probably have hooks into the gauge that lets it re-initialise any state it might need that is normally sent with the assumption
+ // that it is always recieved (for example, fms-v2 fp sync)
+
+ if (this.successfulConnectionCount > 0) {
+ this.emitEvent('connectionRegained');
+ }
+ this.successfulConnectionCount++;
+
+ return;
+ case 'aircraftClientDisconnect':
+ applicationStore.dispatch(
+ updateConnectionState({ connected: ConnectionPhase.ConnectedToBridge, clientName: '' }),
+ );
+ applicationStore.dispatch(clearFlightState());
+ return;
+ case 'aircraftSendSimVarValues':
+ for (let i = 0; i < msg.values.length; i++) {
+ const [id, value] = msg.values[i];
+
+ applicationStore.dispatch(updateSimVarValue({ id, value }));
+ }
+ return;
+ case 'aircraftSendDataStorage':
+ for (const [key, value] of Object.entries(msg.values)) {
+ applicationStore.dispatch(updateDataStorageKey({ key, value }));
+ }
+ return;
+ case 'aircraftSendInstruments':
+ if (!this.enumerateInstrumentsPromiseResolveFn) {
+ return;
+ }
+
+ this.enumerateInstrumentsPromiseResolveFn(msg.instruments);
+ return;
+ case 'aircraftAsyncOperationResponse': {
+ const requestID = msg.requestID;
+
+ if (!this.asyncOperationPromiseFns.has(requestID)) {
+ console.warn(
+ '[RemoteClient](onMessage) aircraftAsyncOperationResponse recieved but associated requestID unknown',
+ );
+ return;
+ }
+
+ const [resolve, reject] = this.asyncOperationPromiseFns.get(requestID)!;
+
+ if (msg.successful) {
+ resolve(msg.result);
+ } else {
+ reject(msg.result);
+ }
+
+ return;
+ }
+ case 'aircraftEventNotification': {
+ const callback = this.eventSubscriptionCallbacks.get(msg.subscriptionID);
+
+ if (callback) {
+ callback(msg.data);
+ }
+ return;
+ }
+ case 'aircraftStatus': {
+ applicationStore.dispatch(setFlightState(msg));
+ return;
+ }
+ default:
+ console.warn(`unknown message type: ${msg.type}`);
+ }
+
+ if (!messageHandled) {
+ this.queuedUnhandledMessages.push(msg);
+ }
+ }
+
+ private onClosed(): void {
+ if (this.heartbeatTimeout !== null) {
+ clearInterval(this.heartbeatTimeout);
+ }
+
+ if (this.ws) {
+ this.ws.close();
+ }
+
+ this.queuedUnhandledMessages.length = 0;
+ this.firstFrameViewListenerOnCalls = {};
+ this.awaitedMessagesTypesToKeys.clear();
+ this.awaitedMessagesPromiseFns = {};
+ this.asyncOperationPromiseFns.clear();
+ this.eventSubscriptionCallbacks.clear();
+
+ applicationStore.dispatch(updateConnectionState({ connected: ConnectionPhase.NotConnected }));
+
+ this.ws = null;
+ }
+
+ private sendMessage(message: protocolV0.Messages) {
+ if (!this.ws) {
+ throw new Error('Cannot send message if no websocket exists');
+ }
+
+ // TODO Connection state, msg queue
+ const msgString = JSON.stringify(message);
+
+ applicationStore.dispatch(appendMessage({ direction: 'up', contents: msgString }));
+
+ this.ws.send(msgString);
+ }
+
+ private async awaitMessageOfType(
+ type: M['type'] & string,
+ uniqueKey: string,
+ ): Promise {
+ if (this.awaitedMessagesTypesToKeys.has(type) && this.awaitedMessagesTypesToKeys.get(type) !== uniqueKey) {
+ throw new Error(
+ '[RemoteClient](awaitMessageOfType) Messages can only be awaited by one consumer at a time. Make sure to call stopAwaitingMessages after you are done handling messages',
+ );
+ }
+
+ this.awaitedMessagesTypesToKeys.set(type, uniqueKey);
+
+ const firstUnhandledMessagesIndex = this.queuedUnhandledMessages.findIndex((it) => it.type === type);
+
+ if (firstUnhandledMessagesIndex !== -1) {
+ const msg = this.queuedUnhandledMessages[firstUnhandledMessagesIndex];
+
+ this.queuedUnhandledMessages.splice(firstUnhandledMessagesIndex, 1);
+
+ return msg as M;
+ }
+
+ return new Promise((resolve, reject) => {
+ let array = this.awaitedMessagesPromiseFns[type];
+ if (!array) {
+ array = this.awaitedMessagesPromiseFns[type] = [];
+ }
+
+ array.push([resolve, reject]);
+ });
+ }
+
+ private stopAwaitingMessages(type: string, uniqueKey: string): void {
+ if (this.awaitedMessagesTypesToKeys.get(type) === uniqueKey) {
+ this.awaitedMessagesTypesToKeys.delete(type);
+ return;
+ }
+ }
+
+ private scheduleConnectionAttempt(): void {
+ setTimeout(() => this.attemptConnect(), 3_000);
+ }
+}
diff --git a/apps/remote/src/assets/Fonts/fbw-a32nx/ECAMFontRegular.ttf b/apps/remote/src/assets/Fonts/fbw-a32nx/ECAMFontRegular.ttf
new file mode 100644
index 00000000..a206331f
Binary files /dev/null and b/apps/remote/src/assets/Fonts/fbw-a32nx/ECAMFontRegular.ttf differ
diff --git a/apps/remote/src/assets/Tail-Alone.svg b/apps/remote/src/assets/Tail-Alone.svg
new file mode 100644
index 00000000..ebcc1fc9
--- /dev/null
+++ b/apps/remote/src/assets/Tail-Alone.svg
@@ -0,0 +1,9 @@
+
diff --git a/apps/remote/src/assets/airfoil.png b/apps/remote/src/assets/airfoil.png
new file mode 100644
index 00000000..3431cf11
Binary files /dev/null and b/apps/remote/src/assets/airfoil.png differ
diff --git a/apps/remote/src/assets/plane.png b/apps/remote/src/assets/plane.png
new file mode 100644
index 00000000..9ebcf5e1
Binary files /dev/null and b/apps/remote/src/assets/plane.png differ
diff --git a/apps/remote/src/assets/react.svg b/apps/remote/src/assets/react.svg
new file mode 100644
index 00000000..8e0e0f15
--- /dev/null
+++ b/apps/remote/src/assets/react.svg
@@ -0,0 +1 @@
+
diff --git a/apps/remote/src/fbw.scss b/apps/remote/src/fbw.scss
new file mode 100644
index 00000000..183d3c0a
--- /dev/null
+++ b/apps/remote/src/fbw.scss
@@ -0,0 +1,97 @@
+/*
+ * FBW Aileron Design Language SCSS
+ * v1.0 - CoherentGT compatible - made for TailwindCSS v3.0 with @flybywiresim/tailwind-config v(TBD)
+ */
+
+:root {
+ --color-brand-cyan-main: rgb(0, 224, 254);
+ --color-brand-cyan-dark: rgb(0, 202, 229);
+ --color-brand-cyan-ight: rgb(51, 231, 255);
+
+ --color-brand-navy-main: rgb(23, 30, 44);
+ --color-brand-navy-dark: rgb(14, 19, 27);
+ --color-brand-navy-light: rgb(31, 42, 61);
+
+ --color-theme-text: var(--color-brand-navy-main);
+
+ --color-utility-red: rgb(220, 38, 38);
+ --color-utility-green: rgb(132, 204, 22);
+ --color-utility-orange: rgb(255, 106, 0);
+ --color-utility-amber: rgb(245, 158, 11);
+ --color-utility-blue: rgb(82, 128, 234);
+ --color-utility-purple: rgb(153, 61, 245);
+ --color-utility-pink: rgb(233, 47, 139);
+ --color-utility-salmon: rgb(248, 113, 113);
+ --color-utility-grey: rgb(208, 208, 208);
+ --color-utility-darkgry: rgb(105, 105, 105);
+ --color-utility-grey-blue: rgb(43, 48, 59);
+
+ --color-brand-quasi-white: rgb(250, 250, 250);
+
+ --color-button-theme-neutral: var(--color-brand-navy-light);
+ --color-button-theme-neutral-confirmation: var(--color-brand-cyan-dark);
+ --color-button-theme-positive: var(--color-utility-green);
+ --color-button-theme-caution: var(--color-utility-orange);
+ --color-button-theme-danger: var(--color-utility-red);
+}
+
+.modal {
+ @apply p-8 w-5/12 max-w-screen-sm text-quasi-white rounded-xl;
+
+ background-color: var(--color-brand-navy-dark);
+
+ @apply border-2;
+ border-color: var(--color-brand-navy-main);
+
+ .modal-title {
+ @apply text-5xl text-quasi-white font-manrope font-bold;
+ }
+}
+
+.button {
+ @apply text-quasi-white font-inter font-bold px-5 py-2.5 border-2 rounded-md transition-colors duration-150;
+
+ font-size: 1.25em;
+ height: 2.35em;
+
+ @mixin color($background, $textColorHover: true, $borderColorHoverValue: $background) {
+ background-color: $background;
+ border-color: $background;
+
+ &:hover {
+ background-color: transparent;
+ border-color: $borderColorHoverValue;
+ @if $textColorHover {
+ color: $background;
+ }
+ }
+ }
+
+ &, &.button-neutral {
+ @apply font-semibold;
+
+ @include color(var(--color-button-theme-neutral), false, var(--color-button-theme-neutral-confirmation));
+ }
+
+ &.button-emphasis {
+ @include color(var(--color-button-theme-neutral-confirmation));
+ color: var(--color-theme-text);
+ }
+
+ &.button-positive {
+ @include color(var(--color-button-theme-positive));
+ color: var(--color-theme-text);
+ }
+
+ &.button-caution {
+ @include color(var(--color-button-theme-caution), false);
+ }
+
+ &.button-danger {
+ @include color(var(--color-button-theme-danger), false);
+ }
+
+ &[disabled] {
+ @apply pointer-events-none opacity-50;
+ }
+}
diff --git a/apps/remote/src/index.scss b/apps/remote/src/index.scss
new file mode 100644
index 00000000..e6028d40
--- /dev/null
+++ b/apps/remote/src/index.scss
@@ -0,0 +1,23 @@
+@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100;300;500;600;700;800;900&family=Manrope:wght@500;700&display=swap");
+@import url("https://fonts.googleapis.com/css2?family=Manrope:wght@200;300;400;500;600;700;800&display=swap");
+@import url("https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800&display=swap");
+
+@import "./fbw.scss";
+
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+html, body, #root {
+ @apply bg-navy-lighter font-inter text-quasi-white;
+
+ width: 100%;
+ height: 100dvh;
+ overflow: hidden;
+
+ font-size: 13px;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ @apply font-manrope;
+}
diff --git a/apps/remote/src/main.tsx b/apps/remote/src/main.tsx
new file mode 100644
index 00000000..816e889c
--- /dev/null
+++ b/apps/remote/src/main.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { applicationStore } from './store';
+import { Provider } from 'react-redux';
+import { Application } from './Application';
+
+import './index.scss';
+import { ModalContextProvider } from './modals/ModalContext';
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+
+
+
+
+ ,
+);
diff --git a/apps/remote/src/modals/ModalContext.tsx b/apps/remote/src/modals/ModalContext.tsx
new file mode 100644
index 00000000..416631c2
--- /dev/null
+++ b/apps/remote/src/modals/ModalContext.tsx
@@ -0,0 +1,70 @@
+import React, { PropsWithChildren, useCallback, useState } from 'react';
+
+export interface ModalContextType {
+ modalShown: boolean;
+ currentModal: React.ReactElement | null;
+ showModal: (modal: React.ReactElement | null) => void;
+ showValueModal: (modal: React.ReactElement | null) => Promise;
+ closeModal: () => void;
+}
+
+export const ModalContext = React.createContext(undefined as any);
+
+export const ModalContextProvider: React.FC = ({ children }) => {
+ const [modalShown, setModalShown] = useState(false);
+ const [currentModal, setCurrentModal] = useState(null);
+ const [currentModalPromiseResolveFn, setCurrentModalPromiseResolveFn] = useState<(() => void) | null>(null);
+
+ const showModal = useCallback(
+ (modal: React.ReactElement | null) => {
+ const nowShowingModal = !modalShown && modal !== null;
+
+ if (nowShowingModal) {
+ setCurrentModal(modal);
+ setModalShown(true);
+ } else {
+ setModalShown(false);
+
+ setTimeout(() => setCurrentModal(null), 300);
+ }
+ },
+ [modalShown],
+ );
+
+ const showValueModal = useCallback(
+ (modal: React.ReactElement | null): Promise => {
+ return new Promise((resolve) => {
+ const nowShowingModal = !modalShown && modal !== null;
+
+ if (nowShowingModal) {
+ setCurrentModal(React.cloneElement(modal));
+ setCurrentModalPromiseResolveFn(resolve);
+ setModalShown(true);
+ } else {
+ setModalShown(false);
+
+ currentModalPromiseResolveFn?.();
+
+ setTimeout(() => setCurrentModal(null), 300);
+ }
+ });
+ },
+ [currentModalPromiseResolveFn, modalShown],
+ );
+
+ const closeModal = () => {
+ if (!modalShown) {
+ return;
+ }
+
+ setModalShown(false);
+
+ setTimeout(() => setCurrentModal(null), 300);
+ };
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/apps/remote/src/modals/ModalHook.ts b/apps/remote/src/modals/ModalHook.ts
new file mode 100644
index 00000000..97575df2
--- /dev/null
+++ b/apps/remote/src/modals/ModalHook.ts
@@ -0,0 +1,4 @@
+import { useContext } from 'react';
+import { ModalContext } from './ModalContext';
+
+export const useModals = () => useContext(ModalContext);
diff --git a/apps/remote/src/modals/ModalWrapper.tsx b/apps/remote/src/modals/ModalWrapper.tsx
new file mode 100644
index 00000000..2dcd41e8
--- /dev/null
+++ b/apps/remote/src/modals/ModalWrapper.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import { useModals } from './ModalHook';
+
+export const ModalWrapper: React.FC = () => {
+ const { modalShown, currentModal, showModal } = useModals();
+
+ const handleClickBackground = () => showModal(null);
+
+ return (
+
+ );
+};
diff --git a/apps/remote/src/modals/SimpleModal.tsx b/apps/remote/src/modals/SimpleModal.tsx
new file mode 100644
index 00000000..d2ab4be5
--- /dev/null
+++ b/apps/remote/src/modals/SimpleModal.tsx
@@ -0,0 +1,34 @@
+import React, { PropsWithChildren } from 'react';
+import { useModals } from './ModalHook';
+
+export interface SimpleModalProps {
+ title: string;
+ onClosed?: () => void;
+}
+
+export const SimpleModal: React.FC> = ({
+ title,
+ onClosed = () => {},
+ children,
+}) => {
+ const { showModal } = useModals();
+
+ const handleClose = () => {
+ onClosed();
+ showModal(null);
+ };
+
+ return (
+
+
{title}
+
+ {children}
+
+
+
+
+
+ );
+};
diff --git a/apps/remote/src/modals/ValueModal.tsx b/apps/remote/src/modals/ValueModal.tsx
new file mode 100644
index 00000000..4824fa19
--- /dev/null
+++ b/apps/remote/src/modals/ValueModal.tsx
@@ -0,0 +1,48 @@
+import React, { PropsWithChildren, useState } from 'react';
+import { SimpleModal, SimpleModalProps } from './SimpleModal';
+import { useModals } from './ModalHook';
+
+export interface ValueModalProps extends SimpleModalProps {
+ render: ValueModalRenderFn;
+ onValuePicked?: (value: T) => void;
+}
+
+type ValueModalRenderFn = (
+ pickValueAndClose: (value: T) => void,
+ pickValue: (value: T) => void,
+) => React.ReactElement;
+
+export const ValueModal = ({
+ title,
+ render = () => <>>,
+ onValuePicked = () => {},
+}: PropsWithChildren>): React.ReactElement => {
+ const { closeModal } = useModals();
+
+ const [pickedValue, setPickedValue] = useState(null);
+
+ const handleClosed = () => {
+ if (pickedValue !== null) {
+ onValuePicked(pickedValue);
+ }
+ };
+
+ const handlePickValueAndClose = (value: T) => {
+ if (value !== null) {
+ onValuePicked(value);
+ }
+ closeModal();
+ };
+
+ const handlePickValue = (value: T) => {
+ if (value !== null) {
+ setPickedValue(value);
+ }
+ };
+
+ return (
+
+ {render(handlePickValueAndClose, handlePickValue)}
+
+ );
+};
diff --git a/apps/remote/src/pages/AuthenticationPage.tsx b/apps/remote/src/pages/AuthenticationPage.tsx
new file mode 100644
index 00000000..0eba3a2e
--- /dev/null
+++ b/apps/remote/src/pages/AuthenticationPage.tsx
@@ -0,0 +1,70 @@
+import React, { useRef, useState } from 'react';
+import { useAppDispatch } from '../store';
+import { ConnectionPhase, updateConnectionState } from '../store/connection';
+import { useDebounce } from 'react-use';
+
+import Tail from '../assets/Tail-Alone.svg';
+
+const URL = 'https://gateway.remote.flybywiresim.com/api/v1';
+
+export const AuthenticationPage: React.FC = () => {
+ const inputRef = useRef(null);
+
+ const dispatch = useAppDispatch();
+
+ const [bridgeIDVerified, setBridgeIDVerified] = useState(false);
+
+ const [typedBridgeID, setTypedBridgeID] = useState('');
+
+ useDebounce(
+ () => {
+ fetch(`${URL}/get-bridge/${typedBridgeID}`, { method: 'GET' }).then((response) => {
+ setBridgeIDVerified(response.ok);
+ });
+ },
+ 200,
+ [typedBridgeID],
+ );
+
+ const handleConnect = () => {
+ if (!inputRef.current) {
+ return;
+ }
+
+ const bridgeName = inputRef.current.value;
+
+ fetch(`${URL}/get-bridge/${bridgeName}`, { method: 'GET' }).then(async (response) => {
+ if (!response.ok) {
+ return;
+ }
+
+ dispatch(updateConnectionState({ bridgeName: bridgeName, connected: ConnectionPhase.ConnectedToBridge }));
+ });
+ };
+
+ return (
+
+
+
+
+ setTypedBridgeID(event.target.value)}
+ />
+
+ GFNCBENFB4TQ
+
+
+ {bridgeIDVerified ? 'Bridge ID valid' : 'Checking connection...'}
+
+
+
+
+
+ );
+};
diff --git a/apps/remote/src/shims/Coherent.ts b/apps/remote/src/shims/Coherent.ts
new file mode 100644
index 00000000..bf2b8d67
--- /dev/null
+++ b/apps/remote/src/shims/Coherent.ts
@@ -0,0 +1,89 @@
+import { simvar } from './SimVar';
+import { RegisterViewListenerCallback, ViewListenerOffCallback, ViewListenerOnCallback } from '../RemoteClient';
+
+export class Coherent {
+ constructor(private readonly simvar: simvar) {}
+
+ trigger(name: string, ...data: unknown[]) {
+ console.log('Coherent.trigger', name, data);
+ return null;
+ }
+
+ on(name: string, callback: (...data: unknown[]) => void): { clear: () => void } {
+ console.log('Coherent.on', name, callback);
+ return { clear: () => null };
+ }
+
+ call(name: string, ...args: any[]): Promise {
+ console.log('Coherent.call', name, args);
+ switch (name) {
+ case 'setValueReg_String':
+ return this.simvar.setValueReg_String(args[0], args[1]);
+ case 'setValueReg_Bool':
+ return this.simvar.setValueReg_Bool(args[0], args[1]);
+ case 'setValueReg_Number':
+ return this.simvar.setValueReg_Number(args[0], args[1]);
+ case 'setValue_LatLongAlt':
+ return this.simvar.setValue_LatLongAlt(args[0], args[1]);
+ case 'setValue_LatLongAltPBH':
+ return this.simvar.setValue_LatLongAltPBH(args[0], args[1]);
+ case 'setValue_PBH':
+ return this.simvar.setValue_PBH(args[0], args[1]);
+ case 'setValue_PID_STRUCT':
+ return this.simvar.setValue_PID_STRUCT(args[0], args[1]);
+ case 'setValue_XYZ':
+ return this.simvar.setValue_XYZ(args[0], args[1]);
+ }
+ return Promise.reject(`Unsupported Coherent call: ${name}`);
+ }
+}
+
+export function RegisterViewListenerFactory(
+ registerViewListenerCallback: RegisterViewListenerCallback,
+ viewListenerOnCallback: ViewListenerOnCallback,
+ viewListenerOffCallback: ViewListenerOffCallback,
+) {
+ return function RegisterViewListener(name: string, callback: () => void) {
+ console.log(`[shim](RegisterViewListener) '${name}'`);
+
+ const [listenerID, promise] = registerViewListenerCallback(name);
+
+ promise.then(callback); // TODO handle errors
+
+ const eventSubscriptionIDs = new Map void, string>>();
+
+ // TODO unregister
+ return {
+ on: (event: string, callback: (...args: any[]) => void) => {
+ const subscriptionID = viewListenerOnCallback(listenerID, event, callback);
+
+ let existingMap = eventSubscriptionIDs.get(event);
+
+ if (!existingMap) {
+ const map = new Map();
+
+ eventSubscriptionIDs.set(event, map);
+ existingMap = map;
+ }
+
+ existingMap.set(callback, subscriptionID);
+ },
+
+ off: (event: string, callback: (...args: unknown[]) => void) => {
+ const subscriptionID = eventSubscriptionIDs.get(event)?.get(callback);
+
+ if (subscriptionID) {
+ viewListenerOffCallback(subscriptionID);
+ }
+ },
+
+ triggerToAllSubscribers: (event: string, data: unknown[]) => {
+ console.log(`[shim][ViewListener](triggerToAllSubscribers) '${event}':`, ...data);
+ },
+
+ unregister: () => {
+ console.log('[shim][ViewListener](unregister)');
+ },
+ };
+ };
+}
diff --git a/apps/remote/src/shims/MsfsSdk.ts b/apps/remote/src/shims/MsfsSdk.ts
new file mode 100644
index 00000000..aaf80db1
--- /dev/null
+++ b/apps/remote/src/shims/MsfsSdk.ts
@@ -0,0 +1,46 @@
+export class BaseInstrument {
+ protected constructor() {}
+
+ public connectedCallback(): void {}
+
+ public Update(): void {}
+
+ private dispatchEvent(): void {
+ console.log('[shim][BaseInstrument](dispatchEvent)');
+ }
+
+ public getGameState(): GameState {
+ return GameState.ingame;
+ }
+}
+
+export function registerInstrument(id: string, Instrument: new () => BaseInstrument) {
+ const instance = new Instrument();
+
+ instance.connectedCallback();
+ (window as unknown as { FBW_REMOTE_INTERVAL: number | null }).FBW_REMOTE_INTERVAL = window.setInterval(
+ () => instance.Update(),
+ 50,
+ );
+}
+
+export enum RunwayDesignator {
+ RUNWAY_DESIGNATOR_NONE,
+ RUNWAY_DESIGNATOR_LEFT,
+ RUNWAY_DESIGNATOR_RIGHT,
+ RUNWAY_DESIGNATOR_CENTER,
+ RUNWAY_DESIGNATOR_WATER,
+ RUNWAY_DESIGNATOR_A,
+ RUNWAY_DESIGNATOR_B,
+}
+
+export enum GameState {
+ mainmenu,
+ loading,
+ briefing,
+ ingame,
+}
+
+export function LaunchFlowEvent(event: string, key: string, bus: string, data: string) {
+ console.log(event, key, bus, JSON.parse(data));
+}
diff --git a/apps/remote/src/shims/SimVar.ts b/apps/remote/src/shims/SimVar.ts
new file mode 100644
index 00000000..bd4b596f
--- /dev/null
+++ b/apps/remote/src/shims/SimVar.ts
@@ -0,0 +1,162 @@
+import { SimVarSetCallback, SimVarSubscribeCallback } from '../RemoteClient';
+import { applicationStore } from '../store';
+import { storeSimVar } from '../store/simVars';
+
+/**
+ * Handles calls to SimVar without msfs-sdk.
+ */
+export class SimVar {
+ constructor(
+ private readonly simVarSubscribeCallback: SimVarSubscribeCallback,
+ private readonly simVarSetCallback: SimVarSetCallback,
+ ) {}
+
+ private defaultValueForUnit(unit: string): any {
+ if (unit === 'latlonalt') {
+ return { lat: 0, lon: 0, alt: 0 };
+ }
+
+ return 0;
+ }
+
+ GetRegisteredId(name: string, unit: string): number {
+ const id = applicationStore.getState().simVars.namesToIDs[`${name};${unit}`];
+
+ if (!id) {
+ const newID = this.simVarSubscribeCallback('simVar', name, unit);
+
+ applicationStore.dispatch(storeSimVar({ name, unit, id: newID }));
+
+ return newID;
+ }
+
+ return id;
+ }
+
+ GetSimVarValue(name: string, unit: string): any {
+ const id = applicationStore.getState().simVars.namesToIDs[`${name};${unit}`];
+
+ if (id === undefined) {
+ if (this.simVarSubscribeCallback) {
+ const newID = this.simVarSubscribeCallback('simVar', name, unit);
+
+ applicationStore.dispatch(storeSimVar({ name, unit, id: newID }));
+
+ return this.defaultValueForUnit(unit);
+ }
+ }
+
+ const storedValue = applicationStore.getState().simVars.values[id];
+
+ if (storedValue === undefined) {
+ if (this.simVarSubscribeCallback && !applicationStore.getState().simVars.namesToIDs[`${name};${unit}`]) {
+ const newID = this.simVarSubscribeCallback('simVar', name, unit);
+
+ applicationStore.dispatch(storeSimVar({ name, unit, id: newID }));
+
+ return this.defaultValueForUnit(unit);
+ }
+ }
+
+ return storedValue ?? this.defaultValueForUnit(unit);
+ }
+
+ GetGlobalVarValue(name: string, unit: string): any {
+ const id = applicationStore.getState().simVars.namesToIDs[`${name};${unit}`];
+
+ if (id === undefined) {
+ if (this.simVarSubscribeCallback) {
+ const newID = this.simVarSubscribeCallback('globalVar', name, unit);
+
+ applicationStore.dispatch(storeSimVar({ name, unit, id: newID }));
+
+ return this.defaultValueForUnit(unit);
+ }
+ }
+
+ const storedValue = applicationStore.getState().simVars.values[id];
+
+ if (storedValue === undefined) {
+ if (this.simVarSubscribeCallback && !applicationStore.getState().simVars.namesToIDs[`${name};${unit}`]) {
+ const newID = this.simVarSubscribeCallback('globalVar', name, unit);
+
+ applicationStore.dispatch(storeSimVar({ name, unit, id: newID }));
+
+ return this.defaultValueForUnit(unit);
+ }
+ }
+
+ return storedValue ?? this.defaultValueForUnit(unit);
+ }
+
+ SetSimVarValue(name: string, unit: string, value: string | number): Promise {
+ return this.simVarSetCallback(name, unit, value);
+ }
+}
+
+/**
+ Handles calls to SimVar with msfs-sdk.
+ */
+export class simvar {
+ constructor(private readonly simVarSetCallback: SimVarSetCallback) {}
+
+ getValueReg(registeredId: number) {
+ return applicationStore.getState().simVars.values[registeredId] ?? 0;
+ }
+
+ getValueReg_String(registeredId: number) {
+ return this.getValueReg(registeredId);
+ }
+ getValue_LatLongAlt(registeredId: number) {
+ return this.getValueReg(registeredId);
+ }
+ getValue_LatLongAltPBH(registeredId: number) {
+ return this.getValueReg(registeredId);
+ }
+ getValue_PBH(registeredId: number) {
+ return this.getValueReg(registeredId);
+ }
+ getValue_PID_STRUCT(registeredId: number) {
+ return this.getValueReg(registeredId);
+ }
+ getValue_XYZ(registeredId: number) {
+ return this.getValueReg(registeredId);
+ }
+
+ setValueReg(registeredId: number, value: any): Promise {
+ const nameAndUnit = applicationStore.getState().simVars.idsToNames[registeredId];
+
+ if (!nameAndUnit) {
+ console.error(`[shim][simvar](setValueReg) cannot find simvar with id=${registeredId}`);
+ }
+
+ const [name, unit] = nameAndUnit.split(';');
+
+ return this.simVarSetCallback(name, unit, value);
+ }
+
+ setValueReg_String(registeredId: number, value: any) {
+ return this.setValueReg(registeredId, value);
+ }
+ setValueReg_Bool(registeredId: number, value: any) {
+ return this.setValueReg(registeredId, value);
+ }
+ setValueReg_Number(registeredId: number, value: any) {
+ return this.setValueReg(registeredId, value);
+ }
+ setValue_LatLongAlt(registeredId: number, value: any) {
+ return this.setValueReg(registeredId, value);
+ }
+ setValue_LatLongAltPBH(registeredId: number, value: any) {
+ return this.setValueReg(registeredId, value);
+ }
+ setValue_PBH(registeredId: number, value: any) {
+ return this.setValueReg(registeredId, value);
+ }
+ setValue_PID_STRUCT(registeredId: number, value: any) {
+ return this.setValueReg(registeredId, value);
+ }
+ setValue_XYZ(registeredId: number, value: any) {
+ return this.setValueReg(registeredId, value);
+ }
+}
diff --git a/apps/remote/src/shims/StoredData.ts b/apps/remote/src/shims/StoredData.ts
new file mode 100644
index 00000000..61713216
--- /dev/null
+++ b/apps/remote/src/shims/StoredData.ts
@@ -0,0 +1,13 @@
+import { applicationStore } from '../store';
+
+export class StoredDataShim {
+ constructor(private readonly setStoredDataCallback: (key: string, value: string) => void) {}
+
+ GetStoredData(key: string): unknown {
+ return applicationStore.getState().dataStorage.values[key] ?? '';
+ }
+
+ SetStoredData(key: string, value: string) {
+ this.setStoredDataCallback(key, value);
+ }
+}
diff --git a/apps/remote/src/shims/index.ts b/apps/remote/src/shims/index.ts
new file mode 100644
index 00000000..f1748601
--- /dev/null
+++ b/apps/remote/src/shims/index.ts
@@ -0,0 +1,74 @@
+import * as CoherentShim from './Coherent';
+import * as SimVarShim from './SimVar';
+import * as MsfsSdk from './MsfsSdk';
+import * as DataStorage from './StoredData';
+import {
+ SimVarSubscribeCallback,
+ DataStorageSetCallback,
+ SimVarSetCallback,
+ RegisterViewListenerCallback,
+ ViewListenerOnCallback,
+ ViewListenerOffCallback,
+} from '../RemoteClient';
+
+export function installShims(
+ window: Window,
+ simVarSubscribeCallback: SimVarSubscribeCallback,
+ simVarSetCallback: SimVarSetCallback,
+ dataStorageSetCallback: DataStorageSetCallback,
+ registerViewListenerCallback: RegisterViewListenerCallback,
+ viewListenerOnCallback: ViewListenerOnCallback,
+ viewListenerOffCallback: ViewListenerOffCallback,
+): void {
+ const simvar = new SimVarShim.simvar(simVarSetCallback);
+ const dataStorage = new DataStorage.StoredDataShim(dataStorageSetCallback);
+
+ const RegisterViewListener = CoherentShim.RegisterViewListenerFactory(
+ registerViewListenerCallback,
+ viewListenerOnCallback,
+ viewListenerOffCallback,
+ );
+
+ const shim = {
+ Coherent: new CoherentShim.Coherent(simvar),
+ RegisterViewListener,
+ SimVar: new SimVarShim.SimVar(simVarSubscribeCallback, simVarSetCallback),
+ simvar,
+ Avionics: {
+ Utils: {
+ DEG2RAD: Math.PI / 180,
+ },
+ },
+ LatLongAlt: class {
+ constructor(
+ private readonly lat: number,
+ private readonly long: number,
+ private readonly alt: number,
+ ) {}
+ },
+ RunwayDesignator: MsfsSdk.RunwayDesignator,
+ GameState: MsfsSdk.GameState,
+ BaseInstrument: MsfsSdk.BaseInstrument,
+ registerInstrument: MsfsSdk.registerInstrument,
+ LaunchFlowEvent: MsfsSdk.LaunchFlowEvent,
+ RegisterGenericDataListener(callback: () => void) {
+ const listener = RegisterViewListener('JS_LISTENER_GENERICDATA', callback);
+
+ (listener as any).onDataReceived = (key: string, callback: (data: unknown) => void) => {
+ listener.on(key, (e: string) => {
+ try {
+ callback(JSON.parse(e));
+ } catch (e) {
+ console.error(e);
+ }
+ });
+ };
+
+ return listener;
+ },
+ GetStoredData: dataStorage.GetStoredData.bind(dataStorage),
+ SetStoredData: dataStorage.SetStoredData.bind(dataStorage),
+ };
+
+ Object.assign(window, shim);
+}
diff --git a/apps/remote/src/store/connection.ts b/apps/remote/src/store/connection.ts
new file mode 100644
index 00000000..5b0e0c82
--- /dev/null
+++ b/apps/remote/src/store/connection.ts
@@ -0,0 +1,46 @@
+import { createSlice } from '@reduxjs/toolkit';
+import type { PayloadAction } from '@reduxjs/toolkit';
+
+export enum ConnectionPhase {
+ NotConnected,
+ ConnectedToBridge,
+ ConnectedToAircraft,
+}
+
+export interface ConnectionState {
+ connected: ConnectionPhase;
+ clientName: string;
+ bridgeName: string | null;
+ currentSubscriptionGroupID: string | null;
+}
+
+const initialState: ConnectionState = {
+ connected: ConnectionPhase.NotConnected,
+ bridgeName: null,
+ clientName: '',
+ currentSubscriptionGroupID: null,
+};
+
+export const connectionStateSlice = createSlice({
+ name: 'connectionState',
+ initialState,
+ reducers: {
+ updateConnectionState: (
+ state,
+ {
+ payload: { connected, clientName, bridgeName },
+ }: PayloadAction>,
+ ) => {
+ connected !== undefined && (state.connected = connected);
+ clientName !== undefined && (state.clientName = clientName);
+ bridgeName !== undefined && (state.bridgeName = bridgeName);
+ },
+ setCurrentSubscriptionGroupID: (state, action: PayloadAction) => {
+ state.currentSubscriptionGroupID = action.payload;
+ },
+ },
+});
+
+export const { updateConnectionState, setCurrentSubscriptionGroupID } = connectionStateSlice.actions;
+
+export default connectionStateSlice.reducer;
diff --git a/apps/remote/src/store/dataStorage.ts b/apps/remote/src/store/dataStorage.ts
new file mode 100644
index 00000000..7cd0034d
--- /dev/null
+++ b/apps/remote/src/store/dataStorage.ts
@@ -0,0 +1,24 @@
+import { createSlice, PayloadAction } from '@reduxjs/toolkit';
+
+export interface DataStorageState {
+ values: Record;
+}
+
+const initialState: DataStorageState = {
+ values: {},
+};
+
+export const dataStorageSlice = createSlice({
+ name: 'dataStorage',
+ initialState,
+ reducers: {
+ clearDataStorage: () => initialState,
+ updateDataStorageKey: (state, { payload: { key, value } }: PayloadAction<{ key: string; value: string }>) => {
+ state.values[key] = value;
+ },
+ },
+});
+
+export const { clearDataStorage, updateDataStorageKey } = dataStorageSlice.actions;
+
+export default dataStorageSlice.reducer;
diff --git a/apps/remote/src/store/flightState.ts b/apps/remote/src/store/flightState.ts
new file mode 100644
index 00000000..a7cf1820
--- /dev/null
+++ b/apps/remote/src/store/flightState.ts
@@ -0,0 +1,31 @@
+import { createSlice } from '@reduxjs/toolkit';
+import type { PayloadAction } from '@reduxjs/toolkit';
+
+export interface FlightStatusState {
+ airframe: {
+ name: string;
+ livery: string;
+ };
+}
+
+const initialState: FlightStatusState = {
+ airframe: {
+ name: '--------',
+ livery: '-------',
+ },
+};
+
+export const flightStatusSlice = createSlice({
+ name: 'flightStatus',
+ initialState,
+ reducers: {
+ setFlightState: (state, action: PayloadAction) => {
+ state.airframe = action.payload.airframe;
+ },
+ clearFlightState: () => initialState,
+ },
+});
+
+export const { setFlightState, clearFlightState } = flightStatusSlice.actions;
+
+export default flightStatusSlice.reducer;
diff --git a/apps/remote/src/store/index.ts b/apps/remote/src/store/index.ts
new file mode 100644
index 00000000..4d59bfca
--- /dev/null
+++ b/apps/remote/src/store/index.ts
@@ -0,0 +1,19 @@
+import { configureStore } from '@reduxjs/toolkit';
+import connectionState from './connection';
+import flightStatus from './flightState';
+import instruments from './instruments';
+import messages from './messages';
+import simVars from './simVars';
+import dataStorage from './dataStorage';
+
+import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
+
+export const applicationStore = configureStore({
+ reducer: { connectionState, flightStatus, instruments, messages, simVars, dataStorage },
+});
+
+export type AppState = ReturnType;
+export type AppDispatch = typeof applicationStore.dispatch;
+
+export const useAppDispatch = () => useDispatch();
+export const useAppSelector: TypedUseSelectorHook = useSelector;
diff --git a/apps/remote/src/store/instruments.ts b/apps/remote/src/store/instruments.ts
new file mode 100644
index 00000000..8700755f
--- /dev/null
+++ b/apps/remote/src/store/instruments.ts
@@ -0,0 +1,58 @@
+import { protocolV0 } from '@flybywiresim/remote-bridge-types';
+import { createSlice, PayloadAction } from '@reduxjs/toolkit';
+
+export interface InstrumentsState {
+ availableInstruments: protocolV0.InstrumentMetadata[];
+ loadedInstrument: protocolV0.InstrumentMetadata | null;
+}
+
+const initialState: InstrumentsState = {
+ availableInstruments: [
+ {
+ instrumentID: 'EFB',
+ gauges: [],
+ dimensions: { width: 0, height: 0 },
+ },
+ {
+ instrumentID: 'PFD',
+ gauges: [],
+ dimensions: { width: 0, height: 0 },
+ },
+ {
+ instrumentID: 'ND',
+ gauges: [],
+ dimensions: { width: 0, height: 0 },
+ },
+ {
+ instrumentID: 'EWD',
+ gauges: [],
+ dimensions: { width: 0, height: 0 },
+ },
+ {
+ instrumentID: 'SD',
+ gauges: [],
+ dimensions: { width: 0, height: 0 },
+ },
+ ],
+ loadedInstrument: null,
+};
+
+export const instrumentsSlice = createSlice({
+ name: 'availableInstruments',
+ initialState,
+ reducers: {
+ addAvailableInstrument: (state, action: PayloadAction) => {
+ state.availableInstruments.push(action.payload);
+ },
+ clearAvailableInstruments: (state) => {
+ state.availableInstruments.length = 0;
+ },
+ setLoadedInstrument: (state, action: PayloadAction) => {
+ state.loadedInstrument = action.payload;
+ },
+ },
+});
+
+export const { addAvailableInstrument, clearAvailableInstruments, setLoadedInstrument } = instrumentsSlice.actions;
+
+export default instrumentsSlice.reducer;
diff --git a/apps/remote/src/store/messages.ts b/apps/remote/src/store/messages.ts
new file mode 100644
index 00000000..f05c97e3
--- /dev/null
+++ b/apps/remote/src/store/messages.ts
@@ -0,0 +1,24 @@
+import { createSlice, PayloadAction } from '@reduxjs/toolkit';
+
+export interface LogMessage {
+ direction: 'up' | 'down';
+ contents: string;
+}
+
+export type MessagesState = LogMessage[];
+
+const initialState: MessagesState = [];
+
+export const messagesSlice = createSlice({
+ name: 'messages',
+ initialState,
+ reducers: {
+ appendMessage: (state, action: PayloadAction) => {
+ state.push(action.payload);
+ },
+ },
+});
+
+export const { appendMessage } = messagesSlice.actions;
+
+export default messagesSlice.reducer;
diff --git a/apps/remote/src/store/simVars.ts b/apps/remote/src/store/simVars.ts
new file mode 100644
index 00000000..49b2d321
--- /dev/null
+++ b/apps/remote/src/store/simVars.ts
@@ -0,0 +1,35 @@
+import { createSlice, PayloadAction } from '@reduxjs/toolkit';
+
+export interface SimVarsState {
+ idsToNames: Record;
+ namesToIDs: Record;
+ values: Record;
+}
+
+const initialState: SimVarsState = {
+ idsToNames: {},
+ namesToIDs: {},
+ values: {},
+};
+
+export const availableInstrumentsSlice = createSlice({
+ name: 'simVars',
+ initialState,
+ reducers: {
+ storeSimVar: (
+ state,
+ { payload: { id, name, unit } }: PayloadAction<{ name: string; unit: string; id: number }>,
+ ) => {
+ state.namesToIDs[`${name};${unit}`] = id;
+ state.idsToNames[id] = `${name};${unit}`;
+ },
+ clearSimVars: () => initialState,
+ updateSimVarValue: (state, { payload: { id, value } }: PayloadAction<{ id: number; value: unknown }>) => {
+ state.values[id] = value;
+ },
+ },
+});
+
+export const { storeSimVar, clearSimVars, updateSimVarValue } = availableInstrumentsSlice.actions;
+
+export default availableInstrumentsSlice.reducer;
diff --git a/apps/remote/src/vite-env.d.ts b/apps/remote/src/vite-env.d.ts
new file mode 100644
index 00000000..11f02fe2
--- /dev/null
+++ b/apps/remote/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/apps/remote/tailwind.config.js b/apps/remote/tailwind.config.js
new file mode 100644
index 00000000..8702d89c
--- /dev/null
+++ b/apps/remote/tailwind.config.js
@@ -0,0 +1,99 @@
+import plugin from 'tailwindcss/plugin';
+
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
+ theme: {
+ extend: {
+ height: {
+ '450px': '450px',
+ },
+ width: {
+ '520px': '520px',
+ '700px': '700px',
+ },
+ spacing: {
+ '14.06px': '14.06px',
+ '17.01px': '17.01px',
+ },
+ colors: {
+ 'quasi-white': '#FAFAFA',
+ grey: {
+ medium: '#EDEDED',
+ },
+ cyan: {
+ DEFAULT: '#00E0FE',
+ medium: '#00C4F5',
+ dark: 'var(--color-brand-cyan-dark)',
+ },
+ dodger: {
+ light: '#00BBFF',
+ },
+ navy: {
+ DEFAULT: '#171E2C',
+ light: '#1F2A3C',
+ lightest: '#273347',
+ lighter: '#222c3d',
+ dark: '#0E131B',
+ },
+ red: {
+ DEFAULT: '#FC3A3A',
+ dark: '#F70404',
+ darker: '#E40303',
+ darkest: '#D10303',
+ },
+ utility: {
+ red: 'var(--color-utility-red)',
+ green: 'var(--color-utility-green)',
+ orange: 'var(--color-utility-orange)',
+ amber: 'var(--color-utility-amber)',
+ blue: 'var(--color-utility-blue)',
+ purple: 'var(--color-utility-purple)',
+ pink: 'var(--color-utility-pink)',
+ salmon: 'var(--color-utility-salmon)',
+ grey: 'var(--color-utility-grey)',
+ 'dark-grey': 'var(--color-utility-dark-grey)',
+ 'grey-blue': 'var(--color-utility-grey-blue)',
+ },
+ },
+ boxShadow: {
+ 'inner-sm': 'inset 0 1px 2px 0 rgba(0, 0, 0, 0.05)',
+ },
+ animation: {
+ 'spin-reverse': 'spin 1s linear infinite reverse',
+ },
+ fontFamily: {
+ inter: ['Inter', 'sans-serif'],
+ manrope: ['Manrope', 'sans-serif'],
+ mono: ['JetBrains Mono', 'monospace'],
+ },
+ borderRadius: {
+ 'sm-md': '4px',
+ },
+ },
+ },
+ variants: {
+ extend: {
+ boxShadow: ['active'],
+ translate: ['active'],
+ brightness: ['hover', 'focus'],
+ backgroundColor: ['first'],
+ },
+ },
+ plugins: [
+ plugin(function ({ addUtilities }) {
+ addUtilities({
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode
+ '.horizontal-writing-tb': { 'writing-mode': 'horizontal-tb' },
+ '.vertical-writing-rl': { 'writing-mode': 'vertical-rl' },
+ '.vertical-writing-lr': { 'writing-mode': 'vertical-lr' },
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation
+ '.orientation-mixed': { 'text-orientation': 'mixed' },
+ '.orientation-upright': { 'text-orientation': 'upright' },
+ '.orientation-sideways-right': { 'text-orientation': 'sideways-right' },
+ '.orientation-sideways': { 'text-orientation': 'sideways' },
+ '.orientation-glyph': { 'text-orientation': 'use-glyph-orientation' },
+ });
+ }),
+ ],
+};
diff --git a/apps/remote/tsconfig.json b/apps/remote/tsconfig.json
new file mode 100644
index 00000000..0378f761
--- /dev/null
+++ b/apps/remote/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "allowSyntheticDefaultImports": true,
+ /* Linting */
+ "strict": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/apps/remote/tsconfig.node.json b/apps/remote/tsconfig.node.json
new file mode 100644
index 00000000..cfa1ab5b
--- /dev/null
+++ b/apps/remote/tsconfig.node.json
@@ -0,0 +1,10 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "node",
+ "allowSyntheticDefaultImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/apps/remote/vite.config.ts b/apps/remote/vite.config.ts
new file mode 100644
index 00000000..d509f00f
--- /dev/null
+++ b/apps/remote/vite.config.ts
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+import * as path from 'path';
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: path.join(__dirname, '..', '..', 'dist/remote/'),
+ },
+ base: '/interfaces/remote/',
+});
diff --git a/apps/server/src/app.module.ts b/apps/server/src/app.module.ts
index 8340d9c9..3b69635e 100644
--- a/apps/server/src/app.module.ts
+++ b/apps/server/src/app.module.ts
@@ -11,6 +11,7 @@ import { UtilitiesModule } from './utilities/utilities.module';
import printerConfig from './config/printer.config';
import serverConfig from './config/server.config';
import { HealthModule } from './health/health.module';
+import { VfsModule } from './utilities/vfs.module';
@Module({
imports: [
@@ -18,11 +19,16 @@ import { HealthModule } from './health/health.module';
rootPath: join(__dirname, '..', 'dist/mcdu'),
serveRoot: '/interfaces/mcdu',
}),
+ ServeStaticModule.forRoot({
+ rootPath: join(__dirname, '..', 'dist/remote'),
+ serveRoot: '/interfaces/remote',
+ }),
WinstonModule.forRootAsync({ useClass: WinstonConfigService }),
ConfigModule.forRoot({ isGlobal: true, load: [printerConfig, serverConfig] }),
CoRouteModule,
TerrainModule,
UtilitiesModule,
+ VfsModule,
InterfacesModule,
HealthModule,
],
diff --git a/apps/server/src/interfaces/interfaces.module.ts b/apps/server/src/interfaces/interfaces.module.ts
index 38800c66..6c5505f3 100644
--- a/apps/server/src/interfaces/interfaces.module.ts
+++ b/apps/server/src/interfaces/interfaces.module.ts
@@ -1,9 +1,11 @@
import { Module } from '@nestjs/common';
import { UtilitiesModule } from '../utilities/utilities.module';
import { McduGateway } from './mcdu.gateway';
+import { RemoteAppGateway } from './remote-app.gateway';
+import { VfsModule } from '../utilities/vfs.module';
@Module({
- imports: [UtilitiesModule],
- providers: [McduGateway],
+ imports: [UtilitiesModule, VfsModule],
+ providers: [McduGateway, RemoteAppGateway],
})
export class InterfacesModule {}
diff --git a/apps/server/src/interfaces/remote-app.gateway.ts b/apps/server/src/interfaces/remote-app.gateway.ts
new file mode 100644
index 00000000..72b8b1e6
--- /dev/null
+++ b/apps/server/src/interfaces/remote-app.gateway.ts
@@ -0,0 +1,277 @@
+import { OnGatewayConnection, OnGatewayInit, WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
+import { Inject, Logger } from '@nestjs/common';
+import { ConfigType } from '@nestjs/config';
+import { Server, WebSocket } from 'ws';
+import serverConfig from '../config/server.config';
+import { NetworkService } from '../utilities/network.service';
+import { protocolV0 } from '@flybywiresim/remote-bridge-types';
+import { VfsService } from '../utilities/vfs.service';
+import { v4 } from 'uuid';
+
+type ClientType = 'aircraft' | 'remote';
+
+interface RemoteBridgeConnection {
+ type: ClientType;
+ clientName: string;
+ clientID: string;
+}
+
+@WebSocketGateway({
+ cors: { origin: '*' },
+ path: '/interfaces/v1/remote-app',
+})
+export class RemoteAppGateway implements OnGatewayInit, OnGatewayConnection {
+ constructor(
+ @Inject(serverConfig.KEY) private serverConf: ConfigType,
+ private networkService: NetworkService,
+ private readonly vfsService: VfsService,
+ ) {}
+
+ private readonly logger = new Logger(RemoteAppGateway.name);
+
+ @WebSocketServer() server: Server;
+
+ private aircraftClient: WebSocket | null = null;
+
+ async afterInit(server: Server) {
+ this.server = server;
+ this.logger.log('Remote app gateway websocket initialised');
+ this.logger.log(
+ `Initialised on http://${await this.networkService.getLocalIp(true)}:${this.serverConf.port}${server.path}`,
+ );
+
+ this.vfsService.requestFile = async (path) => {
+ const data = await this.downloadFile(`/${path}`);
+
+ return Buffer.from(data);
+ };
+ }
+
+ private readonly sessions = new Map();
+
+ private awaitedMessagesTypesToKeys = new Map();
+
+ private queuedUnhandledMessages: protocolV0.Messages[] = [];
+
+ private awaitedMessagesPromiseFns: Record void, (arg: any) => void][]> = {};
+
+ public async downloadFile(fileVfsPath: string): Promise {
+ if (!this.aircraftClient) {
+ throw new Error('Cannot download a file without an aircraft client');
+ }
+
+ const requestID = v4();
+
+ try {
+ this.sendMessage(this.aircraftClient, {
+ type: 'remoteDownloadFile',
+ requestID,
+ fileVfsPath,
+ fromClientID: 'gateway',
+ });
+
+ const chunks: Uint8Array[] = [];
+
+ let doneDownloading = false;
+ while (!doneDownloading) {
+ const nextChunk = await this.awaitMessageOfType(
+ 'aircraftSendFileChunk',
+ requestID,
+ );
+
+ if (nextChunk.requestID !== requestID) {
+ continue;
+ }
+
+ console.log(
+ `[RemoteClient](downloadFile) Received chunk #${nextChunk.chunkIndex + 1} / ${
+ nextChunk.chunkCount
+ } for request ${requestID}`,
+ );
+
+ const chunk = await (await fetch(`data:application/octet-stream;base64,${nextChunk.data}`))
+ .arrayBuffer()
+ .then((it) => new Uint8Array(it));
+
+ chunks.push(chunk);
+
+ if (nextChunk.chunkIndex === nextChunk.chunkCount - 1) {
+ console.log(`[RemoteClient](downloadFile) Done downloading for request ${requestID}`);
+ this.stopAwaitingMessages('aircraftSendFileChunk', requestID);
+ doneDownloading = true;
+ }
+ }
+
+ const totalLength = chunks.reduce((acc, chunk) => acc + chunk.byteLength, 0);
+ const mergedArray = new Uint8Array(totalLength);
+
+ let offset = 0;
+ for (const item of chunks) {
+ mergedArray.set(item, offset);
+ offset += item.length;
+ }
+
+ return mergedArray;
+ } catch (e) {
+ this.stopAwaitingMessages('aircraftSendFileChunk', requestID);
+ throw e;
+ }
+ }
+
+ private async awaitMessageOfType(
+ type: M['type'] & string,
+ uniqueKey: string,
+ ): Promise {
+ if (this.awaitedMessagesTypesToKeys.has(type) && this.awaitedMessagesTypesToKeys.get(type) !== uniqueKey) {
+ throw new Error(
+ '[RemoteClient](awaitMessageOfType) Messages can only be awaited by one consumer at a time. Make sure to call stopAwaitingMessages after you are done handling messages',
+ );
+ }
+
+ this.awaitedMessagesTypesToKeys.set(type, uniqueKey);
+
+ const firstUnhandledMessagesIndex = this.queuedUnhandledMessages.findIndex((it) => it.type === type);
+
+ if (firstUnhandledMessagesIndex !== -1) {
+ const msg = this.queuedUnhandledMessages[firstUnhandledMessagesIndex];
+
+ this.queuedUnhandledMessages.splice(firstUnhandledMessagesIndex, 1);
+
+ return msg as M;
+ }
+
+ return new Promise((resolve, reject) => {
+ let array = this.awaitedMessagesPromiseFns[type];
+ if (!array) {
+ array = this.awaitedMessagesPromiseFns[type] = [];
+ }
+
+ array.push([resolve, reject]);
+ });
+ }
+
+ private stopAwaitingMessages(type: string, uniqueKey: string): void {
+ if (this.awaitedMessagesTypesToKeys.get(type) === uniqueKey) {
+ this.awaitedMessagesTypesToKeys.delete(type);
+ return;
+ }
+ }
+
+ handleConnection(client: WebSocket) {
+ this.logger.log('Client connected');
+
+ this.sendMessage(client, {
+ type: 'protocolGatewayIntroductionMessage',
+ server: `SimBridge v0.5.2`,
+ minProtocolVersion: 0,
+ maxProtocolVersion: 0,
+ heartbeatMinInterval: 2_000,
+ heartbeatMaxInterval: 5_000,
+ messageMaxSizeBytes: 1024 * 1024, // 1 MiB
+ fromClientID: 'gateway',
+ });
+
+ client.on('message', (message: Buffer) => {
+ const json = JSON.parse(message.toString());
+
+ if (!('type' in json)) {
+ return;
+ }
+
+ const existingSession = this.sessions.get(client);
+
+ const msg: protocolV0.Messages = json;
+
+ if (!existingSession && msg.type !== 'remoteSignin' && msg.type !== 'aircraftSignin') {
+ client.send(
+ JSON.stringify({
+ type: 'error',
+ code: 2000,
+ message: "Cannot send any other messages than 'remoteSignin' or 'aircraftSignin' before signing in",
+ }),
+ );
+ return;
+ }
+
+ switch (msg.type) {
+ case 'aircraftSignin': {
+ this.logger.log(`Aircraft client signed in (clientName='${msg.clientName}')`);
+ this.sessions.set(client, { type: 'aircraft', clientName: msg.clientName, clientID: msg.fromClientID });
+
+ this.broadcastMessage(msg, msg.fromClientID, 'remote');
+
+ this.aircraftClient = client;
+
+ break;
+ }
+ case 'remoteSignin': {
+ this.logger.log(`Remote client signed in (clientName='${msg.clientName}')`);
+ this.sessions.set(client, { type: 'remote', clientName: msg.clientName, clientID: msg.fromClientID });
+
+ this.broadcastMessage(msg, msg.fromClientID, 'aircraft');
+ break;
+ }
+ default: {
+ const session = this.sessions.get(client);
+
+ if (!session) {
+ break;
+ }
+
+ this.broadcastMessage(msg, session.clientID, session.type === 'remote' ? 'aircraft' : 'remote');
+ }
+ }
+
+ if (this.awaitedMessagesPromiseFns[msg.type]) {
+ while (this.awaitedMessagesPromiseFns[msg.type].length > 0) {
+ const [resolve] = this.awaitedMessagesPromiseFns[msg.type][0];
+
+ resolve(msg);
+
+ this.awaitedMessagesPromiseFns[msg.type].shift();
+ }
+ }
+ });
+
+ client.on('close', () => {
+ const session = this.sessions.get(client);
+
+ this.logger.log(`Session closed (type=${session?.type ?? ''})`);
+ this.sessions.delete(client);
+
+ if (session && session.type === 'aircraft') {
+ this.broadcastMessage(
+ { type: 'aircraftClientDisconnect', clientID: session.clientID, fromClientID: 'gateway' },
+ session.clientID,
+ 'remote',
+ );
+
+ this.aircraftClient = null;
+ } else if (session) {
+ this.broadcastMessage(
+ { type: 'remoteClientDisconnect', clientID: session.clientID, fromClientID: 'gateway' },
+ session.clientID,
+ 'aircraft',
+ );
+ }
+ });
+ }
+
+ private broadcastMessage(message: protocolV0.Messages, excludeClientID?: string, toSessionType?: ClientType) {
+ for (const [ws, session] of this.sessions) {
+ if (excludeClientID !== undefined && session.clientID === excludeClientID) {
+ continue;
+ }
+
+ if (toSessionType !== undefined && session.type !== toSessionType) {
+ continue;
+ }
+
+ this.sendMessage(ws, message);
+ }
+ }
+
+ private sendMessage(ws: WebSocket, message: protocolV0.Messages) {
+ ws.send(JSON.stringify(message));
+ }
+}
diff --git a/apps/server/src/utilities/systray.service.ts b/apps/server/src/utilities/systray.service.ts
index 2fd17026..e5376e3e 100644
--- a/apps/server/src/utilities/systray.service.ts
+++ b/apps/server/src/utilities/systray.service.ts
@@ -51,6 +51,14 @@ export class SysTrayService implements OnApplicationShutdown {
title: 'Remote Displays',
tooltip: 'Open remote displays',
items: [
+ {
+ title: 'Open Remote App',
+ tooltip: 'Open the remote app with your default browser, using your local IP',
+ enabled: true,
+ click: async () => {
+ open(`http://${await this.networkService.getLocalIp(true)}:${this.serverConf.port}/interfaces/remote`);
+ },
+ },
{
title: 'Open MCDU',
tooltip: 'Open the MCDU remote display with your default browser, using your local IP',
diff --git a/apps/server/src/utilities/vfs.controller.ts b/apps/server/src/utilities/vfs.controller.ts
new file mode 100644
index 00000000..7053df48
--- /dev/null
+++ b/apps/server/src/utilities/vfs.controller.ts
@@ -0,0 +1,44 @@
+import { ApiTags } from '@nestjs/swagger';
+import { Controller, Get, HttpException, HttpStatus, Param, Res, Response, StreamableFile } from '@nestjs/common';
+import { contentType } from 'mime-types';
+import { VfsService } from './vfs.service';
+import * as path from 'node:path';
+import { ExpressAdapter } from '@nestjs/platform-express';
+import { HttpAdapterHost } from '@nestjs/core';
+
+@ApiTags('VFS')
+@Controller('api/v1/remote-app/vfs-proxy')
+export class VfsController {
+ constructor(
+ private readonly vfsService: VfsService,
+ private readonly httpAdapterHost: HttpAdapterHost,
+ ) {}
+
+ @Get('/:filePath(*)')
+ async getFile(@Param('filePath') filePath: string, @Res({ passthrough: true }) res: Response) {
+ if (this.vfsService.requestFile === null) {
+ throw new HttpException(
+ 'The VFS service is not ready to serve files at this moment. Is an airplane client connected to the remote bridge?',
+ HttpStatus.SERVICE_UNAVAILABLE,
+ );
+ }
+
+ const ext = path.extname(filePath);
+
+ if (ext === '') {
+ throw new HttpException('Malformed request: Could not find a file extension', HttpStatus.BAD_REQUEST);
+ }
+
+ const contentTypeHeader = contentType(ext);
+
+ if (contentTypeHeader === false) {
+ throw new HttpException('Malformed request: Could not find a valid file extension', HttpStatus.BAD_REQUEST);
+ }
+
+ const data = await this.vfsService.requestFile(filePath);
+
+ this.httpAdapterHost.httpAdapter.setHeader(res, 'Content-Type', contentTypeHeader);
+
+ return new StreamableFile(data);
+ }
+}
diff --git a/apps/server/src/utilities/vfs.module.ts b/apps/server/src/utilities/vfs.module.ts
new file mode 100644
index 00000000..01de3309
--- /dev/null
+++ b/apps/server/src/utilities/vfs.module.ts
@@ -0,0 +1,10 @@
+import { Module } from '@nestjs/common';
+import { VfsController } from './vfs.controller';
+import { VfsService } from './vfs.service';
+
+@Module({
+ controllers: [VfsController],
+ providers: [VfsService],
+ exports: [VfsService],
+})
+export class VfsModule {}
diff --git a/apps/server/src/utilities/vfs.service.ts b/apps/server/src/utilities/vfs.service.ts
new file mode 100644
index 00000000..06bfd3a8
--- /dev/null
+++ b/apps/server/src/utilities/vfs.service.ts
@@ -0,0 +1,8 @@
+import { Injectable } from '@nestjs/common';
+
+export type RequestFileFunction = (filePath: string) => Promise;
+
+@Injectable()
+export class VfsService {
+ public requestFile: RequestFileFunction | null = null;
+}
diff --git a/apps/server/tsconfig.app.json b/apps/server/tsconfig.app.json
index 877a363b..06d4dec5 100644
--- a/apps/server/tsconfig.app.json
+++ b/apps/server/tsconfig.app.json
@@ -4,7 +4,7 @@
"outDir": "../../dist",
},
"include": ["src/**/*"],
- "exclude": ["node_modules", "dist", "test", "**/*spec.ts"],
+ "exclude": ["test", "**/*spec.ts"],
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
}
diff --git a/package-lock.json b/package-lock.json
index 89acd534..af00c305 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,10 +13,10 @@
],
"dependencies": {
"@flybywiresim/msfs-nodejs": "^0.4.0",
- "@nestjs/axios": "^0.0.6",
- "@nestjs/common": "^8.0.0",
- "@nestjs/config": "^1.2.0",
- "@nestjs/core": "^8.0.0",
+ "@nestjs/axios": "^3.1.3",
+ "@nestjs/common": "^8.4.7",
+ "@nestjs/config": "^1.2.1",
+ "@nestjs/core": "8.4.7",
"@nestjs/platform-express": "^8.0.0",
"@nestjs/platform-ws": "^8.3.1",
"@nestjs/serve-static": "^2.2.2",
@@ -25,18 +25,18 @@
"@nestjs/websockets": "^8.3.1",
"@types/pdfjs-dist": "^2.10.378",
"class-transformer": "^0.4.0",
- "class-validator": "^0.13.2",
+ "class-validator": "^0.14.1",
"copyfiles": "^2.4.1",
"dns-packet": "^5.4.0",
"gpu.js": "^2.16.0",
- "ip": "^1.1.5",
+ "ip": "^2.0.1",
"mime-types": "^2.1.34",
"multicast-dns": "^7.2.5",
"nest-winston": "^1.6.2",
"node-hide-console-window": "^2.2.0",
"open": "^8.4.0",
"pdf-to-printer": "5.3.0",
- "pdfjs-dist": "^2.13.216",
+ "pdfjs-dist": "4.2.67",
"pdfkit": "^0.13.0",
"platform-folders": "^0.6.0",
"react": "^17.0.0",
@@ -51,8 +51,8 @@
"systray2": "^2.1.4",
"winston": "^3.3.3",
"winston-daily-rotate-file": "^4.5.5",
- "ws": "^8.5.0",
- "xml2js": "^0.4.23"
+ "ws": "8.17.1",
+ "xml2js": "0.5.0"
},
"devDependencies": {
"@angablue/exe": "^2.0.2",
@@ -66,9 +66,10 @@
"@babel/preset-react": "^7.16.7",
"@babel/runtime": "^7.17.2",
"@flybywiresim/fragmenter": "^0.7.1",
- "@nestjs/cli": "^8.0.0",
- "@nestjs/schematics": "^8.0.0",
- "@nestjs/testing": "^8.0.0",
+ "@flybywiresim/remote-bridge-types": "^0.1.0-alpha.1",
+ "@nestjs/cli": "^8.2.8",
+ "@nestjs/schematics": "^8.0.11",
+ "@nestjs/testing": "^8.4.7",
"@rollup/plugin-babel": "^5.2.1",
"@rollup/plugin-commonjs": "^15.1.0",
"@rollup/plugin-image": "~2.0.6",
@@ -90,7 +91,7 @@
"@types/xml2js": "^0.4.9",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
- "axios": "^0.27.2",
+ "axios": "1.7.4",
"babel-loader": "^8.2.3",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
"copy-webpack-plugin": "^10.2.4",
@@ -105,7 +106,7 @@
"node-fetch": "^2.6.7",
"pkg": "^5.5.1",
"renamer": "^4.0.0",
- "rollup": "^2.67.2",
+ "rollup": "2.79.2",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-css-only": "^2.1.0",
"rollup-plugin-livereload": "~2.0.0",
@@ -122,12 +123,12 @@
"tsconfig-paths": "^3.10.1",
"typescript": "^4.3.5",
"url-loader": "^4.1.1",
- "webpack": "^5.66.0",
+ "webpack": "5.94.0",
"webpack-cli": "^4.9.2",
"webpack-node-externals": "^3.0.0"
},
"engines": {
- "node": "18.x.x"
+ "node": "20.x.x"
},
"peerDependencies": {
"react": "^17.0.0",
@@ -2401,6 +2402,16 @@
"zip-lib": "^0.7.3"
}
},
+ "node_modules/@flybywiresim/fragmenter/node_modules/axios": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+ "dev": true,
+ "dependencies": {
+ "follow-redirects": "^1.14.9",
+ "form-data": "^4.0.0"
+ }
+ },
"node_modules/@flybywiresim/msfs-nodejs": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@flybywiresim/msfs-nodejs/-/msfs-nodejs-0.4.0.tgz",
@@ -2409,6 +2420,12 @@
"node-addon-api": "^5.0.0"
}
},
+ "node_modules/@flybywiresim/remote-bridge-types": {
+ "version": "0.1.0-alpha.1",
+ "resolved": "https://registry.npmjs.org/@flybywiresim/remote-bridge-types/-/remote-bridge-types-0.1.0-alpha.1.tgz",
+ "integrity": "sha512-+YKzrfOwKMrkmIzHAHrx9KVYpypS5Nc7vCbtKWgwJVIcOVT/xU/esTTTk9Pkg5PUH0k/LOaZCj04PTd/XM6o0w==",
+ "dev": true
+ },
"node_modules/@gar/promisify": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
@@ -3227,9 +3244,9 @@
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.20",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
- "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
@@ -3360,26 +3377,15 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/@nestjs/axios": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-0.0.6.tgz",
- "integrity": "sha512-RgtKUziiEPRtWS3KJNDqq0Epw9ffFdIKAtcj6cXnWeJvgHLwnDkw2rUsmHpDYrhszG+8bc4H8sDygRKwNPPAQA==",
- "dependencies": {
- "axios": "0.26.0"
- },
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.1.3.tgz",
+ "integrity": "sha512-RZ/63c1tMxGLqyG3iOCVt7A72oy4x1eM6QEhd4KzCYpaVWW0igq0WSREeRoEZhIxRcZfDfIIkvsOMiM7yfVGZQ==",
"peerDependencies": {
- "@nestjs/common": "^7.0.0 || ^8.0.0",
- "reflect-metadata": "^0.1.12",
+ "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0",
+ "axios": "^1.3.1",
"rxjs": "^6.0.0 || ^7.0.0"
}
},
- "node_modules/@nestjs/axios/node_modules/axios": {
- "version": "0.26.0",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz",
- "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==",
- "dependencies": {
- "follow-redirects": "^1.14.8"
- }
- },
"node_modules/@nestjs/cli": {
"version": "8.2.8",
"resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-8.2.8.tgz",
@@ -3839,6 +3845,15 @@
}
}
},
+ "node_modules/@nestjs/common/node_modules/axios": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+ "dependencies": {
+ "follow-redirects": "^1.14.9",
+ "form-data": "^4.0.0"
+ }
+ },
"node_modules/@nestjs/common/node_modules/tslib": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
@@ -3903,25 +3918,6 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
},
- "node_modules/@nestjs/mapped-types": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.0.1.tgz",
- "integrity": "sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg==",
- "peerDependencies": {
- "@nestjs/common": "^7.0.8 || ^8.0.0",
- "class-transformer": "^0.2.0 || ^0.3.0 || ^0.4.0 || ^0.5.0",
- "class-validator": "^0.11.1 || ^0.12.0 || ^0.13.0",
- "reflect-metadata": "^0.1.12"
- },
- "peerDependenciesMeta": {
- "class-transformer": {
- "optional": true
- },
- "class-validator": {
- "optional": true
- }
- }
- },
"node_modules/@nestjs/platform-express": {
"version": "8.4.7",
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-8.4.7.tgz",
@@ -4170,6 +4166,36 @@
}
}
},
+ "node_modules/@nestjs/swagger/node_modules/@nestjs/mapped-types": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.0.1.tgz",
+ "integrity": "sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg==",
+ "peerDependencies": {
+ "@nestjs/common": "^7.0.8 || ^8.0.0",
+ "class-transformer": "^0.2.0 || ^0.3.0 || ^0.4.0 || ^0.5.0",
+ "class-validator": "^0.11.1 || ^0.12.0 || ^0.13.0",
+ "reflect-metadata": "^0.1.12"
+ },
+ "peerDependenciesMeta": {
+ "class-transformer": {
+ "optional": true
+ },
+ "class-validator": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@nestjs/swagger/node_modules/class-validator": {
+ "version": "0.13.2",
+ "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz",
+ "integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "libphonenumber-js": "^1.9.43",
+ "validator": "^13.7.0"
+ }
+ },
"node_modules/@nestjs/terminus": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/@nestjs/terminus/-/terminus-8.1.1.tgz",
@@ -5050,6 +5076,11 @@
"resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
"integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="
},
+ "node_modules/@types/validator": {
+ "version": "13.12.2",
+ "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.2.tgz",
+ "integrity": "sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA=="
+ },
"node_modules/@types/ws": {
"version": "8.5.10",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
@@ -5378,148 +5409,148 @@
"dev": true
},
"node_modules/@webassemblyjs/ast": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz",
- "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
+ "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
"dev": true,
"dependencies": {
- "@webassemblyjs/helper-numbers": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6"
+ "@webassemblyjs/helper-numbers": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2"
}
},
"node_modules/@webassemblyjs/floating-point-hex-parser": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
- "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
+ "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
"dev": true
},
"node_modules/@webassemblyjs/helper-api-error": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
- "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
+ "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
"dev": true
},
"node_modules/@webassemblyjs/helper-buffer": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz",
- "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
+ "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
"dev": true
},
"node_modules/@webassemblyjs/helper-numbers": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
- "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
+ "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
"dev": true,
"dependencies": {
- "@webassemblyjs/floating-point-hex-parser": "1.11.6",
- "@webassemblyjs/helper-api-error": "1.11.6",
+ "@webassemblyjs/floating-point-hex-parser": "1.13.2",
+ "@webassemblyjs/helper-api-error": "1.13.2",
"@xtuc/long": "4.2.2"
}
},
"node_modules/@webassemblyjs/helper-wasm-bytecode": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
- "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
+ "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
"dev": true
},
"node_modules/@webassemblyjs/helper-wasm-section": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz",
- "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
+ "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
"dev": true,
"dependencies": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-buffer": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/wasm-gen": "1.11.6"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/wasm-gen": "1.14.1"
}
},
"node_modules/@webassemblyjs/ieee754": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
- "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
+ "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
"dev": true,
"dependencies": {
"@xtuc/ieee754": "^1.2.0"
}
},
"node_modules/@webassemblyjs/leb128": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
- "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
+ "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
"dev": true,
"dependencies": {
"@xtuc/long": "4.2.2"
}
},
"node_modules/@webassemblyjs/utf8": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
- "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
+ "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
"dev": true
},
"node_modules/@webassemblyjs/wasm-edit": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz",
- "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
+ "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
"dev": true,
"dependencies": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-buffer": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/helper-wasm-section": "1.11.6",
- "@webassemblyjs/wasm-gen": "1.11.6",
- "@webassemblyjs/wasm-opt": "1.11.6",
- "@webassemblyjs/wasm-parser": "1.11.6",
- "@webassemblyjs/wast-printer": "1.11.6"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/helper-wasm-section": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-opt": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1",
+ "@webassemblyjs/wast-printer": "1.14.1"
}
},
"node_modules/@webassemblyjs/wasm-gen": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz",
- "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
+ "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
"dev": true,
"dependencies": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/ieee754": "1.11.6",
- "@webassemblyjs/leb128": "1.11.6",
- "@webassemblyjs/utf8": "1.11.6"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
}
},
"node_modules/@webassemblyjs/wasm-opt": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz",
- "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
+ "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
"dev": true,
"dependencies": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-buffer": "1.11.6",
- "@webassemblyjs/wasm-gen": "1.11.6",
- "@webassemblyjs/wasm-parser": "1.11.6"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1"
}
},
"node_modules/@webassemblyjs/wasm-parser": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz",
- "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
+ "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
"dev": true,
"dependencies": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-api-error": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/ieee754": "1.11.6",
- "@webassemblyjs/leb128": "1.11.6",
- "@webassemblyjs/utf8": "1.11.6"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
}
},
"node_modules/@webassemblyjs/wast-printer": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz",
- "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
+ "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
"dev": true,
"dependencies": {
- "@webassemblyjs/ast": "1.11.6",
+ "@webassemblyjs/ast": "1.14.1",
"@xtuc/long": "4.2.2"
}
},
@@ -5638,6 +5669,15 @@
"acorn": "^8"
}
},
+ "node_modules/acorn-import-attributes": {
+ "version": "1.9.5",
+ "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
+ "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^8"
+ }
+ },
"node_modules/acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
@@ -5911,12 +5951,13 @@
}
},
"node_modules/axios": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
- "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz",
+ "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==",
"dependencies": {
- "follow-redirects": "^1.14.9",
- "form-data": "^4.0.0"
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
}
},
"node_modules/b4a": {
@@ -6655,6 +6696,56 @@
}
]
},
+ "node_modules/canvas": {
+ "version": "2.11.2",
+ "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz",
+ "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==",
+ "hasInstallScript": true,
+ "optional": true,
+ "dependencies": {
+ "@mapbox/node-pre-gyp": "^1.0.0",
+ "nan": "^2.17.0",
+ "simple-get": "^3.0.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/canvas/node_modules/decompress-response": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
+ "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
+ "optional": true,
+ "dependencies": {
+ "mimic-response": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/canvas/node_modules/mimic-response": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
+ "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
+ "optional": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/canvas/node_modules/simple-get": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
+ "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
+ "optional": true,
+ "dependencies": {
+ "decompress-response": "^4.2.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
"node_modules/cargo-cp-artifact": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.8.tgz",
@@ -6771,12 +6862,13 @@
"integrity": "sha512-ETWD/H2TbWbKEi7m9N4Km5+cw1hNcqJSxlSYhsLsNjQzWWiZIYA1zafxpK9PwVfaZ6AqR5rrjPVUBGESm5tQUA=="
},
"node_modules/class-validator": {
- "version": "0.13.2",
- "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz",
- "integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==",
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz",
+ "integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==",
"dependencies": {
- "libphonenumber-js": "^1.9.43",
- "validator": "^13.7.0"
+ "@types/validator": "^13.11.8",
+ "libphonenumber-js": "^1.10.53",
+ "validator": "^13.9.0"
}
},
"node_modules/clean-css": {
@@ -8137,12 +8229,6 @@
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
- "node_modules/dommatrix": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/dommatrix/-/dommatrix-1.0.3.tgz",
- "integrity": "sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww==",
- "deprecated": "dommatrix is no longer maintained. Please use @thednp/dommatrix."
- },
"node_modules/domutils": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
@@ -8260,9 +8346,9 @@
}
},
"node_modules/enhanced-resolve": {
- "version": "5.15.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
- "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
+ "version": "5.18.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz",
+ "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.2.4",
@@ -9281,9 +9367,9 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"node_modules/follow-redirects": {
- "version": "1.15.3",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
- "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
+ "version": "1.15.9",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
"funding": [
{
"type": "individual",
@@ -10523,9 +10609,9 @@
}
},
"node_modules/ip": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz",
- "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg=="
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz",
+ "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ=="
},
"node_modules/ipaddr.js": {
"version": "1.9.1",
@@ -13043,9 +13129,9 @@
}
},
"node_modules/libphonenumber-js": {
- "version": "1.10.51",
- "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.51.tgz",
- "integrity": "sha512-vY2I+rQwrDQzoPds0JeTEpeWzbUJgqoV0O4v31PauHBb/e+1KCXKylHcDnBMgJZ9fH9mErsEbROJY3Z3JtqEmg=="
+ "version": "1.11.17",
+ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.17.tgz",
+ "integrity": "sha512-Jr6v8thd5qRlOlc6CslSTzGzzQW03uiscab7KHQZX1Dfo4R6n6FDhZ0Hri6/X7edLIDv9gl4VMZXhxTjLnl0VQ=="
},
"node_modules/lilconfig": {
"version": "2.1.0",
@@ -14686,26 +14772,30 @@
"node": ">=8"
}
},
+ "node_modules/path2d": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/path2d/-/path2d-0.2.2.tgz",
+ "integrity": "sha512-+vnG6S4dYcYxZd+CZxzXCNKdELYZSKfohrk98yajCo1PtRoDgCTrrwOvK1GT0UoAdVszagDVllQc0U1vaX4NUQ==",
+ "optional": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/pdf-to-printer": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/pdf-to-printer/-/pdf-to-printer-5.3.0.tgz",
"integrity": "sha512-st1pTOfks+vr+QpGe04x2XAaEaeYfinlOCUL5H/breP7C4Dwx0Z74i9Hcjv9Yljbns5IXoUb2wY7em3EQoZOpw=="
},
"node_modules/pdfjs-dist": {
- "version": "2.16.105",
- "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.16.105.tgz",
- "integrity": "sha512-J4dn41spsAwUxCpEoVf6GVoz908IAA3mYiLmNxg8J9kfRXc2jxpbUepcP0ocp0alVNLFthTAM8DZ1RaHh8sU0A==",
- "dependencies": {
- "dommatrix": "^1.0.3",
- "web-streams-polyfill": "^3.2.1"
- },
- "peerDependencies": {
- "worker-loader": "^3.0.8"
+ "version": "4.2.67",
+ "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-4.2.67.tgz",
+ "integrity": "sha512-rJmuBDFpD7cqC8WIkQUEClyB4UAH05K4AsyewToMTp2gSy3Rrx8c1ydAVqlJlGv3yZSOrhEERQU/4ScQQFlLHA==",
+ "engines": {
+ "node": ">=18"
},
- "peerDependenciesMeta": {
- "worker-loader": {
- "optional": true
- }
+ "optionalDependencies": {
+ "canvas": "^2.11.2",
+ "path2d": "^0.2.0"
}
},
"node_modules/pdfkit": {
@@ -15893,6 +15983,11 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
"node_modules/psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
@@ -16477,9 +16572,9 @@
}
},
"node_modules/rollup": {
- "version": "2.79.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
- "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
+ "version": "2.79.2",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz",
+ "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==",
"dev": true,
"bin": {
"rollup": "dist/bin/rollup"
@@ -16970,9 +17065,9 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/serialize-javascript": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
- "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
+ "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
"dependencies": {
"randombytes": "^2.1.0"
@@ -17334,11 +17429,6 @@
"node": ">= 10"
}
},
- "node_modules/socks/node_modules/ip": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
- "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ=="
- },
"node_modules/source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
@@ -18013,9 +18103,9 @@
}
},
"node_modules/terser": {
- "version": "5.26.0",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz",
- "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==",
+ "version": "5.37.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz",
+ "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==",
"dev": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
@@ -18031,16 +18121,16 @@
}
},
"node_modules/terser-webpack-plugin": {
- "version": "5.3.9",
- "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz",
- "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==",
+ "version": "5.3.11",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz",
+ "integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==",
"dev": true,
"dependencies": {
- "@jridgewell/trace-mapping": "^0.3.17",
+ "@jridgewell/trace-mapping": "^0.3.25",
"jest-worker": "^27.4.5",
- "schema-utils": "^3.1.1",
- "serialize-javascript": "^6.0.1",
- "terser": "^5.16.8"
+ "schema-utils": "^4.3.0",
+ "serialize-javascript": "^6.0.2",
+ "terser": "^5.31.1"
},
"engines": {
"node": ">= 10.13.0"
@@ -18064,46 +18154,16 @@
}
}
},
- "node_modules/terser-webpack-plugin/node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
- "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true,
- "peerDependencies": {
- "ajv": "^6.9.1"
- }
- },
- "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
"node_modules/terser-webpack-plugin/node_modules/schema-utils": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
- "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
+ "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
"dev": true,
"dependencies": {
- "@types/json-schema": "^7.0.8",
- "ajv": "^6.12.5",
- "ajv-keywords": "^3.5.2"
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
},
"engines": {
"node": ">= 10.13.0"
@@ -19106,9 +19166,9 @@
}
},
"node_modules/watchpack": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
- "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
+ "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
"dev": true,
"dependencies": {
"glob-to-regexp": "^0.4.1",
@@ -19127,14 +19187,6 @@
"defaults": "^1.0.3"
}
},
- "node_modules/web-streams-polyfill": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
- "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/webgpu": {
"version": "0.1.16",
"resolved": "https://registry.npmjs.org/webgpu/-/webgpu-0.1.16.tgz",
@@ -19153,34 +19205,33 @@
}
},
"node_modules/webpack": {
- "version": "5.89.0",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz",
- "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==",
+ "version": "5.94.0",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz",
+ "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==",
"dev": true,
"dependencies": {
- "@types/eslint-scope": "^3.7.3",
- "@types/estree": "^1.0.0",
- "@webassemblyjs/ast": "^1.11.5",
- "@webassemblyjs/wasm-edit": "^1.11.5",
- "@webassemblyjs/wasm-parser": "^1.11.5",
+ "@types/estree": "^1.0.5",
+ "@webassemblyjs/ast": "^1.12.1",
+ "@webassemblyjs/wasm-edit": "^1.12.1",
+ "@webassemblyjs/wasm-parser": "^1.12.1",
"acorn": "^8.7.1",
- "acorn-import-assertions": "^1.9.0",
- "browserslist": "^4.14.5",
+ "acorn-import-attributes": "^1.9.5",
+ "browserslist": "^4.21.10",
"chrome-trace-event": "^1.0.2",
- "enhanced-resolve": "^5.15.0",
+ "enhanced-resolve": "^5.17.1",
"es-module-lexer": "^1.2.1",
"eslint-scope": "5.1.1",
"events": "^3.2.0",
"glob-to-regexp": "^0.4.1",
- "graceful-fs": "^4.2.9",
+ "graceful-fs": "^4.2.11",
"json-parse-even-better-errors": "^2.3.1",
"loader-runner": "^4.2.0",
"mime-types": "^2.1.27",
"neo-async": "^2.6.2",
"schema-utils": "^3.2.0",
"tapable": "^2.1.1",
- "terser-webpack-plugin": "^5.3.7",
- "watchpack": "^2.4.0",
+ "terser-webpack-plugin": "^5.3.10",
+ "watchpack": "^2.4.1",
"webpack-sources": "^3.2.3"
},
"bin": {
@@ -19736,9 +19787,9 @@
}
},
"node_modules/ws": {
- "version": "8.15.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.15.1.tgz",
- "integrity": "sha512-W5OZiCjXEmk0yZ66ZN82beM5Sz7l7coYxpRkzS+p9PP+ToQry8szKh+61eNktr7EA9DOwvFGhfC605jDHbP6QQ==",
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
+ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"engines": {
"node": ">=10.0.0"
},
@@ -19762,9 +19813,9 @@
"dev": true
},
"node_modules/xml2js": {
- "version": "0.4.23",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
- "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
+ "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
"dependencies": {
"sax": ">=0.6.0",
"xmlbuilder": "~11.0.0"
@@ -21479,6 +21530,18 @@
"split-file": "^2.3.0",
"url-join": "^4.0.1",
"zip-lib": "^0.7.3"
+ },
+ "dependencies": {
+ "axios": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+ "dev": true,
+ "requires": {
+ "follow-redirects": "^1.14.9",
+ "form-data": "^4.0.0"
+ }
+ }
}
},
"@flybywiresim/msfs-nodejs": {
@@ -21489,6 +21552,12 @@
"node-addon-api": "^5.0.0"
}
},
+ "@flybywiresim/remote-bridge-types": {
+ "version": "0.1.0-alpha.1",
+ "resolved": "https://registry.npmjs.org/@flybywiresim/remote-bridge-types/-/remote-bridge-types-0.1.0-alpha.1.tgz",
+ "integrity": "sha512-+YKzrfOwKMrkmIzHAHrx9KVYpypS5Nc7vCbtKWgwJVIcOVT/xU/esTTTk9Pkg5PUH0k/LOaZCj04PTd/XM6o0w==",
+ "dev": true
+ },
"@gar/promisify": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
@@ -22112,9 +22181,9 @@
"dev": true
},
"@jridgewell/trace-mapping": {
- "version": "0.3.20",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
- "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dev": true,
"requires": {
"@jridgewell/resolve-uri": "^3.1.0",
@@ -22220,22 +22289,10 @@
}
},
"@nestjs/axios": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-0.0.6.tgz",
- "integrity": "sha512-RgtKUziiEPRtWS3KJNDqq0Epw9ffFdIKAtcj6cXnWeJvgHLwnDkw2rUsmHpDYrhszG+8bc4H8sDygRKwNPPAQA==",
- "requires": {
- "axios": "0.26.0"
- },
- "dependencies": {
- "axios": {
- "version": "0.26.0",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz",
- "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==",
- "requires": {
- "follow-redirects": "^1.14.8"
- }
- }
- }
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.1.3.tgz",
+ "integrity": "sha512-RZ/63c1tMxGLqyG3iOCVt7A72oy4x1eM6QEhd4KzCYpaVWW0igq0WSREeRoEZhIxRcZfDfIIkvsOMiM7yfVGZQ==",
+ "requires": {}
},
"@nestjs/cli": {
"version": "8.2.8",
@@ -22604,6 +22661,15 @@
"uuid": "8.3.2"
},
"dependencies": {
+ "axios": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+ "requires": {
+ "follow-redirects": "^1.14.9",
+ "form-data": "^4.0.0"
+ }
+ },
"tslib": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
@@ -22643,12 +22709,6 @@
}
}
},
- "@nestjs/mapped-types": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.0.1.tgz",
- "integrity": "sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg==",
- "requires": {}
- },
"@nestjs/platform-express": {
"version": "8.4.7",
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-8.4.7.tgz",
@@ -22826,6 +22886,25 @@
"@nestjs/mapped-types": "1.0.1",
"lodash": "4.17.21",
"path-to-regexp": "3.2.0"
+ },
+ "dependencies": {
+ "@nestjs/mapped-types": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.0.1.tgz",
+ "integrity": "sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg==",
+ "requires": {}
+ },
+ "class-validator": {
+ "version": "0.13.2",
+ "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz",
+ "integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==",
+ "optional": true,
+ "peer": true,
+ "requires": {
+ "libphonenumber-js": "^1.9.43",
+ "validator": "^13.7.0"
+ }
+ }
}
},
"@nestjs/terminus": {
@@ -23555,6 +23634,11 @@
"resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
"integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="
},
+ "@types/validator": {
+ "version": "13.12.2",
+ "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.2.tgz",
+ "integrity": "sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA=="
+ },
"@types/ws": {
"version": "8.5.10",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
@@ -23773,148 +23857,148 @@
"dev": true
},
"@webassemblyjs/ast": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz",
- "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
+ "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
"dev": true,
"requires": {
- "@webassemblyjs/helper-numbers": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6"
+ "@webassemblyjs/helper-numbers": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2"
}
},
"@webassemblyjs/floating-point-hex-parser": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
- "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
+ "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
"dev": true
},
"@webassemblyjs/helper-api-error": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
- "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
+ "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
"dev": true
},
"@webassemblyjs/helper-buffer": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz",
- "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
+ "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
"dev": true
},
"@webassemblyjs/helper-numbers": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
- "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
+ "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
"dev": true,
"requires": {
- "@webassemblyjs/floating-point-hex-parser": "1.11.6",
- "@webassemblyjs/helper-api-error": "1.11.6",
+ "@webassemblyjs/floating-point-hex-parser": "1.13.2",
+ "@webassemblyjs/helper-api-error": "1.13.2",
"@xtuc/long": "4.2.2"
}
},
"@webassemblyjs/helper-wasm-bytecode": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
- "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
+ "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
"dev": true
},
"@webassemblyjs/helper-wasm-section": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz",
- "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
+ "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
"dev": true,
"requires": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-buffer": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/wasm-gen": "1.11.6"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/wasm-gen": "1.14.1"
}
},
"@webassemblyjs/ieee754": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
- "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
+ "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
"dev": true,
"requires": {
"@xtuc/ieee754": "^1.2.0"
}
},
"@webassemblyjs/leb128": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
- "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
+ "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
"dev": true,
"requires": {
"@xtuc/long": "4.2.2"
}
},
"@webassemblyjs/utf8": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
- "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
+ "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
"dev": true
},
"@webassemblyjs/wasm-edit": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz",
- "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
+ "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
"dev": true,
"requires": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-buffer": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/helper-wasm-section": "1.11.6",
- "@webassemblyjs/wasm-gen": "1.11.6",
- "@webassemblyjs/wasm-opt": "1.11.6",
- "@webassemblyjs/wasm-parser": "1.11.6",
- "@webassemblyjs/wast-printer": "1.11.6"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/helper-wasm-section": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-opt": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1",
+ "@webassemblyjs/wast-printer": "1.14.1"
}
},
"@webassemblyjs/wasm-gen": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz",
- "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
+ "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
"dev": true,
"requires": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/ieee754": "1.11.6",
- "@webassemblyjs/leb128": "1.11.6",
- "@webassemblyjs/utf8": "1.11.6"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
}
},
"@webassemblyjs/wasm-opt": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz",
- "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
+ "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
"dev": true,
"requires": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-buffer": "1.11.6",
- "@webassemblyjs/wasm-gen": "1.11.6",
- "@webassemblyjs/wasm-parser": "1.11.6"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1"
}
},
"@webassemblyjs/wasm-parser": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz",
- "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
+ "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
"dev": true,
"requires": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-api-error": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/ieee754": "1.11.6",
- "@webassemblyjs/leb128": "1.11.6",
- "@webassemblyjs/utf8": "1.11.6"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
}
},
"@webassemblyjs/wast-printer": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz",
- "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
+ "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
"dev": true,
"requires": {
- "@webassemblyjs/ast": "1.11.6",
+ "@webassemblyjs/ast": "1.14.1",
"@xtuc/long": "4.2.2"
}
},
@@ -24004,6 +24088,13 @@
"dev": true,
"requires": {}
},
+ "acorn-import-attributes": {
+ "version": "1.9.5",
+ "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
+ "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
+ "dev": true,
+ "requires": {}
+ },
"acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
@@ -24208,12 +24299,13 @@
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="
},
"axios": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
- "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz",
+ "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==",
"requires": {
- "follow-redirects": "^1.14.9",
- "form-data": "^4.0.0"
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
}
},
"b4a": {
@@ -24770,6 +24862,45 @@
"integrity": "sha512-vSUkH84HontZJ88MiNrOau1EBrCqEQYgkC5gIySiDlpsm8sGVrhU7Kx4V6h0tnqaHzIHZv08HlJIwPbL4XL9+A==",
"dev": true
},
+ "canvas": {
+ "version": "2.11.2",
+ "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz",
+ "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==",
+ "optional": true,
+ "requires": {
+ "@mapbox/node-pre-gyp": "^1.0.0",
+ "nan": "^2.17.0",
+ "simple-get": "^3.0.3"
+ },
+ "dependencies": {
+ "decompress-response": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
+ "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
+ "optional": true,
+ "requires": {
+ "mimic-response": "^2.0.0"
+ }
+ },
+ "mimic-response": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
+ "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
+ "optional": true
+ },
+ "simple-get": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
+ "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
+ "optional": true,
+ "requires": {
+ "decompress-response": "^4.2.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ }
+ }
+ },
"cargo-cp-artifact": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.8.tgz",
@@ -24848,12 +24979,13 @@
"integrity": "sha512-ETWD/H2TbWbKEi7m9N4Km5+cw1hNcqJSxlSYhsLsNjQzWWiZIYA1zafxpK9PwVfaZ6AqR5rrjPVUBGESm5tQUA=="
},
"class-validator": {
- "version": "0.13.2",
- "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz",
- "integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==",
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz",
+ "integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==",
"requires": {
- "libphonenumber-js": "^1.9.43",
- "validator": "^13.7.0"
+ "@types/validator": "^13.11.8",
+ "libphonenumber-js": "^1.10.53",
+ "validator": "^13.9.0"
}
},
"clean-css": {
@@ -25865,11 +25997,6 @@
"domelementtype": "^2.2.0"
}
},
- "dommatrix": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/dommatrix/-/dommatrix-1.0.3.tgz",
- "integrity": "sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww=="
- },
"domutils": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
@@ -25968,9 +26095,9 @@
}
},
"enhanced-resolve": {
- "version": "5.15.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
- "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
+ "version": "5.18.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz",
+ "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.2.4",
@@ -26741,9 +26868,9 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"follow-redirects": {
- "version": "1.15.3",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
- "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q=="
+ "version": "1.15.9",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="
},
"fontkit": {
"version": "1.9.0",
@@ -27650,9 +27777,9 @@
}
},
"ip": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz",
- "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg=="
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz",
+ "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ=="
},
"ipaddr.js": {
"version": "1.9.1",
@@ -29493,9 +29620,9 @@
}
},
"libphonenumber-js": {
- "version": "1.10.51",
- "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.51.tgz",
- "integrity": "sha512-vY2I+rQwrDQzoPds0JeTEpeWzbUJgqoV0O4v31PauHBb/e+1KCXKylHcDnBMgJZ9fH9mErsEbROJY3Z3JtqEmg=="
+ "version": "1.11.17",
+ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.17.tgz",
+ "integrity": "sha512-Jr6v8thd5qRlOlc6CslSTzGzzQW03uiscab7KHQZX1Dfo4R6n6FDhZ0Hri6/X7edLIDv9gl4VMZXhxTjLnl0VQ=="
},
"lilconfig": {
"version": "2.1.0",
@@ -30719,18 +30846,24 @@
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true
},
+ "path2d": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/path2d/-/path2d-0.2.2.tgz",
+ "integrity": "sha512-+vnG6S4dYcYxZd+CZxzXCNKdELYZSKfohrk98yajCo1PtRoDgCTrrwOvK1GT0UoAdVszagDVllQc0U1vaX4NUQ==",
+ "optional": true
+ },
"pdf-to-printer": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/pdf-to-printer/-/pdf-to-printer-5.3.0.tgz",
"integrity": "sha512-st1pTOfks+vr+QpGe04x2XAaEaeYfinlOCUL5H/breP7C4Dwx0Z74i9Hcjv9Yljbns5IXoUb2wY7em3EQoZOpw=="
},
"pdfjs-dist": {
- "version": "2.16.105",
- "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.16.105.tgz",
- "integrity": "sha512-J4dn41spsAwUxCpEoVf6GVoz908IAA3mYiLmNxg8J9kfRXc2jxpbUepcP0ocp0alVNLFthTAM8DZ1RaHh8sU0A==",
+ "version": "4.2.67",
+ "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-4.2.67.tgz",
+ "integrity": "sha512-rJmuBDFpD7cqC8WIkQUEClyB4UAH05K4AsyewToMTp2gSy3Rrx8c1ydAVqlJlGv3yZSOrhEERQU/4ScQQFlLHA==",
"requires": {
- "dommatrix": "^1.0.3",
- "web-streams-polyfill": "^3.2.1"
+ "canvas": "^2.11.2",
+ "path2d": "^0.2.0"
}
},
"pdfkit": {
@@ -31529,6 +31662,11 @@
"ipaddr.js": "1.9.1"
}
},
+ "proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
"psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
@@ -31977,9 +32115,9 @@
}
},
"rollup": {
- "version": "2.79.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
- "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
+ "version": "2.79.2",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz",
+ "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==",
"dev": true,
"requires": {
"fsevents": "~2.3.2"
@@ -32354,9 +32492,9 @@
}
},
"serialize-javascript": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
- "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
+ "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"
@@ -32615,13 +32753,6 @@
"requires": {
"ip": "^2.0.0",
"smart-buffer": "^4.2.0"
- },
- "dependencies": {
- "ip": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
- "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ=="
- }
}
},
"socks-proxy-agent": {
@@ -33150,9 +33281,9 @@
}
},
"terser": {
- "version": "5.26.0",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz",
- "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==",
+ "version": "5.37.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz",
+ "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==",
"dev": true,
"requires": {
"@jridgewell/source-map": "^0.3.3",
@@ -33170,52 +33301,28 @@
}
},
"terser-webpack-plugin": {
- "version": "5.3.9",
- "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz",
- "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==",
+ "version": "5.3.11",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz",
+ "integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==",
"dev": true,
"requires": {
- "@jridgewell/trace-mapping": "^0.3.17",
+ "@jridgewell/trace-mapping": "^0.3.25",
"jest-worker": "^27.4.5",
- "schema-utils": "^3.1.1",
- "serialize-javascript": "^6.0.1",
- "terser": "^5.16.8"
+ "schema-utils": "^4.3.0",
+ "serialize-javascript": "^6.0.2",
+ "terser": "^5.31.1"
},
"dependencies": {
- "ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "requires": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- }
- },
- "ajv-keywords": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
- "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true,
- "requires": {}
- },
- "json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
"schema-utils": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
- "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
+ "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
"dev": true,
"requires": {
- "@types/json-schema": "^7.0.8",
- "ajv": "^6.12.5",
- "ajv-keywords": "^3.5.2"
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
}
}
}
@@ -33931,9 +34038,9 @@
}
},
"watchpack": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
- "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
+ "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
"dev": true,
"requires": {
"glob-to-regexp": "^0.4.1",
@@ -33949,11 +34056,6 @@
"defaults": "^1.0.3"
}
},
- "web-streams-polyfill": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
- "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q=="
- },
"webgpu": {
"version": "0.1.16",
"resolved": "https://registry.npmjs.org/webgpu/-/webgpu-0.1.16.tgz",
@@ -33966,34 +34068,33 @@
"dev": true
},
"webpack": {
- "version": "5.89.0",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz",
- "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==",
+ "version": "5.94.0",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz",
+ "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==",
"dev": true,
"requires": {
- "@types/eslint-scope": "^3.7.3",
- "@types/estree": "^1.0.0",
- "@webassemblyjs/ast": "^1.11.5",
- "@webassemblyjs/wasm-edit": "^1.11.5",
- "@webassemblyjs/wasm-parser": "^1.11.5",
+ "@types/estree": "^1.0.5",
+ "@webassemblyjs/ast": "^1.12.1",
+ "@webassemblyjs/wasm-edit": "^1.12.1",
+ "@webassemblyjs/wasm-parser": "^1.12.1",
"acorn": "^8.7.1",
- "acorn-import-assertions": "^1.9.0",
- "browserslist": "^4.14.5",
+ "acorn-import-attributes": "^1.9.5",
+ "browserslist": "^4.21.10",
"chrome-trace-event": "^1.0.2",
- "enhanced-resolve": "^5.15.0",
+ "enhanced-resolve": "^5.17.1",
"es-module-lexer": "^1.2.1",
"eslint-scope": "5.1.1",
"events": "^3.2.0",
"glob-to-regexp": "^0.4.1",
- "graceful-fs": "^4.2.9",
+ "graceful-fs": "^4.2.11",
"json-parse-even-better-errors": "^2.3.1",
"loader-runner": "^4.2.0",
"mime-types": "^2.1.27",
"neo-async": "^2.6.2",
"schema-utils": "^3.2.0",
"tapable": "^2.1.1",
- "terser-webpack-plugin": "^5.3.7",
- "watchpack": "^2.4.0",
+ "terser-webpack-plugin": "^5.3.10",
+ "watchpack": "^2.4.1",
"webpack-sources": "^3.2.3"
},
"dependencies": {
@@ -34399,9 +34500,9 @@
}
},
"ws": {
- "version": "8.15.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.15.1.tgz",
- "integrity": "sha512-W5OZiCjXEmk0yZ66ZN82beM5Sz7l7coYxpRkzS+p9PP+ToQry8szKh+61eNktr7EA9DOwvFGhfC605jDHbP6QQ==",
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
+ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"requires": {}
},
"xml-name-validator": {
@@ -34411,9 +34512,9 @@
"dev": true
},
"xml2js": {
- "version": "0.4.23",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
- "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
+ "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
"requires": {
"sax": ">=0.6.0",
"xmlbuilder": "~11.0.0"
diff --git a/package.json b/package.json
index a3ef8e02..c979eabb 100644
--- a/package.json
+++ b/package.json
@@ -9,15 +9,16 @@
"win32"
],
"engines": {
- "node": "18.x.x"
+ "node": "20.x.x"
},
"scripts": {
"prepub": "copy package.json dist && copy README.md dist && copy LICENSE dist && copy CODE_OF_CONDUCT.md dist",
"pub": "cd dist && npm publish",
"postpub": "cd dist && del package.json && del README.md && del LICENSE && del CODE_OF_CONDUCT.md",
"prebuild": "rimraf dist && rimraf build && rimraf build-modules",
- "build": "npm run build:server && npm run build:mcdu",
+ "build": "npm run build:server && npm run build:mcdu && npm run build:remote",
"build:mcdu": "webpack --config apps/mcdu/webpack.config.js",
+ "build:remote": "cd apps/remote/ && npm run build",
"build:server": "nest build server",
"build:exec": "npm run build && npm run install:exec",
"build:package": "node scripts/package.js",
@@ -38,6 +39,9 @@
"start:prod": "node dist/main",
"lint": "eslint --cache **/*.{js,mjs,jsx,ts,tsx}",
"lint:fix": "npm run lint -- --fix",
+ "typecheck": "npm run typecheck:server && npm run typecheck:remote-app",
+ "typecheck:server": "tsc --noEmit",
+ "typecheck:remote-app": "cd apps/remote/ && tsc --noEmit",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
@@ -50,10 +54,10 @@
},
"dependencies": {
"@flybywiresim/msfs-nodejs": "^0.4.0",
- "@nestjs/axios": "^0.0.6",
- "@nestjs/common": "^8.0.0",
- "@nestjs/config": "^1.2.0",
- "@nestjs/core": "^8.0.0",
+ "@nestjs/axios": "^3.1.3",
+ "@nestjs/common": "^8.4.7",
+ "@nestjs/config": "^1.2.1",
+ "@nestjs/core": "8.4.7",
"@nestjs/platform-express": "^8.0.0",
"@nestjs/platform-ws": "^8.3.1",
"@nestjs/serve-static": "^2.2.2",
@@ -62,18 +66,18 @@
"@nestjs/websockets": "^8.3.1",
"@types/pdfjs-dist": "^2.10.378",
"class-transformer": "^0.4.0",
- "class-validator": "^0.13.2",
+ "class-validator": "^0.14.1",
"copyfiles": "^2.4.1",
"dns-packet": "^5.4.0",
"gpu.js": "^2.16.0",
- "ip": "^1.1.5",
+ "ip": "^2.0.1",
"mime-types": "^2.1.34",
"multicast-dns": "^7.2.5",
"nest-winston": "^1.6.2",
"node-hide-console-window": "^2.2.0",
"open": "^8.4.0",
"pdf-to-printer": "5.3.0",
- "pdfjs-dist": "^2.13.216",
+ "pdfjs-dist": "4.2.67",
"pdfkit": "^0.13.0",
"platform-folders": "^0.6.0",
"react": "^17.0.0",
@@ -88,8 +92,8 @@
"systray2": "^2.1.4",
"winston": "^3.3.3",
"winston-daily-rotate-file": "^4.5.5",
- "ws": "^8.5.0",
- "xml2js": "^0.4.23"
+ "ws": "8.17.1",
+ "xml2js": "0.5.0"
},
"devDependencies": {
"@angablue/exe": "^2.0.2",
@@ -103,9 +107,10 @@
"@babel/preset-react": "^7.16.7",
"@babel/runtime": "^7.17.2",
"@flybywiresim/fragmenter": "^0.7.1",
- "@nestjs/cli": "^8.0.0",
- "@nestjs/schematics": "^8.0.0",
- "@nestjs/testing": "^8.0.0",
+ "@flybywiresim/remote-bridge-types": "^0.1.0-alpha.1",
+ "@nestjs/cli": "^8.2.8",
+ "@nestjs/schematics": "^8.0.11",
+ "@nestjs/testing": "^8.4.7",
"@rollup/plugin-babel": "^5.2.1",
"@rollup/plugin-commonjs": "^15.1.0",
"@rollup/plugin-image": "~2.0.6",
@@ -127,7 +132,7 @@
"@types/xml2js": "^0.4.9",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
- "axios": "^0.27.2",
+ "axios": "1.7.4",
"babel-loader": "^8.2.3",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
"copy-webpack-plugin": "^10.2.4",
@@ -142,7 +147,7 @@
"node-fetch": "^2.6.7",
"pkg": "^5.5.1",
"renamer": "^4.0.0",
- "rollup": "^2.67.2",
+ "rollup": "2.79.2",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-css-only": "^2.1.0",
"rollup-plugin-livereload": "~2.0.0",
@@ -159,7 +164,7 @@
"tsconfig-paths": "^3.10.1",
"typescript": "^4.3.5",
"url-loader": "^4.1.1",
- "webpack": "^5.66.0",
+ "webpack": "5.94.0",
"webpack-cli": "^4.9.2",
"webpack-node-externals": "^3.0.0"
},
@@ -207,6 +212,7 @@
"node_modules/platform-folders/build/**/*.*",
"/node_modules/systray2/traybin/*.exe",
"dist/mcdu/**/*",
+ "dist/remote/**/*",
"dist/assets/**/*",
"dist/terrain/mapdata/**/*.*",
"dist/terrain/processing/**/*.*",
diff --git a/tsconfig.json b/tsconfig.json
index f4f03e21..45fb5645 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,7 @@
{
"compilerOptions": {
"module": "commonjs",
+ "moduleResolution": "node",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
@@ -18,5 +19,6 @@
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,
"paths": {}
- }
-}
\ No newline at end of file
+ },
+ "exclude": ["apps/**/*"]
+}