From 7585f6a40b85589c17b2c7949f5feb3b2f655eb3 Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Fri, 3 Mar 2023 01:50:23 +0700 Subject: [PATCH] Moving to TS, add user lists commands --- dist/index.js | 208 +++++++++++++++++++++ index.js | 99 ---------- package.json | 10 +- pnpm-lock.yaml | 477 ++++++++++++++++++++++++++++++++++++++++++++++++- src/index.ts | 243 +++++++++++++++++++++++++ tsconfig.json | 103 +++++++++++ 6 files changed, 1034 insertions(+), 106 deletions(-) create mode 100644 dist/index.js delete mode 100644 index.js create mode 100644 src/index.ts create mode 100644 tsconfig.json 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. */ + } +}