From dc9ca7c2afc5a3fc195b41645ef2df286ba4a2d1 Mon Sep 17 00:00:00 2001 From: Andrew Lalis Date: Thu, 26 May 2022 09:16:02 +0200 Subject: [PATCH] Removed old vue project, improved live connection infrastructure. --- component-drivers.md | 111 + railsignal-app/.env.development | 2 - railsignal-app/.env.production | 2 - railsignal-app/.eslintrc.cjs | 11 - railsignal-app/.gitignore | 28 - railsignal-app/README.md | 35 - railsignal-app/deploy_to_spring.d | 15 - railsignal-app/index.html | 13 - railsignal-app/package-lock.json | 3226 ----------------- railsignal-app/package.json | 25 - .../public/android-chrome-192x192.png | Bin 9827 -> 0 bytes .../public/android-chrome-512x512.png | Bin 36805 -> 0 bytes railsignal-app/public/apple-touch-icon.png | Bin 8729 -> 0 bytes railsignal-app/public/favicon-16x16.png | Bin 422 -> 0 bytes railsignal-app/public/favicon-32x32.png | Bin 840 -> 0 bytes railsignal-app/public/favicon.ico | Bin 15406 -> 0 bytes railsignal-app/public/site.webmanifest | 1 - railsignal-app/src/App.vue | 30 - railsignal-app/src/api/components.js | 101 - railsignal-app/src/api/constants.js | 2 - railsignal-app/src/api/linkTokens.js | 57 - railsignal-app/src/api/paths.js | 64 - railsignal-app/src/api/railSystems.js | 53 - railsignal-app/src/api/segments.js | 50 - railsignal-app/src/api/websocket.js | 39 - railsignal-app/src/assets/icon.png | Bin 6886 -> 0 bytes railsignal-app/src/assets/icon.svg | 90 - railsignal-app/src/components/AppNavbar.vue | 87 - .../src/components/ConfirmModal.vue | 77 - railsignal-app/src/components/RailSystem.vue | 36 - .../railsystem/AddRailSystemModal.vue | 78 - .../components/railsystem/AddSegmentModal.vue | 87 - .../railsystem/CreateLinkTokenModal.vue | 115 - .../src/components/railsystem/MapView.vue | 47 - .../railsystem/RailSystemPropertiesView.vue | 112 - .../components/railsystem/SegmentsView.vue | 52 - .../src/components/railsystem/canvasUtils.js | 16 - .../component/AddSegmentBoundaryModal.vue | 113 - .../railsystem/component/AddSignalModal.vue | 99 - .../railsystem/component/AddSwitchModal.vue | 123 - .../railsystem/component/ComponentView.vue | 88 - .../component/PathNodeComponentView.vue | 84 - .../SegmentBoundaryNodeComponentView.vue | 28 - .../component/SignalComponentView.vue | 27 - .../component/SwitchComponentView.vue | 44 - .../src/components/railsystem/drawing.js | 132 - .../src/components/railsystem/mapRenderer.js | 248 -- .../railsystem/util/ComponentSelector.vue | 106 - railsignal-app/src/main.js | 11 - railsignal-app/src/stores/railSystemsStore.js | 32 - railsignal-app/vite.config.js | 17 - .../railsignalapi/live/ComponentDownlink.java | 2 +- .../live/ComponentDownlinkService.java | 15 +- .../live/ComponentUplinkMessageHandler.java | 4 +- .../live/dto/ComponentDataMessage.java | 19 + ...linkMessage.java => ComponentMessage.java} | 24 +- .../railsignalapi/live/dto/ErrorMessage.java | 13 + .../dto/SegmentBoundaryUpdateMessage.java | 5 +- .../live/dto/SegmentStatusMessage.java | 28 +- .../live/dto/SwitchUpdateMessage.java | 14 +- .../live/tcp_socket/ConnectMessage.java | 5 + .../live/tcp_socket/TcpLinkManager.java | 16 +- .../live/websocket/AppUpdateService.java | 5 + .../websocket/ComponentWebsocketHandler.java | 17 +- .../railsignalapi/model/component/Switch.java | 10 - .../andrewl/railsignalapi/rest/WebConfig.java | 4 + .../railsignalapi/service/SegmentService.java | 6 +- .../railsignalapi/service/SwitchService.java | 17 +- src/main/resources/application.properties | 2 - src/main/resources/driver/utils.lua | 41 + 70 files changed, 315 insertions(+), 5746 deletions(-) create mode 100644 component-drivers.md delete mode 100644 railsignal-app/.env.development delete mode 100644 railsignal-app/.env.production delete mode 100644 railsignal-app/.eslintrc.cjs delete mode 100644 railsignal-app/.gitignore delete mode 100644 railsignal-app/README.md delete mode 100755 railsignal-app/deploy_to_spring.d delete mode 100644 railsignal-app/index.html delete mode 100644 railsignal-app/package-lock.json delete mode 100644 railsignal-app/package.json delete mode 100644 railsignal-app/public/android-chrome-192x192.png delete mode 100644 railsignal-app/public/android-chrome-512x512.png delete mode 100644 railsignal-app/public/apple-touch-icon.png delete mode 100644 railsignal-app/public/favicon-16x16.png delete mode 100644 railsignal-app/public/favicon-32x32.png delete mode 100644 railsignal-app/public/favicon.ico delete mode 100644 railsignal-app/public/site.webmanifest delete mode 100644 railsignal-app/src/App.vue delete mode 100644 railsignal-app/src/api/components.js delete mode 100644 railsignal-app/src/api/constants.js delete mode 100644 railsignal-app/src/api/linkTokens.js delete mode 100644 railsignal-app/src/api/paths.js delete mode 100644 railsignal-app/src/api/railSystems.js delete mode 100644 railsignal-app/src/api/segments.js delete mode 100644 railsignal-app/src/api/websocket.js delete mode 100644 railsignal-app/src/assets/icon.png delete mode 100644 railsignal-app/src/assets/icon.svg delete mode 100644 railsignal-app/src/components/AppNavbar.vue delete mode 100644 railsignal-app/src/components/ConfirmModal.vue delete mode 100644 railsignal-app/src/components/RailSystem.vue delete mode 100644 railsignal-app/src/components/railsystem/AddRailSystemModal.vue delete mode 100644 railsignal-app/src/components/railsystem/AddSegmentModal.vue delete mode 100644 railsignal-app/src/components/railsystem/CreateLinkTokenModal.vue delete mode 100644 railsignal-app/src/components/railsystem/MapView.vue delete mode 100644 railsignal-app/src/components/railsystem/RailSystemPropertiesView.vue delete mode 100644 railsignal-app/src/components/railsystem/SegmentsView.vue delete mode 100644 railsignal-app/src/components/railsystem/canvasUtils.js delete mode 100644 railsignal-app/src/components/railsystem/component/AddSegmentBoundaryModal.vue delete mode 100644 railsignal-app/src/components/railsystem/component/AddSignalModal.vue delete mode 100644 railsignal-app/src/components/railsystem/component/AddSwitchModal.vue delete mode 100644 railsignal-app/src/components/railsystem/component/ComponentView.vue delete mode 100644 railsignal-app/src/components/railsystem/component/PathNodeComponentView.vue delete mode 100644 railsignal-app/src/components/railsystem/component/SegmentBoundaryNodeComponentView.vue delete mode 100644 railsignal-app/src/components/railsystem/component/SignalComponentView.vue delete mode 100644 railsignal-app/src/components/railsystem/component/SwitchComponentView.vue delete mode 100644 railsignal-app/src/components/railsystem/drawing.js delete mode 100644 railsignal-app/src/components/railsystem/mapRenderer.js delete mode 100644 railsignal-app/src/components/railsystem/util/ComponentSelector.vue delete mode 100644 railsignal-app/src/main.js delete mode 100644 railsignal-app/src/stores/railSystemsStore.js delete mode 100644 railsignal-app/vite.config.js create mode 100644 src/main/java/nl/andrewl/railsignalapi/live/dto/ComponentDataMessage.java rename src/main/java/nl/andrewl/railsignalapi/live/dto/{ComponentUplinkMessage.java => ComponentMessage.java} (55%) create mode 100644 src/main/java/nl/andrewl/railsignalapi/live/dto/ErrorMessage.java create mode 100644 src/main/resources/driver/utils.lua diff --git a/component-drivers.md b/component-drivers.md new file mode 100644 index 0000000..bb5a29c --- /dev/null +++ b/component-drivers.md @@ -0,0 +1,111 @@ +# Component Drivers +This document describes the general methodology for writing component drivers that operate within your rail system to connect it to the online system's up- and down-link services. + +The following types of components are supported by Rail Signal: +- `SIGNAL` +- `SEGMENT_BOUNDARY` +- `SWITCH` + +The following information is generally required for any driver to be able to connect to the system and operate nominally: +- A valid link token +- The base URL of the system's API. Usually `http://localhost:8080` or whatever you've configured it to be. +- Live connection information. This differs depending on what type of communication your device supports. + - For devices with **websocket** support, you will need the base URL of the websocket. Usually `ws://localhost:8080` or whatever you've configured your server to use. + - For devices with **TCP socket** support, you will need the hostname and port of the system's server socket. By default, this is `localhost:8081`. + +A device is not limited to a single component, but will act as a relay for all components linked to the device's link token. Generally, there is no limit to the number of components that a single device can manage, but more components will lead to more load on the device. + +## Live Communication +The main purpose of component drivers is to relay real-time messages between actual component devices, and their representations in the online rail system. While multiple types of communication are available, in general, all messages are sent as JSON UTF-8 encoded strings. Devices must present their link token when they initiate the connection. + +If the link token is valid, the connection will be initiated, and the device will immediately receive a `COMPONENT_DATA` message for each component that the token is linked to. + +### Websocket +Websocket connections should be made to `{BASE_WS_URL}/api/ws/component?token={token}`, where `{BASE_WS_URL}` is the base websocket URL, such as `ws://localhost:8080`, and `{token}` is the device's link token. + +- If the link token is missing or improperly formatted, a 400 Bad Request response is given. +- If the link token is not correct or not active or otherwise set to reject connections, a 401 Unauthorized response is given. + +### TCP Socket +TCP socket connections should be made to the server's TCP socket address, which by default is `localhost:8081`. The device should immediately send 2 bytes indicating the length of its token string, followed by the token string's bytes. The client should expect to receive in response a *connect message*: +```json +{ + "valid": true, + "message": "Connection established." +} +``` + +- If the token is invalid, a `"valid": false` is returned and the server closes the socket. + +Note: All messages sent via TCP are sent as JSON messages with a 2-byte length header. + +## Components +Each device should be designed to handle multiple independent components concurrently. The device may receive messages at any time pertaining to any of the components, and the device may send messages at any time, pertaining to any of the components. Messages are only sent regarding a single component. + +Every component message should contain at least the following two properties: +```json +{ + "cId": 123, + "type": "COMPONENT_DATA", + ... +} +``` +`cId` is the id of the component that this message is about. `type` is the type of message. This defines what additional structure to expect. + +All components may receive `COMPONENT_DATA` messages. For example, the following could be a message regarding a signal: +```json +{ + "cId": 123, + "type": "COMPONENT_DATA", + "data": { + "id": 123, + "position": {"x": 0, "y": 0, "z": 0}, + "name": "my-component", + "type": "SIGNAL", + "online": true, + "segment": { + "id": 4, + "name": "my-segment", + "occupied": false + } + } +} +``` + +The following sections will provide more detail about the other types of messages that can be sent and received by the different components. + +### Signal +Signals display the status of a connected segment, and as such can only receive data. They will receive `SEGMENT_STATUS` messages: +```json +{ + "cId": 123, + "type": "SEGMENT_STATUS", + "sId": 4, + "occupied": true +} +``` +`sId` is the id of the segment that was updated. `occupied` contains the current status of the segment. + +### Segment Boundary +Segment boundaries send updates as trains pass them, in order to provide information to the system about the state of connected segments. +```json +{ + "cId": 123, + "type": "SEGMENT_BOUNDARY_UPDATE", + "toSegmentId": 3, + "eventType": "ENTERING" +} +``` +`toSegmentId` is the id of the segment a train is moving towards. `eventType` is the type of boundary event. This can either be `ENTERING` if a train has just begun entering the segment, or `ENTERED` if a train has just left the boundary and completely entered the segment. + +### Switch +Switches can send information about their status, if it's been updated, and they can also receive messages that direct them to change their status. + +```json +{ + "cId": 123, + "type": "SWITCH_UPDATE", + "activeConfigId": 497238 +} +``` +`activeConfigId` is the id of the switch configuration that's active. This message can be sent by either the system or the switch. diff --git a/railsignal-app/.env.development b/railsignal-app/.env.development deleted file mode 100644 index a90eb52..0000000 --- a/railsignal-app/.env.development +++ /dev/null @@ -1,2 +0,0 @@ -VITE_API_URL=http://localhost:8080/api -VITE_WS_URL=ws://localhost:8080/api/ws/app \ No newline at end of file diff --git a/railsignal-app/.env.production b/railsignal-app/.env.production deleted file mode 100644 index a90eb52..0000000 --- a/railsignal-app/.env.production +++ /dev/null @@ -1,2 +0,0 @@ -VITE_API_URL=http://localhost:8080/api -VITE_WS_URL=ws://localhost:8080/api/ws/app \ No newline at end of file diff --git a/railsignal-app/.eslintrc.cjs b/railsignal-app/.eslintrc.cjs deleted file mode 100644 index deed24f..0000000 --- a/railsignal-app/.eslintrc.cjs +++ /dev/null @@ -1,11 +0,0 @@ -/* eslint-env node */ -module.exports = { - "root": true, - "extends": [ - "plugin:vue/vue3-essential", - "eslint:recommended" - ], - "env": { - "vue/setup-compiler-macros": true - } -} diff --git a/railsignal-app/.gitignore b/railsignal-app/.gitignore deleted file mode 100644 index 38adffa..0000000 --- a/railsignal-app/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -.DS_Store -dist -dist-ssr -coverage -*.local - -/cypress/videos/ -/cypress/screenshots/ - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/railsignal-app/README.md b/railsignal-app/README.md deleted file mode 100644 index 6e6e3ef..0000000 --- a/railsignal-app/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# railsignal-app - -This template should help get you started developing with Vue 3 in Vite. - -## Recommended IDE Setup - -[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.vscode-typescript-vue-plugin). - -## Customize configuration - -See [Vite Configuration Reference](https://vitejs.dev/config/). - -## Project Setup - -```sh -npm install -``` - -### Compile and Hot-Reload for Development - -```sh -npm run dev -``` - -### Compile and Minify for Production - -```sh -npm run build -``` - -### Lint with [ESLint](https://eslint.org/) - -```sh -npm run lint -``` diff --git a/railsignal-app/deploy_to_spring.d b/railsignal-app/deploy_to_spring.d deleted file mode 100755 index bd136d8..0000000 --- a/railsignal-app/deploy_to_spring.d +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env dub -/+ dub.sdl: - dependency "dsh" version="~>1.6.1" -+/ -import dsh; - -const DEST = "../src/main/resources/static"; - -void main() { - print("Deploying Vue app to Spring's /static directory."); - runOrQuit("vite build --base=/app/"); - rmdirRecurse(DEST); - copyDir("./dist", DEST); -} - diff --git a/railsignal-app/index.html b/railsignal-app/index.html deleted file mode 100644 index ecca371..0000000 --- a/railsignal-app/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - Rail Signal - - -
- - - diff --git a/railsignal-app/package-lock.json b/railsignal-app/package-lock.json deleted file mode 100644 index 0b2610b..0000000 --- a/railsignal-app/package-lock.json +++ /dev/null @@ -1,3226 +0,0 @@ -{ - "name": "railsignal-app", - "version": "0.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "railsignal-app", - "version": "0.0.0", - "dependencies": { - "@popperjs/core": "^2.11.5", - "axios": "^0.27.2", - "bootstrap": "^5.1.3", - "pinia": "^2.0.14", - "three": "^0.140.0", - "vue": "^3.2.33", - "vue-router": "^4.0.14" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^2.3.2", - "eslint": "^8.5.0", - "eslint-plugin-vue": "^8.2.0", - "vite": "^2.9.8" - } - }, - "node_modules/@babel/parser": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", - "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz", - "integrity": "sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.1", - "globals": "^13.9.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@popperjs/core": { - "version": "2.11.5", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", - "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/@vitejs/plugin-vue": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.2.tgz", - "integrity": "sha512-umyypfSHS4kQLdYAnJHhaASq7FRzNCdvcRoQ3uYGNk1/M4a+hXUd7ysN7BLhCrWH6uBokyCkFeUAaFDzSaaSrQ==", - "dev": true, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "vite": "^2.5.10", - "vue": "^3.2.25" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.33.tgz", - "integrity": "sha512-AAmr52ji3Zhk7IKIuigX2osWWsb2nQE5xsdFYjdnmtQ4gymmqXbjLvkSE174+fF3A3kstYrTgGkqgOEbsdLDpw==", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.33", - "estree-walker": "^2.0.2", - "source-map": "^0.6.1" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.33.tgz", - "integrity": "sha512-GhiG1C8X98Xz9QUX/RlA6/kgPBWJkjq0Rq6//5XTAGSYrTMBgcLpP9+CnlUg1TFxnnCVughAG+KZl28XJqw8uQ==", - "dependencies": { - "@vue/compiler-core": "3.2.33", - "@vue/shared": "3.2.33" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.33.tgz", - "integrity": "sha512-H8D0WqagCr295pQjUYyO8P3IejM3vEzeCO1apzByAEaAR/WimhMYczHfZVvlCE/9yBaEu/eu9RdiWr0kF8b71Q==", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.33", - "@vue/compiler-dom": "3.2.33", - "@vue/compiler-ssr": "3.2.33", - "@vue/reactivity-transform": "3.2.33", - "@vue/shared": "3.2.33", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.33.tgz", - "integrity": "sha512-XQh1Xdk3VquDpXsnoCd7JnMoWec9CfAzQDQsaMcSU79OrrO2PNR0ErlIjm/mGq3GmBfkQjzZACV+7GhfRB8xMQ==", - "dependencies": { - "@vue/compiler-dom": "3.2.33", - "@vue/shared": "3.2.33" - } - }, - "node_modules/@vue/devtools-api": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz", - "integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==" - }, - "node_modules/@vue/reactivity": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.33.tgz", - "integrity": "sha512-62Sq0mp9/0bLmDuxuLD5CIaMG2susFAGARLuZ/5jkU1FCf9EDbwUuF+BO8Ub3Rbodx0ziIecM/NsmyjardBxfQ==", - "dependencies": { - "@vue/shared": "3.2.33" - } - }, - "node_modules/@vue/reactivity-transform": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.33.tgz", - "integrity": "sha512-4UL5KOIvSQb254aqenW4q34qMXbfZcmEsV/yVidLUgvwYQQ/D21bGX3DlgPUGI3c4C+iOnNmDCkIxkILoX/Pyw==", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.33", - "@vue/shared": "3.2.33", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" - } - }, - "node_modules/@vue/runtime-core": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.33.tgz", - "integrity": "sha512-N2D2vfaXsBPhzCV3JsXQa2NECjxP3eXgZlFqKh4tgakp3iX6LCGv76DLlc+IfFZq+TW10Y8QUfeihXOupJ1dGw==", - "dependencies": { - "@vue/reactivity": "3.2.33", - "@vue/shared": "3.2.33" - } - }, - "node_modules/@vue/runtime-dom": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.33.tgz", - "integrity": "sha512-LSrJ6W7CZTSUygX5s8aFkraDWlO6K4geOwA3quFF2O+hC3QuAMZt/0Xb7JKE3C4JD4pFwCSO7oCrZmZ0BIJUnw==", - "dependencies": { - "@vue/runtime-core": "3.2.33", - "@vue/shared": "3.2.33", - "csstype": "^2.6.8" - } - }, - "node_modules/@vue/server-renderer": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.33.tgz", - "integrity": "sha512-4jpJHRD4ORv8PlbYi+/MfP8ec1okz6rybe36MdpkDrGIdEItHEUyaHSKvz+ptNEyQpALmmVfRteHkU9F8vxOew==", - "dependencies": { - "@vue/compiler-ssr": "3.2.33", - "@vue/shared": "3.2.33" - }, - "peerDependencies": { - "vue": "3.2.33" - } - }, - "node_modules/@vue/shared": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.33.tgz", - "integrity": "sha512-UBc1Pg1T3yZ97vsA2ueER0F6GbJebLHYlEi4ou1H5YL4KWvMOOWwpYo9/QpWq93wxKG6Wo13IY74Hcn/f7c7Bg==" - }, - "node_modules/acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "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/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "node_modules/bootstrap": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz", - "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/bootstrap" - }, - "peerDependencies": { - "@popperjs/core": "^2.10.2" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "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/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "2.6.20", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", - "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/esbuild": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.38.tgz", - "integrity": "sha512-12fzJ0fsm7gVZX1YQ1InkOE5f9Tl7cgf6JPYXRJtPIoE0zkWAbHdPHVPPaLi9tYAcEBqheGzqLn/3RdTOyBfcA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "esbuild-android-64": "0.14.38", - "esbuild-android-arm64": "0.14.38", - "esbuild-darwin-64": "0.14.38", - "esbuild-darwin-arm64": "0.14.38", - "esbuild-freebsd-64": "0.14.38", - "esbuild-freebsd-arm64": "0.14.38", - "esbuild-linux-32": "0.14.38", - "esbuild-linux-64": "0.14.38", - "esbuild-linux-arm": "0.14.38", - "esbuild-linux-arm64": "0.14.38", - "esbuild-linux-mips64le": "0.14.38", - "esbuild-linux-ppc64le": "0.14.38", - "esbuild-linux-riscv64": "0.14.38", - "esbuild-linux-s390x": "0.14.38", - "esbuild-netbsd-64": "0.14.38", - "esbuild-openbsd-64": "0.14.38", - "esbuild-sunos-64": "0.14.38", - "esbuild-windows-32": "0.14.38", - "esbuild-windows-64": "0.14.38", - "esbuild-windows-arm64": "0.14.38" - } - }, - "node_modules/esbuild-android-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.38.tgz", - "integrity": "sha512-aRFxR3scRKkbmNuGAK+Gee3+yFxkTJO/cx83Dkyzo4CnQl/2zVSurtG6+G86EQIZ+w+VYngVyK7P3HyTBKu3nw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.38.tgz", - "integrity": "sha512-L2NgQRWuHFI89IIZIlpAcINy9FvBk6xFVZ7xGdOwIm8VyhX1vNCEqUJO3DPSSy945Gzdg98cxtNt8Grv1CsyhA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.38.tgz", - "integrity": "sha512-5JJvgXkX87Pd1Og0u/NJuO7TSqAikAcQQ74gyJ87bqWRVeouky84ICoV4sN6VV53aTW+NE87qLdGY4QA2S7KNA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.38.tgz", - "integrity": "sha512-eqF+OejMI3mC5Dlo9Kdq/Ilbki9sQBw3QlHW3wjLmsLh+quNfHmGMp3Ly1eWm981iGBMdbtSS9+LRvR2T8B3eQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.38.tgz", - "integrity": "sha512-epnPbhZUt93xV5cgeY36ZxPXDsQeO55DppzsIgWM8vgiG/Rz+qYDLmh5ts3e+Ln1wA9dQ+nZmVHw+RjaW3I5Ig==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.38.tgz", - "integrity": "sha512-/9icXUYJWherhk+y5fjPI5yNUdFPtXHQlwP7/K/zg8t8lQdHVj20SqU9/udQmeUo5pDFHMYzcEFfJqgOVeKNNQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.38.tgz", - "integrity": "sha512-QfgfeNHRFvr2XeHFzP8kOZVnal3QvST3A0cgq32ZrHjSMFTdgXhMhmWdKzRXP/PKcfv3e2OW9tT9PpcjNvaq6g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.38.tgz", - "integrity": "sha512-uuZHNmqcs+Bj1qiW9k/HZU3FtIHmYiuxZ/6Aa+/KHb/pFKr7R3aVqvxlAudYI9Fw3St0VCPfv7QBpUITSmBR1Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.38.tgz", - "integrity": "sha512-FiFvQe8J3VKTDXG01JbvoVRXQ0x6UZwyrU4IaLBZeq39Bsbatd94Fuc3F1RGqPF5RbIWW7RvkVQjn79ejzysnA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.38.tgz", - "integrity": "sha512-HlMGZTEsBrXrivr64eZ/EO0NQM8H8DuSENRok9d+Jtvq8hOLzrxfsAT9U94K3KOGk2XgCmkaI2KD8hX7F97lvA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.38.tgz", - "integrity": "sha512-qd1dLf2v7QBiI5wwfil9j0HG/5YMFBAmMVmdeokbNAMbcg49p25t6IlJFXAeLzogv1AvgaXRXvgFNhScYEUXGQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.38.tgz", - "integrity": "sha512-mnbEm7o69gTl60jSuK+nn+pRsRHGtDPfzhrqEUXyCl7CTOCLtWN2bhK8bgsdp6J/2NyS/wHBjs1x8aBWwP2X9Q==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.38.tgz", - "integrity": "sha512-+p6YKYbuV72uikChRk14FSyNJZ4WfYkffj6Af0/Tw63/6TJX6TnIKE+6D3xtEc7DeDth1fjUOEqm+ApKFXbbVQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.38.tgz", - "integrity": "sha512-0zUsiDkGJiMHxBQ7JDU8jbaanUY975CdOW1YDrurjrM0vWHfjv9tLQsW9GSyEb/heSK1L5gaweRjzfUVBFoybQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.38.tgz", - "integrity": "sha512-cljBAApVwkpnJZfnRVThpRBGzCi+a+V9Ofb1fVkKhtrPLDYlHLrSYGtmnoTVWDQdU516qYI8+wOgcGZ4XIZh0Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.38.tgz", - "integrity": "sha512-CDswYr2PWPGEPpLDUO50mL3WO/07EMjnZDNKpmaxUPsrW+kVM3LoAqr/CE8UbzugpEiflYqJsGPLirThRB18IQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.38.tgz", - "integrity": "sha512-2mfIoYW58gKcC3bck0j7lD3RZkqYA7MmujFYmSn9l6TiIcAMpuEvqksO+ntBgbLep/eyjpgdplF7b+4T9VJGOA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-32": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.38.tgz", - "integrity": "sha512-L2BmEeFZATAvU+FJzJiRLFUP+d9RHN+QXpgaOrs2klshoAm1AE6Us4X6fS9k33Uy5SzScn2TpcgecbqJza1Hjw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.38.tgz", - "integrity": "sha512-Khy4wVmebnzue8aeSXLC+6clo/hRYeNIm0DyikoEqX+3w3rcvrhzpoix0S+MF9vzh6JFskkIGD7Zx47ODJNyCw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.38.tgz", - "integrity": "sha512-k3FGCNmHBkqdJXuJszdWciAH77PukEyDsdIryEHn9cKLQFxzhT39dSumeTuggaQcXY57UlmLGIkklWZo2qzHpw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz", - "integrity": "sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^1.2.2", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "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.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-vue": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz", - "integrity": "sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==", - "dev": true, - "dependencies": { - "eslint-utils": "^3.0.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.0.1", - "postcss-selector-parser": "^6.0.9", - "semver": "^7.3.5", - "vue-eslint-parser": "^8.0.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/espree": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", - "dev": true, - "dependencies": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", - "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "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/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "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/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/pinia": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz", - "integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==", - "dependencies": { - "@vue/devtools-api": "^6.1.4", - "vue-demi": "*" - }, - "funding": { - "url": "https://github.com/sponsors/posva" - }, - "peerDependencies": { - "@vue/composition-api": "^1.4.0", - "typescript": ">=4.4.4", - "vue": "^2.6.14 || ^3.2.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/pinia/node_modules/vue-demi": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", - "integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } - } - }, - "node_modules/postcss": { - "version": "8.4.13", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", - "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.3", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.8.1", - "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", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "2.72.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.72.0.tgz", - "integrity": "sha512-KqtR2YcO35/KKijg4nx4STO3569aqCUeGRkKWnJ6r+AvBBrVY9L4pmf4NHVrQr4mTOq6msbohflxr2kpihhaOA==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/three": { - "version": "0.140.0", - "resolved": "https://registry.npmjs.org/three/-/three-0.140.0.tgz", - "integrity": "sha512-jcHjbnYspPLDdsDQChmzyAoZ5KhJbgFk6pNGlAIc9fQMvsfPGjF5H9glrngqvb2CR/qXcClMyp5PYdF996lldA==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/vite": { - "version": "2.9.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.8.tgz", - "integrity": "sha512-zsBGwn5UT3YS0NLSJ7hnR54+vUKfgzMUh/Z9CxF1YKEBVIe213+63jrFLmZphgGI5zXwQCSmqIdbPuE8NJywPw==", - "dev": true, - "dependencies": { - "esbuild": "^0.14.27", - "postcss": "^8.4.13", - "resolve": "^1.22.0", - "rollup": "^2.59.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": ">=12.2.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "less": "*", - "sass": "*", - "stylus": "*" - }, - "peerDependenciesMeta": { - "less": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - } - } - }, - "node_modules/vue": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.33.tgz", - "integrity": "sha512-si1ExAlDUrLSIg/V7D/GgA4twJwfsfgG+t9w10z38HhL/HA07132pUQ2KuwAo8qbCyMJ9e6OqrmWrOCr+jW7ZQ==", - "dependencies": { - "@vue/compiler-dom": "3.2.33", - "@vue/compiler-sfc": "3.2.33", - "@vue/runtime-dom": "3.2.33", - "@vue/server-renderer": "3.2.33", - "@vue/shared": "3.2.33" - } - }, - "node_modules/vue-eslint-parser": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz", - "integrity": "sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==", - "dev": true, - "dependencies": { - "debug": "^4.3.2", - "eslint-scope": "^7.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.0.0", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, - "node_modules/vue-router": { - "version": "4.0.15", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.15.tgz", - "integrity": "sha512-xa+pIN9ZqORdIW1MkN2+d9Ui2pCM1b/UMgwYUCZOiFYHAvz/slKKBDha8DLrh5aCG/RibtrpyhKjKOZ85tYyWg==", - "dependencies": { - "@vue/devtools-api": "^6.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/posva" - }, - "peerDependencies": { - "vue": "^3.2.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - }, - "dependencies": { - "@babel/parser": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", - "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==" - }, - "@eslint/eslintrc": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz", - "integrity": "sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.1", - "globals": "^13.9.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - } - }, - "@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@popperjs/core": { - "version": "2.11.5", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", - "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==" - }, - "@vitejs/plugin-vue": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.2.tgz", - "integrity": "sha512-umyypfSHS4kQLdYAnJHhaASq7FRzNCdvcRoQ3uYGNk1/M4a+hXUd7ysN7BLhCrWH6uBokyCkFeUAaFDzSaaSrQ==", - "dev": true, - "requires": {} - }, - "@vue/compiler-core": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.33.tgz", - "integrity": "sha512-AAmr52ji3Zhk7IKIuigX2osWWsb2nQE5xsdFYjdnmtQ4gymmqXbjLvkSE174+fF3A3kstYrTgGkqgOEbsdLDpw==", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.33", - "estree-walker": "^2.0.2", - "source-map": "^0.6.1" - } - }, - "@vue/compiler-dom": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.33.tgz", - "integrity": "sha512-GhiG1C8X98Xz9QUX/RlA6/kgPBWJkjq0Rq6//5XTAGSYrTMBgcLpP9+CnlUg1TFxnnCVughAG+KZl28XJqw8uQ==", - "requires": { - "@vue/compiler-core": "3.2.33", - "@vue/shared": "3.2.33" - } - }, - "@vue/compiler-sfc": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.33.tgz", - "integrity": "sha512-H8D0WqagCr295pQjUYyO8P3IejM3vEzeCO1apzByAEaAR/WimhMYczHfZVvlCE/9yBaEu/eu9RdiWr0kF8b71Q==", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.33", - "@vue/compiler-dom": "3.2.33", - "@vue/compiler-ssr": "3.2.33", - "@vue/reactivity-transform": "3.2.33", - "@vue/shared": "3.2.33", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" - } - }, - "@vue/compiler-ssr": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.33.tgz", - "integrity": "sha512-XQh1Xdk3VquDpXsnoCd7JnMoWec9CfAzQDQsaMcSU79OrrO2PNR0ErlIjm/mGq3GmBfkQjzZACV+7GhfRB8xMQ==", - "requires": { - "@vue/compiler-dom": "3.2.33", - "@vue/shared": "3.2.33" - } - }, - "@vue/devtools-api": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz", - "integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==" - }, - "@vue/reactivity": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.33.tgz", - "integrity": "sha512-62Sq0mp9/0bLmDuxuLD5CIaMG2susFAGARLuZ/5jkU1FCf9EDbwUuF+BO8Ub3Rbodx0ziIecM/NsmyjardBxfQ==", - "requires": { - "@vue/shared": "3.2.33" - } - }, - "@vue/reactivity-transform": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.33.tgz", - "integrity": "sha512-4UL5KOIvSQb254aqenW4q34qMXbfZcmEsV/yVidLUgvwYQQ/D21bGX3DlgPUGI3c4C+iOnNmDCkIxkILoX/Pyw==", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.33", - "@vue/shared": "3.2.33", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" - } - }, - "@vue/runtime-core": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.33.tgz", - "integrity": "sha512-N2D2vfaXsBPhzCV3JsXQa2NECjxP3eXgZlFqKh4tgakp3iX6LCGv76DLlc+IfFZq+TW10Y8QUfeihXOupJ1dGw==", - "requires": { - "@vue/reactivity": "3.2.33", - "@vue/shared": "3.2.33" - } - }, - "@vue/runtime-dom": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.33.tgz", - "integrity": "sha512-LSrJ6W7CZTSUygX5s8aFkraDWlO6K4geOwA3quFF2O+hC3QuAMZt/0Xb7JKE3C4JD4pFwCSO7oCrZmZ0BIJUnw==", - "requires": { - "@vue/runtime-core": "3.2.33", - "@vue/shared": "3.2.33", - "csstype": "^2.6.8" - } - }, - "@vue/server-renderer": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.33.tgz", - "integrity": "sha512-4jpJHRD4ORv8PlbYi+/MfP8ec1okz6rybe36MdpkDrGIdEItHEUyaHSKvz+ptNEyQpALmmVfRteHkU9F8vxOew==", - "requires": { - "@vue/compiler-ssr": "3.2.33", - "@vue/shared": "3.2.33" - } - }, - "@vue/shared": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.33.tgz", - "integrity": "sha512-UBc1Pg1T3yZ97vsA2ueER0F6GbJebLHYlEi4ou1H5YL4KWvMOOWwpYo9/QpWq93wxKG6Wo13IY74Hcn/f7c7Bg==" - }, - "acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "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" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "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" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "bootstrap": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz", - "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==", - "requires": {} - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "csstype": { - "version": "2.6.20", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", - "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "esbuild": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.38.tgz", - "integrity": "sha512-12fzJ0fsm7gVZX1YQ1InkOE5f9Tl7cgf6JPYXRJtPIoE0zkWAbHdPHVPPaLi9tYAcEBqheGzqLn/3RdTOyBfcA==", - "dev": true, - "requires": { - "esbuild-android-64": "0.14.38", - "esbuild-android-arm64": "0.14.38", - "esbuild-darwin-64": "0.14.38", - "esbuild-darwin-arm64": "0.14.38", - "esbuild-freebsd-64": "0.14.38", - "esbuild-freebsd-arm64": "0.14.38", - "esbuild-linux-32": "0.14.38", - "esbuild-linux-64": "0.14.38", - "esbuild-linux-arm": "0.14.38", - "esbuild-linux-arm64": "0.14.38", - "esbuild-linux-mips64le": "0.14.38", - "esbuild-linux-ppc64le": "0.14.38", - "esbuild-linux-riscv64": "0.14.38", - "esbuild-linux-s390x": "0.14.38", - "esbuild-netbsd-64": "0.14.38", - "esbuild-openbsd-64": "0.14.38", - "esbuild-sunos-64": "0.14.38", - "esbuild-windows-32": "0.14.38", - "esbuild-windows-64": "0.14.38", - "esbuild-windows-arm64": "0.14.38" - } - }, - "esbuild-android-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.38.tgz", - "integrity": "sha512-aRFxR3scRKkbmNuGAK+Gee3+yFxkTJO/cx83Dkyzo4CnQl/2zVSurtG6+G86EQIZ+w+VYngVyK7P3HyTBKu3nw==", - "dev": true, - "optional": true - }, - "esbuild-android-arm64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.38.tgz", - "integrity": "sha512-L2NgQRWuHFI89IIZIlpAcINy9FvBk6xFVZ7xGdOwIm8VyhX1vNCEqUJO3DPSSy945Gzdg98cxtNt8Grv1CsyhA==", - "dev": true, - "optional": true - }, - "esbuild-darwin-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.38.tgz", - "integrity": "sha512-5JJvgXkX87Pd1Og0u/NJuO7TSqAikAcQQ74gyJ87bqWRVeouky84ICoV4sN6VV53aTW+NE87qLdGY4QA2S7KNA==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.38.tgz", - "integrity": "sha512-eqF+OejMI3mC5Dlo9Kdq/Ilbki9sQBw3QlHW3wjLmsLh+quNfHmGMp3Ly1eWm981iGBMdbtSS9+LRvR2T8B3eQ==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.38.tgz", - "integrity": "sha512-epnPbhZUt93xV5cgeY36ZxPXDsQeO55DppzsIgWM8vgiG/Rz+qYDLmh5ts3e+Ln1wA9dQ+nZmVHw+RjaW3I5Ig==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.38.tgz", - "integrity": "sha512-/9icXUYJWherhk+y5fjPI5yNUdFPtXHQlwP7/K/zg8t8lQdHVj20SqU9/udQmeUo5pDFHMYzcEFfJqgOVeKNNQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.38.tgz", - "integrity": "sha512-QfgfeNHRFvr2XeHFzP8kOZVnal3QvST3A0cgq32ZrHjSMFTdgXhMhmWdKzRXP/PKcfv3e2OW9tT9PpcjNvaq6g==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.38.tgz", - "integrity": "sha512-uuZHNmqcs+Bj1qiW9k/HZU3FtIHmYiuxZ/6Aa+/KHb/pFKr7R3aVqvxlAudYI9Fw3St0VCPfv7QBpUITSmBR1Q==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.38.tgz", - "integrity": "sha512-FiFvQe8J3VKTDXG01JbvoVRXQ0x6UZwyrU4IaLBZeq39Bsbatd94Fuc3F1RGqPF5RbIWW7RvkVQjn79ejzysnA==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.38.tgz", - "integrity": "sha512-HlMGZTEsBrXrivr64eZ/EO0NQM8H8DuSENRok9d+Jtvq8hOLzrxfsAT9U94K3KOGk2XgCmkaI2KD8hX7F97lvA==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.38.tgz", - "integrity": "sha512-qd1dLf2v7QBiI5wwfil9j0HG/5YMFBAmMVmdeokbNAMbcg49p25t6IlJFXAeLzogv1AvgaXRXvgFNhScYEUXGQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.38.tgz", - "integrity": "sha512-mnbEm7o69gTl60jSuK+nn+pRsRHGtDPfzhrqEUXyCl7CTOCLtWN2bhK8bgsdp6J/2NyS/wHBjs1x8aBWwP2X9Q==", - "dev": true, - "optional": true - }, - "esbuild-linux-riscv64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.38.tgz", - "integrity": "sha512-+p6YKYbuV72uikChRk14FSyNJZ4WfYkffj6Af0/Tw63/6TJX6TnIKE+6D3xtEc7DeDth1fjUOEqm+ApKFXbbVQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-s390x": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.38.tgz", - "integrity": "sha512-0zUsiDkGJiMHxBQ7JDU8jbaanUY975CdOW1YDrurjrM0vWHfjv9tLQsW9GSyEb/heSK1L5gaweRjzfUVBFoybQ==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.38.tgz", - "integrity": "sha512-cljBAApVwkpnJZfnRVThpRBGzCi+a+V9Ofb1fVkKhtrPLDYlHLrSYGtmnoTVWDQdU516qYI8+wOgcGZ4XIZh0Q==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.38.tgz", - "integrity": "sha512-CDswYr2PWPGEPpLDUO50mL3WO/07EMjnZDNKpmaxUPsrW+kVM3LoAqr/CE8UbzugpEiflYqJsGPLirThRB18IQ==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.38.tgz", - "integrity": "sha512-2mfIoYW58gKcC3bck0j7lD3RZkqYA7MmujFYmSn9l6TiIcAMpuEvqksO+ntBgbLep/eyjpgdplF7b+4T9VJGOA==", - "dev": true, - "optional": true - }, - "esbuild-windows-32": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.38.tgz", - "integrity": "sha512-L2BmEeFZATAvU+FJzJiRLFUP+d9RHN+QXpgaOrs2klshoAm1AE6Us4X6fS9k33Uy5SzScn2TpcgecbqJza1Hjw==", - "dev": true, - "optional": true - }, - "esbuild-windows-64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.38.tgz", - "integrity": "sha512-Khy4wVmebnzue8aeSXLC+6clo/hRYeNIm0DyikoEqX+3w3rcvrhzpoix0S+MF9vzh6JFskkIGD7Zx47ODJNyCw==", - "dev": true, - "optional": true - }, - "esbuild-windows-arm64": { - "version": "0.14.38", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.38.tgz", - "integrity": "sha512-k3FGCNmHBkqdJXuJszdWciAH77PukEyDsdIryEHn9cKLQFxzhT39dSumeTuggaQcXY57UlmLGIkklWZo2qzHpw==", - "dev": true, - "optional": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz", - "integrity": "sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.2.2", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "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.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - } - }, - "eslint-plugin-vue": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz", - "integrity": "sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==", - "dev": true, - "requires": { - "eslint-utils": "^3.0.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.0.1", - "postcss-selector-parser": "^6.0.9", - "semver": "^7.3.5", - "vue-eslint-parser": "^8.0.1" - } - }, - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "espree": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", - "dev": true, - "requires": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.3.0" - } - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", - "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==" - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "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" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "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 - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "requires": { - "sourcemap-codec": "^1.4.8" - } - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "pinia": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz", - "integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==", - "requires": { - "@vue/devtools-api": "^6.1.4", - "vue-demi": "*" - }, - "dependencies": { - "vue-demi": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", - "integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", - "requires": {} - } - } - }, - "postcss": { - "version": "8.4.13", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", - "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", - "requires": { - "nanoid": "^3.3.3", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "requires": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rollup": { - "version": "2.72.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.72.0.tgz", - "integrity": "sha512-KqtR2YcO35/KKijg4nx4STO3569aqCUeGRkKWnJ6r+AvBBrVY9L4pmf4NHVrQr4mTOq6msbohflxr2kpihhaOA==", - "dev": true, - "requires": { - "fsevents": "~2.3.2" - } - }, - "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "three": { - "version": "0.140.0", - "resolved": "https://registry.npmjs.org/three/-/three-0.140.0.tgz", - "integrity": "sha512-jcHjbnYspPLDdsDQChmzyAoZ5KhJbgFk6pNGlAIc9fQMvsfPGjF5H9glrngqvb2CR/qXcClMyp5PYdF996lldA==" - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "vite": { - "version": "2.9.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.8.tgz", - "integrity": "sha512-zsBGwn5UT3YS0NLSJ7hnR54+vUKfgzMUh/Z9CxF1YKEBVIe213+63jrFLmZphgGI5zXwQCSmqIdbPuE8NJywPw==", - "dev": true, - "requires": { - "esbuild": "^0.14.27", - "fsevents": "~2.3.2", - "postcss": "^8.4.13", - "resolve": "^1.22.0", - "rollup": "^2.59.0" - } - }, - "vue": { - "version": "3.2.33", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.33.tgz", - "integrity": "sha512-si1ExAlDUrLSIg/V7D/GgA4twJwfsfgG+t9w10z38HhL/HA07132pUQ2KuwAo8qbCyMJ9e6OqrmWrOCr+jW7ZQ==", - "requires": { - "@vue/compiler-dom": "3.2.33", - "@vue/compiler-sfc": "3.2.33", - "@vue/runtime-dom": "3.2.33", - "@vue/server-renderer": "3.2.33", - "@vue/shared": "3.2.33" - } - }, - "vue-eslint-parser": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz", - "integrity": "sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==", - "dev": true, - "requires": { - "debug": "^4.3.2", - "eslint-scope": "^7.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.0.0", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.5" - } - }, - "vue-router": { - "version": "4.0.15", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.15.tgz", - "integrity": "sha512-xa+pIN9ZqORdIW1MkN2+d9Ui2pCM1b/UMgwYUCZOiFYHAvz/slKKBDha8DLrh5aCG/RibtrpyhKjKOZ85tYyWg==", - "requires": { - "@vue/devtools-api": "^6.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } -} diff --git a/railsignal-app/package.json b/railsignal-app/package.json deleted file mode 100644 index 65879a2..0000000 --- a/railsignal-app/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "railsignal-app", - "version": "0.0.0", - "scripts": { - "dev": "vite", - "build": "vite build --base=/app/ --mode=development", - "preview": "vite preview --port 5050", - "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore" - }, - "dependencies": { - "@popperjs/core": "^2.11.5", - "axios": "^0.27.2", - "bootstrap": "^5.1.3", - "pinia": "^2.0.14", - "three": "^0.140.0", - "vue": "^3.2.33", - "vue-router": "^4.0.14" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^2.3.2", - "eslint": "^8.5.0", - "eslint-plugin-vue": "^8.2.0", - "vite": "^2.9.8" - } -} diff --git a/railsignal-app/public/android-chrome-192x192.png b/railsignal-app/public/android-chrome-192x192.png deleted file mode 100644 index 8805d9ec016b9eb28735d83967681708437bfa86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9827 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 Ku}0o1`2PTPQ?Pgd diff --git a/railsignal-app/public/android-chrome-512x512.png b/railsignal-app/public/android-chrome-512x512.png deleted file mode 100644 index cdaaf8f6a3b6fed42ae49653d20410001dbce1aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36805 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 C-l8S| diff --git a/railsignal-app/public/favicon-16x16.png b/railsignal-app/public/favicon-16x16.png deleted file mode 100644 index 04cca1208cfe387b9a5b0fb65da90fac0407379d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 422 zcmV;X0a^ZuP)YEW77*46BHC=*tTuk5lc%;Tety0+qJ{O!Y;2~y&7&Hg9}hP4T%2(@oXU8gD^KV zH1z+fRjYJ?uDA-;05rhfz`)?Z#fujqs?>mZJrJ`%HT?n7fk1oN22V0AkMq;u#1R5%vO1EfbXS z57j$F8-PPU5rGJ_FrSx!A%`Dg^VE+F3==++-~~%|28Oj_z*GiJ75{;O82pNX;rLG? z12Kt*fuU6h)!)_c7#QY#A<_U%U;^4D2~0;&7yJRb!1Xx;!wpb^!jX_LlClRUFbw#h zVepB8Vf%N4i!hQhNQ$D&1Tp}Wop0Q@F=_q!^}e{Wvw(oW*MNY4Ey&p!0J>V^5##%> Q(EtDd07*qoM6N<$f^U8C=|N8t69lOTYXt?hm6n9qM&o}INcVn|29C+;RyxI4DJM-So8x?U{tyb%Y zY8cl`l}e?*TrTh8jTP$G>2&KFjpl<&rFsN?6xa7c<5WVOaC)^`ttR5}cyBBgqhhg0 zc<#hMsnu#S8ja-h`N-?_uHxAPhzIRPwgAAnrBo{A>~?!kE|=@bDQ~dNW}|F2yQbIc zF9PCO^SBlOINu57Yp2sWkjZ4a;=Ex5HYt@#y}|QIK>Tdra7y`nzGgC+&f$KJ2jCBf!_iPE#J6;Yg%pHAG`D3u_#rR&ufjG3 z0)b%wO!5Fi9*<`{nM?{>IfCwokY0|HRrFthd=%EZ-EK-G5~BdP#RC|{T8(knpH0jS z{ugd&?n1)CV;l|#rPJv#0F3_~0L$oO5&-kiUseiW8itQb04zdpRSMuX44;<(cnbZH zQUDehz5@~bf1;nIqz^Ky6ace30&xgHFz4*wHNl^u?FV7QHcK^6Q$W7MeFDN#RHSte zpy5PUzbQ+^MP1!}0C|2lNBw^Q`g%5$ME0%bN$T1RT*KNA^${Jf*GTj0$j%j_`-lZG zmaYJV_Yirp8DV#AX>9k7V>1eVS1=8&8l?KctoDY4B zWpI8~2;k*mB7;P2ynuK({YfE!nL|V;dc>3e?HZBgvqAt92tYTYU#umO4I`XDl#>Ob zC7A&=^ApTMAFG`O+6ro2E53elv*v9bB&Q_vM1*X+L S-dJ4#0000N7-_x8ze1f)FvwZz|LNrehVj5(i0u66F z3co+M+dZMPv-9(9+qPZbuwjE73GD0W==g%N!;LjJH=lAkof7SSK^e;G^`(^4i;Iih zLv#}#mm;Iii^OF^Y*Lmwnhn&8X3m^>SH}L36qEjzBIjQ(Shr6b?58Ys4E4vpcvn}m z!8TuPruy-P@ZWvc2J387)u-IJSEb1A@?u=Ype}8g`uF(}!UjEJ=rvK+w?U5xM86z* z=Y3#ZXT#M0BapucT=Ic+w)t$B>OZg3)oid$RX-21?K&H*v&~rl-toH#^0mO10PDK= zhmT+MiD2#@>hqrDy=ij)_8Q&4v=PXU&zW3c0l?>z)gSJ|9AM|2J9oNzdwct@UcD-< zfI5i1i#7mD1R%evzrVj{|Ni}Q&YU?iE-p^S#Kc$vb!N|=EopleX!@hy(iOx3#sonQJ3Eo_1R* zo`Ww-k#^7v)@^Bib!d~e>BEozimh9>`n4nC=Sz`w;qEhBdkm&0&x_cy-XFT=(zAXl?HS`N(s*GaHMD_#Hs zSto(o;17AW15>Q+jV%*6 zHZU;I*U-@5E-WmR4u?b9?e>sA$7nMpB}En#6iE7_Pxx*mhd^RL{7KL~i1Bgz(4j*z zH5F?sexBo@?BkmMzJ2@TjT<)x$N^kZti}MHXD}{%_UzdslatlIg+diaQc{wvs;c6> z!8N|sR`?_4M4$`f(Vdx@8L_+%k3B6d%`=w3<#%#YjREnlz_oLim6dtk@5Al-{hQyd z_Nh`Nu9V_|*MT=sUxBuKeAAA#oQt(<*K&=M>wCo(`0wfN?v{CZc^3TP8$a%0tV8UO zV&ZwM0sP}#kKmdF>zO}E;rs|P+;_TnkHsh_`T6;>tE-FabDyg4N1QguHng;~SbNTJ z56pEMT(20fB{2@lj44pg3!h7kjg91gj@-;*fJ`iK=E#vF%07fG9lTD0H*&45`xusx zaea?gsCp?<6-B{*1Mzrbf|ztQ0Bld&i0)XWzc0*3U8J{1En`tME)daNq#> zUkVF<`xNA}St0MkV#xd%_w<8G{JB>WHvS3NH_qy?&OiGy)-=`jV#3Nl={bB`f{Qjb zRLkr?u|@@5h4B+!{!fGdZvpWC1N@;IZT@5C;n|L{teSUCE~^vIQRqgSe~d$l^rP1K zXEfk_4Bcq+r~iay{@+_#&b5;7xWwg3+!j8M?ZdK@; zfxJUTA?JFT$nn>&wSlKC!#B^d&N=%0^|1t3k52xB<2;)G8q4>YK4+n`~=D!>qS_9zU2AwDG1O6+)f#;r8^RCJL0v+l`JO7V?!`T4%GiK^W zn}04i91np1N$5zqNsXeQRs0XMbJQhnNCBM*)BDF}}AbGXqfM&OLtac`~Pf>H0bB@~ndO z{fiiInhv}NaBPz+b4{>*3gEns+$pQbpL-})_Ah+=pTNGOd)>Nq*7uL%!OaCM1YYui z^-O?$io7+s^73+d{rYw8AFU)el^*mhM$+7GcK0>0Co}SLJ11j!LKzaX; zF(QUl+`HVpd-wgYe_EoFcfAbb1@`i6LTzoW96x@1NOH>5n1TDI+%tl2?qBZ(#_74K z)^QD7KrPNA+-PcQaxY%ISY~8o$oTkp>-U8p-aLavn;b7iMMaXnaDLz>cpoDNRlXz1 zL7(S0DiK4w{`>~dT!iZUMrCE?knd#YI|R|8+6e&sfPI6}k!;RzbF ZMVmk!?3em{neH`e{6@>s3 - - - - - - - diff --git a/railsignal-app/src/api/components.js b/railsignal-app/src/api/components.js deleted file mode 100644 index 57268cb..0000000 --- a/railsignal-app/src/api/components.js +++ /dev/null @@ -1,101 +0,0 @@ -import axios from "axios"; -import {API_URL} from "./constants"; - -export function refreshComponents(rs) { - return new Promise((resolve, reject) => { - axios.get(`${API_URL}/rs/${rs.id}/c`) - .then(response => { - const previousSelectedComponentId = rs.selectedComponent ? rs.selectedComponent.id : null; - rs.components = response.data; - if (previousSelectedComponentId !== null) { - const previousComponent = rs.components.find(c => c.id === previousSelectedComponentId); - if (previousComponent) { - rs.selectedComponent = previousComponent; - } else { - rs.selectedComponent = null; - } - } else { - rs.selectedComponent = null; - } - resolve(); - }) - .catch(reject); - }); -} - -export function refreshSomeComponents(rs, components) { - const promises = []; - for (let i = 0; i < components.length; i++) { - const promise = new Promise((resolve, reject) => { - axios.get(`${API_URL}/rs/${rs.id}/c/${components[i].id}`) - .then(resp => { - const idx = rs.components.findIndex(c => c.id === resp.data.id); - if (idx > -1) rs.components[idx] = resp.data; - resolve(); - }) - .catch(reject); - }); - promises.push(promise); - } - return Promise.all(promises); -} - -export function getComponent(rs, id) { - return new Promise((resolve, reject) => { - axios.get(`${this.apiUrl}/rs/${rs.id}/c/${id}`) - .then(response => resolve(response.data)) - .catch(reject); - }); -} - -/** - * Searches through the rail system's components. - * @param {RailSystem} rs - * @param {string|null} searchQuery - * @return {Promise} - */ -export function searchComponents(rs, searchQuery) { - return new Promise((resolve, reject) => { - const params = { - page: 0, - size: 25 - }; - if (searchQuery) params.q = searchQuery; - axios.get(`${API_URL}/rs/${rs.id}/c/search`, {params: params}) - .then(response => { - resolve(response.data); - }) - .catch(reject); - }); -} - -export function createComponent(rs, data) { - return new Promise((resolve, reject) => { - axios.post(`${API_URL}/rs/${rs.id}/c`, data) - .then(response => { - const newComponentId = response.data.id; - refreshComponents(rs) - .then(() => { - const newComponent = rs.components.find(c => c.id === newComponentId); - if (newComponent) { - rs.selectedComponent = newComponent; - } - resolve(); - }) - .catch(reject); - }) - .catch(reject); - }); -} - -export function removeComponent(rs, id) { - return new Promise((resolve, reject) => { - axios.delete(`${API_URL}/rs/${rs.id}/c/${id}`) - .then(() => { - refreshComponents(rs) - .then(resolve) - .catch(reject); - }) - .catch(reject); - }); -} diff --git a/railsignal-app/src/api/constants.js b/railsignal-app/src/api/constants.js deleted file mode 100644 index 51239b5..0000000 --- a/railsignal-app/src/api/constants.js +++ /dev/null @@ -1,2 +0,0 @@ -export const API_URL = import.meta.env.VITE_API_URL; -export const WS_URL = import.meta.env.VITE_WS_URL; \ No newline at end of file diff --git a/railsignal-app/src/api/linkTokens.js b/railsignal-app/src/api/linkTokens.js deleted file mode 100644 index 38e601c..0000000 --- a/railsignal-app/src/api/linkTokens.js +++ /dev/null @@ -1,57 +0,0 @@ -import {API_URL} from "./constants"; -import axios from "axios"; - -/** - * A token that's used by components to provide real-time up and down links. - */ -export class LinkToken { - constructor(data) { - this.id = data.id; - this.label = data.label; - this.components = data.components; - } -} - -/** - * Gets the list of link tokens in a rail system. - * @param {RailSystem} rs - * @return {Promise} - */ -export function getTokens(rs) { - return new Promise((resolve, reject) => { - axios.get(`${API_URL}/rs/${rs.id}/lt`) - .then(response => { - resolve(response.data.map(obj => new LinkToken(obj))); - }) - .catch(reject); - }); -} - -/** - * Creates a new link token. - * @param {RailSystem} rs - * @param {LinkToken} data - * @return {Promise} A promise that resolves to the token that was created. - */ -export function createLinkToken(rs, data) { - return new Promise((resolve, reject) => { - axios.post(`${API_URL}/rs/${rs.id}/lt`, data) - .then(response => { - resolve(response.data.token); - }) - .catch(reject); - }); -} - -/** - * Deletes a link token. - * @param {RailSystem} rs - * @param {Number} tokenId - */ -export function deleteToken(rs, tokenId) { - return new Promise((resolve, reject) => { - axios.delete(`${API_URL}/rs/${rs.id}/lt/${tokenId}`) - .then(resolve) - .catch(reject); - }); -} \ No newline at end of file diff --git a/railsignal-app/src/api/paths.js b/railsignal-app/src/api/paths.js deleted file mode 100644 index 0e2db39..0000000 --- a/railsignal-app/src/api/paths.js +++ /dev/null @@ -1,64 +0,0 @@ -import axios from "axios"; -import {API_URL} from "./constants"; -import {refreshSomeComponents} from "./components"; - -/** - * Updates the connections to a path node. - * @param {RailSystem} rs The rail system to which the node belongs. - * @param {Object} node The node to update. - * @returns {Promise} - */ -export function updateConnections(rs, node) { - return new Promise((resolve, reject) => { - axios.patch( - `${API_URL}/rs/${rs.id}/c/${node.id}/connectedNodes`, - node - ) - .then(response => { - node.connectedNodes = response.data.connectedNodes; - resolve(); - }) - .catch(reject); - }); -} - -/** - * Adds a connection to a path node. - * @param {RailSystem} rs - * @param {Object} node - * @param {Object} other - * @returns {Promise} - */ -export function addConnection(rs, node, other) { - node.connectedNodes.push(other); - return updateConnections(rs, node); -} - -/** - * Removes a connection from a path node. - * @param {RailSystem} rs - * @param {Object} node - * @param {Object} other - * @returns {Promise} - */ -export function removeConnection(rs, node, other) { - const idx = node.connectedNodes.findIndex(n => n.id === other.id); - return new Promise((resolve, reject) => { - if (idx > -1) { - node.connectedNodes.splice(idx, 1); - updateConnections(rs, node) - .then(() => { - const nodes = []; - nodes.push(...node.connectedNodes); - nodes.push(other); - refreshSomeComponents(rs, nodes) - .then(resolve) - .catch(reject); - }) - .catch(reject); - } else { - resolve(); - } - }); - -} \ No newline at end of file diff --git a/railsignal-app/src/api/railSystems.js b/railsignal-app/src/api/railSystems.js deleted file mode 100644 index c01c1d9..0000000 --- a/railsignal-app/src/api/railSystems.js +++ /dev/null @@ -1,53 +0,0 @@ -import axios from "axios"; -import {API_URL} from "./constants"; - -export class RailSystem { - constructor(data) { - this.id = data.id; - this.name = data.name; - this.segments = []; - this.components = []; - this.websocket = null; - this.selectedComponent = null; - } -} - -export function refreshRailSystems(rsStore) { - return new Promise(resolve => { - axios.get(`${API_URL}/rs`) - .then(response => { - const rsItems = response.data; - rsStore.railSystems.length = 0; - for (let i = 0; i < rsItems.length; i++) { - rsStore.railSystems.push(new RailSystem(rsItems[i])); - } - resolve(); - }) - .catch(error => console.error(error)); - }) -} - -export function createRailSystem(rsStore, name) { - return new Promise((resolve, reject) => { - axios.post(`${API_URL}/rs`, {name: name}) - .then(response => { - const newId = response.data.id; - refreshRailSystems(rsStore) - .then(() => resolve(rsStore.railSystems.find(rs => rs.id === newId))) - .catch(error => reject(error)); - }) - .catch(error => reject(error)); - }); -} - -export function removeRailSystem(rsStore, id) { - return new Promise((resolve, reject) => { - axios.delete(`${API_URL}/rs/${id}`) - .then(() => { - rsStore.selectedRailSystem = null; - refreshRailSystems(rsStore) - .then(() => resolve) - .catch(error => reject(error)); - }); - }); -} diff --git a/railsignal-app/src/api/segments.js b/railsignal-app/src/api/segments.js deleted file mode 100644 index c49e0ec..0000000 --- a/railsignal-app/src/api/segments.js +++ /dev/null @@ -1,50 +0,0 @@ -import axios from "axios"; -import {API_URL} from "./constants"; - -/** - * Fetches the set of segments for a rail system. - * @param {Number} rsId - * @returns {Promise<[Object]>} - */ -export function getSegments(rsId) { - return new Promise((resolve, reject) => { - axios.get(`${API_URL}/rs/${rsId}/s`) - .then(response => resolve(response.data)) - .catch(error => reject(error)); - }); -} - -export function refreshSegments(rs) { - return new Promise(resolve => { - getSegments(rs.id) - .then(segments => { - rs.segments = segments; - resolve(); - }) - .catch(error => console.error(error)); - }); -} - -export function createSegment(rs, name) { - return new Promise((resolve, reject) => { - axios.post(`${API_URL}/rs/${rs.id}/s`, {name: name}) - .then(() => { - refreshSegments(rs) - .then(() => resolve()) - .catch(error => reject(error)); - }) - .catch(error => reject(error)); - }); -} - -export function removeSegment(rs, segmentId) { - return new Promise((resolve, reject) => { - axios.delete(`${API_URL}/rs/${rs.id}/${segmentId}`) - .then(() => { - refreshSegments(rs) - .then(() => resolve()) - .catch(error => reject(error)); - }) - .catch(error => reject(error)); - }); -} diff --git a/railsignal-app/src/api/websocket.js b/railsignal-app/src/api/websocket.js deleted file mode 100644 index 741c548..0000000 --- a/railsignal-app/src/api/websocket.js +++ /dev/null @@ -1,39 +0,0 @@ -import {WS_URL} from "./constants"; - -/** - * Establishes a websocket connection to the given rail system. - * @param {RailSystem} rs - */ -export function establishWebsocketConnection(rs) { - closeWebsocketConnection(rs); - rs.websocket = new WebSocket(`${WS_URL}/${rs.id}`); - rs.websocket.onopen = () => { - console.log("Opened websocket connection to rail system " + rs.id); - }; - rs.websocket.onclose = event => { - if (event.code !== 1000) { - console.warn("Lost websocket connection. Attempting to reestablish."); - setTimeout(() => { - establishWebsocketConnection(rs); - }, 3000); - } - console.log("Closed websocket connection to rail system " + rs.id); - }; - rs.websocket.onmessage = msg => { - console.log(msg); - }; - rs.websocket.onerror = error => { - console.log(error); - }; -} - -/** - * Closes the websocket connection to a rail system, if possible. - * @param {RailSystem} rs - */ -export function closeWebsocketConnection(rs) { - if (rs.websocket) { - rs.websocket.close(); - rs.websocket = null; - } -} diff --git a/railsignal-app/src/assets/icon.png b/railsignal-app/src/assets/icon.png deleted file mode 100644 index 3c98a5e33a3b611876956838c9747a80e9b5042e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6886 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 Lp-#nB`>6i{E*B5| diff --git a/railsignal-app/src/assets/icon.svg b/railsignal-app/src/assets/icon.svg deleted file mode 100644 index 2684f47..0000000 --- a/railsignal-app/src/assets/icon.svg +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/railsignal-app/src/components/AppNavbar.vue b/railsignal-app/src/components/AppNavbar.vue deleted file mode 100644 index b946953..0000000 --- a/railsignal-app/src/components/AppNavbar.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/ConfirmModal.vue b/railsignal-app/src/components/ConfirmModal.vue deleted file mode 100644 index 9df94b8..0000000 --- a/railsignal-app/src/components/ConfirmModal.vue +++ /dev/null @@ -1,77 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/RailSystem.vue b/railsignal-app/src/components/RailSystem.vue deleted file mode 100644 index a7870e8..0000000 --- a/railsignal-app/src/components/RailSystem.vue +++ /dev/null @@ -1,36 +0,0 @@ - - - - - diff --git a/railsignal-app/src/components/railsystem/AddRailSystemModal.vue b/railsignal-app/src/components/railsystem/AddRailSystemModal.vue deleted file mode 100644 index 0289ace..0000000 --- a/railsignal-app/src/components/railsystem/AddRailSystemModal.vue +++ /dev/null @@ -1,78 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/AddSegmentModal.vue b/railsignal-app/src/components/railsystem/AddSegmentModal.vue deleted file mode 100644 index 7cc8aa3..0000000 --- a/railsignal-app/src/components/railsystem/AddSegmentModal.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/CreateLinkTokenModal.vue b/railsignal-app/src/components/railsystem/CreateLinkTokenModal.vue deleted file mode 100644 index 746380f..0000000 --- a/railsignal-app/src/components/railsystem/CreateLinkTokenModal.vue +++ /dev/null @@ -1,115 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/MapView.vue b/railsignal-app/src/components/railsystem/MapView.vue deleted file mode 100644 index 3ce9e1a..0000000 --- a/railsignal-app/src/components/railsystem/MapView.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/RailSystemPropertiesView.vue b/railsignal-app/src/components/railsystem/RailSystemPropertiesView.vue deleted file mode 100644 index a7e25e8..0000000 --- a/railsignal-app/src/components/railsystem/RailSystemPropertiesView.vue +++ /dev/null @@ -1,112 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/SegmentsView.vue b/railsignal-app/src/components/railsystem/SegmentsView.vue deleted file mode 100644 index 8b4fe0a..0000000 --- a/railsignal-app/src/components/railsystem/SegmentsView.vue +++ /dev/null @@ -1,52 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/canvasUtils.js b/railsignal-app/src/components/railsystem/canvasUtils.js deleted file mode 100644 index 726b394..0000000 --- a/railsignal-app/src/components/railsystem/canvasUtils.js +++ /dev/null @@ -1,16 +0,0 @@ -export function roundedRect(ctx, x, y, w, h, r) { - if (w < 2 * r) r = w / 2; - if (h < 2 * r) r = h / 2; - ctx.beginPath(); - ctx.moveTo(x+r, y); - ctx.arcTo(x+w, y, x+w, y+h, r); - ctx.arcTo(x+w, y+h, x, y+h, r); - ctx.arcTo(x, y+h, x, y, r); - ctx.arcTo(x, y, x+w, y, r); - ctx.closePath(); -} - -export function circle(ctx, x, y, r) { - ctx.beginPath(); - ctx.arc(x, y, r, 0, Math.PI * 2); -} \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/component/AddSegmentBoundaryModal.vue b/railsignal-app/src/components/railsystem/component/AddSegmentBoundaryModal.vue deleted file mode 100644 index 9ce6272..0000000 --- a/railsignal-app/src/components/railsystem/component/AddSegmentBoundaryModal.vue +++ /dev/null @@ -1,113 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/component/AddSignalModal.vue b/railsignal-app/src/components/railsystem/component/AddSignalModal.vue deleted file mode 100644 index 863eada..0000000 --- a/railsignal-app/src/components/railsystem/component/AddSignalModal.vue +++ /dev/null @@ -1,99 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/component/AddSwitchModal.vue b/railsignal-app/src/components/railsystem/component/AddSwitchModal.vue deleted file mode 100644 index 4c8ac54..0000000 --- a/railsignal-app/src/components/railsystem/component/AddSwitchModal.vue +++ /dev/null @@ -1,123 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/component/ComponentView.vue b/railsignal-app/src/components/railsystem/component/ComponentView.vue deleted file mode 100644 index fdfb31c..0000000 --- a/railsignal-app/src/components/railsystem/component/ComponentView.vue +++ /dev/null @@ -1,88 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/component/PathNodeComponentView.vue b/railsignal-app/src/components/railsystem/component/PathNodeComponentView.vue deleted file mode 100644 index 422547a..0000000 --- a/railsignal-app/src/components/railsystem/component/PathNodeComponentView.vue +++ /dev/null @@ -1,84 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/component/SegmentBoundaryNodeComponentView.vue b/railsignal-app/src/components/railsystem/component/SegmentBoundaryNodeComponentView.vue deleted file mode 100644 index 672e3e4..0000000 --- a/railsignal-app/src/components/railsystem/component/SegmentBoundaryNodeComponentView.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/component/SignalComponentView.vue b/railsignal-app/src/components/railsystem/component/SignalComponentView.vue deleted file mode 100644 index 5f7c9dc..0000000 --- a/railsignal-app/src/components/railsystem/component/SignalComponentView.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/component/SwitchComponentView.vue b/railsignal-app/src/components/railsystem/component/SwitchComponentView.vue deleted file mode 100644 index f6b4e68..0000000 --- a/railsignal-app/src/components/railsystem/component/SwitchComponentView.vue +++ /dev/null @@ -1,44 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/components/railsystem/drawing.js b/railsignal-app/src/components/railsystem/drawing.js deleted file mode 100644 index b32f834..0000000 --- a/railsignal-app/src/components/railsystem/drawing.js +++ /dev/null @@ -1,132 +0,0 @@ -/* -Helper functions to actually perform rendering of different components. -*/ - -import {getScaleFactor, isComponentHovered} from "./mapRenderer"; -import {roundedRect, circle} from "./canvasUtils"; - -export function drawComponent(ctx, worldTx, component) { - const tx = DOMMatrix.fromMatrix(worldTx); - tx.translateSelf(component.position.x, component.position.z, 0); - const s = getScaleFactor(); - tx.scaleSelf(1/s, 1/s, 1/s); - tx.scaleSelf(20, 20, 20); - ctx.setTransform(tx); - - if (component.type === "SIGNAL") { - drawSignal(ctx, component); - } else if (component.type === "SEGMENT_BOUNDARY") { - drawSegmentBoundary(ctx, component); - } else if (component.type === "SWITCH") { - drawSwitch(ctx, component); - } - - ctx.setTransform(tx.translate(0.75, -0.75)); - if (component.online !== undefined && component.online !== null) { - drawOnlineIndicator(ctx, component); - } - - ctx.setTransform(tx); - // Draw hovered status. - if (isComponentHovered(component)) { - ctx.fillStyle = `rgba(255, 255, 0, 0.5)`; - circle(ctx, 0, 0, 0.75); - ctx.fill(); - } -} - -function drawSignal(ctx) { - roundedRect(ctx, -0.3, -0.5, 0.6, 1, 0.25); - ctx.fillStyle = "black"; - ctx.fill(); - ctx.fillStyle = "rgb(0, 255, 0)"; - circle(ctx, 0, -0.2, 0.15); - ctx.fill(); -} - -function drawSegmentBoundary(ctx) { - ctx.fillStyle = `rgb(150, 58, 224)`; - ctx.beginPath(); - ctx.moveTo(0, -0.5); - ctx.lineTo(-0.5, 0); - ctx.lineTo(0, 0.5); - ctx.lineTo(0.5, 0); - ctx.lineTo(0, -0.5); - ctx.fill(); -} - -function drawSwitch(ctx, sw) { - const colors = [ - `rgba(61, 148, 66, 0.25)`, - `rgba(59, 22, 135, 0.25)`, - `rgba(145, 17, 90, 0.25)`, - `rgba(191, 49, 10, 0.25)` - ]; - ctx.lineWidth = 1; - for (let i = 0; i < sw.possibleConfigurations.length; i++) { - const config = sw.possibleConfigurations[i]; - ctx.strokeStyle = colors[i]; - for (let j = 0; j < config.nodes.length; j++) { - const node = config.nodes[j]; - const diff = { - x: sw.position.x - node.position.x, - y: sw.position.z - node.position.z, - }; - const mag = Math.sqrt(Math.pow(diff.x, 2) + Math.pow(diff.y, 2)); - diff.x = 2 * -diff.x / mag; - diff.y = 2 * -diff.y / mag; - ctx.beginPath(); - ctx.moveTo(0, 0); - ctx.lineTo(diff.x, diff.y); - ctx.stroke(); - } - } - ctx.fillStyle = `rgb(245, 188, 66)`; - ctx.strokeStyle = `rgb(245, 188, 66)`; - ctx.lineWidth = 0.2; - circle(ctx, 0, 0.3, 0.2); - ctx.fill(); - circle(ctx, -0.3, -0.3, 0.2); - ctx.fill(); - circle(ctx, 0.3, -0.3, 0.2); - ctx.fill(); - ctx.beginPath(); - ctx.moveTo(0, 0.3); - ctx.lineTo(0, 0); - ctx.lineTo(0.3, -0.3); - ctx.moveTo(0, 0); - ctx.lineTo(-0.3, -0.3); - ctx.stroke(); -} - -function drawOnlineIndicator(ctx, component) { - ctx.lineWidth = 0.1; - if (component.online) { - ctx.fillStyle = `rgba(52, 174, 235, 128)`; - ctx.strokeStyle = `rgba(52, 174, 235, 128)`; - } else { - ctx.fillStyle = `rgba(153, 153, 153, 128)`; - ctx.strokeStyle = `rgba(153, 153, 153, 128)`; - } - ctx.beginPath(); - ctx.arc(0, 0.2, 0.125, 0, Math.PI * 2); - ctx.fill(); - for (let r = 0; r < 3; r++) { - ctx.beginPath(); - ctx.arc(0, 0, 0.1 + 0.2 * r, 7 * Math.PI / 6, 11 * Math.PI / 6); - ctx.stroke(); - } -} - -export function drawConnectedNodes(ctx, worldTx, component) { - const s = getScaleFactor(); - ctx.lineWidth = 5 / s; - ctx.strokeStyle = "black"; - for (let i = 0; i < component.connectedNodes.length; i++) { - const node = component.connectedNodes[i]; - ctx.beginPath(); - ctx.moveTo(component.position.x, component.position.z); - ctx.lineTo(node.position.x, node.position.z); - ctx.stroke(); - } -} diff --git a/railsignal-app/src/components/railsystem/mapRenderer.js b/railsignal-app/src/components/railsystem/mapRenderer.js deleted file mode 100644 index c31c7dd..0000000 --- a/railsignal-app/src/components/railsystem/mapRenderer.js +++ /dev/null @@ -1,248 +0,0 @@ -/* -This component is responsible for the rendering of a RailSystem in a 2d map -view. - */ - -import {drawComponent, drawConnectedNodes} from "./drawing"; - -const SCALE_VALUES = [0.01, 0.1, 0.25, 0.5, 1.0, 1.25, 1.5, 2.0, 3.0, 4.0, 6.0, 8.0, 10.0, 12.0, 16.0, 20.0, 30.0, 45.0, 60.0, 80.0, 100.0]; -const SCALE_INDEX_NORMAL = 7; -const HOVER_RADIUS = 10; - -let mapContainerDiv = null; -let mapCanvas = null; -let railSystem = null; - -let mapScaleIndex = SCALE_INDEX_NORMAL; -let mapTranslation = {x: 0, y: 0}; -let mapDragOrigin = null; -let mapDragTranslation = null; -let lastMousePoint = new DOMPoint(0, 0, 0, 0); -const hoveredElements = []; - -export function initMap(rs) { - railSystem = rs; - console.log("Initializing map for rail system: " + rs.name); - hoveredElements.length = 0; - mapCanvas = document.getElementById("railSystemMapCanvas"); - mapContainerDiv = document.getElementById("railSystemMapCanvasContainer"); - mapCanvas.removeEventListener("wheel", onMouseWheel); - mapCanvas.addEventListener("wheel", onMouseWheel); - mapCanvas.removeEventListener("mousedown", onMouseDown); - mapCanvas.addEventListener("mousedown", onMouseDown); - mapCanvas.removeEventListener("mouseup", onMouseUp); - mapCanvas.addEventListener("mouseup", onMouseUp); - mapCanvas.removeEventListener("mousemove", onMouseMove); - mapCanvas.addEventListener("mousemove", onMouseMove); - - // Do an initial draw. - draw(); -} - -export function draw() { - if (!(mapCanvas && railSystem && railSystem.components)) { - console.warn("Attempted to draw map without canvas or railSystem."); - return; - } - const ctx = mapCanvas.getContext("2d"); - if (mapCanvas.width !== mapContainerDiv.clientWidth) { - mapCanvas.width = mapContainerDiv.clientWidth; - } - if (mapCanvas.height !== mapContainerDiv.clientHeight) { - mapCanvas.height = mapContainerDiv.clientHeight; - } - const width = mapCanvas.width; - const height = mapCanvas.height; - ctx.resetTransform(); - ctx.fillStyle = `rgb(240, 240, 240)`; - ctx.fillRect(0, 0, width, height); - const worldTx = getWorldTransform(); - ctx.setTransform(worldTx); - - // Draw segments! - const segmentPoints = new Map(); - railSystem.segments.forEach(segment => segmentPoints.set(segment.id, [])); - for (let i = 0; i < railSystem.components.length; i++) { - const c = railSystem.components[i]; - if (c.type === "SEGMENT_BOUNDARY") { - for (let j = 0; j < c.segments.length; j++) { - segmentPoints.get(c.segments[j].id).push({x: c.position.x, y: c.position.z}); - } - } - } - railSystem.segments.forEach(segment => { - const points = segmentPoints.get(segment.id); - const avgPoint = {x: 0, y: 0}; - points.forEach(point => { - avgPoint.x += point.x; - avgPoint.y += point.y; - }); - avgPoint.x /= points.length; - avgPoint.y /= points.length; - let r = 5; - points.forEach(point => { - const dist2 = Math.pow(avgPoint.x - point.x, 2) + Math.pow(avgPoint.y - point.y, 2); - if (dist2 > r * r) { - r = Math.sqrt(dist2); - } - }); - ctx.fillStyle = `rgba(200, 200, 200, 0.25)`; - const p = worldPointToMap(new DOMPoint(avgPoint.x, avgPoint.y, 0, 0)); - const s = getScaleFactor(); - ctx.beginPath(); - ctx.arc(p.x / s, p.y / s, r, 0, Math.PI * 2); - ctx.fill(); - ctx.fillStyle = "rgba(0, 0, 0, 0.5)"; - ctx.font = "3px Sans-Serif"; - ctx.fillText(`${segment.name}`, p.x / s, p.y / s); - }); - - for (let i = 0; i < railSystem.components.length; i++) { - const c = railSystem.components[i]; - if (c.connectedNodes !== undefined && c.connectedNodes !== null) { - drawConnectedNodes(ctx, worldTx, c); - } - } - - for (let i = 0; i < railSystem.components.length; i++) { - drawComponent(ctx, worldTx, railSystem.components[i]); - } - - // Draw debug info. - ctx.resetTransform(); - ctx.fillStyle = "black"; - ctx.strokeStyle = "black"; - ctx.font = "10px Sans-Serif"; - const lastWorldPoint = mapPointToWorld(lastMousePoint); - const lines = [ - "Scale factor: " + getScaleFactor(), - `(x = ${lastWorldPoint.x.toFixed(2)}, y = ${lastWorldPoint.y.toFixed(2)}, z = ${lastWorldPoint.z.toFixed(2)})`, - `Components: ${railSystem.components.length}`, - `Hovered elements: ${hoveredElements.length}` - ] - for (let i = 0; i < lines.length; i++) { - ctx.fillText(lines[i], 10, 20 + (i * 15)); - } -} - -export function getScaleFactor() { - return SCALE_VALUES[mapScaleIndex]; -} - -function getWorldTransform() { - const canvasRect = mapCanvas.getBoundingClientRect(); - const scale = getScaleFactor(); - const tx = new DOMMatrix(); - tx.translateSelf(canvasRect.width / 2, canvasRect.height / 2, 0); - tx.scaleSelf(scale, scale, scale); - tx.translateSelf(mapTranslation.x, mapTranslation.y, 0); - if (mapDragOrigin !== null && mapDragTranslation !== null) { - tx.translateSelf(mapDragTranslation.x, mapDragTranslation.y, 0); - } - return tx; -} - -export function isComponentHovered(component) { - for (let i = 0; i < hoveredElements.length; i++) { - if (hoveredElements[i].id === component.id) return true; - } - return false; -} - -/** - * Maps a point on the map coordinates to world coordinates. - * @param {DOMPoint} p - * @returns {DOMPoint} - */ -function mapPointToWorld(p) { - return getWorldTransform().invertSelf().transformPoint(p); -} - -/** - * Maps a point in the world to map coordinates. - * @param {DOMPoint} p - * @returns {DOMPoint} - */ -function worldPointToMap(p) { - return getWorldTransform().transformPoint(p); -} - -/* -EVENT HANDLING -*/ - -/** - * @param {WheelEvent} event - */ -function onMouseWheel(event) { - const s = event.deltaY; - if (s > 0) { - mapScaleIndex = Math.max(0, mapScaleIndex - 1); - } else if (s < 0) { - mapScaleIndex = Math.min(SCALE_VALUES.length - 1, mapScaleIndex + 1); - } - draw(); - event.stopPropagation(); - return false; -} - -/** - * @param {MouseEvent} event - */ -function onMouseDown(event) { - const p = getMousePoint(event); - mapDragOrigin = {x: p.x, y: p.y}; -} - -function onMouseUp() { - if (mapDragTranslation !== null) { - mapTranslation.x += mapDragTranslation.x; - mapTranslation.y += mapDragTranslation.y; - } - if (hoveredElements.length === 1) { - railSystem.selectedComponent = hoveredElements[0]; - } else { - railSystem.selectedComponent = null; - } - mapDragOrigin = null; - mapDragTranslation = null; -} - -/** - * @param {MouseEvent} event - */ -function onMouseMove(event) { - const p = getMousePoint(event); - lastMousePoint = p; - if (mapDragOrigin !== null) { - const scale = getScaleFactor(); - const dx = p.x - mapDragOrigin.x; - const dy = p.y - mapDragOrigin.y; - mapDragTranslation = {x: dx / scale, y: dy / scale}; - } else { - hoveredElements.length = 0; - // Populate with list of hovered elements. - for (let i = 0; i < railSystem.components.length; i++) { - const c = railSystem.components[i]; - const componentPoint = new DOMPoint(c.position.x, c.position.z, 0, 1); - const mapComponentPoint = worldPointToMap(componentPoint); - const dist2 = (p.x - mapComponentPoint.x) * (p.x - mapComponentPoint.x) + (p.y - mapComponentPoint.y) * (p.y - mapComponentPoint.y); - if (dist2 < HOVER_RADIUS * HOVER_RADIUS) { - hoveredElements.push(c); - } - } - } - draw(); -} - -/** - * Gets the point at which the user clicked on the map. - * @param {MouseEvent} event - * @returns {DOMPoint} - */ -function getMousePoint(event) { - const rect = mapCanvas.getBoundingClientRect(); - const x = event.clientX - rect.left; - const y = event.clientY - rect.top; - return new DOMPoint(x, y, 0, 1); -} diff --git a/railsignal-app/src/components/railsystem/util/ComponentSelector.vue b/railsignal-app/src/components/railsystem/util/ComponentSelector.vue deleted file mode 100644 index 835b00f..0000000 --- a/railsignal-app/src/components/railsystem/util/ComponentSelector.vue +++ /dev/null @@ -1,106 +0,0 @@ - - - - - \ No newline at end of file diff --git a/railsignal-app/src/main.js b/railsignal-app/src/main.js deleted file mode 100644 index b50d2ca..0000000 --- a/railsignal-app/src/main.js +++ /dev/null @@ -1,11 +0,0 @@ -import {createApp} from 'vue'; -import {createPinia} from 'pinia'; -import App from './App.vue' -import "bootstrap/dist/css/bootstrap.min.css"; -import "bootstrap"; - - -const pinia = createPinia(); -const app = createApp(App); -app.use(pinia); -app.mount('#app') diff --git a/railsignal-app/src/stores/railSystemsStore.js b/railsignal-app/src/stores/railSystemsStore.js deleted file mode 100644 index 6defbda..0000000 --- a/railsignal-app/src/stores/railSystemsStore.js +++ /dev/null @@ -1,32 +0,0 @@ -import {defineStore} from "pinia"; -import {refreshSegments} from "../api/segments" -import {refreshComponents} from "../api/components"; -import {closeWebsocketConnection, establishWebsocketConnection} from "../api/websocket"; - -export const useRailSystemsStore = defineStore('RailSystemsStore', { - state: () => ({ - /** - * @type {RailSystem[]} - */ - railSystems: [], - /** - * @type {RailSystem | null} - */ - selectedRailSystem: null - }), - actions: { - onSelectedRailSystemChanged() { - this.railSystems.forEach(rs => closeWebsocketConnection(rs)); - if (!this.selectedRailSystem) return; - refreshSegments(this.selectedRailSystem); - refreshComponents(this.selectedRailSystem); - establishWebsocketConnection(this.selectedRailSystem); - } - }, - getters: { - rsId() { - if (this.selectedRailSystem === null) return null; - return this.selectedRailSystem.id; - } - } -}); \ No newline at end of file diff --git a/railsignal-app/vite.config.js b/railsignal-app/vite.config.js deleted file mode 100644 index 802da0a..0000000 --- a/railsignal-app/vite.config.js +++ /dev/null @@ -1,17 +0,0 @@ -import { fileURLToPath, URL } from 'url' - -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' - -// https://vitejs.dev/config/ -export default defineConfig(({command, mode}) => { - return { - plugins: [vue()], - resolve: { - alias: { - '@': fileURLToPath(new URL('./src', import.meta.url)) - } - }, - base: mode === "production" ? "/app/" : undefined - } -}) diff --git a/src/main/java/nl/andrewl/railsignalapi/live/ComponentDownlink.java b/src/main/java/nl/andrewl/railsignalapi/live/ComponentDownlink.java index db3aafb..ab61eb3 100644 --- a/src/main/java/nl/andrewl/railsignalapi/live/ComponentDownlink.java +++ b/src/main/java/nl/andrewl/railsignalapi/live/ComponentDownlink.java @@ -3,7 +3,7 @@ package nl.andrewl.railsignalapi.live; import lombok.Getter; /** - * A downlink connection to one or more components (linked by a {@link nl.andrewl.railsignalapi.model.LinkToken} + * A downlink connection to one or more components (linked by a {@link nl.andrewl.railsignalapi.model.LinkToken}) * which we can send messages to. */ public abstract class ComponentDownlink { diff --git a/src/main/java/nl/andrewl/railsignalapi/live/ComponentDownlinkService.java b/src/main/java/nl/andrewl/railsignalapi/live/ComponentDownlinkService.java index 5cf293c..a0ba9ee 100644 --- a/src/main/java/nl/andrewl/railsignalapi/live/ComponentDownlinkService.java +++ b/src/main/java/nl/andrewl/railsignalapi/live/ComponentDownlinkService.java @@ -4,6 +4,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import nl.andrewl.railsignalapi.dao.ComponentRepository; import nl.andrewl.railsignalapi.dao.LinkTokenRepository; +import nl.andrewl.railsignalapi.live.dto.ComponentDataMessage; +import nl.andrewl.railsignalapi.live.dto.ComponentMessage; import nl.andrewl.railsignalapi.live.websocket.AppUpdateService; import nl.andrewl.railsignalapi.model.component.Component; import org.springframework.stereotype.Service; @@ -31,13 +33,18 @@ public class ComponentDownlinkService { * @param downlink The downlink to register. */ @Transactional - public synchronized void registerDownlink(ComponentDownlink downlink) { + public synchronized void registerDownlink(ComponentDownlink downlink) throws Exception { Set components = tokenRepository.findById(downlink.getTokenId()).orElseThrow().getComponents(); componentDownlinks.put(downlink, components.stream().map(Component::getId).collect(Collectors.toSet())); for (var c : components) { c.setOnline(true); componentRepository.save(c); - appUpdateService.sendComponentUpdate(c.getRailSystem().getId(), c.getId()); + + // Immediately send a data message to the downlink and app for each component that comes online. + var msg = new ComponentDataMessage(c); + downlink.send(msg); + appUpdateService.sendUpdate(c.getRailSystem().getId(), msg); + Set downlinks = downlinksByCId.computeIfAbsent(c.getId(), aLong -> new HashSet<>()); downlinks.add(downlink); } @@ -97,4 +104,8 @@ public class ComponentDownlinkService { } } } + + public void sendMessage(ComponentMessage msg) { + sendMessage(msg.cId, msg); + } } diff --git a/src/main/java/nl/andrewl/railsignalapi/live/ComponentUplinkMessageHandler.java b/src/main/java/nl/andrewl/railsignalapi/live/ComponentUplinkMessageHandler.java index c2f837b..c3baf01 100644 --- a/src/main/java/nl/andrewl/railsignalapi/live/ComponentUplinkMessageHandler.java +++ b/src/main/java/nl/andrewl/railsignalapi/live/ComponentUplinkMessageHandler.java @@ -2,7 +2,7 @@ package nl.andrewl.railsignalapi.live; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import nl.andrewl.railsignalapi.live.dto.ComponentUplinkMessage; +import nl.andrewl.railsignalapi.live.dto.ComponentMessage; import nl.andrewl.railsignalapi.live.dto.SegmentBoundaryUpdateMessage; import nl.andrewl.railsignalapi.live.dto.SwitchUpdateMessage; import nl.andrewl.railsignalapi.service.SegmentService; @@ -22,7 +22,7 @@ public class ComponentUplinkMessageHandler { private final SegmentService segmentService; @Transactional - public void messageReceived(ComponentUplinkMessage msg) { + public void messageReceived(ComponentMessage msg) { if (msg instanceof SegmentBoundaryUpdateMessage sb) { segmentService.onBoundaryUpdate(sb); } else if (msg instanceof SwitchUpdateMessage sw) { diff --git a/src/main/java/nl/andrewl/railsignalapi/live/dto/ComponentDataMessage.java b/src/main/java/nl/andrewl/railsignalapi/live/dto/ComponentDataMessage.java new file mode 100644 index 0000000..4896d67 --- /dev/null +++ b/src/main/java/nl/andrewl/railsignalapi/live/dto/ComponentDataMessage.java @@ -0,0 +1,19 @@ +package nl.andrewl.railsignalapi.live.dto; + +import lombok.Getter; +import nl.andrewl.railsignalapi.model.component.Component; +import nl.andrewl.railsignalapi.rest.dto.component.out.ComponentResponse; + +/** + * A message that's sent to devices which contains the full component response + * for a specific component. + */ +@Getter +public class ComponentDataMessage extends ComponentMessage { + private final ComponentResponse data; + + public ComponentDataMessage(Component c) { + super(c.getId(), "COMPONENT_DATA"); + this.data = ComponentResponse.of(c); + } +} diff --git a/src/main/java/nl/andrewl/railsignalapi/live/dto/ComponentUplinkMessage.java b/src/main/java/nl/andrewl/railsignalapi/live/dto/ComponentMessage.java similarity index 55% rename from src/main/java/nl/andrewl/railsignalapi/live/dto/ComponentUplinkMessage.java rename to src/main/java/nl/andrewl/railsignalapi/live/dto/ComponentMessage.java index 43f8e96..37ffd19 100644 --- a/src/main/java/nl/andrewl/railsignalapi/live/dto/ComponentUplinkMessage.java +++ b/src/main/java/nl/andrewl/railsignalapi/live/dto/ComponentMessage.java @@ -3,18 +3,32 @@ package nl.andrewl.railsignalapi.live.dto; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import lombok.NoArgsConstructor; /** - * The parent class for all uplink messages that can be sent by connected - * components. + * Base class for all messages that will be sent to components. */ @JsonIgnoreProperties(ignoreUnknown = true) @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", include = JsonTypeInfo.As.EXISTING_PROPERTY, visible = true) @JsonSubTypes({ - @JsonSubTypes.Type(value = SegmentBoundaryUpdateMessage.class, name = "sb"), - @JsonSubTypes.Type(value = SwitchUpdateMessage.class, name = "sw") + @JsonSubTypes.Type(value = SegmentBoundaryUpdateMessage.class, name = "SEGMENT_BOUNDARY_UPDATE"), + @JsonSubTypes.Type(value = SwitchUpdateMessage.class, name = "SWITCH_UPDATE"), + @JsonSubTypes.Type(value = ErrorMessage.class, name = "ERROR") }) -public abstract class ComponentUplinkMessage { +@NoArgsConstructor +public abstract class ComponentMessage { + /** + * The id of the component that this message is for. + */ public long cId; + + /** + * The type of message. + */ public String type; + + public ComponentMessage(long cId, String type) { + this.cId = cId; + this.type = type; + } } diff --git a/src/main/java/nl/andrewl/railsignalapi/live/dto/ErrorMessage.java b/src/main/java/nl/andrewl/railsignalapi/live/dto/ErrorMessage.java new file mode 100644 index 0000000..8921aec --- /dev/null +++ b/src/main/java/nl/andrewl/railsignalapi/live/dto/ErrorMessage.java @@ -0,0 +1,13 @@ +package nl.andrewl.railsignalapi.live.dto; + +/** + * A message that's sent regarding an error that occurred. + */ +public class ErrorMessage extends ComponentMessage { + public String message; + + public ErrorMessage(long cId, String message) { + super(cId, "ERROR"); + this.message = message; + } +} diff --git a/src/main/java/nl/andrewl/railsignalapi/live/dto/SegmentBoundaryUpdateMessage.java b/src/main/java/nl/andrewl/railsignalapi/live/dto/SegmentBoundaryUpdateMessage.java index 4c7da55..382941d 100644 --- a/src/main/java/nl/andrewl/railsignalapi/live/dto/SegmentBoundaryUpdateMessage.java +++ b/src/main/java/nl/andrewl/railsignalapi/live/dto/SegmentBoundaryUpdateMessage.java @@ -1,9 +1,12 @@ package nl.andrewl.railsignalapi.live.dto; +import lombok.NoArgsConstructor; + /** * Message that's sent by segment boundaries when a train crosses it. */ -public class SegmentBoundaryUpdateMessage extends ComponentUplinkMessage { +@NoArgsConstructor +public class SegmentBoundaryUpdateMessage extends ComponentMessage { /** * The id of the segment that a train detected by the segment boundary is * moving towards. diff --git a/src/main/java/nl/andrewl/railsignalapi/live/dto/SegmentStatusMessage.java b/src/main/java/nl/andrewl/railsignalapi/live/dto/SegmentStatusMessage.java index be90693..1ebb3c7 100644 --- a/src/main/java/nl/andrewl/railsignalapi/live/dto/SegmentStatusMessage.java +++ b/src/main/java/nl/andrewl/railsignalapi/live/dto/SegmentStatusMessage.java @@ -1,6 +1,26 @@ package nl.andrewl.railsignalapi.live.dto; -public record SegmentStatusMessage ( - long cId, - boolean occupied -) {} +import lombok.Getter; + +/** + * A message that's sent to signal components regarding a change in a segment's + * status. + */ +@Getter +public class SegmentStatusMessage extends ComponentMessage { + /** + * The id of the segment that updated. + */ + private final long sId; + + /** + * Whether the segment is occupied. + */ + private final boolean occupied; + + public SegmentStatusMessage(long cId, long sId, boolean occupied) { + super(cId, "SEGMENT_STATUS"); + this.sId = sId; + this.occupied = occupied; + } +} diff --git a/src/main/java/nl/andrewl/railsignalapi/live/dto/SwitchUpdateMessage.java b/src/main/java/nl/andrewl/railsignalapi/live/dto/SwitchUpdateMessage.java index ea1e91b..74b6cbc 100644 --- a/src/main/java/nl/andrewl/railsignalapi/live/dto/SwitchUpdateMessage.java +++ b/src/main/java/nl/andrewl/railsignalapi/live/dto/SwitchUpdateMessage.java @@ -1,13 +1,19 @@ package nl.andrewl.railsignalapi.live.dto; -import java.util.Set; +import lombok.NoArgsConstructor; /** * Message that's sent by a switch when its active configuration is updated. */ -public class SwitchUpdateMessage extends ComponentUplinkMessage { +@NoArgsConstructor +public class SwitchUpdateMessage extends ComponentMessage { /** - * A set of path node ids that represents the active configuration. + * The id of the configuration that's active. */ - public Set configuration; + public long activeConfigId; + + public SwitchUpdateMessage(long cId, long activeConfigId) { + super(cId, "SWITCH_UPDATE"); + this.activeConfigId = activeConfigId; + } } diff --git a/src/main/java/nl/andrewl/railsignalapi/live/tcp_socket/ConnectMessage.java b/src/main/java/nl/andrewl/railsignalapi/live/tcp_socket/ConnectMessage.java index 26c55a0..75139f8 100644 --- a/src/main/java/nl/andrewl/railsignalapi/live/tcp_socket/ConnectMessage.java +++ b/src/main/java/nl/andrewl/railsignalapi/live/tcp_socket/ConnectMessage.java @@ -1,5 +1,10 @@ package nl.andrewl.railsignalapi.live.tcp_socket; +/** + * A message that's sent in response to a client's attempt to connect. + * @param valid Whether the connection is valid. + * @param message A message. + */ public record ConnectMessage( boolean valid, String message diff --git a/src/main/java/nl/andrewl/railsignalapi/live/tcp_socket/TcpLinkManager.java b/src/main/java/nl/andrewl/railsignalapi/live/tcp_socket/TcpLinkManager.java index bf78068..63befe6 100644 --- a/src/main/java/nl/andrewl/railsignalapi/live/tcp_socket/TcpLinkManager.java +++ b/src/main/java/nl/andrewl/railsignalapi/live/tcp_socket/TcpLinkManager.java @@ -4,7 +4,7 @@ import lombok.extern.slf4j.Slf4j; import nl.andrewl.railsignalapi.live.ComponentDownlink; import nl.andrewl.railsignalapi.live.ComponentDownlinkService; import nl.andrewl.railsignalapi.live.ComponentUplinkMessageHandler; -import nl.andrewl.railsignalapi.live.dto.ComponentUplinkMessage; +import nl.andrewl.railsignalapi.live.dto.ComponentMessage; import nl.andrewl.railsignalapi.util.JsonUtils; import java.io.DataInputStream; @@ -43,10 +43,20 @@ public class TcpLinkManager extends ComponentDownlink implements Runnable { @Override public void run() { - downlinkService.registerDownlink(this); + try { + downlinkService.registerDownlink(this); + } catch (Exception e) { + log.error("An error occurred while registering a downlink."); + try { + shutdown(); + } catch (IOException ex) { + log.error("An error occurred while shutting down a downlink.", ex); + } + return; + } while (!socket.isClosed()) { try { - var msg = JsonUtils.readMessage(in, ComponentUplinkMessage.class); + var msg = JsonUtils.readMessage(in, ComponentMessage.class); uplinkMessageHandler.messageReceived(msg); } catch (IOException e) { log.warn("An error occurred while receiving an uplink message.", e); diff --git a/src/main/java/nl/andrewl/railsignalapi/live/websocket/AppUpdateService.java b/src/main/java/nl/andrewl/railsignalapi/live/websocket/AppUpdateService.java index 0c066e2..b21c974 100644 --- a/src/main/java/nl/andrewl/railsignalapi/live/websocket/AppUpdateService.java +++ b/src/main/java/nl/andrewl/railsignalapi/live/websocket/AppUpdateService.java @@ -53,6 +53,11 @@ public class AppUpdateService { log.info("De-registered an app websocket session."); } + /** + * Sends an update to any connected apps. + * @param rsId The id of the rail system that the update pertains to. + * @param msg The message to send. + */ public synchronized void sendUpdate(long rsId, Object msg) { Set sessionsForRs = sessions.get(rsId); if (sessionsForRs != null) { diff --git a/src/main/java/nl/andrewl/railsignalapi/live/websocket/ComponentWebsocketHandler.java b/src/main/java/nl/andrewl/railsignalapi/live/websocket/ComponentWebsocketHandler.java index 3ec526e..237d1ac 100644 --- a/src/main/java/nl/andrewl/railsignalapi/live/websocket/ComponentWebsocketHandler.java +++ b/src/main/java/nl/andrewl/railsignalapi/live/websocket/ComponentWebsocketHandler.java @@ -4,7 +4,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import nl.andrewl.railsignalapi.live.ComponentDownlinkService; import nl.andrewl.railsignalapi.live.ComponentUplinkMessageHandler; -import nl.andrewl.railsignalapi.live.dto.ComponentUplinkMessage; +import nl.andrewl.railsignalapi.live.dto.ComponentMessage; import nl.andrewl.railsignalapi.util.JsonUtils; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -13,6 +13,8 @@ import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; +import java.io.IOException; + /** * Handler for websocket connections that components open to send and receive * real-time updates from the server. @@ -28,12 +30,21 @@ public class ComponentWebsocketHandler extends TextWebSocketHandler { @Transactional(readOnly = true) public void afterConnectionEstablished(WebSocketSession session) { long tokenId = (long) session.getAttributes().get("tokenId"); - componentDownlinkService.registerDownlink(new WebsocketDownlink(tokenId, session)); + try { + componentDownlinkService.registerDownlink(new WebsocketDownlink(tokenId, session)); + } catch (Exception e) { + log.error("An error occurred while registering a new websocket downlink.", e); + try { + session.close(); + } catch (IOException ex) { + log.error("An error occurred while closing a websocket downlink.", e); + } + } } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { - var msg = JsonUtils.readMessage(message.getPayload(), ComponentUplinkMessage.class); + var msg = JsonUtils.readMessage(message.getPayload(), ComponentMessage.class); uplinkMessageHandler.messageReceived(msg); } diff --git a/src/main/java/nl/andrewl/railsignalapi/model/component/Switch.java b/src/main/java/nl/andrewl/railsignalapi/model/component/Switch.java index f77d192..ce3b1e9 100644 --- a/src/main/java/nl/andrewl/railsignalapi/model/component/Switch.java +++ b/src/main/java/nl/andrewl/railsignalapi/model/component/Switch.java @@ -7,9 +7,7 @@ import lombok.Setter; import nl.andrewl.railsignalapi.model.RailSystem; import javax.persistence.*; -import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; /** * A switch is a component that directs traffic between several connected @@ -38,12 +36,4 @@ public class Switch extends PathNode { this.possibleConfigurations = possibleConfigurations; this.activeConfiguration = activeConfiguration; } - - public Optional findConfiguration(Set pathNodeIds) { - for (var config : possibleConfigurations) { - Set configNodeIds = config.getNodes().stream().map(Component::getId).collect(Collectors.toSet()); - if (pathNodeIds.equals(configNodeIds)) return Optional.of(config); - } - return Optional.empty(); - } } diff --git a/src/main/java/nl/andrewl/railsignalapi/rest/WebConfig.java b/src/main/java/nl/andrewl/railsignalapi/rest/WebConfig.java index ad2091f..3fe5ae4 100644 --- a/src/main/java/nl/andrewl/railsignalapi/rest/WebConfig.java +++ b/src/main/java/nl/andrewl/railsignalapi/rest/WebConfig.java @@ -14,6 +14,10 @@ public class WebConfig implements WebMvcConfigurer { // Configure resource handlers to use the /app directory for all vue frontend stuff. registry.addResourceHandler("/app/**") .addResourceLocations("classpath:/app/"); + + // Configure resource handlers for driver files. + registry.addResourceHandler("/driver/**") + .addResourceLocations("classpath:/driver/"); } @Override diff --git a/src/main/java/nl/andrewl/railsignalapi/service/SegmentService.java b/src/main/java/nl/andrewl/railsignalapi/service/SegmentService.java index 0513697..553748f 100644 --- a/src/main/java/nl/andrewl/railsignalapi/service/SegmentService.java +++ b/src/main/java/nl/andrewl/railsignalapi/service/SegmentService.java @@ -68,11 +68,15 @@ public class SegmentService { private void sendSegmentOccupiedStatus(Segment segment) { for (var signal : segment.getSignals()) { - downlinkService.sendMessage(signal.getId(), new SegmentStatusMessage(signal.getId(), segment.isOccupied())); + downlinkService.sendMessage(signal.getId(), new SegmentStatusMessage(signal.getId(), segment.getId(), segment.isOccupied())); appUpdateService.sendComponentUpdate(segment.getRailSystem().getId(), signal.getId()); } } + /** + * Handles updates from segment boundary components. + * @param msg The update message. + */ @Transactional public void onBoundaryUpdate(SegmentBoundaryUpdateMessage msg) { var segmentBoundary = segmentBoundaryRepository.findById(msg.cId) diff --git a/src/main/java/nl/andrewl/railsignalapi/service/SwitchService.java b/src/main/java/nl/andrewl/railsignalapi/service/SwitchService.java index c1df8ed..81876d5 100644 --- a/src/main/java/nl/andrewl/railsignalapi/service/SwitchService.java +++ b/src/main/java/nl/andrewl/railsignalapi/service/SwitchService.java @@ -3,9 +3,11 @@ package nl.andrewl.railsignalapi.service; import lombok.RequiredArgsConstructor; import nl.andrewl.railsignalapi.dao.ComponentRepository; import nl.andrewl.railsignalapi.live.ComponentDownlinkService; +import nl.andrewl.railsignalapi.live.dto.ErrorMessage; import nl.andrewl.railsignalapi.live.dto.SwitchUpdateMessage; import nl.andrewl.railsignalapi.live.websocket.AppUpdateService; import nl.andrewl.railsignalapi.model.component.Switch; +import nl.andrewl.railsignalapi.model.component.SwitchConfiguration; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -23,11 +25,16 @@ public class SwitchService { @Transactional public void onSwitchUpdate(SwitchUpdateMessage msg) { switchRepository.findById(msg.cId).ifPresent(sw -> { - sw.findConfiguration(msg.configuration).ifPresent(config -> { - sw.setActiveConfiguration(config); - switchRepository.save(sw); - appUpdateService.sendComponentUpdate(sw.getRailSystem().getId(), sw.getId()); - }); + sw.getPossibleConfigurations().stream() + .filter(c -> c.getId().equals(msg.activeConfigId)) + .findFirst() + .ifPresentOrElse(config -> { + sw.setActiveConfiguration(config); + switchRepository.save(sw); + appUpdateService.sendComponentUpdate(sw.getRailSystem().getId(), sw.getId()); + }, () -> { + downlinkService.sendMessage(new ErrorMessage(sw.getId(), "Invalid active config id.")); + }); }); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b47e28e..77f5b55 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -5,8 +5,6 @@ spring.jpa.open-in-view=false spring.datasource.hikari.maximum-pool-size=5 spring.datasource.hikari.minimum-idle=1 -spring.thymeleaf.enabled=false - server.port=8080 server.tomcat.threads.max=10 server.tomcat.threads.min-spare=2 diff --git a/src/main/resources/driver/utils.lua b/src/main/resources/driver/utils.lua new file mode 100644 index 0000000..d3ee215 --- /dev/null +++ b/src/main/resources/driver/utils.lua @@ -0,0 +1,41 @@ +function tableLength(t) + local c = 0 + for _ in pairs(t) do + c = c + 1 + end + return c +end + +function startsWith(str, s) + return str:find(s, 1, true) == 1 +end + +function readNum(validationFunction) + local func = validationFunction or function (n) + return n ~= nil + end + local num = nil + while true do + local s = io.read() + if s ~= nil then num = tonumber(s) end + if not func(num) then + print("The number you entered is not valid.") + else + return num + end + end +end + +function readStr(validationFunction) + local func = validationFunction or function (s) + return s ~= nil and string.len(s) > 0 + end + while true do + local str = io.read() + if func(str) then + return str + else + print("The string you entered is not valid.") + end + end +end