diff --git a/dist/index.js b/dist/index.js
new file mode 100644
index 0000000..6b3d214
--- /dev/null
+++ b/dist/index.js
@@ -0,0 +1,208 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const express_1 = __importDefault(require("express"));
+const http_1 = __importDefault(require("http"));
+const socket_io_1 = require("socket.io");
+const admin_ui_1 = require("@socket.io/admin-ui");
+const app = (0, express_1.default)();
+const server = http_1.default.createServer(app);
+const io = new socket_io_1.Server(server);
+class Client {
+ get login() {
+ return this._login;
+ }
+ get password() {
+ return this._password;
+ }
+ get inGame() {
+ return this._inGame;
+ }
+ constructor(login, password) {
+ this._login = login;
+ this._password = password;
+ this._inGame = false;
+ }
+ setInGame(inGame) {
+ this._inGame = inGame;
+ }
+}
+class Game {
+ constructor(player1, player2) {
+ this.player1 = player1;
+ this.player2 = player2;
+ this.turn = 1;
+ this.board = [
+ [0, 0, 0],
+ [0, 0, 0],
+ [0, 0, 0],
+ ];
+ }
+}
+class Room {
+ get availablePlayers() {
+ return this._availablePlayers;
+ }
+ constructor() {
+ this._availablePlayers = new Map();
+ }
+ addPlayer(player) {
+ this._availablePlayers.set(player.login, player);
+ }
+ removePlayer(player) {
+ this._availablePlayers.delete(player.login);
+ }
+}
+let registeredClients = [];
+let onlineClients = new Map();
+let guessersRoom = new Room();
+let suggestersRoom = new Room();
+app.get("/", (req, res) => {
+ res.send("
Hello world
");
+});
+io.on("connection", (socket) => {
+ console.log("someone connected");
+ socket.emit("hello", "I don't know you");
+ socket.on("register", (login, password) => {
+ console.log("user send register with login: " + login + " and password: " + password);
+ if (login.length < 3 || login.length > 20 || password.length < 3 || password.length > 20) {
+ socket.emit("register", false, "Login or password is too short or too long");
+ console.log("user tried to register with too short or too long login or password");
+ return;
+ }
+ if (registeredClients.find((client) => client.login === login)) {
+ socket.emit("register", false, "User with this login already exists");
+ console.log("user tried to register with existing login");
+ return;
+ }
+ registeredClients.push(new Client(login, password));
+ onlineClients.set(socket, new Client(login, password));
+ socket.emit("register", true, "User registered successfully");
+ console.log("user registered successfully");
+ });
+ socket.on("login", (login, password) => {
+ console.log("user send login with login: " + login + " and password: " + password);
+ if (login.length < 3 || login.length > 20 || password.length < 3 || password.length > 20) {
+ socket.emit("login", false, "Login or password is too short or too long");
+ console.log("user tried to login with too short or too long login or password");
+ return;
+ }
+ if (!registeredClients.find((client) => client.login === login)) {
+ socket.emit("login", false, "User with this login does not exist");
+ console.log("user tried to login with non existing login");
+ return;
+ }
+ if (registeredClients.find((client) => client.login === login && client.password !== password)) {
+ socket.emit("login", false, "Wrong password");
+ console.log("user tried to login with wrong password");
+ return;
+ }
+ onlineClients.set(socket, new Client(login, password));
+ socket.emit("login", true, "User logged in successfully");
+ io.emit("updateNeeded");
+ });
+ socket.on("getUpdate", () => {
+ const client = onlineClients.get(socket);
+ if (client === undefined) {
+ socket.emit("update", false, 403);
+ return;
+ }
+ socket.emit("update", true, {
+ guessers: Array.from(guessersRoom.availablePlayers.values()).map((e) => e.login),
+ suggesters: Array.from(suggestersRoom.availablePlayers.values()).map((e) => e.login),
+ });
+ });
+ socket.on("join", (room) => {
+ const client = onlineClients.get(socket);
+ if (client === undefined) {
+ socket.emit("joinResponse", false, 403);
+ return;
+ }
+ if (client.inGame || guessersRoom.availablePlayers.has(client.login) || suggestersRoom.availablePlayers.has(client.login)) {
+ socket.emit("joinResponse", false, 400);
+ return;
+ }
+ if (room === "guessers") {
+ guessersRoom.addPlayer(client);
+ console.log("user " + client.login + " joined guessers");
+ socket.emit("joinResponse", [true]);
+ io.emit("updateNeeded");
+ }
+ else if (room === "suggesters") {
+ suggestersRoom.addPlayer(client);
+ console.log("user " + client.login + " joined suggesters");
+ socket.emit("joinResponse", [true]);
+ io.emit("updateNeeded");
+ }
+ else {
+ socket.emit("joinResponse", false, 400);
+ console.log("user " + client.login + " tried to join non existing room");
+ }
+ });
+ socket.on("leave", (room) => {
+ const client = onlineClients.get(socket);
+ if (client === undefined) {
+ socket.emit("leaveResponse", false, 403);
+ return;
+ }
+ if (client.inGame || (!guessersRoom.availablePlayers.has(client.login) && !suggestersRoom.availablePlayers.has(client.login))) {
+ socket.emit("leaveResponse", false, 400);
+ return;
+ }
+ if (room === "guessers") {
+ guessersRoom.removePlayer(client);
+ console.log("user " + client.login + " left guessers");
+ socket.emit("leaveResponse", [true]);
+ io.emit("updateNeeded");
+ }
+ else if (room === "suggesters") {
+ suggestersRoom.removePlayer(client);
+ console.log("user " + client.login + " left suggesters");
+ socket.emit("leaveResponse", [true]);
+ io.emit("updateNeeded");
+ }
+ else {
+ socket.emit("leaveResponse", false, 400);
+ console.log("user " + client.login + " tried to left non existing room");
+ }
+ });
+ socket.on("sendRequest", (sendTo) => {
+ const client = onlineClients.get(socket);
+ if (client === undefined) {
+ socket.emit("sendRequestResponse", false, 403);
+ return;
+ }
+ if (client.inGame || sendTo === client.login) {
+ socket.emit("sendRequestResponse", false, 400);
+ return;
+ }
+ const otherClientSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key).login === sendTo);
+ if (otherClientSocket === undefined) {
+ socket.emit("sendRequestResponse", false, 404);
+ return;
+ }
+ otherClientSocket.emit("gameRequest", client.login);
+ socket.emit("sendRequestResponse", [true]);
+ });
+ socket.on("disconnect", () => {
+ const client = onlineClients.get(socket);
+ if (client !== undefined) {
+ console.log("user " + client.login + " disconnected");
+ guessersRoom.removePlayer(client);
+ suggestersRoom.removePlayer(client);
+ onlineClients.delete(socket);
+ }
+ else {
+ console.log("anonymous disconnected");
+ }
+ io.emit("updateNeeded");
+ });
+});
+(0, admin_ui_1.instrument)(io, {
+ auth: false,
+});
+server.listen(9800, () => {
+ console.log("⚡️ listening on *:9800");
+});
diff --git a/index.js b/index.js
deleted file mode 100644
index 8c42199..0000000
--- a/index.js
+++ /dev/null
@@ -1,99 +0,0 @@
-const express = require('express');
-const app = express();
-const http = require('http');
-const server = http.createServer(app);
-const { Server, Socket } = require("socket.io");
-const { instrument } = require("@socket.io/admin-ui");
-const io = new Server(server);
-
-class Client {
- constructor(login, password) {
- this.login = login;
- this.password = password;
- }
-}
-
-class Game {
- constructor(id, player1, player2) {
- this.id = id;
- this.player1 = player1;
- this.player2 = player2;
- this.turn = 1;
- this.board = [
- [0, 0, 0],
- [0, 0, 0],
- [0, 0, 0]
- ];
- }
-}
-
-/** @type {Client[]} */
-let registeredClients = [];
-
-/** @type {Map} */
-let onlineClients = new Map();
-
-let games = [];
-
-app.get('/', (req, res) => {
- res.send('Hello world
');
-});
-
-io.on('connection', (socket) => {
- console.log('someone connected');
-
- socket.on('register', (login, password) => {
- console.log('user send register with login: ' + login + ' and password: ' + password);
- if (login.length < 3 || login.length > 20 || password.length < 3 || password.length > 20) {
- socket.emit('register', false, 'Login or password is too short or too long');
- console.log('user tried to register with too short or too long login or password');
- return;
- }
- if (registeredClients.find(client => client.login === login)) {
- socket.emit('register', false, 'User with this login already exists');
- console.log('user tried to register with existing login');
- return;
- }
- registeredClients.push(new Client(login, password));
- onlineClients.set(socket, new Client(login, password));
- socket.emit('register', true, 'User registered successfully');
- console.log('user registered successfully');
- });
-
- socket.on('login', (login, password) => {
- console.log('user send login with login: ' + login + ' and password: ' + password);
- if (login.length < 3 || login.length > 20 || password.length < 3 || password.length > 20) {
- socket.emit('login', false, 'Login or password is too short or too long');
- console.log('user tried to login with too short or too long login or password');
- return;
- }
- if (!registeredClients.find(client => client.login === login)) {
- socket.emit('login', false, 'User with this login does not exist');
- console.log('user tried to login with non existing login');
- return;
- }
- if (registeredClients.find(client => client.login === login && client.password !== password)) {
- socket.emit('login', false, 'Wrong password');
- console.log('user tried to login with wrong password');
- return;
- }
- onlineClients.set(socket, new Client(login, password));
- socket.emit('login', true, 'User logged in successfully');
- });
-
- socket.on('disconnect', () => {
- if (onlineClients.has(socket)) {
- console.log('user ' + onlineClients.get(socket).login + ' disconnected');
- } else {
- console.log('anonymous disconnected');
- }
- });
-});
-
-instrument(io, {
- auth: false
-});
-
-server.listen(9800, () => {
- console.log('listening on *:9800');
-});
\ No newline at end of file
diff --git a/package.json b/package.json
index 7a0d071..355de73 100644
--- a/package.json
+++ b/package.json
@@ -4,14 +4,22 @@
"description": "",
"main": "index.js",
"scripts": {
- "start": "node index.js"
+ "build": "npx tsc",
+ "start": "node dist/index.js",
+ "dev": "concurrently \"npx tsc --watch\" \"nodemon -q dist/index.js\""
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@socket.io/admin-ui": "^0.5.1",
+ "dotenv": "^16.0.3",
"express": "^4.18.2",
"socket.io": "^4.6.1"
+ },
+ "devDependencies": {
+ "@types/express": "^4.17.17",
+ "@types/node": "^18.14.4",
+ "typescript": "^4.9.5"
}
}
\ No newline at end of file
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0e0de97..e8c3c99 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2,14 +2,28 @@ lockfileVersion: 5.4
specifiers:
'@socket.io/admin-ui': ^0.5.1
+ '@types/express': ^4.17.17
+ '@types/node': ^18.14.4
+ concurrently: ^7.6.0
+ dotenv: ^16.0.3
express: ^4.18.2
+ nodemon: ^2.0.20
socket.io: ^4.6.1
+ typescript: ^4.9.5
dependencies:
'@socket.io/admin-ui': 0.5.1_socket.io@4.6.1
+ dotenv: 16.0.3
express: 4.18.2
socket.io: 4.6.1
+devDependencies:
+ '@types/express': 4.17.17
+ '@types/node': 18.14.4
+ concurrently: 7.6.0
+ nodemon: 2.0.20
+ typescript: 4.9.5
+
packages:
/@socket.io/admin-ui/0.5.1_socket.io@4.6.1:
@@ -33,6 +47,19 @@ packages:
resolution: {integrity: sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ==}
dev: false
+ /@types/body-parser/1.19.2:
+ resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==}
+ dependencies:
+ '@types/connect': 3.4.35
+ '@types/node': 18.14.4
+ dev: true
+
+ /@types/connect/3.4.35:
+ resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==}
+ dependencies:
+ '@types/node': 18.14.4
+ dev: true
+
/@types/cookie/0.4.1:
resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==}
dev: false
@@ -40,12 +67,51 @@ packages:
/@types/cors/2.8.13:
resolution: {integrity: sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==}
dependencies:
- '@types/node': 18.14.2
+ '@types/node': 18.14.4
dev: false
- /@types/node/18.14.2:
- resolution: {integrity: sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA==}
- dev: false
+ /@types/express-serve-static-core/4.17.33:
+ resolution: {integrity: sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==}
+ dependencies:
+ '@types/node': 18.14.4
+ '@types/qs': 6.9.7
+ '@types/range-parser': 1.2.4
+ dev: true
+
+ /@types/express/4.17.17:
+ resolution: {integrity: sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==}
+ dependencies:
+ '@types/body-parser': 1.19.2
+ '@types/express-serve-static-core': 4.17.33
+ '@types/qs': 6.9.7
+ '@types/serve-static': 1.15.1
+ dev: true
+
+ /@types/mime/3.0.1:
+ resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==}
+ dev: true
+
+ /@types/node/18.14.4:
+ resolution: {integrity: sha512-VhCw7I7qO2X49+jaKcAUwi3rR+hbxT5VcYF493+Z5kMLI0DL568b7JI4IDJaxWFH0D/xwmGJNoXisyX+w7GH/g==}
+
+ /@types/qs/6.9.7:
+ resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==}
+ dev: true
+
+ /@types/range-parser/1.2.4:
+ resolution: {integrity: sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==}
+ dev: true
+
+ /@types/serve-static/1.15.1:
+ resolution: {integrity: sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==}
+ dependencies:
+ '@types/mime': 3.0.1
+ '@types/node': 18.14.4
+ dev: true
+
+ /abbrev/1.1.1:
+ resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
+ dev: true
/accepts/1.3.8:
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
@@ -55,10 +121,34 @@ packages:
negotiator: 0.6.3
dev: false
+ /ansi-regex/5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /ansi-styles/4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+ dependencies:
+ color-convert: 2.0.1
+ dev: true
+
+ /anymatch/3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+ dev: true
+
/array-flatten/1.1.1:
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
dev: false
+ /balanced-match/1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ dev: true
+
/base64id/2.0.0:
resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==}
engines: {node: ^4.5.0 || >= 5.9}
@@ -68,6 +158,11 @@ packages:
resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==}
dev: false
+ /binary-extensions/2.2.0:
+ resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
+ engines: {node: '>=8'}
+ dev: true
+
/body-parser/1.20.1:
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
@@ -88,6 +183,20 @@ packages:
- supports-color
dev: false
+ /brace-expansion/1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+ dev: true
+
+ /braces/3.0.2:
+ resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+ engines: {node: '>=8'}
+ dependencies:
+ fill-range: 7.0.1
+ dev: true
+
/bytes/3.1.2:
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
engines: {node: '>= 0.8'}
@@ -100,6 +209,69 @@ packages:
get-intrinsic: 1.2.0
dev: false
+ /chalk/4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+ dev: true
+
+ /chokidar/3.5.3:
+ resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
+ engines: {node: '>= 8.10.0'}
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.2
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /cliui/8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+ dev: true
+
+ /color-convert/2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+ dependencies:
+ color-name: 1.1.4
+ dev: true
+
+ /color-name/1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ dev: true
+
+ /concat-map/0.0.1:
+ resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
+ dev: true
+
+ /concurrently/7.6.0:
+ resolution: {integrity: sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==}
+ engines: {node: ^12.20.0 || ^14.13.0 || >=16.0.0}
+ hasBin: true
+ dependencies:
+ chalk: 4.1.2
+ date-fns: 2.29.3
+ lodash: 4.17.21
+ rxjs: 7.8.0
+ shell-quote: 1.8.0
+ spawn-command: 0.0.2-1
+ supports-color: 8.1.1
+ tree-kill: 1.2.2
+ yargs: 17.7.1
+ dev: true
+
/content-disposition/0.5.4:
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
engines: {node: '>= 0.6'}
@@ -134,6 +306,11 @@ packages:
vary: 1.1.2
dev: false
+ /date-fns/2.29.3:
+ resolution: {integrity: sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==}
+ engines: {node: '>=0.11'}
+ dev: true
+
/debug/2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
@@ -145,6 +322,18 @@ packages:
ms: 2.0.0
dev: false
+ /debug/3.2.7_supports-color@5.5.0:
+ resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.3
+ supports-color: 5.5.0
+ dev: true
+
/debug/4.3.4:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'}
@@ -167,10 +356,19 @@ packages:
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
dev: false
+ /dotenv/16.0.3:
+ resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==}
+ engines: {node: '>=12'}
+ dev: false
+
/ee-first/1.1.1:
resolution: {integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=}
dev: false
+ /emoji-regex/8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+ dev: true
+
/encodeurl/1.0.2:
resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
engines: {node: '>= 0.8'}
@@ -187,7 +385,7 @@ packages:
dependencies:
'@types/cookie': 0.4.1
'@types/cors': 2.8.13
- '@types/node': 18.14.2
+ '@types/node': 18.14.4
accepts: 1.3.8
base64id: 2.0.0
cookie: 0.4.2
@@ -201,6 +399,11 @@ packages:
- utf-8-validate
dev: false
+ /escalade/3.1.1:
+ resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
+ engines: {node: '>=6'}
+ dev: true
+
/escape-html/1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
dev: false
@@ -249,6 +452,13 @@ packages:
- supports-color
dev: false
+ /fill-range/7.0.1:
+ resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ to-regex-range: 5.0.1
+ dev: true
+
/finalhandler/1.2.0:
resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==}
engines: {node: '>= 0.8'}
@@ -274,10 +484,23 @@ packages:
engines: {node: '>= 0.6'}
dev: false
+ /fsevents/2.3.2:
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/function-bind/1.1.1:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
dev: false
+ /get-caller-file/2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+ dev: true
+
/get-intrinsic/1.2.0:
resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==}
dependencies:
@@ -286,6 +509,23 @@ packages:
has-symbols: 1.0.3
dev: false
+ /glob-parent/5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /has-flag/3.0.0:
+ resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /has-flag/4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
/has-symbols/1.0.3:
resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
engines: {node: '>= 0.4'}
@@ -316,6 +556,10 @@ packages:
safer-buffer: 2.1.2
dev: false
+ /ignore-by-default/1.0.1:
+ resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==}
+ dev: true
+
/inherits/2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: false
@@ -325,6 +569,39 @@ packages:
engines: {node: '>= 0.10'}
dev: false
+ /is-binary-path/2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+ dependencies:
+ binary-extensions: 2.2.0
+ dev: true
+
+ /is-extglob/2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-fullwidth-code-point/3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-glob/4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ is-extglob: 2.1.1
+ dev: true
+
+ /is-number/7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+ dev: true
+
+ /lodash/4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+ dev: true
+
/media-typer/0.3.0:
resolution: {integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=}
engines: {node: '>= 0.6'}
@@ -357,6 +634,12 @@ packages:
hasBin: true
dev: false
+ /minimatch/3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ dependencies:
+ brace-expansion: 1.1.11
+ dev: true
+
/ms/2.0.0:
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
dev: false
@@ -367,13 +650,41 @@ packages:
/ms/2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
- dev: false
/negotiator/0.6.3:
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
engines: {node: '>= 0.6'}
dev: false
+ /nodemon/2.0.20:
+ resolution: {integrity: sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==}
+ engines: {node: '>=8.10.0'}
+ hasBin: true
+ dependencies:
+ chokidar: 3.5.3
+ debug: 3.2.7_supports-color@5.5.0
+ ignore-by-default: 1.0.1
+ minimatch: 3.1.2
+ pstree.remy: 1.1.8
+ semver: 5.7.1
+ simple-update-notifier: 1.1.0
+ supports-color: 5.5.0
+ touch: 3.1.0
+ undefsafe: 2.0.5
+ dev: true
+
+ /nopt/1.0.10:
+ resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==}
+ hasBin: true
+ dependencies:
+ abbrev: 1.1.1
+ dev: true
+
+ /normalize-path/3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
/object-assign/4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
@@ -399,6 +710,11 @@ packages:
resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
dev: false
+ /picomatch/2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+ dev: true
+
/proxy-addr/2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
@@ -407,6 +723,10 @@ packages:
ipaddr.js: 1.9.1
dev: false
+ /pstree.remy/1.1.8:
+ resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==}
+ dev: true
+
/qs/6.11.0:
resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==}
engines: {node: '>=0.6'}
@@ -429,6 +749,24 @@ packages:
unpipe: 1.0.0
dev: false
+ /readdirp/3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+ dependencies:
+ picomatch: 2.3.1
+ dev: true
+
+ /require-directory/2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /rxjs/7.8.0:
+ resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==}
+ dependencies:
+ tslib: 2.5.0
+ dev: true
+
/safe-buffer/5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
dev: false
@@ -437,6 +775,16 @@ packages:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
dev: false
+ /semver/5.7.1:
+ resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
+ hasBin: true
+ dev: true
+
+ /semver/7.0.0:
+ resolution: {integrity: sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==}
+ hasBin: true
+ dev: true
+
/send/0.18.0:
resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
engines: {node: '>= 0.8.0'}
@@ -474,6 +822,10 @@ packages:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
dev: false
+ /shell-quote/1.8.0:
+ resolution: {integrity: sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==}
+ dev: true
+
/side-channel/1.0.4:
resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
dependencies:
@@ -482,6 +834,13 @@ packages:
object-inspect: 1.12.3
dev: false
+ /simple-update-notifier/1.1.0:
+ resolution: {integrity: sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==}
+ engines: {node: '>=8.10.0'}
+ dependencies:
+ semver: 7.0.0
+ dev: true
+
/socket.io-adapter/2.5.2:
resolution: {integrity: sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==}
dependencies:
@@ -517,16 +876,80 @@ packages:
- utf-8-validate
dev: false
+ /spawn-command/0.0.2-1:
+ resolution: {integrity: sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==}
+ dev: true
+
/statuses/2.0.1:
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'}
dev: false
+ /string-width/4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+ dev: true
+
+ /strip-ansi/6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-regex: 5.0.1
+ dev: true
+
+ /supports-color/5.5.0:
+ resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+ engines: {node: '>=4'}
+ dependencies:
+ has-flag: 3.0.0
+ dev: true
+
+ /supports-color/7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /supports-color/8.1.1:
+ resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
+ engines: {node: '>=10'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /to-regex-range/5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+ dependencies:
+ is-number: 7.0.0
+ dev: true
+
/toidentifier/1.0.1:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
dev: false
+ /touch/3.1.0:
+ resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==}
+ hasBin: true
+ dependencies:
+ nopt: 1.0.10
+ dev: true
+
+ /tree-kill/1.2.2:
+ resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+ hasBin: true
+ dev: true
+
+ /tslib/2.5.0:
+ resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==}
+ dev: true
+
/type-is/1.6.18:
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
engines: {node: '>= 0.6'}
@@ -535,6 +958,16 @@ packages:
mime-types: 2.1.35
dev: false
+ /typescript/4.9.5:
+ resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==}
+ engines: {node: '>=4.2.0'}
+ hasBin: true
+ dev: true
+
+ /undefsafe/2.0.5:
+ resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==}
+ dev: true
+
/unpipe/1.0.0:
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
engines: {node: '>= 0.8'}
@@ -550,6 +983,15 @@ packages:
engines: {node: '>= 0.8'}
dev: false
+ /wrap-ansi/7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ dev: true
+
/ws/8.11.0:
resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==}
engines: {node: '>=10.0.0'}
@@ -562,3 +1004,26 @@ packages:
utf-8-validate:
optional: true
dev: false
+
+ /y18n/5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /yargs-parser/21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /yargs/17.7.1:
+ resolution: {integrity: sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==}
+ engines: {node: '>=12'}
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.1.1
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
+ dev: true
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 0000000..d1d60c7
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,243 @@
+import express, { Express, Request, Response } from "express";
+import http from "http";
+
+import { Server, Socket } from "socket.io";
+import { instrument } from "@socket.io/admin-ui";
+
+const app = express();
+const server = http.createServer(app);
+
+const io = new Server(server);
+
+class Client {
+ private _login: String;
+ private _password: String;
+ private _inGame: Boolean;
+
+ public get login() {
+ return this._login;
+ }
+ public get password() {
+ return this._password;
+ }
+ public get inGame() {
+ return this._inGame;
+ }
+
+ constructor(login: String, password: String) {
+ this._login = login;
+ this._password = password;
+ this._inGame = false;
+ }
+
+ public setInGame(inGame: Boolean) {
+ this._inGame = inGame;
+ }
+}
+
+class Game {
+ private player1: Client;
+ private player2: Client;
+ private turn: Number;
+ private board: Number[][];
+
+ constructor(player1: Client, player2: Client) {
+ this.player1 = player1;
+ this.player2 = player2;
+ this.turn = 1;
+ this.board = [
+ [0, 0, 0],
+ [0, 0, 0],
+ [0, 0, 0],
+ ];
+ }
+}
+
+class Room {
+ private _availablePlayers: Map;
+
+ public get availablePlayers() {
+ return this._availablePlayers;
+ }
+
+ constructor() {
+ this._availablePlayers = new Map();
+ }
+
+ public addPlayer(player: Client) {
+ this._availablePlayers.set(player.login, player);
+ }
+
+ public removePlayer(player: Client) {
+ this._availablePlayers.delete(player.login);
+ }
+}
+
+let registeredClients: Client[] = [];
+let onlineClients: Map = new Map();
+let guessersRoom: Room = new Room();
+let suggestersRoom: Room = new Room();
+
+app.get("/", (req, res) => {
+ res.send("Hello world
");
+});
+
+io.on("connection", (socket) => {
+ console.log("someone connected");
+
+ socket.emit("hello", "I don't know you");
+
+ socket.on("register", (login, password) => {
+ console.log("user send register with login: " + login + " and password: " + password);
+ if (login.length < 3 || login.length > 20 || password.length < 3 || password.length > 20) {
+ socket.emit("register", false, "Login or password is too short or too long");
+ console.log("user tried to register with too short or too long login or password");
+ return;
+ }
+ if (registeredClients.find((client) => client.login === login)) {
+ socket.emit("register", false, "User with this login already exists");
+ console.log("user tried to register with existing login");
+ return;
+ }
+ registeredClients.push(new Client(login, password));
+ onlineClients.set(socket, new Client(login, password));
+ socket.emit("register", true, "User registered successfully");
+ console.log("user registered successfully");
+ });
+
+ socket.on("login", (login, password) => {
+ console.log("user send login with login: " + login + " and password: " + password);
+ if (login.length < 3 || login.length > 20 || password.length < 3 || password.length > 20) {
+ socket.emit("login", false, "Login or password is too short or too long");
+ console.log("user tried to login with too short or too long login or password");
+ return;
+ }
+ if (!registeredClients.find((client) => client.login === login)) {
+ socket.emit("login", false, "User with this login does not exist");
+ console.log("user tried to login with non existing login");
+ return;
+ }
+ if (registeredClients.find((client) => client.login === login && client.password !== password)) {
+ socket.emit("login", false, "Wrong password");
+ console.log("user tried to login with wrong password");
+ return;
+ }
+ onlineClients.set(socket, new Client(login, password));
+ socket.emit("login", true, "User logged in successfully");
+
+ io.emit("updateNeeded");
+ });
+
+ socket.on("getUpdate", () => {
+ const client = onlineClients.get(socket);
+ if (client === undefined) {
+ socket.emit("update", false, 403);
+ return;
+ }
+
+ socket.emit("update", true, {
+ guessers: Array.from(guessersRoom.availablePlayers.values()).map((e) => e.login),
+ suggesters: Array.from(suggestersRoom.availablePlayers.values()).map((e) => e.login),
+ });
+ });
+
+ socket.on("join", (room) => {
+ const client = onlineClients.get(socket);
+ if (client === undefined) {
+ socket.emit("joinResponse", false, 403);
+ return;
+ }
+
+ if (client.inGame || guessersRoom.availablePlayers.has(client.login) || suggestersRoom.availablePlayers.has(client.login)) {
+ socket.emit("joinResponse", false, 400);
+ return;
+ }
+
+ if (room === "guessers") {
+ guessersRoom.addPlayer(client);
+ console.log("user " + client.login + " joined guessers");
+ socket.emit("joinResponse", [true]);
+ io.emit("updateNeeded");
+ } else if (room === "suggesters") {
+ suggestersRoom.addPlayer(client);
+ console.log("user " + client.login + " joined suggesters");
+ socket.emit("joinResponse", [true]);
+ io.emit("updateNeeded");
+ } else {
+ socket.emit("joinResponse", false, 400);
+ console.log("user " + client.login + " tried to join non existing room");
+ }
+ });
+
+ socket.on("leave", (room) => {
+ const client = onlineClients.get(socket);
+ if (client === undefined) {
+ socket.emit("leaveResponse", false, 403);
+ return;
+ }
+
+ if (client.inGame || (!guessersRoom.availablePlayers.has(client.login) && !suggestersRoom.availablePlayers.has(client.login))) {
+ socket.emit("leaveResponse", false, 400);
+ return;
+ }
+
+ if (room === "guessers") {
+ guessersRoom.removePlayer(client);
+ console.log("user " + client.login + " left guessers");
+ socket.emit("leaveResponse", [true]);
+ io.emit("updateNeeded");
+ } else if (room === "suggesters") {
+ suggestersRoom.removePlayer(client);
+ console.log("user " + client.login + " left suggesters");
+ socket.emit("leaveResponse", [true]);
+ io.emit("updateNeeded");
+ } else {
+ socket.emit("leaveResponse", false, 400);
+ console.log("user " + client.login + " tried to left non existing room");
+ }
+ });
+
+ socket.on("sendRequest", (sendTo) => {
+ const client = onlineClients.get(socket);
+ if (client === undefined) {
+ socket.emit("sendRequestResponse", false, 403);
+ return;
+ }
+
+ if (client.inGame || sendTo === client.login) {
+ socket.emit("sendRequestResponse", false, 400);
+ return;
+ }
+
+ const otherClientSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)!!.login === sendTo);
+ if (otherClientSocket === undefined) {
+ socket.emit("sendRequestResponse", false, 404);
+ return;
+ }
+
+ otherClientSocket.emit("gameRequest", client.login);
+ socket.emit("sendRequestResponse", [true]);
+ });
+
+ socket.on("disconnect", () => {
+ const client = onlineClients.get(socket);
+ if (client !== undefined) {
+ console.log("user " + client.login + " disconnected");
+ guessersRoom.removePlayer(client);
+ suggestersRoom.removePlayer(client);
+ onlineClients.delete(socket);
+ } else {
+ console.log("anonymous disconnected");
+ }
+
+ io.emit("updateNeeded");
+ });
+});
+
+instrument(io, {
+ auth: false,
+});
+
+server.listen(9800, () => {
+ console.log("⚡️ listening on *:9800");
+});
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..ad9258d
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,103 @@
+{
+ "compilerOptions": {
+ /* Visit https://aka.ms/tsconfig to read more about this file */
+
+ /* Projects */
+ // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
+ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
+ // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
+ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
+ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
+ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
+
+ /* Language and Environment */
+ "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
+ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
+ // "jsx": "preserve", /* Specify what JSX code is generated. */
+ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
+ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
+ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
+ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
+ // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
+ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
+ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
+ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
+
+ /* Modules */
+ "module": "commonjs" /* Specify what module code is generated. */,
+ "rootDir": "./src" /* Specify the root folder within your source files. */,
+ // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
+ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
+ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
+ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
+ // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
+ // "types": [], /* Specify type package names to be included without being referenced in a source file. */
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
+ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "resolveJsonModule": true, /* Enable importing .json files. */
+ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
+
+ /* JavaScript Support */
+ // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
+ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
+ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
+
+ /* Emit */
+ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+ // "declarationMap": true, /* Create sourcemaps for d.ts files. */
+ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
+ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
+ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
+ "outDir": "./dist" /* Specify an output folder for all emitted files. */,
+ // "removeComments": true, /* Disable emitting comments. */
+ // "noEmit": true, /* Disable emitting files from a compilation. */
+ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
+ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+ // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
+ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
+ // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
+ // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+ // "newLine": "crlf", /* Set the newline character for emitting files. */
+ // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
+ // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
+ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
+ // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
+ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
+ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+
+ /* Interop Constraints */
+ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
+ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
+ "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
+ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
+ "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
+
+ /* Type Checking */
+ "strict": true /* Enable all strict type-checking options. */,
+ // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
+ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
+ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
+ // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
+ // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
+ // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
+ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
+ // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
+ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
+ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
+ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
+ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
+ // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
+ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
+ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
+ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
+ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
+
+ /* Completeness */
+ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */
+ }
+}