This commit is contained in:
Jake Walker 2022-08-05 16:30:13 +01:00
parent c89d435b5a
commit 5a53e7069d
10 changed files with 201 additions and 16 deletions

View file

@ -1,2 +1,2 @@
allowedServers: allowedServers:
- "127.0.0.1:16000" - "195.201.123.169:16000"

View file

@ -3,7 +3,7 @@ module git.vh7.uk/jakew/echo-web/bridge
go 1.18 go 1.18
require ( require (
git.vh7.uk/jakew/echo-go v0.0.0-20220803185705-357282c0e444 git.vh7.uk/jakew/echo-go v0.0.0-20220805101505-158189ae7d58
github.com/gorilla/websocket v1.5.0 github.com/gorilla/websocket v1.5.0
github.com/rs/zerolog v1.27.0 github.com/rs/zerolog v1.27.0
github.com/samber/lo v1.27.0 github.com/samber/lo v1.27.0

View file

@ -1,5 +1,7 @@
git.vh7.uk/jakew/echo-go v0.0.0-20220803185705-357282c0e444 h1:/GiYRoIHnYqoF9bAHwYXlLCy4praom2KlwBed8pW3ZU= git.vh7.uk/jakew/echo-go v0.0.0-20220803185705-357282c0e444 h1:/GiYRoIHnYqoF9bAHwYXlLCy4praom2KlwBed8pW3ZU=
git.vh7.uk/jakew/echo-go v0.0.0-20220803185705-357282c0e444/go.mod h1:Q4YqOodoX+qYvfM0gSf78cCk0o7dkg1GLNYUFgB6qhU= git.vh7.uk/jakew/echo-go v0.0.0-20220803185705-357282c0e444/go.mod h1:Q4YqOodoX+qYvfM0gSf78cCk0o7dkg1GLNYUFgB6qhU=
git.vh7.uk/jakew/echo-go v0.0.0-20220805101505-158189ae7d58 h1:gMa91PLcG4jRunbntD/YSt/7U3eSyAHUNxIdWu4ELjU=
git.vh7.uk/jakew/echo-go v0.0.0-20220805101505-158189ae7d58/go.mod h1:Q4YqOodoX+qYvfM0gSf78cCk0o7dkg1GLNYUFgB6qhU=
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=

View file

@ -1,15 +1,17 @@
package main package main
import ( import (
"encoding/json"
"io/ioutil"
"net/http"
"os"
echo "git.vh7.uk/jakew/echo-go" echo "git.vh7.uk/jakew/echo-go"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/rs/zerolog" "github.com/rs/zerolog"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/samber/lo" "github.com/samber/lo"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"io/ioutil"
"net/http"
"os"
) )
type Config struct { type Config struct {
@ -26,6 +28,27 @@ var upgrader = websocket.Upgrader{
}, },
} }
func (h *websocketHandler) receiver(conn *websocket.Conn, client *echo.Client) {
defer conn.Close()
for {
msgs, err := client.Receive()
if err != nil {
log.Error().Err(err).Msg("failed to receive from server")
return
}
for _, msg := range msgs {
log.Info().Interface("msg", msg).Msg("received message")
bytes, err := json.Marshal(&msg)
if err != nil {
log.Error().Err(err).Msg("failed to marshal message")
}
conn.WriteMessage(websocket.TextMessage, bytes)
}
}
}
func (h *websocketHandler) socketHandler(w http.ResponseWriter, r *http.Request) { func (h *websocketHandler) socketHandler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil) conn, err := upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
@ -40,7 +63,7 @@ func (h *websocketHandler) socketHandler(w http.ResponseWriter, r *http.Request)
username := r.URL.Query().Get("username") username := r.URL.Query().Get("username")
password := r.URL.Query().Get("password") password := r.URL.Query().Get("password")
if !lo.Contains[string](h.config.AllowedServers, server) { if !lo.Contains(h.config.AllowedServers, server) {
_ = conn.WriteMessage(websocket.TextMessage, []byte("{\"error\": \"Server not allowed\"}")) _ = conn.WriteMessage(websocket.TextMessage, []byte("{\"error\": \"Server not allowed\"}"))
return return
} }
@ -54,34 +77,37 @@ func (h *websocketHandler) socketHandler(w http.ResponseWriter, r *http.Request)
} }
defer client.Disconnect() defer client.Disconnect()
err = client.HandshakeLoop(password) err = client.HandshakeLoop("4.0.0", password)
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to handshake with server") log.Error().Err(err).Msg("failed to handshake with server")
_ = conn.WriteMessage(websocket.TextMessage, []byte("{\"error\": \"Failed to connect\"}")) _ = conn.WriteMessage(websocket.TextMessage, []byte("{\"error\": \"Failed to connect\"}"))
return return
} }
go h.receiver(conn, client)
for { for {
messageType, message, err := conn.ReadMessage() messageType, message, err := conn.ReadMessage()
if err != nil { if err != nil {
log.Warn().Err(err).Msg("failed to receive websocket message") log.Warn().Err(err).Msg("failed to receive websocket message")
break return
} }
if messageType == websocket.CloseMessage { if messageType == websocket.CloseMessage {
log.Debug().Msg("websocket closed")
break break
} else if messageType == websocket.TextMessage { } else if messageType == websocket.TextMessage {
err = conn.WriteMessage(messageType, message) var echoMessage echo.RawMessage
err = json.Unmarshal(message, &echoMessage)
if err != nil { if err != nil {
log.Warn().Err(err).Msg("failed to send websocket message") log.Warn().Err(err).Msg("failed to unmarshal message")
break break
} }
client.Send(echoMessage.MessageType, echoMessage.Data, echoMessage.SubType, []string{})
} else { } else {
log.Warn().Int("type", messageType).Bytes("message", message).Msg("message type not implemented") log.Warn().Int("type", messageType).Bytes("message", message).Msg("message type not implemented")
} }
} }
log.Info().Str("address", conn.RemoteAddr().String()).Msg("websocket connection closed")
} }
func main() { func main() {

View file

@ -15,14 +15,18 @@
"@mantine/hooks": "^5.0.2", "@mantine/hooks": "^5.0.2",
"@mantine/modals": "^5.0.2", "@mantine/modals": "^5.0.2",
"@mantine/notifications": "^5.0.2", "@mantine/notifications": "^5.0.2",
"@reduxjs/toolkit": "^1.8.3",
"dayjs": "^1.11.4", "dayjs": "^1.11.4",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-feather": "^2.0.10" "react-feather": "^2.0.10",
"react-redux": "^8.0.2",
"ws": "^8.8.1"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^18.0.15", "@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6", "@types/react-dom": "^18.0.6",
"@types/ws": "^8.5.3",
"@vitejs/plugin-react": "^2.0.0", "@vitejs/plugin-react": "^2.0.0",
"typescript": "^4.6.4", "typescript": "^4.6.4",
"vite": "^3.0.0" "vite": "^3.0.0"

View file

@ -3,11 +3,15 @@ import ReactDOM from 'react-dom/client'
import { MantineProvider } from '@mantine/core'; import { MantineProvider } from '@mantine/core';
import App from './App' import App from './App'
import './index.css'; import './index.css';
import { Provider } from 'react-redux';
import store from './store';
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode> <React.StrictMode>
<MantineProvider withGlobalStyles withNormalizeCSS> <MantineProvider withGlobalStyles withNormalizeCSS>
<Provider store={store}>
<App /> <App />
</Provider>
</MantineProvider> </MantineProvider>
</React.StrictMode> </React.StrictMode>
) )

