1
Fork 0

Move server & lib to separate repository

This commit is contained in:
Tobias Berger 2022-01-07 19:02:56 +01:00
parent 1acc2566be
commit a47a9d7da3
12 changed files with 199 additions and 165 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "src/lib"]
path = src/lib
url = https://github.com/Toby222/web-drs-lib.git

View file

@ -1,25 +0,0 @@
import { WebSocketServer } from "ws";
const port = 8989;
const wss = new WebSocketServer({ port: port });
console.log("listening on port: " + port);
wss.on("connection", function connection(ws) {
ws.on("message", function (message) {
console.log("message: " + message);
ws.send(
JSON.stringify({
date: Date.now(),
author: "ECHO Service",
content: message.toString("utf-8"),
})
);
});
ws.on("close", function close() {
console.log("closed a connection");
});
console.log("new client connected!");
ws.send("connected!");
});

View file

@ -1,6 +1,7 @@
module.exports = {
eslint: {
ignoreDuringBuilds: true,
reactStrictMode: true,
},
webpack(config, { dev }) {
if (!dev) {

View file

@ -22,6 +22,7 @@
"next": "^11.0.1",
"preact": "^10.5.14",
"react-use-websocket": "^2.9.1",
"sass": "^1.46.0",
"typescript": "^4.3.5"
},
"devDependencies": {
@ -39,8 +40,7 @@
"pre-commit": "^1.2.2",
"prettier": "^2.3.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"ws": "^8.4.0"
"react-dom": "^17.0.2"
},
"pre-commit": "test",
"license": "MIT"

View file

@ -0,0 +1,16 @@
import { FunctionComponent } from "react";
import { TextMessage } from "src/lib/types/ServerMessage";
type Props = {
message: TextMessage;
};
const MessageComponent: FunctionComponent<Props> = ({ message }) => {
return (
<span>
{new Date(message.date).toISOString()}
{message.content}
</span>
);
};
export default MessageComponent;

1
src/lib Submodule

@ -0,0 +1 @@
Subproject commit 9fc4e8f80d335abc3ab02bfc24d64afcc91f3567

View file

@ -1,3 +1,3 @@
import "./styles.css";
import "../styles.scss";
export { default } from "next/app";

View file

@ -1,83 +1,108 @@
import { useCallback, useState } from "react";
import useWebSocket, {
ReadyState,
ReadyState as WebSocketReadyState,
} from "react-use-websocket";
import type { Message } from "../util/types/Message";
import MessageComponent from "src/components/Message";
import { MessageType, TextMessage } from "src/lib/types/ServerMessage";
import { isServerMessage, isTextMessage } from "src/lib/types/ServerMessage";
export default function Index(): JSX.Element {
const [enableSSL, setEnableSSL] = useState(true);
const protocol = enableSSL ? "wss" : "ws";
const [count, setCount] = useState(0);
const [messageHistory, setMessageHistory] = useState<Message[]>([]);
const [socketUrl, setSocketUrl] = useState(
"wss://toby222-web-drs-4gjg49gj355qq-8989.githubpreview.dev/"
);
const [messageHistory, setMessageHistory] = useState<TextMessage[]>([]);
const [socketUrl, setSocketUrl] = useState("localhost:8989/");
function onMessage(event: MessageEvent<string>): void {
const message: Message = JSON.parse(event.data);
const message = JSON.parse(event.data);
setMessageHistory([message, ...messageHistory]);
if (!isServerMessage(message)) {
console.log("DEBUG: ", message);
throw new Error(`Server sent unexpected message \`${event.data}}\``);
}
if (isTextMessage(message)) {
setMessageHistory([message, ...messageHistory]);
}
}
const websocket = useWebSocket(socketUrl, {
let keepAliveInterval: NodeJS.Timeout;
const websocket = useWebSocket(protocol + ":" + socketUrl, {
onMessage,
onOpen() {
keepAliveInterval = setInterval(() => {
websocket.sendJsonMessage({
type: MessageType.ACK,
date: Date.now(),
});
}, 1000);
},
onClose() {
clearInterval(keepAliveInterval);
},
});
const handleClickSendMessage = useCallback(() => {
setCount(count + 1);
websocket.sendMessage(`${count + 1}`);
const message: TextMessage = {
author: "AUTHOR NOT IMPLEMENTED YET",
type: MessageType.TEXT,
date: Date.now(),
content: `Hello, world! ${count}`,
};
websocket.sendJsonMessage(message);
}, [count, websocket]);
const connectionStatus = {
[WebSocketReadyState.CONNECTING]: "Connecting",
[WebSocketReadyState.OPEN]: "Open",
[WebSocketReadyState.CLOSING]: "Closing",
[WebSocketReadyState.CLOSED]: "Closed",
[WebSocketReadyState.UNINSTANTIATED]: "Uninstantiated",
}[websocket.readyState];
const trySetSocketUrl = useCallback(
(url: string) => {
try {
console.log(new URL(protocol + ":" + url), url);
setSocketUrl(url);
} catch (e) {
console.debug("Invalid URL");
// Invalid URL, don't do anything
} finally {
if (websocket.readyState === WebSocketReadyState.OPEN) {
websocket.getWebSocket()?.close();
}
}
},
[websocket, protocol]
);
function trySetSocketUrl(url: string) {
try {
console.log(new URL("wss:" + url), url);
setSocketUrl("wss:" + url);
} catch (e) {
// Invalid URL, don't do anything
} finally {
websocket.getWebSocket()?.close();
}
}
const toggleSSL = useCallback(() => {
setEnableSSL(!enableSSL);
trySetSocketUrl(socketUrl.replace(/^wss?/, protocol));
}, [enableSSL, socketUrl, trySetSocketUrl, protocol]);
return (
<>
<span>
Ready state: {ReadyState[websocket.readyState]} ({websocket.readyState})
</span>
<main>
{/* DEBUG
<div>
<h4>Last messages:</h4>
{websocket.lastMessage?.data.toString() ?? "No message received"}
<hr />
<h4>Ready state:</h4>
{connectionStatus} ({websocket.readyState})
</div>
*/}
<ol>
<div id="messages-container">
{messageHistory.map((message, idx) => {
return (
<span key={messageHistory.length - idx}>
<span>{new Date(message.date).toISOString()}</span>
{" - "}
<span>{message.content}</span>
<br />
</span>
);
return <MessageComponent message={message} key={idx} />;
})}
</ol>
<div>
</div>
<div id="message-writing-area">
<label htmlFor="ws-url">WebSocket URL:</label>
<input
id="ws-url"
type={"text"}
value={socketUrl.replace(/wss:(?:\/\/)?/, "")}
type="text"
value={socketUrl}
onChange={(e) => trySetSocketUrl(e.target.value)}
/>
<label htmlFor="wss">Enable SSL:</label>
<input
id="wss"
type="checkbox"
checked={enableSSL}
onChange={toggleSSL}
/>
<button
disabled={websocket.readyState !== WebSocketReadyState.OPEN}
onClick={handleClickSendMessage}

View file

@ -1,75 +0,0 @@
:root {
--primay: black;
--bg-primay: white;
--link: #2a0b0b;
text-align: center;
}
p {
margin: 20px 0px;
}
button {
outline: none;
border: none;
border-radius: 0;
padding: 10px 35px;
background: #845ec2;
color: white;
/* font-size: calc(10px + 2vmin); */
}
button:disabled {
filter: brightness(30%);
}
button:hover {
filter: brightness(120%);
cursor: pointer;
}
@media (prefers-reduced-motion: no-preference) {
.logo {
animation: logo-spin infinite 20s linear;
}
}
.app-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
background: var(--bg-primay);
color: var(--primay);
}
.link {
color: var(--link);
}
@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}

57
src/styles.scss Normal file
View file

@ -0,0 +1,57 @@
:root {
--primay: black;
--bg-primay: white;
--link: #2a0b0b;
text-align: center;
}
p {
margin: 20px 0px;
}
button {
outline: none;
border: none;
border-radius: 0;
padding: 10px 35px;
background: #845ec2;
color: white;
&:hover:not(:disabled) {
filter: brightness(120%);
cursor: pointer;
}
&:disabled {
filter: brightness(30%);
cursor: default;
}
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
main {
display: flex;
flex-direction: column;
height: 100vh;
justify-content: space-between;
#messages-container {
display: flex;
flex-direction: column-reverse;
overflow-y: scroll;
> :nth-child(even) {
background-color: lightgray;
}
}
#message-writing-area {
}
}

View file

@ -1,5 +0,0 @@
export type Message = {
author: string;
content: string;
date: number;
};

View file

@ -381,7 +381,7 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
anymatch@~3.1.1:
anymatch@~3.1.1, anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
@ -713,6 +713,21 @@ chokidar@3.5.1:
optionalDependencies:
fsevents "~2.3.1"
"chokidar@>=3.0.0 <4.0.0":
version "3.5.2"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75"
integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==
dependencies:
anymatch "~3.1.2"
braces "~3.0.2"
glob-parent "~5.1.2"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.6.0"
optionalDependencies:
fsevents "~2.3.2"
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
@ -1449,7 +1464,7 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
fsevents@~2.3.1:
fsevents@~2.3.1, fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
@ -1488,7 +1503,7 @@ get-symbol-description@^1.0.0:
call-bind "^1.0.2"
get-intrinsic "^1.1.1"
glob-parent@^5.1.2, glob-parent@~5.1.0:
glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
@ -1665,6 +1680,11 @@ image-size@1.0.0:
dependencies:
queue "6.0.2"
immutable@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23"
integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==
import-fresh@^3.0.0, import-fresh@^3.2.1:
version "3.3.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
@ -2658,6 +2678,13 @@ readdirp@~3.5.0:
dependencies:
picomatch "^2.2.1"
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
dependencies:
picomatch "^2.2.1"
regenerator-runtime@^0.13.4:
version "0.13.9"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
@ -2745,6 +2772,15 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sass@^1.46.0:
version "1.46.0"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.46.0.tgz#923117049525236026a7ede69715580eb0fac751"
integrity sha512-Z4BYTgioAOlMmo4LU3Ky2txR8KR0GRPLXxO38kklaYxgo7qMTgy+mpNN4eKsrXDTFlwS5vdruvazG4cihxHRVQ==
dependencies:
chokidar ">=3.0.0 <4.0.0"
immutable "^4.0.0"
source-map-js ">=0.6.2 <2.0.0"
scheduler@^0.20.2:
version "0.20.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
@ -2835,6 +2871,11 @@ slice-ansi@^4.0.0:
astral-regex "^2.0.0"
is-fullwidth-code-point "^3.0.0"
"source-map-js@>=0.6.2 <2.0.0":
version "1.0.1"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf"
integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==
source-map@0.7.3:
version "0.7.3"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
@ -3323,11 +3364,6 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
ws@^8.4.0:
version "8.4.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.4.0.tgz#f05e982a0a88c604080e8581576e2a063802bed6"
integrity sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==
xtend@^4.0.0, xtend@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"