View file

@ -0,0 +1,24 @@
import { Middleware } from "@reduxjs/toolkit";
import WebSocket from 'ws';
import { chatActions } from "../slices/chat";
const chatMiddleware: Middleware = (store) => (next) => (action) => {
if (!chatActions.startConnecting.match(action)) {
return next(action);
}
const socket = new WebSocket("ws://127.0.0.1:4000?server=195.201.123.169:16000&username=jake");
socket.on('connect', () => {
console.log('Connected to WebSocket!');
store.dispatch(chatActions.connectionEstablished());
});
socket.on('message', (message: any) => {
store.dispatch(chatActions.recieveMessage({ message }))
});
next(action);
};
export default chatMiddleware;

View file

@ -0,0 +1,36 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
export interface ChatState {
messages: any[];
isEstablishingConnection: boolean;
isConnected: boolean;
}
const initialState: ChatState = {
messages: [],
isEstablishingConnection: false,
isConnected: false
};
const chatSlice = createSlice({
name: "chat",
initialState,
reducers: {
startConnecting: (state) => {
state.isEstablishingConnection = true;
},
connectionEstablished: (state) => {
state.isConnected = true;
state.isEstablishingConnection = true;
},
recieveMessage: (state, action: PayloadAction<{
message: any
}>) => {
state.messages.push(action.payload.message);
}
}
});
export const chatActions = chatSlice.actions;
export default chatSlice;

5
frontend/src/store.ts Normal file
View file

@ -0,0 +1,5 @@
import { configureStore } from '@reduxjs/toolkit';
export default configureStore({
reducer: {}
});

View file

@ -206,7 +206,7 @@
"@babel/plugin-syntax-jsx" "^7.18.6" "@babel/plugin-syntax-jsx" "^7.18.6"
"@babel/types" "^7.18.10" "@babel/types" "^7.18.10"
"@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.18.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.18.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.18.9" version "7.18.9"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a"
integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw== integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==
@ -545,6 +545,29 @@
dependencies: dependencies:
"@babel/runtime" "^7.13.10" "@babel/runtime" "^7.13.10"
"@reduxjs/toolkit@^1.8.3":
version "1.8.3"
resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.8.3.tgz#9c6a9c497bde43a67618d37a4175a00ae12efeb2"
integrity sha512-lU/LDIfORmjBbyDLaqFN2JB9YmAT1BElET9y0ZszwhSBa5Ef3t6o5CrHupw5J1iOXwd+o92QfQZ8OJpwXvsssg==
dependencies:
immer "^9.0.7"
redux "^4.1.2"
redux-thunk "^2.4.1"
reselect "^4.1.5"
"@types/hoist-non-react-statics@^3.3.1":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
dependencies:
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
"@types/node@*":
version "18.6.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.4.tgz#fd26723a8a3f8f46729812a7f9b4fc2d1608ed39"
integrity sha512-I4BD3L+6AWiUobfxZ49DlU43gtI+FTHSv9pE2Zekg6KjMpre4ByusaljW3vYSLJrvQ1ck1hUaeVu8HVlY3vzHg==
"@types/parse-json@^4.0.0": "@types/parse-json@^4.0.0":
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
@ -576,6 +599,18 @@
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
"@types/use-sync-external-store@^0.0.3":
version "0.0.3"
resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43"
integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==
"@types/ws@^8.5.3":
version "8.5.3"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d"
integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==
dependencies:
"@types/node" "*"
"@vitejs/plugin-react@^2.0.0": "@vitejs/plugin-react@^2.0.0":
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-2.0.0.tgz#12decd097773a00620e44b780b1d2c00df101449" resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-2.0.0.tgz#12decd097773a00620e44b780b1d2c00df101449"
@ -897,13 +932,18 @@ has@^1.0.3:
dependencies: dependencies:
function-bind "^1.1.1" function-bind "^1.1.1"
hoist-non-react-statics@^3.3.1: hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
version "3.3.2" version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies: dependencies:
react-is "^16.7.0" react-is "^16.7.0"
immer@^9.0.7:
version "9.0.15"
resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.15.tgz#0b9169e5b1d22137aba7d43f8a81a495dd1b62dc"
integrity sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==
import-fresh@^3.2.1: import-fresh@^3.2.1:
version "3.3.0" version "3.3.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
@ -1053,6 +1093,23 @@ react-is@^16.13.1, react-is@^16.7.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^18.0.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
react-redux@^8.0.2:
version "8.0.2"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-8.0.2.tgz#bc2a304bb21e79c6808e3e47c50fe1caf62f7aad"
integrity sha512-nBwiscMw3NoP59NFCXFf02f8xdo+vSHT/uZ1ldDwF7XaTpzm+Phk97VT4urYBl5TYAPNVaFm12UHAEyzkpNzRA==
dependencies:
"@babel/runtime" "^7.12.1"
"@types/hoist-non-react-statics" "^3.3.1"
"@types/use-sync-external-store" "^0.0.3"
hoist-non-react-statics "^3.3.2"
react-is "^18.0.0"
use-sync-external-store "^1.0.0"
react-refresh@^0.14.0: react-refresh@^0.14.0:
version "0.14.0" version "0.14.0"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e"
@ -1084,11 +1141,28 @@ react@^18.2.0:
dependencies: dependencies:
loose-envify "^1.1.0" loose-envify "^1.1.0"
redux-thunk@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.1.tgz#0dd8042cf47868f4b29699941de03c9301a75714"
integrity sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==
redux@^4.1.2:
version "4.2.0"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.0.tgz#46f10d6e29b6666df758780437651eeb2b969f13"
integrity sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==
dependencies:
"@babel/runtime" "^7.9.2"
regenerator-runtime@^0.13.4: regenerator-runtime@^0.13.4:
version "0.13.9" version "0.13.9"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
reselect@^4.1.5:
version "4.1.6"
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.6.tgz#19ca2d3d0b35373a74dc1c98692cdaffb6602656"
integrity sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ==
resolve-from@^4.0.0: resolve-from@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
@ -1199,6 +1273,11 @@ use-latest@^1.2.1:
dependencies: dependencies:
use-isomorphic-layout-effect "^1.1.1" use-isomorphic-layout-effect "^1.1.1"
use-sync-external-store@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
vite@^3.0.0: vite@^3.0.0:
version "3.0.4" version "3.0.4"
resolved "https://registry.yarnpkg.com/vite/-/vite-3.0.4.tgz#c61688d6b97573e96cf5ac25f2d68597b5ce68e8" resolved "https://registry.yarnpkg.com/vite/-/vite-3.0.4.tgz#c61688d6b97573e96cf5ac25f2d68597b5ce68e8"
@ -1211,6 +1290,11 @@ vite@^3.0.0:
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.2"
ws@^8.8.1:
version "8.8.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.1.tgz#5dbad0feb7ade8ecc99b830c1d77c913d4955ff0"
integrity sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==
yaml@^1.10.0: yaml@^1.10.0:
version "1.10.2" version "1.10.2"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"