diff --git a/Makefile b/Makefile index ba00eaec..fed7dc65 100644 --- a/Makefile +++ b/Makefile @@ -24,8 +24,7 @@ start_dev: start_prod: docker compose -f ${DOCKERCOMPOSEPATH} start prod -restart:stop - @make up +re: down dev down: docker compose -f ${DOCKERCOMPOSEPATH} -v down diff --git a/memo.txt b/memo.txt new file mode 100644 index 00000000..48f096cc --- /dev/null +++ b/memo.txt @@ -0,0 +1,50 @@ +DONE : + + +TODO : + - timeout in gameserver for private match (TO test) + + - If in game, destroy game scripts stuff when changing page. + (I need to dig deeper in svelte to know how this could work) + - mode spectateur + - quelques routes cote serveur + - une interface cote front (liste des matchs en cours) + - etat du client (en ligne, en jeu, ...) + - le chat + +-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- +"Bonus" : + - HTTPS + - mettre le site en ligne +-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- +BUG : + - Bug de son étonnant dans le front, ça pop une fois de temps en temps : + Uncaught (in promise) DOMException: The element has no supported sources. + 18.ogg et 24.ogg bug peut-etre. + - l'avatar ne se charge pas après avoir redémarré les containers (mais sans avoir supprimé les volumes) + normal ou oubli ? +-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- + +- Comment fonctionne .env ? Comment faire pour ne pas le push sur le depot ? + +- certains status 200 pourrait peut-être être du 204 ? + (exemple dans TwoFactorAuthentication.svelte) + +A la place de : +``` + if (response.status === 401) { + // Wrong + } + if (response.status === 200) { + // Ok + } +``` +On pourrait mettre : +``` + if (!response.ok) { + // Wrong + } + else { + // Ok + } +``` diff --git a/srcs/.env b/srcs/.env index a8fbadb8..33b89fe8 100644 --- a/srcs/.env +++ b/srcs/.env @@ -1,4 +1,5 @@ NODE_ENV=development +WEBSITE_HOST=transcendance POSTGRES_USER=postgres POSTGRES_PASSWORD=9pKpKEgiamxwk5P7Ggsz POSTGRES_DB=transcendance_db diff --git a/srcs/docker-compose.yml b/srcs/docker-compose.yml index 62dc9479..56d1199d 100644 --- a/srcs/docker-compose.yml +++ b/srcs/docker-compose.yml @@ -16,6 +16,18 @@ services: - postgresql - redis + game_server: + build: + context: ./requirements/game_server + dockerfile: Dockerfile + environment: + NODE_ENV: "${NODE_ENV}" + restart: unless-stopped + ports: + - "8042:8042" + depends_on: + - backend_dev + frontend_dev: build: context: ./requirements/svelte @@ -42,6 +54,7 @@ services: restart: unless-stopped volumes: - ./requirements/nginx/conf/default.conf:/etc/nginx/conf.d/default.conf:ro + - ./requirements/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro command: [nginx-debug, "-g", "daemon off;"] ports: - "8080:8080" @@ -68,8 +81,6 @@ services: redis: container_name: nestjs_redis image: redis:alpine - expose: - - "6379" restart: unless-stopped environment: REDIS_HOST: "${REDIS_HOST}" diff --git a/srcs/requirements/game_server/Dockerfile b/srcs/requirements/game_server/Dockerfile new file mode 100644 index 00000000..72857a78 --- /dev/null +++ b/srcs/requirements/game_server/Dockerfile @@ -0,0 +1,15 @@ +FROM node:alpine AS build + +WORKDIR /usr/app + +COPY ./game_back ./ + +RUN npm install typescript + +RUN npx tsc + +WORKDIR /usr/app/src/server + +EXPOSE 8042 + +CMD [ "node", "wsServer.js"] diff --git a/srcs/requirements/game_server/game_back/jsconfig.json b/srcs/requirements/game_server/game_back/jsconfig.json new file mode 100644 index 00000000..347bf03f --- /dev/null +++ b/srcs/requirements/game_server/game_back/jsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "Node", + "target": "ES2020", + "strictNullChecks": true, + "strictFunctionTypes": true + }, + "exclude": [ + "node_modules", + "**/node_modules/*" + ] +} \ No newline at end of file diff --git a/srcs/requirements/game_server/game_back/package-lock.json b/srcs/requirements/game_server/game_back/package-lock.json new file mode 100644 index 00000000..414d8d22 --- /dev/null +++ b/srcs/requirements/game_server/game_back/package-lock.json @@ -0,0 +1,121 @@ +{ + "name": "game_back", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "uuid": "^9.0.0", + "ws": "^8.10.0" + }, + "devDependencies": { + "@types/node": "^18.11.5", + "@types/uuid": "^8.3.4", + "@types/ws": "^8.5.3", + "typescript": "^4.9.4" + } + }, + "node_modules/@types/node": { + "version": "18.11.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.5.tgz", + "integrity": "sha512-3JRwhbjI+cHLAkUorhf8RnqUbFXajvzX4q6fMn5JwkgtuwfYtRQYI3u4V92vI6NJuTsbBQWWh3RZjFsuevyMGQ==", + "dev": true + }, + "node_modules/@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "dev": true + }, + "node_modules/@types/ws": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/typescript": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/ws": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.10.0.tgz", + "integrity": "sha512-+s49uSmZpvtAsd2h37vIPy1RBusaLawVe8of+GyEPsaJTCMpj/2v8NpeK1SHXjBlQ95lQTmQofOJnFiLoaN3yw==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + }, + "dependencies": { + "@types/node": { + "version": "18.11.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.5.tgz", + "integrity": "sha512-3JRwhbjI+cHLAkUorhf8RnqUbFXajvzX4q6fMn5JwkgtuwfYtRQYI3u4V92vI6NJuTsbBQWWh3RZjFsuevyMGQ==", + "dev": true + }, + "@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "dev": true + }, + "@types/ws": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "typescript": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "dev": true + }, + "uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" + }, + "ws": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.10.0.tgz", + "integrity": "sha512-+s49uSmZpvtAsd2h37vIPy1RBusaLawVe8of+GyEPsaJTCMpj/2v8NpeK1SHXjBlQ95lQTmQofOJnFiLoaN3yw==", + "requires": {} + } + } +} diff --git a/srcs/requirements/game_server/game_back/package.json b/srcs/requirements/game_server/game_back/package.json new file mode 100644 index 00000000..b9702186 --- /dev/null +++ b/srcs/requirements/game_server/game_back/package.json @@ -0,0 +1,13 @@ +{ + "type": "module", + "devDependencies": { + "@types/node": "^18.11.5", + "@types/uuid": "^8.3.4", + "@types/ws": "^8.5.3", + "typescript": "^4.9.4" + }, + "dependencies": { + "uuid": "^9.0.0", + "ws": "^8.10.0" + } +} diff --git a/srcs/requirements/game_server/game_back/src/server/class/Client.ts b/srcs/requirements/game_server/game_back/src/server/class/Client.ts new file mode 100644 index 00000000..864472ec --- /dev/null +++ b/srcs/requirements/game_server/game_back/src/server/class/Client.ts @@ -0,0 +1,36 @@ + +import { WebSocket } from "../wsServer.js"; +import { Racket } from "../../shared_js/class/Rectangle.js"; +import { GameSession } from "./GameSession.js"; +import * as ev from "../../shared_js/class/Event.js" +import * as en from "../../shared_js/enums.js" + +export class Client { + socket: WebSocket; + id: string; // same as "socket.id" + isAlive: boolean = true; + gameSession: GameSession = null; + constructor(socket: WebSocket, id: string) { + this.socket = socket; + this.id = id; + } +} + +export class ClientPlayer extends Client { + token: string; + username: string; + matchOptions: en.MatchOptions = 0; + inputBuffer: ev.EventInput = new ev.EventInput(); + lastInputId: number = 0; + racket: Racket; + constructor(socket: WebSocket, id: string, racket: Racket) { + super(socket, id); + this.racket = racket; + } +} + +export class ClientSpectator extends Client { + constructor(socket: WebSocket, id: string) { + super(socket, id); + } +} diff --git a/srcs/requirements/game_server/game_back/src/server/class/GameComponentsServer.ts b/srcs/requirements/game_server/game_back/src/server/class/GameComponentsServer.ts new file mode 100644 index 00000000..691a3991 --- /dev/null +++ b/srcs/requirements/game_server/game_back/src/server/class/GameComponentsServer.ts @@ -0,0 +1,12 @@ + +import * as en from "../../shared_js/enums.js" +import { GameComponents } from "../../shared_js/class/GameComponents.js"; + +export class GameComponentsServer extends GameComponents { + scoreLeft: number = 0; + scoreRight: number = 0; + constructor(options: en.MatchOptions) + { + super(options); + } +} diff --git a/srcs/requirements/game_server/game_back/src/server/class/GameSession.ts b/srcs/requirements/game_server/game_back/src/server/class/GameSession.ts new file mode 100644 index 00000000..322b845d --- /dev/null +++ b/srcs/requirements/game_server/game_back/src/server/class/GameSession.ts @@ -0,0 +1,267 @@ + +import * as en from "../../shared_js/enums.js" +import * as ev from "../../shared_js/class/Event.js" +import * as c from "../constants.js" +import { ClientPlayer, ClientSpectator } from "./Client"; +import { GameComponentsServer } from "./GameComponentsServer.js"; +import { clientInputListener, clientTerminate } from "../wsServer.js"; +import { random } from "../utils.js"; +import { Ball } from "../../shared_js/class/Rectangle.js"; +import { wallsMovements } from "../../shared_js/wallsMovement.js"; + +/* + multiples methods of GameSession have parameter "s: GameSession". + its used with calls to setTimeout(), + because "this" is not equal to the GameSession but to "this: Timeout" +*/ +export class GameSession { + id: string; // url ? + playersMap: Map = new Map(); + unreadyPlayersMap: Map = new Map(); + spectatorsMap: Map = new Map(); + gameLoopInterval: NodeJS.Timer | number = 0; + playersUpdateInterval: NodeJS.Timer | number = 0; + spectatorsUpdateInterval: NodeJS.Timer | number = 0; + components: GameComponentsServer; + matchOptions: en.MatchOptions; + isPrivateMatch: boolean; // WIP: could be used to separate leaderboards for example. + matchEnded: boolean = false; + lastStateSnapshot: ev.EventGameUpdate; + + actual_time: number; + last_time: number; + delta_time: number; + + constructor(id: string, matchOptions: en.MatchOptions, isPrivateMatch: boolean = false) { + this.id = id; + this.matchOptions = matchOptions; + this.isPrivateMatch = isPrivateMatch; + this.components = new GameComponentsServer(this.matchOptions); + } + start() { + const gc = this.components; + setTimeout(this.resume, c.matchStartDelay, this); + + let timeout = c.matchStartDelay + c.newRoundDelay; + gc.ballsArr.forEach((ball) => { + setTimeout(this._newRound, timeout, this, ball); + timeout += c.newRoundDelay*0.5; + }); + } + resume(s: GameSession) { + s.playersMap.forEach( (client) => { + client.socket.on("message", clientInputListener); + }); + + s.actual_time = Date.now(); + s.lastStateSnapshot = s._gameStateSnapshot(); + s.gameLoopInterval = setInterval(s._gameLoop, c.serverGameLoopIntervalMS, s); + s.playersUpdateInterval = setInterval(s._playersUpdate, c.playersUpdateIntervalMS, s); + s.spectatorsUpdateInterval = setInterval(s._spectatorsUpdate, c.spectatorsUpdateIntervalMS, s); + } + pause(s: GameSession) { + s.playersMap.forEach( (client) => { + client.socket.off("message", clientInputListener); + }); + + clearInterval(s.gameLoopInterval); + clearInterval(s.playersUpdateInterval); + clearInterval(s.spectatorsUpdateInterval); + } + instantInputDebug(client: ClientPlayer) { + this._handleInput(c.fixedDeltaTime, client); + } + private _handleInput(delta: number, client: ClientPlayer) { + // if (client.inputBuffer === null) {return;} + const gc = this.components; + const input = client.inputBuffer.input; + + if (input === en.InputEnum.up) { + client.racket.dir.y = -1; + } + else if (input === en.InputEnum.down) { + client.racket.dir.y = 1; + } + + if (input !== en.InputEnum.noInput) { + client.racket.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]); + } + + client.lastInputId = client.inputBuffer.id; + // client.inputBuffer = null; + } + private _gameLoop(s: GameSession) { + /* s.last_time = s.actual_time; + s.actual_time = Date.now(); + s.delta_time = (s.actual_time - s.last_time) / 1000; */ + s.delta_time = c.fixedDeltaTime; + + // WIP, replaced by instantInputDebug() to prevent desynchro + /* s.playersMap.forEach( (client) => { + s._handleInput(s.delta_time, client); + }); */ + + const gc = s.components; + gc.ballsArr.forEach((ball) => { + s._ballMovement(s.delta_time, ball); + }); + + if (s.matchOptions & en.MatchOptions.movingWalls) { + wallsMovements(s.delta_time, gc); + } + } + private _ballMovement(delta: number, ball: Ball) { + const gc = this.components; + if (ball.ballInPlay) + { + ball.moveAndBounce(delta, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]); + if (ball.pos.x > c.w + || ball.pos.x < 0 - ball.width) + { + ball.ballInPlay = false; + if (this.matchEnded) { + return; + } + this._scoreUpdate(ball); + setTimeout(this._newRound, c.newRoundDelay, this, ball); + } + } + } + private _scoreUpdate(ball: Ball) { + const gc = this.components; + if (ball.pos.x > c.w) { + ++gc.scoreLeft; + } + else if (ball.pos.x < 0 - ball.width) { + ++gc.scoreRight; + } + this.playersMap.forEach( (client) => { + client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight))); + }); + this.spectatorsMap.forEach( (client) => { + client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight))); + }); + } + private _playersUpdate(s: GameSession) { + s.lastStateSnapshot = s._gameStateSnapshot(); + s.playersMap.forEach( (client) => { + s.lastStateSnapshot.lastInputId = client.lastInputId; + client.socket.send(JSON.stringify(s.lastStateSnapshot)); + }); + } + private _spectatorsUpdate(s: GameSession) { + s.lastStateSnapshot.lastInputId = 0; + s.spectatorsMap.forEach( (client) => { + client.socket.send(JSON.stringify(s.lastStateSnapshot)); + }); + } + private _gameStateSnapshot() : ev.EventGameUpdate { + const gc = this.components; + const snapshot = new ev.EventGameUpdate(); + snapshot.playerLeft.y = gc.playerLeft.pos.y; + snapshot.playerRight.y = gc.playerRight.pos.y; + gc.ballsArr.forEach((ball) => { + snapshot.ballsArr.push({ + x: ball.pos.x, + y: ball.pos.y, + dirX: ball.dir.x, + dirY: ball.dir.y, + speed: ball.speed + }); + }); + if (this.matchOptions & en.MatchOptions.movingWalls) { + snapshot.wallTop.y = gc.wallTop.pos.y; + snapshot.wallBottom.y = gc.wallBottom.pos.y; + } + return (snapshot); + } + private _newRound(s: GameSession, ball: Ball) { + if (s._checkDisconnexions()) { + return; + } + // https://fr.wikipedia.org/wiki/Tennis_de_table#Nombre_de_manches + const gc = s.components; + const minScore = 11;// can be changed for testing + if (gc.scoreLeft >= minScore || gc.scoreRight >= minScore) + { + if (Math.abs(gc.scoreLeft - gc.scoreRight) >= 2) + { + if (gc.scoreLeft > gc.scoreRight) { + s._matchEnd(en.PlayerSide.left); + } + else { + s._matchEnd(en.PlayerSide.right); + } + return; + } + } + ball.pos.x = c.w_mid; + ball.pos.y = random(c.h*0.3, c.h*0.7); + ball.speed = ball.baseSpeed; + ball.ballInPlay = true; + } + private _checkDisconnexions() { + if (this.playersMap.size !== 2) + { + this.matchEnded = true; + if (this.playersMap.size != 0) + { + console.log("Forfeit Ending"); + const gc = this.components; + const luckyWinner: ClientPlayer = this.playersMap.values().next().value; + if (luckyWinner.racket === gc.playerLeft) { + this._matchEnd(en.PlayerSide.left, true); + } + else { + this._matchEnd(en.PlayerSide.right, true); + } + } + return true; + } + return false; + } + private async _matchEnd(winner: en.PlayerSide, forfeit_flag: boolean = false) + { + this.matchEnded = true; + let eventEnd: ev.EventMatchEnd; + eventEnd = new ev.EventMatchEnd(winner, forfeit_flag); + this.playersMap.forEach( (client) => { + client.socket.send(JSON.stringify(eventEnd)); + }); + this.spectatorsMap.forEach( (client) => { + client.socket.send(JSON.stringify(eventEnd)); + }); + + const gc = this.components; + await fetch(c.addressBackEnd + "/game/gameserver/updategame", + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + gameServerIdOfTheMatch: this.id, + playerOneUsernameResult: gc.scoreLeft, + playerTwoUsernameResult: gc.scoreRight, + }) + }); + + const gameSession = this; + setTimeout(function kickRemainingClients() { + gameSession.spectatorsMap.forEach((client) => { + clientTerminate(client); + }); + gameSession.playersMap.forEach((client) => { + clientTerminate(client); + }); + }, 15000); + + // logs + if (winner === en.PlayerSide.left) { + console.log("Player Left WIN"); + } + else { + console.log("Player Right WIN"); + } + } +} diff --git a/srcs/requirements/game_server/game_back/src/server/constants.ts b/srcs/requirements/game_server/game_back/src/server/constants.ts new file mode 100644 index 00000000..3ae3e722 --- /dev/null +++ b/srcs/requirements/game_server/game_back/src/server/constants.ts @@ -0,0 +1,12 @@ + +export * from "../shared_js/constants.js" + +// 15ms == 1000/66.666 +export const serverGameLoopIntervalMS = 15; // millisecond +export const fixedDeltaTime = serverGameLoopIntervalMS/1000; // second + +// 33.333ms == 1000/30 +export const playersUpdateIntervalMS = 1000/30; // millisecond +export const spectatorsUpdateIntervalMS = 1000/30; // millisecond + +export const addressBackEnd = "http://backend_dev:3000/api/v2"; diff --git a/srcs/requirements/game_server/game_back/src/server/utils.ts b/srcs/requirements/game_server/game_back/src/server/utils.ts new file mode 100644 index 00000000..3cd0a4a5 --- /dev/null +++ b/srcs/requirements/game_server/game_back/src/server/utils.ts @@ -0,0 +1,6 @@ + +export * from "../shared_js/utils.js" + +export function shortId(id: string): string { + return id.substring(0, id.indexOf("-")); +} diff --git a/srcs/requirements/game_server/game_back/src/server/wsServer.ts b/srcs/requirements/game_server/game_back/src/server/wsServer.ts new file mode 100644 index 00000000..d28fcff9 --- /dev/null +++ b/srcs/requirements/game_server/game_back/src/server/wsServer.ts @@ -0,0 +1,393 @@ + +import { WebSocketServer, WebSocket as BaseLibWebSocket } from "ws"; + +export class WebSocket extends BaseLibWebSocket { + id?: string; +} + +import { IncomingMessage } from "http"; +import { v4 as uuidv4 } from 'uuid'; + +import * as en from "../shared_js/enums.js" +import * as ev from "../shared_js/class/Event.js" +import * as c from "./constants.js" +import { Client, ClientPlayer, ClientSpectator } from "./class/Client.js" +import { GameSession } from "./class/GameSession.js" +import { shortId } from "./utils.js"; +import { gameSessionIdPLACEHOLDER } from "./constants.js"; + +const wsPort = 8042; +export const wsServer = new WebSocketServer({host: "0.0.0.0", port: wsPort, path: "/pong"}); +const clientsMap: Map = new Map; // socket.id/Client +const matchmakingMap: Map = new Map; // socket.id/ClientPlayer (duplicates with clientsMap) +const privateMatchmakingMap: Map = new Map; // socket.id/ClientPlayer (duplicates with clientsMap) +const gameSessionsMap: Map = new Map; // GameSession.id(url)/GameSession + +wsServer.on("connection", connectionListener); +wsServer.on("error", errorListener); +wsServer.on("close", closeListener); + + +function connectionListener(socket: WebSocket, request: IncomingMessage) +{ + const id = uuidv4(); + const client = new Client(socket, id); + clientsMap.set(id, client); + socket.id = id; + + socket.on("pong", function heartbeat() { + client.isAlive = true; + console.log(`client ${shortId(client.id)} is alive`); + }); + + socket.on("message", function log(data: string) { + try { + const event: ev.ClientEvent = JSON.parse(data); + if (event.type === en.EventTypes.clientInput) { + return; + } + } + catch (e) {} + console.log("data: " + data); + }); + + socket.once("message", clientAnnounceListener); +} + + +async function clientAnnounceListener(this: WebSocket, data: string) +{ + try { + const msg : ev.ClientAnnounce = JSON.parse(data); + if (msg.type === en.EventTypes.clientAnnounce) + { + // TODO: reconnection with msg.clientId ? + // "/pong" to play, "/pong?ID_OF_A_GAMESESSION" to spectate (or something like that) + if (msg.role === en.ClientRole.player) + { + const announce: ev.ClientAnnouncePlayer = msg; + + // WIP nest, fetch token validation + const body = { + playerOneUsername: announce.username, + playerTwoUsername: "", + gameOptions: announce.matchOptions, + isGameIsWithInvitation: announce.privateMatch, + token: announce.token, + }; + if (announce.privateMatch) { + body.playerTwoUsername = announce.playerTwoUsername; + } + const response = await fetch(c.addressBackEnd + "/game/gameserver/validate", + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body) + }); + if (!response.ok) + { + this.send(JSON.stringify( new ev.EventError((await response.json()).message))); + clientTerminate(clientsMap.get(this.id)); + return; + } + + const player = clientsMap.get(this.id) as ClientPlayer; + player.matchOptions = announce.matchOptions; + player.token = announce.token; + announce.isInvitedPerson ? player.username = announce.playerTwoUsername : player.username = announce.username; + this.send(JSON.stringify( new ev.EventAssignId(this.id) )); // unused + this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchmakingInProgress) )); + if (announce.privateMatch) { + privateMatchmaking(player); + } + else { + publicMatchmaking(player); + } + } + else if (msg.role === en.ClientRole.spectator) + { + const announce: ev.ClientAnnounceSpectator = msg; + const gameSession = gameSessionsMap.get(announce.gameSessionId); + if (!gameSession) { + this.send(JSON.stringify( new ev.EventError("invalid gameSessionId"))); + clientTerminate(clientsMap.get(this.id)); + return; + } + const spectator = clientsMap.get(this.id) as ClientSpectator; + spectator.gameSession = gameSession; + gameSession.spectatorsMap.set(spectator.id, spectator); + this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchStart) )); + } + } + else { + console.log("Invalid ClientAnnounce"); + } + return; + } + catch (e) { + console.log("Invalid JSON (clientAnnounceListener)"); + } + this.once("message", clientAnnounceListener); +} + + +function publicMatchmaking(player: ClientPlayer) +{ + const minPlayersNumber = 2; + const maxPlayersNumber = 2; + matchmakingMap.set(player.id, player); + const matchOptions = player.matchOptions; + + const compatiblePlayers: ClientPlayer[] = []; + for (const [id, client] of matchmakingMap) + { + if (client.matchOptions === matchOptions) + { + compatiblePlayers.push(client); + if (compatiblePlayers.length === maxPlayersNumber) { + break; + } + } + } + + if (compatiblePlayers.length >= minPlayersNumber) { + compatiblePlayers.forEach((client) => { + matchmakingMap.delete(client.id); + }); + createGameSession(compatiblePlayers, matchOptions); + } +} + + +function privateMatchmaking(player: ClientPlayer) +{ + const minPlayersNumber = 2; + const maxPlayersNumber = 2; + privateMatchmakingMap.set(player.id, player); + const matchOptions = player.matchOptions; + + const token = player.token; + const compatiblePlayers: ClientPlayer[] = []; + for (const [id, client] of privateMatchmakingMap) + { + if (client.token === token) + { + compatiblePlayers.push(client); + if (compatiblePlayers.length === maxPlayersNumber) { + break; + } + } + } + + if (compatiblePlayers.length >= minPlayersNumber) { + compatiblePlayers.forEach((client) => { + privateMatchmakingMap.delete(client.id); + }); + createGameSession(compatiblePlayers, matchOptions); + } + else + { + setTimeout(async function abortMatch() { + if (!player.gameSession) + { + if (player.socket.OPEN) { + player.socket.send(JSON.stringify( new ev.EventMatchAbort() )); + } + const response = await fetch(c.addressBackEnd + "/game/gameserver/destroysession",{ + method: "POST", + headers : {"Content-Type": "application/json"}, + body : JSON.stringify({ + token : player.token + }) + }) + .then(x => x.json()) + .catch(error => console.log("ERROR : " + error)); + clientTerminate(player); + } + }, 60000); + } +} + + +function createGameSession(playersArr: ClientPlayer[], matchOptions: en.MatchOptions) +{ + // const id = gameSessionIdPLACEHOLDER; // Force ID, TESTING SPECTATOR + const id = uuidv4(); + const gameSession = new GameSession(id, matchOptions); + gameSessionsMap.set(id, gameSession); + + playersArr.forEach((client) => { + client.gameSession = gameSession; + gameSession.playersMap.set(client.id, client); + gameSession.unreadyPlayersMap.set(client.id, client); + client.socket.once("message", playerReadyConfirmationListener); + }); + + // REFACTORING: Not pretty, hardcoded two players. + // Could be done in gameSession maybe ? + const gameSessionPlayersIterator = gameSession.playersMap.values(); + let player: ClientPlayer; + player = (gameSessionPlayersIterator.next().value); + player.racket = gameSession.components.playerLeft; + player.socket.send(JSON.stringify( new ev.EventMatchmakingComplete(en.PlayerSide.left) )); + + player = (gameSessionPlayersIterator.next().value); + player.racket = gameSession.components.playerRight; + player.socket.send(JSON.stringify( new ev.EventMatchmakingComplete(en.PlayerSide.right) )); + // REFACTORING + + setTimeout(function abortMatch() { + if (gameSession.unreadyPlayersMap.size !== 0) + { + gameSessionsMap.delete(gameSession.id); + gameSession.playersMap.forEach((client) => { + client.socket.send(JSON.stringify( new ev.EventMatchAbort() )); + client.gameSession = null; + clientTerminate(client); + }); + } + }, 5000); +} + + +async function playerReadyConfirmationListener(this: WebSocket, data: string) +{ + try { + const msg : ev.ClientEvent = JSON.parse(data); + if (msg.type === en.EventTypes.clientPlayerReady) + { + const client = clientsMap.get(this.id); + const gameSession = client.gameSession; + gameSession.unreadyPlayersMap.delete(this.id); + if (gameSession.unreadyPlayersMap.size === 0) + { + // WIP nest , send gameSession.id + const gameSessionPlayersIterator = gameSession.playersMap.values(); + const body = { + gameServerIdOfTheMatch : gameSession.id, + gameOptions: gameSession.matchOptions, + playerOneUsername: (gameSessionPlayersIterator.next().value).username, + playerTwoUsername: (gameSessionPlayersIterator.next().value).username, + playerOneUsernameResult : 0, + playerTwoUsernameResult : 0 + }; + const response = await fetch(c.addressBackEnd + "/game/gameserver/creategame", + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body) + }); + if (!response.ok) + { + gameSessionsMap.delete(gameSession.id); + gameSession.playersMap.forEach((client) => { + client.socket.send(JSON.stringify( new ev.EventMatchAbort() )); + client.gameSession = null; + clientTerminate(client); + }); + return; + } + + gameSession.playersMap.forEach( (client) => { + client.socket.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchStart) )); + }); + gameSession.start(); + } + } + else { + console.log("Invalid playerReadyConfirmation"); + } + return; + } + catch (e) { + console.log("Invalid JSON (playerReadyConfirmationListener)"); + } + this.once("message", playerReadyConfirmationListener); +} + + +export function clientInputListener(this: WebSocket, data: string) +{ + try { + // const input: ev.ClientEvent = JSON.parse(data); + const input: ev.EventInput = JSON.parse(data); + if (input.type === en.EventTypes.clientInput) + { + const client = clientsMap.get(this.id) as ClientPlayer; + client.inputBuffer = input; + client.gameSession.instantInputDebug(client); // wip + } + else { + console.log("Invalid clientInput"); + } + } + catch (e) { + console.log("Invalid JSON (clientInputListener)"); + } +} + +//////////// +//////////// + +const pingInterval = setInterval( () => { + let deleteLog = ""; + clientsMap.forEach( (client) => { + if (!client.isAlive) { + clientTerminate(client); + deleteLog += ` ${shortId(client.id)} |`; + } + else { + client.isAlive = false; + client.socket.ping(); + } + }); + + if (deleteLog) { + console.log(`Disconnected:${deleteLog}`); + } + console.log("gameSessionMap size: " + gameSessionsMap.size); + console.log("clientsMap size: " + clientsMap.size); + console.log("matchmakingMap size: " + matchmakingMap.size); + console.log("privateMatchmakingMap size: " + privateMatchmakingMap.size); + console.log(""); +}, 4200); + + +export function clientTerminate(client: Client) +{ + client.socket.terminate(); + if (client.gameSession) + { + client.gameSession.playersMap.delete(client.id); + if (client.gameSession.playersMap.size === 0) + { + clearInterval(client.gameSession.playersUpdateInterval); + clearInterval(client.gameSession.spectatorsUpdateInterval); + clearInterval(client.gameSession.gameLoopInterval); + gameSessionsMap.delete(client.gameSession.id); + } + } + clientsMap.delete(client.id); + if (matchmakingMap.has(client.id)) { + matchmakingMap.delete(client.id); + } + else if (privateMatchmakingMap.has(client.id)) { + privateMatchmakingMap.delete(client.id); + } +} + + +function closeListener() +{ + clearInterval(pingInterval); +} + + +function errorListener(error: Error) +{ + console.log("Error: " + JSON.stringify(error)); +} diff --git a/srcs/requirements/game_server/game_back/src/shared_js/class/Event.ts b/srcs/requirements/game_server/game_back/src/shared_js/class/Event.ts new file mode 100644 index 00000000..0147ead8 --- /dev/null +++ b/srcs/requirements/game_server/game_back/src/shared_js/class/Event.ts @@ -0,0 +1,144 @@ + +import * as en from "../enums.js" + +/* From Server */ +export class ServerEvent { + type: en.EventTypes; + constructor(type: en.EventTypes = 0) { + this.type = type; + } +} + +export class EventAssignId extends ServerEvent { + id: string; + constructor(id: string) { + super(en.EventTypes.assignId); + this.id = id; + } +} + +export class EventMatchmakingComplete extends ServerEvent { + side: en.PlayerSide; + constructor(side: en.PlayerSide) { + super(en.EventTypes.matchmakingComplete); + this.side = side; + } +} + +export class EventGameUpdate extends ServerEvent { + playerLeft = { + y: 0 + }; + playerRight = { + y: 0 + }; + ballsArr: { + x: number, + y: number, + dirX: number, + dirY: number, + speed: number + }[] = []; + wallTop? = { + y: 0 + }; + wallBottom? = { + y: 0 + }; + lastInputId = 0; + constructor() { // TODO: constructor that take GameComponentsServer maybe ? + super(en.EventTypes.gameUpdate); + } +} + +export class EventScoreUpdate extends ServerEvent { + scoreLeft: number; + scoreRight: number; + constructor(scoreLeft: number, scoreRight: number) { + super(en.EventTypes.scoreUpdate); + this.scoreLeft = scoreLeft; + this.scoreRight = scoreRight; + } +} + +export class EventMatchEnd extends ServerEvent { + winner: en.PlayerSide; + forfeit: boolean; + constructor(winner: en.PlayerSide, forfeit = false) { + super(en.EventTypes.matchEnd); + this.winner = winner; + this.forfeit = forfeit; + } +} + +export class EventMatchAbort extends ServerEvent { + constructor() { + super(en.EventTypes.matchAbort); + } +} + +export class EventError extends ServerEvent { + message: string; + constructor(message: string) { + super(en.EventTypes.error); + this.message = message; + } +} + + +/* From Client */ +export class ClientEvent { + type: en.EventTypes; // readonly ? + constructor(type: en.EventTypes = 0) { + this.type = type; + } +} + +export class ClientAnnounce extends ClientEvent { + role: en.ClientRole; + constructor(role: en.ClientRole) { + super(en.EventTypes.clientAnnounce); + this.role = role; + } +} + +export class ClientAnnouncePlayer extends ClientAnnounce { + clientId: string; // unused + matchOptions: en.MatchOptions; + token: string; + username: string; + privateMatch: boolean; + playerTwoUsername?: string; + isInvitedPerson? : boolean; + constructor(matchOptions: en.MatchOptions, token: string, username: string, privateMatch: boolean = false, playerTwoUsername?: string, isInvitedPerson? : boolean) { + super(en.ClientRole.player); + this.matchOptions = matchOptions; + this.token = token; + this.username = username; + this.privateMatch = privateMatch; + if (isInvitedPerson) { + this.isInvitedPerson = isInvitedPerson; + } + if (playerTwoUsername) { + this.playerTwoUsername = playerTwoUsername; + } + } +} + +export class ClientAnnounceSpectator extends ClientAnnounce { + gameSessionId: string; + constructor(gameSessionId: string) { + super(en.ClientRole.spectator); + this.gameSessionId = gameSessionId; + } +} + +export class EventInput extends ClientEvent { + input: en.InputEnum; + id: number; + constructor(input: en.InputEnum = en.InputEnum.noInput, id: number = 0) { + super(en.EventTypes.clientInput); + this.input = input; + this.id = id; + } +} diff --git a/srcs/requirements/svelte/api_front/public/game/class/GameComponents.ts b/srcs/requirements/game_server/game_back/src/shared_js/class/GameComponents.ts similarity index 97% rename from srcs/requirements/svelte/api_front/public/game/class/GameComponents.ts rename to srcs/requirements/game_server/game_back/src/shared_js/class/GameComponents.ts index 10e60932..ec36f15f 100644 --- a/srcs/requirements/svelte/api_front/public/game/class/GameComponents.ts +++ b/srcs/requirements/game_server/game_back/src/shared_js/class/GameComponents.ts @@ -5,7 +5,7 @@ import { VectorInteger } from "./Vector.js"; import { Rectangle, MovingRectangle, Racket, Ball } from "./Rectangle.js"; import { random } from "../utils.js"; -class GameComponents { +export class GameComponents { wallTop: Rectangle | MovingRectangle; wallBottom: Rectangle | MovingRectangle; playerLeft: Racket; @@ -61,5 +61,3 @@ class GameComponents { } } } - -export {GameComponents} diff --git a/srcs/requirements/svelte/api_front/public/game/class/Rectangle.ts b/srcs/requirements/game_server/game_back/src/shared_js/class/Rectangle.ts similarity index 93% rename from srcs/requirements/svelte/api_front/public/game/class/Rectangle.ts rename to srcs/requirements/game_server/game_back/src/shared_js/class/Rectangle.ts index fff71dc9..d258c553 100644 --- a/srcs/requirements/svelte/api_front/public/game/class/Rectangle.ts +++ b/srcs/requirements/game_server/game_back/src/shared_js/class/Rectangle.ts @@ -1,9 +1,9 @@ import { Vector, VectorInteger } from "./Vector.js"; -import { Component, Moving } from "./interface.js"; +import type { Component, Moving } from "./interface.js"; import * as c from "../constants.js" -class Rectangle implements Component { +export class Rectangle implements Component { pos: VectorInteger; width: number; height: number; @@ -33,7 +33,7 @@ class Rectangle implements Component { } } -class MovingRectangle extends Rectangle implements Moving { +export class MovingRectangle extends Rectangle implements Moving { dir: Vector = new Vector(0,0); speed: number; readonly baseSpeed: number; @@ -61,7 +61,7 @@ class MovingRectangle extends Rectangle implements Moving { } } -class Racket extends MovingRectangle { +export class Racket extends MovingRectangle { constructor(pos: VectorInteger, width: number, height: number, baseSpeed: number) { super(pos, width, height, baseSpeed); } @@ -72,13 +72,22 @@ class Racket extends MovingRectangle { } } -class Ball extends MovingRectangle { +export class Ball extends MovingRectangle { readonly speedIncrease: number; ballInPlay: boolean = false; constructor(pos: VectorInteger, size: number, baseSpeed: number, speedIncrease: number) { super(pos, size, size, baseSpeed); this.speedIncrease = speedIncrease; } + moveAndBounce(delta: number, colliderArr: Rectangle[]) { + this.move(delta); + let i = colliderArr.findIndex(this.collision, this); + if (i != -1) + { + this.bounce(colliderArr[i]); + this.move(delta); + } + } bounce(collider?: Rectangle) { this._bounceAlgo(collider); } @@ -92,15 +101,6 @@ class Ball extends MovingRectangle { this._bounceWall(); } } - moveAndBounce(delta: number, colliderArr: Rectangle[]) { - this.move(delta); - let i = colliderArr.findIndex(this.collision, this); - if (i != -1) - { - this.bounce(colliderArr[i]); - this.move(delta); - } - } protected _bounceWall() { // Should be enough for Wall this.dir.y = this.dir.y * -1; } @@ -140,5 +140,3 @@ class Ball extends MovingRectangle { // console.log(`x: ${this.dir.x}, y: ${this.dir.y}`); } } - -export {Rectangle, MovingRectangle, Racket, Ball} diff --git a/srcs/requirements/svelte/api_front/public/game/class/Vector.ts b/srcs/requirements/game_server/game_back/src/shared_js/class/Vector.ts similarity index 88% rename from srcs/requirements/svelte/api_front/public/game/class/Vector.ts rename to srcs/requirements/game_server/game_back/src/shared_js/class/Vector.ts index 025bca36..fbe121e5 100644 --- a/srcs/requirements/svelte/api_front/public/game/class/Vector.ts +++ b/srcs/requirements/game_server/game_back/src/shared_js/class/Vector.ts @@ -1,5 +1,5 @@ -class Vector { +export class Vector { x: number; y: number; constructor(x: number = 0, y: number = 0) { @@ -16,13 +16,13 @@ class Vector { } } -class VectorInteger extends Vector { +export class VectorInteger extends Vector { // PLACEHOLDER // VectorInteger with set/get dont work (No draw on the screen). Why ? } /* -class VectorInteger { +export class VectorInteger { // private _x: number = 0; // private _y: number = 0; // constructor(x: number = 0, y: number = 0) { @@ -45,5 +45,3 @@ class VectorInteger { // } } */ - -export {Vector, VectorInteger} diff --git a/srcs/requirements/svelte/api_front/public/game/class/interface.ts b/srcs/requirements/game_server/game_back/src/shared_js/class/interface.ts similarity index 53% rename from srcs/requirements/svelte/api_front/public/game/class/interface.ts rename to srcs/requirements/game_server/game_back/src/shared_js/class/interface.ts index 39753de1..0f484da3 100644 --- a/srcs/requirements/svelte/api_front/public/game/class/interface.ts +++ b/srcs/requirements/game_server/game_back/src/shared_js/class/interface.ts @@ -1,21 +1,19 @@ -import { Vector, VectorInteger } from "./Vector.js"; +import type { Vector, VectorInteger } from "./Vector.js"; -interface Component { +export interface Component { pos: VectorInteger; } -interface GraphicComponent extends Component { +export interface GraphicComponent extends Component { ctx: CanvasRenderingContext2D; color: string; update: () => void; clear: (pos?: VectorInteger) => void; } -interface Moving { +export interface Moving { dir: Vector; speed: number; // pixel per second move(delta: number): void; } - -export {Component, GraphicComponent, Moving} diff --git a/srcs/requirements/svelte/api_front/public/game/constants copy.ts b/srcs/requirements/game_server/game_back/src/shared_js/constants.ts similarity index 74% rename from srcs/requirements/svelte/api_front/public/game/constants copy.ts rename to srcs/requirements/game_server/game_back/src/shared_js/constants.ts index ae3320e5..44c282c2 100644 --- a/srcs/requirements/svelte/api_front/public/game/constants copy.ts +++ b/srcs/requirements/game_server/game_back/src/shared_js/constants.ts @@ -11,8 +11,8 @@ export const pw = Math.floor(w*0.017); export const ph = pw*6; export const ballSize = pw; export const wallSize = Math.floor(w*0.01); -export const racketSpeed = Math.floor(w*0.66); // pixel per second -export const ballSpeed = Math.floor(w*0.66); // pixel per second +export const racketSpeed = Math.floor(w*0.60); // pixel per second +export const ballSpeed = Math.floor(w*0.55); // pixel per second export const ballSpeedIncrease = Math.floor(ballSpeed*0.05); // pixel per second export const normalizedSpeed = false; // for consistency in speed independent of direction @@ -24,3 +24,7 @@ export const newRoundDelay = 1500; // millisecond export const multiBallsCount = 3; export const movingWallPosMax = Math.floor(w*0.12); export const movingWallSpeed = Math.floor(w*0.08); + + +export const gameSessionIdPLACEHOLDER = "42"; // TESTING SPECTATOR PLACEHOLDER +// for testing, force gameSession.id in wsServer.ts->matchmaking() \ No newline at end of file diff --git a/srcs/requirements/svelte/api_front/public/game/enums.ts b/srcs/requirements/game_server/game_back/src/shared_js/enums.ts similarity index 74% rename from srcs/requirements/svelte/api_front/public/game/enums.ts rename to srcs/requirements/game_server/game_back/src/shared_js/enums.ts index dfba2aa3..b86571e5 100644 --- a/srcs/requirements/svelte/api_front/public/game/enums.ts +++ b/srcs/requirements/game_server/game_back/src/shared_js/enums.ts @@ -1,15 +1,17 @@ -enum EventTypes { +export enum EventTypes { // Class Implemented gameUpdate = 1, scoreUpdate, matchEnd, assignId, matchmakingComplete, + error, // Generic matchmakingInProgress, matchStart, + matchAbort, matchNewRound, // unused matchPause, // unused matchResume, // unused @@ -21,27 +23,25 @@ enum EventTypes { } -enum InputEnum { +export enum InputEnum { noInput = 0, up = 1, down, } -enum PlayerSide { +export enum PlayerSide { left = 1, right } -enum ClientRole { +export enum ClientRole { player = 1, spectator } -enum MatchOptions { +export enum MatchOptions { // binary flags, can be mixed noOption = 0b0, multiBalls = 1 << 0, movingWalls = 1 << 1 } - -export {EventTypes, InputEnum, PlayerSide, ClientRole, MatchOptions} diff --git a/srcs/requirements/game_server/game_back/src/shared_js/utils.ts b/srcs/requirements/game_server/game_back/src/shared_js/utils.ts new file mode 100644 index 00000000..dd3d40d0 --- /dev/null +++ b/srcs/requirements/game_server/game_back/src/shared_js/utils.ts @@ -0,0 +1,25 @@ + +import type { MovingRectangle } from "./class/Rectangle.js"; + +export function random(min: number = 0, max: number = 1) { + return Math.random() * (max - min) + min; +} + +export function sleep (ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +export function clamp(n: number, min: number, max: number) : number +{ + if (n < min) + n = min; + else if (n > max) + n = max; + return (n); +} + +// Typescript hack, unused +export function assertMovingRectangle(value: unknown): asserts value is MovingRectangle { + // if (value !== MovingRectangle) throw new Error("Not a MovingRectangle"); + return; +} diff --git a/srcs/requirements/svelte/api_front/public/game/wallsMovement.ts b/srcs/requirements/game_server/game_back/src/shared_js/wallsMovement.ts similarity index 69% rename from srcs/requirements/svelte/api_front/public/game/wallsMovement.ts rename to srcs/requirements/game_server/game_back/src/shared_js/wallsMovement.ts index dbf3f558..b2c2b581 100644 --- a/srcs/requirements/svelte/api_front/public/game/wallsMovement.ts +++ b/srcs/requirements/game_server/game_back/src/shared_js/wallsMovement.ts @@ -1,9 +1,9 @@ import * as c from "./constants.js"; -import { MovingRectangle } from "../shared_js/class/Rectangle.js"; -import { GameComponents } from "./class/GameComponents.js"; +import type { MovingRectangle } from "../shared_js/class/Rectangle.js"; +import type { GameComponents } from "./class/GameComponents.js"; -function wallsMovements(delta: number, gc: GameComponents) +export function wallsMovements(delta: number, gc: GameComponents) { const wallTop = gc.wallTop; const wallBottom = gc.wallBottom; @@ -16,5 +16,3 @@ function wallsMovements(delta: number, gc: GameComponents) wallTop.moveAndCollide(delta, [gc.playerLeft, gc.playerRight]); wallBottom.moveAndCollide(delta, [gc.playerLeft, gc.playerRight]); } - -export {wallsMovements} diff --git a/srcs/requirements/game_server/game_back/tsconfig.json b/srcs/requirements/game_server/game_back/tsconfig.json new file mode 100644 index 00000000..9344b2b4 --- /dev/null +++ b/srcs/requirements/game_server/game_back/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": "ES6", /* Specify what module code is generated. */ + // "rootDir": "./", /* 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": "./", /* 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": false, /* 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. */ + } + } diff --git a/srcs/requirements/nestjs/api_back/.env b/srcs/requirements/nestjs/api_back/.env index 7799ac26..5f815441 100644 --- a/srcs/requirements/nestjs/api_back/.env +++ b/srcs/requirements/nestjs/api_back/.env @@ -7,7 +7,7 @@ POSTGRES_DATABASE=transcendance_db # OAUTH2 42 API FORTYTWO_CLIENT_ID=u-s4t2ud-49dc7b539bcfe1acb48b928b2b281671c99fc5bfab1faca57a536ab7e0075500 -FORTYTWO_CLIENT_SECRET=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 +FORTYTWO_CLIENT_SECRET=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 FORTYTWO_CALLBACK_URL=http://transcendance:8080/api/v2/auth/redirect COOKIE_SECRET=248cdc831110eec8796d7c1edbf79835 # JWT @@ -20,3 +20,6 @@ REDIS_PORT=6379 REDIS_PASSWORD=1a5e04138b91b3d683c708e4689454c2 #2fa TWO_FACTOR_AUTHENTICATION_APP_NAME=Transcendance + +NAME_OF_REDIS_DB = tokenGameDatabase +TICKET_FOR_PLAYING_GAME_SECRET = a2aef785c388497f5fca18f9ccff37ed diff --git a/srcs/requirements/nestjs/api_back/package-lock.json b/srcs/requirements/nestjs/api_back/package-lock.json index 9678a46f..88f1e737 100644 --- a/srcs/requirements/nestjs/api_back/package-lock.json +++ b/srcs/requirements/nestjs/api_back/package-lock.json @@ -237,30 +237,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.4.tgz", - "integrity": "sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz", + "integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.6.tgz", - "integrity": "sha512-D2Ue4KHpc6Ys2+AxpIx1BZ8+UegLLLE2p3KJEuJRKmokHOtl49jQ5ny1773KsGLZs8MQvBidAF6yWUJxRqtKtg==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz", + "integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.6", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helpers": "^7.19.4", - "@babel/parser": "^7.19.6", + "@babel/generator": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-module-transforms": "^7.20.2", + "@babel/helpers": "^7.20.5", + "@babel/parser": "^7.20.5", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.6", - "@babel/types": "^7.19.4", + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -285,12 +285,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.6.tgz", - "integrity": "sha512-oHGRUQeoX1QrKeJIKVe0hwjGqNnVYsM5Nep5zo0uE0m42sLH+Fsd2pStJ5sRM1bNyTUUoz0pe2lTeMJrb/taTA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz", + "integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==", "dev": true, "dependencies": { - "@babel/types": "^7.19.4", + "@babel/types": "^7.20.5", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -313,12 +313,12 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz", - "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz", + "integrity": "sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.19.3", + "@babel/compat-data": "^7.20.0", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.21.3", "semver": "^6.3.0" @@ -386,40 +386,40 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.6.tgz", - "integrity": "sha512-fCmcfQo/KYr/VXXDIyd3CBGZ6AFhPFy1TfSEJ+PilGVlQT6jcbqtHAM4C1EciRqMza7/TpOUZliuSH+U6HAhJw==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz", + "integrity": "sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.19.4", + "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.6", - "@babel/types": "^7.19.4" + "@babel/traverse": "^7.20.1", + "@babel/types": "^7.20.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", + "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.19.4.tgz", - "integrity": "sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "dev": true, "dependencies": { - "@babel/types": "^7.19.4" + "@babel/types": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -465,14 +465,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.4.tgz", - "integrity": "sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.6.tgz", + "integrity": "sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==", "dev": true, "dependencies": { "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.4", - "@babel/types": "^7.19.4" + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5" }, "engines": { "node": ">=6.9.0" @@ -564,9 +564,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.6.tgz", - "integrity": "sha512-h1IUp81s2JYJ3mRkdxJgs4UvmSsRvDrx5ICSJbPvtWYv5i1nTBGcBpnog+89rAFMwvvru6E5NUHdBe01UeSzYA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", + "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -723,12 +723,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", - "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", + "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.19.0" }, "engines": { "node": ">=6.9.0" @@ -752,19 +752,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.6.tgz", - "integrity": "sha512-6l5HrUCzFM04mfbG09AagtYyR2P0B71B1wN7PfSPiksDPz2k5H9CBC1tcZpz2M8OxbKTPccByoOJ22rUKbpmQQ==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz", + "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.6", + "@babel/generator": "^7.20.5", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.6", - "@babel/types": "^7.19.4", + "@babel/parser": "^7.20.5", + "@babel/types": "^7.20.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -782,9 +782,9 @@ } }, "node_modules/@babel/types": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.4.tgz", - "integrity": "sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz", + "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.19.4", @@ -834,15 +834,15 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.0.tgz", + "integrity": "sha512-7yfvXy6MWLgWSFsLhz5yH3iQ52St8cdUY6FoGieKkRDVxuxmrNuUetIuu6cmjNWwniUHiWXjxCr5tTXDrbYS5A==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.4.0", - "globals": "^13.15.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -879,14 +879,14 @@ "dev": true }, "node_modules/@humanwhocodes/config-array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", - "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" @@ -911,6 +911,13 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", + "optional": true, + "peer": true + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1450,9 +1457,9 @@ } }, "node_modules/@nestjs/cli": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-9.1.4.tgz", - "integrity": "sha512-cvN4DcLzaqFzKRmpU3tOeLmw7+1p4XXsFLyWgteId0Szf6cAk5KJpD5jl2Kw7f39vNw9Pss8yiJ1q1CD/fcbwQ==", + "version": "9.1.5", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-9.1.5.tgz", + "integrity": "sha512-rSp26+Nv7PFtYrRSP18Gv5ZK8rRSc2SCCF5wh4SdZaVGgkxShpNq9YEfI+ik/uziN3KC5o74ppYRXGj+aHGVsA==", "dev": true, "dependencies": { "@angular-devkit/core": "14.2.2", @@ -1474,7 +1481,7 @@ "tree-kill": "1.2.2", "tsconfig-paths": "4.1.0", "tsconfig-paths-webpack-plugin": "4.0.0", - "typescript": "4.8.3", + "typescript": "4.8.4", "webpack": "5.74.0", "webpack-node-externals": "3.0.0" }, @@ -1486,9 +1493,9 @@ } }, "node_modules/@nestjs/cli/node_modules/typescript": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -1498,13 +1505,60 @@ "node": ">=4.2.0" } }, + "node_modules/@nestjs/cli/node_modules/webpack": { + "version": "5.74.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", + "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.10.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, "node_modules/@nestjs/common": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.1.4.tgz", - "integrity": "sha512-hmGTZ8ShKFDqqlU02uU8e/8PNE4bnES4pcFa6s/T1pLDYWjyf/75Klunro1W4aQPHcxnnohBmB27WxMqFTPEfw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.2.1.tgz", + "integrity": "sha512-nZuo3oDsSSlC5mti/M2aCWTEIfHPGDXmBwWgPeCpRbrNz3IWd109rkajll+yxgidVjznAdBS9y00JkAVJblNYw==", "dependencies": { "iterare": "1.2.1", - "tslib": "2.4.0", + "tslib": "2.4.1", "uuid": "9.0.0" }, "funding": { @@ -1546,14 +1600,6 @@ "rxjs": "^6.0.0 || ^7.2.0" } }, - "node_modules/@nestjs/config/node_modules/dotenv": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", - "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==", - "engines": { - "node": ">=12" - } - }, "node_modules/@nestjs/config/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -1563,9 +1609,9 @@ } }, "node_modules/@nestjs/core": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.1.4.tgz", - "integrity": "sha512-S6KpGeKotPYh126hhRqYLhvg9lxSbAmGfEbK8m09crIK7CYP05t32KtT6n12xl5/iva1G4Ch87Z/3rYP76etUg==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.2.1.tgz", + "integrity": "sha512-a9GkXuu8uXgNgCVW+17iI8kLCltO+HwHpU2IhR+32JKnN2WEQ1YEWU4t3GJ2MNq44YkjIw9zrKvFkjJBlYrNbQ==", "hasInstallScript": true, "dependencies": { "@nuxtjs/opencollective": "0.3.2", @@ -1573,7 +1619,7 @@ "iterare": "1.2.1", "object-hash": "3.0.0", "path-to-regexp": "3.2.0", - "tslib": "2.4.0", + "tslib": "2.4.1", "uuid": "9.0.0" }, "funding": { @@ -1612,14 +1658,6 @@ "@nestjs/common": "^8.0.0 || ^9.0.0" } }, - "node_modules/@nestjs/jwt/node_modules/@types/jsonwebtoken": { - "version": "8.5.8", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.8.tgz", - "integrity": "sha512-zm6xBQpFDIDM6o9r6HSgDeIcLy82TKWctCXEPbJJcXb5AKmi5BNNdLXneixK4lplX3PqIVcwLBCGE/kAGnlD4A==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@nestjs/mapped-types": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.2.0.tgz", @@ -1649,15 +1687,15 @@ } }, "node_modules/@nestjs/platform-express": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.1.4.tgz", - "integrity": "sha512-SLJWDa6V54QrUvzKI4Eyt7gyrjV7F9FY1uHFihshjmQfpf0ebCGacR9jzNwf01aHl0BJX3DUn/KYteBjz6DJXw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.2.1.tgz", + "integrity": "sha512-7PecaXt8lrdS1p6Vb1X/am3GGv+EO1VahyDzaEGOK6C0zwhc0VPfLtwihkjjfhS6BjpRIXXgviwEjONUvxVZnA==", "dependencies": { - "body-parser": "1.20.0", + "body-parser": "1.20.1", "cors": "2.8.5", - "express": "4.18.1", + "express": "4.18.2", "multer": "1.4.4-lts.1", - "tslib": "2.4.0" + "tslib": "2.4.1" }, "funding": { "type": "opencollective", @@ -1668,65 +1706,6 @@ "@nestjs/core": "^9.0.0" } }, - "node_modules/@nestjs/platform-express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.0", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.10.3", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/@nestjs/platform-express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, "node_modules/@nestjs/schematics": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.0.3.tgz", @@ -1824,12 +1803,12 @@ "dev": true }, "node_modules/@nestjs/testing": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-9.1.4.tgz", - "integrity": "sha512-gO6b9QJyUajh38DNdss9gSE0UO7x60Jh10W4SwHEjQT1W+yxaEWr3aLyuQItTvUVY6C28XKFLTykMpr8GO28Ug==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-9.2.1.tgz", + "integrity": "sha512-lemXZdRSuqoZ87l0orCrS/c7gqwxeduIFOd21g9g2RUeQ4qlWPegbQDKASzbfC28klPyrgJLW4MNq7uv2JwV8w==", "dev": true, "dependencies": { - "tslib": "2.4.0" + "tslib": "2.4.1" }, "funding": { "type": "opencollective", @@ -1991,9 +1970,9 @@ } }, "node_modules/@redis/client": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.3.1.tgz", - "integrity": "sha512-FKEHpOu7Q4+cuM6VWjA54988K5jkqOxvhvj2hEGSx086lvKwXyjzO7Lya7hcirZ0/Db8FLBJN7UXsJuyoNWPJg==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.4.2.tgz", + "integrity": "sha512-oUdEjE0I7JS5AyaAjkD3aOXn9NhO7XKyPyXEyrgFDu++VrVBHUPnV6dgEya9TcMuj5nIJRuCzCm8ZP+c9zCHPw==", "dependencies": { "cluster-key-slot": "1.1.1", "generic-pool": "3.9.0", @@ -2028,23 +2007,23 @@ } }, "node_modules/@redis/time-series": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.3.tgz", - "integrity": "sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", + "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@sinclair/typebox": { - "version": "0.24.47", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.47.tgz", - "integrity": "sha512-J4Xw0xYK4h7eC34MNOPQi6IkNxGRck6n4VJpWDzXIFVTW8I/D43Gf+NfWz/v/7NHlzWOPd3+T4PJ4OqklQ2u7A==", + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", "dev": true }, "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, "dependencies": { "type-detect": "4.0.8" @@ -2089,9 +2068,9 @@ "devOptional": true }, "node_modules/@types/babel__core": { - "version": "7.1.19", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", - "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "version": "7.1.20", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", + "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", @@ -2121,9 +2100,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz", - "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", + "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", "dev": true, "dependencies": { "@babel/types": "^7.3.0" @@ -2153,9 +2132,9 @@ "dev": true }, "node_modules/@types/eslint": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.7.tgz", - "integrity": "sha512-ehM7cCt2RSFs42mb+lcmhFT9ouIlV92PuaeRGn8N8c98oMjG4Z5pJHA9b1QiCcuqnbPSHcyfiD3mlhqMaHsQIw==", + "version": "8.4.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", + "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", "dev": true, "dependencies": { "@types/estree": "*", @@ -2179,12 +2158,12 @@ "dev": true }, "node_modules/@types/express": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", - "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.15.tgz", + "integrity": "sha512-Yv0k4bXGOH+8a+7bELd2PqHQsuiANB+A8a4gnQrkRWzrkKlb6KHaVvyXhqs04sVW/OWlbPyYxRgYlIXLfrufMQ==", "dependencies": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", + "@types/express-serve-static-core": "^4.17.31", "@types/qs": "*", "@types/serve-static": "*" } @@ -2257,10 +2236,9 @@ "dev": true }, "node_modules/@types/jsonwebtoken": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.9.tgz", - "integrity": "sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg==", - "dev": true, + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.8.tgz", + "integrity": "sha512-zm6xBQpFDIDM6o9r6HSgDeIcLy82TKWctCXEPbJJcXb5AKmi5BNNdLXneixK4lplX3PqIVcwLBCGE/kAGnlD4A==", "dependencies": { "@types/node": "*" } @@ -2280,9 +2258,9 @@ } }, "node_modules/@types/node": { - "version": "16.11.68", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.68.tgz", - "integrity": "sha512-JkRpuVz3xCNCWaeQ5EHLR/6woMbHZz/jZ7Kmc63AkU+1HxnoUugzSWMck7dsR4DvNYX8jp9wTi9K7WvnxOIQZQ==" + "version": "16.18.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.10.tgz", + "integrity": "sha512-XU1+v7h81p7145ddPfjv7jtWvkSilpcnON3mQ+bDi9Yuf7OI56efOglXRyXWgQ57xH3fEQgh7WOJMncRHVew5w==" }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -2300,9 +2278,9 @@ } }, "node_modules/@types/passport-jwt": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-3.0.7.tgz", - "integrity": "sha512-qRQ4qlww1Yhs3IaioDKrsDNmKy6gLDLgFsGwpCnc2YqWovO2Oxu9yCQdWHMJafQ7UIuOba4C4/TNXcGkQfEjlQ==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-3.0.8.tgz", + "integrity": "sha512-VKJZDJUAHFhPHHYvxdqFcc5vlDht8Q2pL1/ePvKAgqRThDaCc84lSYOTQmnx3+JIkDlN+2KfhFhXIzlcVT+Pcw==", "dev": true, "dependencies": { "@types/express": "*", @@ -2357,9 +2335,9 @@ } }, "node_modules/@types/semver": { - "version": "7.3.12", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.12.tgz", - "integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==", + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", "dev": true }, "node_modules/@types/serve-static": { @@ -2378,9 +2356,9 @@ "dev": true }, "node_modules/@types/superagent": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", - "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.16.tgz", + "integrity": "sha512-tLfnlJf6A5mB6ddqF159GqcDizfzbMUB1/DeT59/wBNqzRTNNKsaw79A/1TZ84X+f/EwWH8FeuSkjlCLyqS/zQ==", "dev": true, "dependencies": { "@types/cookiejar": "*", @@ -2397,14 +2375,14 @@ } }, "node_modules/@types/validator": { - "version": "13.7.9", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.9.tgz", - "integrity": "sha512-y5KJ1PjGXPpU4CZ7lThDu31s+FqvzhqwMOR6Go/x6xaQMFjgzwfzfOvCwABsylr/5n8sB1qFQm1Vi7TaCB8P+A==" + "version": "13.7.10", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.10.tgz", + "integrity": "sha512-t1yxFAR2n0+VO6hd/FJ9F2uezAZVWHLmpmlJzm1eX03+H7+HsuTAp7L8QJs+2pQCfWkP1+EXsGK9Z9v7o/qPVQ==" }, "node_modules/@types/yargs": { - "version": "17.0.13", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", - "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "version": "17.0.17", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.17.tgz", + "integrity": "sha512-72bWxFKTK6uwWJAVT+3rF6Jo6RTojiJ27FQo8Rf60AL+VZbzoVPnMFhKsUnbjR8A3BTCYQ7Mv3hnl8T0A+CX9g==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -2417,16 +2395,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz", - "integrity": "sha512-FsWboKkWdytGiXT5O1/R9j37YgcjO8MKHSUmWnIEjVaz0krHkplPnYi7mwdb+5+cs0toFNQb0HIrN7zONdIEWg==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.46.1.tgz", + "integrity": "sha512-YpzNv3aayRBwjs4J3oz65eVLXc9xx0PDbIRisHj+dYhvBn02MjYOD96P8YGiWEIFBrojaUjxvkaUpakD82phsA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.40.1", - "@typescript-eslint/type-utils": "5.40.1", - "@typescript-eslint/utils": "5.40.1", + "@typescript-eslint/scope-manager": "5.46.1", + "@typescript-eslint/type-utils": "5.46.1", + "@typescript-eslint/utils": "5.46.1", "debug": "^4.3.4", "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" @@ -2449,14 +2428,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.1.tgz", - "integrity": "sha512-IK6x55va5w4YvXd4b3VrXQPldV9vQTxi5ov+g4pMANsXPTXOcfjx08CRR1Dfrcc51syPtXHF5bgLlMHYFrvQtg==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.1.tgz", + "integrity": "sha512-RelQ5cGypPh4ySAtfIMBzBGyrNerQcmfA1oJvPj5f+H4jI59rl9xxpn4bonC0tQvUKOEN7eGBFWxFLK3Xepneg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.40.1", - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/typescript-estree": "5.40.1", + "@typescript-eslint/scope-manager": "5.46.1", + "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/typescript-estree": "5.46.1", "debug": "^4.3.4" }, "engines": { @@ -2476,13 +2455,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.1.tgz", - "integrity": "sha512-jkn4xsJiUQucI16OLCXrLRXDZ3afKhOIqXs4R3O+M00hdQLKR58WuyXPZZjhKLFCEP2g+TXdBRtLQ33UfAdRUg==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.46.1.tgz", + "integrity": "sha512-iOChVivo4jpwUdrJZyXSMrEIM/PvsbbDOX1y3UCKjSgWn+W89skxWaYXACQfxmIGhPVpRWK/VWPYc+bad6smIA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/visitor-keys": "5.40.1" + "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/visitor-keys": "5.46.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2493,13 +2472,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.1.tgz", - "integrity": "sha512-DLAs+AHQOe6n5LRraXiv27IYPhleF0ldEmx6yBqBgBLaNRKTkffhV1RPsjoJBhVup2zHxfaRtan8/YRBgYhU9Q==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.46.1.tgz", + "integrity": "sha512-V/zMyfI+jDmL1ADxfDxjZ0EMbtiVqj8LUGPAGyBkXXStWmCUErMpW873zEHsyguWCuq2iN4BrlWUkmuVj84yng==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.40.1", - "@typescript-eslint/utils": "5.40.1", + "@typescript-eslint/typescript-estree": "5.46.1", + "@typescript-eslint/utils": "5.46.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -2520,9 +2499,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", - "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.46.1.tgz", + "integrity": "sha512-Z5pvlCaZgU+93ryiYUwGwLl9AQVB/PQ1TsJ9NZ/gHzZjN7g9IAn6RSDkpCV8hqTwAiaj6fmCcKSQeBPlIpW28w==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2533,13 +2512,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz", - "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.46.1.tgz", + "integrity": "sha512-j9W4t67QiNp90kh5Nbr1w92wzt+toiIsaVPnEblB2Ih2U9fqBTyqV9T3pYWZBRt6QoMh/zVWP59EpuCjc4VRBg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/visitor-keys": "5.40.1", + "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/visitor-keys": "5.46.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2560,16 +2539,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.1.tgz", - "integrity": "sha512-a2TAVScoX9fjryNrW6BZRnreDUszxqm9eQ9Esv8n5nXApMW0zeANUYlwh/DED04SC/ifuBvXgZpIK5xeJHQ3aw==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.46.1.tgz", + "integrity": "sha512-RBdBAGv3oEpFojaCYT4Ghn4775pdjvwfDOfQ2P6qzNVgQOVrnSPe5/Pb88kv7xzYQjoio0eKHKB9GJ16ieSxvA==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.40.1", - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/typescript-estree": "5.40.1", + "@typescript-eslint/scope-manager": "5.46.1", + "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/typescript-estree": "5.46.1", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" @@ -2586,12 +2565,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", - "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.46.1.tgz", + "integrity": "sha512-jczZ9noovXwy59KjRTk1OftT78pwygdcmCuBf8yMoWt/8O8l+6x2LSEze0E4TeepXK4MezW3zGSyoDRZK7Y9cg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/types": "5.46.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -2773,9 +2752,9 @@ } }, "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "devOptional": true, "bin": { "acorn": "bin/acorn" @@ -2908,9 +2887,9 @@ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" }, "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "dependencies": { "normalize-path": "^3.0.0", @@ -3144,9 +3123,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.4", @@ -3156,7 +3135,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.10.3", + "qs": "6.11.0", "raw-body": "2.5.1", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -3340,9 +3319,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001422", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001422.tgz", - "integrity": "sha512-hSesn02u1QacQHhaxl/kNMZwqVG35Sz/8DgvmgedxSH8z9UUpcDYSPYgsj3x5dQNRcNp6BwpSfQfVzYUTm+fog==", + "version": "1.0.30001439", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz", + "integrity": "sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A==", "dev": true, "funding": [ { @@ -3420,10 +3399,13 @@ } }, "node_modules/ci-info": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", - "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", - "dev": true + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz", + "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==", + "dev": true, + "engines": { + "node": ">=8" + } }, "node_modules/cjs-module-lexer": { "version": "1.2.2", @@ -3746,9 +3728,9 @@ } }, "node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, "dependencies": { "@types/parse-json": "^4.0.0", @@ -3859,6 +3841,16 @@ "node": ">=0.4.0" } }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -3943,9 +3935,9 @@ } }, "node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", + "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==", "engines": { "node": ">=12" } @@ -4017,9 +4009,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", - "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -4070,14 +4062,15 @@ } }, "node_modules/eslint": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", - "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.30.0.tgz", + "integrity": "sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.10.5", + "@eslint/eslintrc": "^1.4.0", + "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -4093,14 +4086,14 @@ "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "globby": "^11.1.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", @@ -4279,9 +4272,9 @@ "dev": true }, "node_modules/espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", "dev": true, "dependencies": { "acorn": "^8.8.0", @@ -4513,29 +4506,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -4554,20 +4524,6 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, - "node_modules/express/node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -4628,9 +4584,9 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -4837,21 +4793,6 @@ "url": "https://ko-fi.com/tunnckoCore/commissions" } }, - "node_modules/formidable/node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -5009,9 +4950,9 @@ "dev": true }, "node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "version": "13.19.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", + "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -5163,9 +5104,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", + "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==", "dev": true, "engines": { "node": ">= 4" @@ -5296,6 +5237,31 @@ "node": ">= 0.10" } }, + "node_modules/ioredis": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.2.4.tgz", + "integrity": "sha512-qIpuAEt32lZJQ0XyrloCRdlEdUUNGG9i0UOk6zgzK6igyudNWqEBxfH6OlbnOOoBBvr1WB02mm8fR55CnikRng==", + "optional": true, + "peer": true, + "dependencies": { + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.0.1", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -5390,6 +5356,15 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -5933,9 +5908,9 @@ } }, "node_modules/jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "engines": { "node": ">=6" @@ -6316,10 +6291,14 @@ } }, "node_modules/js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", + "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } }, "node_modules/js-tokens": { "version": "4.0.0", @@ -6369,9 +6348,9 @@ "dev": true }, "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.2.tgz", + "integrity": "sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ==", "dev": true, "bin": { "json5": "lib/cli.js" @@ -6478,9 +6457,9 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.10.14", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.14.tgz", - "integrity": "sha512-McGS7GV/WjJ2KjfOGhJU1oJn29RYeo7Q+RpANRbUNMQ9gj5XArpbjurSuyYPTejFwbaUojstQ4XyWCrAzGOUXw==" + "version": "1.10.15", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.15.tgz", + "integrity": "sha512-sLeVLmWX17VCKKulc+aDIRHS95TxoTsKMRJi5s5gJdwlqNzMWcBCtSHHruVyXjqfi67daXM2SnLf2juSrdx5Sg==" }, "node_modules/lines-and-columns": { "version": "1.2.4", @@ -6517,11 +6496,25 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "optional": true, + "peer": true + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "optional": true, + "peer": true + }, "node_modules/lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", @@ -6680,9 +6673,9 @@ } }, "node_modules/memfs": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz", - "integrity": "sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw==", + "version": "3.4.12", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.12.tgz", + "integrity": "sha512-BcjuQn6vfqP+k100e0E9m61Hyqa//Brp+I3f0OBmN0ATHlFA8vx3Lt8z57R3u2bPqe3WGDBC+nF72fTH7isyEw==", "dev": true, "dependencies": { "fs-monkey": "^1.0.3" @@ -6845,6 +6838,12 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -6905,9 +6904,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", + "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", "dev": true }, "node_modules/normalize-path": { @@ -7544,9 +7543,9 @@ } }, "node_modules/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz", + "integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==", "dev": true, "bin": { "prettier": "bin-prettier.js" @@ -7773,9 +7772,9 @@ } }, "node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dependencies": { "side-channel": "^1.0.4" }, @@ -7895,16 +7894,39 @@ } }, "node_modules/redis": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.4.0.tgz", - "integrity": "sha512-tQyFG6O9iewLxxHYRyirJNklhe2QI7M/0o8q0jk7D9Z/Cxh/7oZrQyHKyjWz0TkkCls8ool/xvhL9K8zRnkaYQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.5.1.tgz", + "integrity": "sha512-oxXSoIqMJCQVBTfxP6BNTCtDMyh9G6Vi5wjdPdV/sRKkufyZslDqCScSGcOr6XGR/reAWZefz7E4leM31RgdBA==", "dependencies": { "@redis/bloom": "1.1.0", - "@redis/client": "1.3.1", + "@redis/client": "1.4.2", "@redis/graph": "1.1.0", "@redis/json": "1.0.4", "@redis/search": "1.1.0", - "@redis/time-series": "1.0.3" + "@redis/time-series": "1.0.4" + } + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "optional": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "optional": true, + "peer": true, + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" } }, "node_modules/reflect-metadata": { @@ -8072,9 +8094,9 @@ } }, "node_modules/rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", + "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", "dependencies": { "tslib": "^2.1.0" } @@ -8362,6 +8384,7 @@ "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", "dev": true }, "node_modules/split2": { @@ -8379,9 +8402,9 @@ "dev": true }, "node_modules/stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "dependencies": { "escape-string-regexp": "^2.0.0" @@ -8399,6 +8422,13 @@ "node": ">=8" } }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "optional": true, + "peer": true + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -8496,10 +8526,9 @@ } }, "node_modules/superagent": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.0.2.tgz", - "integrity": "sha512-QtYZ9uaNAMexI7XWl2vAXAh0j4q9H7T0WVEI/y5qaUB3QLwxo+voUgCQ217AokJzUTIVOp0RTo7fhZrwhD7A2Q==", - "deprecated": "Please use v8.0.0 until https://github.com/visionmedia/superagent/issues/1743 is resolved", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.0.6.tgz", + "integrity": "sha512-HqSe6DSIh3hEn6cJvCkaM1BLi466f1LHi4yubR0tpewlMpk4RUFFy35bKz8SsPBwYfIIJy5eclp+3tCYAuX0bw==", "dev": true, "dependencies": { "component-emitter": "^1.3.0", @@ -8507,11 +8536,11 @@ "debug": "^4.3.4", "fast-safe-stringify": "^2.1.1", "form-data": "^4.0.0", - "formidable": "^2.0.1", + "formidable": "^2.1.1", "methods": "^1.1.2", "mime": "2.6.0", "qs": "^6.11.0", - "semver": "^7.3.7" + "semver": "^7.3.8" }, "engines": { "node": ">=6.4.0 <13 || >=14" @@ -8529,29 +8558,14 @@ "node": ">=4.0.0" } }, - "node_modules/superagent/node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/supertest": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.0.tgz", - "integrity": "sha512-QgWju1cNoacP81Rv88NKkQ4oXTzGg0eNZtOoxp1ROpbS4OHY/eK5b8meShuFtdni161o5X0VQvgo7ErVyKK+Ow==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.3.tgz", + "integrity": "sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==", "dev": true, "dependencies": { "methods": "^1.1.2", - "superagent": "^8.0.0" + "superagent": "^8.0.5" }, "engines": { "node": ">=6.4.0" @@ -8628,9 +8642,9 @@ } }, "node_modules/terser": { - "version": "5.15.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz", - "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", + "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.2", @@ -8872,9 +8886,9 @@ } }, "node_modules/ts-loader": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.1.tgz", - "integrity": "sha512-384TYAqGs70rn9F0VBnh6BPTfhga7yFNdC5gXbQpDrBj9/KsT4iRkGqKXhziofHOlE2j6YEaiTYVGKKvPhGWvw==", + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.2.tgz", + "integrity": "sha512-OmlC4WVmFv5I0PpaxYb+qGeGOdm5giHU7HwDDUjw59emP2UYMHy9fFSDcYgSNoH8sXcj4hGCSEhlDZ9ULeDraA==", "dev": true, "dependencies": { "chalk": "^4.1.0", @@ -9003,9 +9017,9 @@ } }, "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -9079,9 +9093,9 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "node_modules/typeorm": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.10.tgz", - "integrity": "sha512-VMKiM84EpJQ+Mz9xDIPqnfplWhyUy1d8ccaKdMY9obifxJOTFnv8GYVyPsGwG8Lk7Nb8MlttHyHWENGAhBA3WA==", + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.11.tgz", + "integrity": "sha512-pzdOyWbVuz/z8Ww6gqvBW4nylsM0KLdUCDExr2gR20/x1khGSVxQkjNV/3YqliG90jrWzrknYbYscpk8yxFJVg==", "dependencies": { "@sqltools/formatter": "^1.2.2", "app-root-path": "^3.0.0", @@ -9115,7 +9129,7 @@ "peerDependencies": { "@google-cloud/spanner": "^5.18.0", "@sap/hana-client": "^2.12.25", - "better-sqlite3": "^7.1.2", + "better-sqlite3": "^7.1.2 || ^8.0.0", "hdb-pool": "^0.1.6", "ioredis": "^5.0.4", "mongodb": "^3.6.0", @@ -9243,9 +9257,9 @@ } }, "node_modules/typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "devOptional": true, "bin": { "tsc": "bin/tsc", @@ -9417,10 +9431,11 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/webpack": { - "version": "5.74.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", - "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", + "version": "5.75.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", + "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", "dev": true, + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", @@ -9666,9 +9681,9 @@ } }, "node_modules/yargs": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", - "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -9676,7 +9691,7 @@ "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" }, "engines": { "node": ">=12" @@ -9842,27 +9857,27 @@ } }, "@babel/compat-data": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.4.tgz", - "integrity": "sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz", + "integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==", "dev": true }, "@babel/core": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.6.tgz", - "integrity": "sha512-D2Ue4KHpc6Ys2+AxpIx1BZ8+UegLLLE2p3KJEuJRKmokHOtl49jQ5ny1773KsGLZs8MQvBidAF6yWUJxRqtKtg==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz", + "integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==", "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.6", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helpers": "^7.19.4", - "@babel/parser": "^7.19.6", + "@babel/generator": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-module-transforms": "^7.20.2", + "@babel/helpers": "^7.20.5", + "@babel/parser": "^7.20.5", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.6", - "@babel/types": "^7.19.4", + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -9879,12 +9894,12 @@ } }, "@babel/generator": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.6.tgz", - "integrity": "sha512-oHGRUQeoX1QrKeJIKVe0hwjGqNnVYsM5Nep5zo0uE0m42sLH+Fsd2pStJ5sRM1bNyTUUoz0pe2lTeMJrb/taTA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz", + "integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==", "dev": true, "requires": { - "@babel/types": "^7.19.4", + "@babel/types": "^7.20.5", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -9903,12 +9918,12 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz", - "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz", + "integrity": "sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==", "dev": true, "requires": { - "@babel/compat-data": "^7.19.3", + "@babel/compat-data": "^7.20.0", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.21.3", "semver": "^6.3.0" @@ -9957,34 +9972,34 @@ } }, "@babel/helper-module-transforms": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.6.tgz", - "integrity": "sha512-fCmcfQo/KYr/VXXDIyd3CBGZ6AFhPFy1TfSEJ+PilGVlQT6jcbqtHAM4C1EciRqMza7/TpOUZliuSH+U6HAhJw==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz", + "integrity": "sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==", "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.19.4", + "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.6", - "@babel/types": "^7.19.4" + "@babel/traverse": "^7.20.1", + "@babel/types": "^7.20.2" } }, "@babel/helper-plugin-utils": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", + "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", "dev": true }, "@babel/helper-simple-access": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.19.4.tgz", - "integrity": "sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "dev": true, "requires": { - "@babel/types": "^7.19.4" + "@babel/types": "^7.20.2" } }, "@babel/helper-split-export-declaration": { @@ -10015,14 +10030,14 @@ "dev": true }, "@babel/helpers": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.4.tgz", - "integrity": "sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.6.tgz", + "integrity": "sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==", "dev": true, "requires": { "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.4", - "@babel/types": "^7.19.4" + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5" } }, "@babel/highlight": { @@ -10095,9 +10110,9 @@ } }, "@babel/parser": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.6.tgz", - "integrity": "sha512-h1IUp81s2JYJ3mRkdxJgs4UvmSsRvDrx5ICSJbPvtWYv5i1nTBGcBpnog+89rAFMwvvru6E5NUHdBe01UeSzYA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", + "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==", "dev": true }, "@babel/plugin-syntax-async-generators": { @@ -10209,12 +10224,12 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", - "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", + "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.19.0" } }, "@babel/template": { @@ -10229,19 +10244,19 @@ } }, "@babel/traverse": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.6.tgz", - "integrity": "sha512-6l5HrUCzFM04mfbG09AagtYyR2P0B71B1wN7PfSPiksDPz2k5H9CBC1tcZpz2M8OxbKTPccByoOJ22rUKbpmQQ==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz", + "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.6", + "@babel/generator": "^7.20.5", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.6", - "@babel/types": "^7.19.4", + "@babel/parser": "^7.20.5", + "@babel/types": "^7.20.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -10255,9 +10270,9 @@ } }, "@babel/types": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.4.tgz", - "integrity": "sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz", + "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==", "dev": true, "requires": { "@babel/helper-string-parser": "^7.19.4", @@ -10300,15 +10315,15 @@ } }, "@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.0.tgz", + "integrity": "sha512-7yfvXy6MWLgWSFsLhz5yH3iQ52St8cdUY6FoGieKkRDVxuxmrNuUetIuu6cmjNWwniUHiWXjxCr5tTXDrbYS5A==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.4.0", - "globals": "^13.15.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -10337,14 +10352,14 @@ } }, "@humanwhocodes/config-array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", - "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" } }, "@humanwhocodes/module-importer": { @@ -10359,6 +10374,13 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", + "optional": true, + "peer": true + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -10785,9 +10807,9 @@ } }, "@nestjs/cli": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-9.1.4.tgz", - "integrity": "sha512-cvN4DcLzaqFzKRmpU3tOeLmw7+1p4XXsFLyWgteId0Szf6cAk5KJpD5jl2Kw7f39vNw9Pss8yiJ1q1CD/fcbwQ==", + "version": "9.1.5", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-9.1.5.tgz", + "integrity": "sha512-rSp26+Nv7PFtYrRSP18Gv5ZK8rRSc2SCCF5wh4SdZaVGgkxShpNq9YEfI+ik/uziN3KC5o74ppYRXGj+aHGVsA==", "dev": true, "requires": { "@angular-devkit/core": "14.2.2", @@ -10809,26 +10831,58 @@ "tree-kill": "1.2.2", "tsconfig-paths": "4.1.0", "tsconfig-paths-webpack-plugin": "4.0.0", - "typescript": "4.8.3", + "typescript": "4.8.4", "webpack": "5.74.0", "webpack-node-externals": "3.0.0" }, "dependencies": { "typescript": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true + }, + "webpack": { + "version": "5.74.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", + "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.10.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + } } } }, "@nestjs/common": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.1.4.tgz", - "integrity": "sha512-hmGTZ8ShKFDqqlU02uU8e/8PNE4bnES4pcFa6s/T1pLDYWjyf/75Klunro1W4aQPHcxnnohBmB27WxMqFTPEfw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.2.1.tgz", + "integrity": "sha512-nZuo3oDsSSlC5mti/M2aCWTEIfHPGDXmBwWgPeCpRbrNz3IWd109rkajll+yxgidVjznAdBS9y00JkAVJblNYw==", "requires": { "iterare": "1.2.1", - "tslib": "2.4.0", + "tslib": "2.4.1", "uuid": "9.0.0" } }, @@ -10843,11 +10897,6 @@ "uuid": "8.3.2" }, "dependencies": { - "dotenv": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", - "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==" - }, "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -10856,16 +10905,16 @@ } }, "@nestjs/core": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.1.4.tgz", - "integrity": "sha512-S6KpGeKotPYh126hhRqYLhvg9lxSbAmGfEbK8m09crIK7CYP05t32KtT6n12xl5/iva1G4Ch87Z/3rYP76etUg==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.2.1.tgz", + "integrity": "sha512-a9GkXuu8uXgNgCVW+17iI8kLCltO+HwHpU2IhR+32JKnN2WEQ1YEWU4t3GJ2MNq44YkjIw9zrKvFkjJBlYrNbQ==", "requires": { "@nuxtjs/opencollective": "0.3.2", "fast-safe-stringify": "2.1.1", "iterare": "1.2.1", "object-hash": "3.0.0", "path-to-regexp": "3.2.0", - "tslib": "2.4.0", + "tslib": "2.4.1", "uuid": "9.0.0" } }, @@ -10876,16 +10925,6 @@ "requires": { "@types/jsonwebtoken": "8.5.8", "jsonwebtoken": "8.5.1" - }, - "dependencies": { - "@types/jsonwebtoken": { - "version": "8.5.8", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.8.tgz", - "integrity": "sha512-zm6xBQpFDIDM6o9r6HSgDeIcLy82TKWctCXEPbJJcXb5AKmi5BNNdLXneixK4lplX3PqIVcwLBCGE/kAGnlD4A==", - "requires": { - "@types/node": "*" - } - } } }, "@nestjs/mapped-types": { @@ -10901,73 +10940,15 @@ "requires": {} }, "@nestjs/platform-express": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.1.4.tgz", - "integrity": "sha512-SLJWDa6V54QrUvzKI4Eyt7gyrjV7F9FY1uHFihshjmQfpf0ebCGacR9jzNwf01aHl0BJX3DUn/KYteBjz6DJXw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.2.1.tgz", + "integrity": "sha512-7PecaXt8lrdS1p6Vb1X/am3GGv+EO1VahyDzaEGOK6C0zwhc0VPfLtwihkjjfhS6BjpRIXXgviwEjONUvxVZnA==", "requires": { - "body-parser": "1.20.0", + "body-parser": "1.20.1", "cors": "2.8.5", - "express": "4.18.1", + "express": "4.18.2", "multer": "1.4.4-lts.1", - "tslib": "2.4.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.0", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.10.3", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - } + "tslib": "2.4.1" } }, "@nestjs/schematics": { @@ -11049,12 +11030,12 @@ } }, "@nestjs/testing": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-9.1.4.tgz", - "integrity": "sha512-gO6b9QJyUajh38DNdss9gSE0UO7x60Jh10W4SwHEjQT1W+yxaEWr3aLyuQItTvUVY6C28XKFLTykMpr8GO28Ug==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-9.2.1.tgz", + "integrity": "sha512-lemXZdRSuqoZ87l0orCrS/c7gqwxeduIFOd21g9g2RUeQ4qlWPegbQDKASzbfC28klPyrgJLW4MNq7uv2JwV8w==", "dev": true, "requires": { - "tslib": "2.4.0" + "tslib": "2.4.1" } }, "@nestjs/typeorm": { @@ -11168,9 +11149,9 @@ "requires": {} }, "@redis/client": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.3.1.tgz", - "integrity": "sha512-FKEHpOu7Q4+cuM6VWjA54988K5jkqOxvhvj2hEGSx086lvKwXyjzO7Lya7hcirZ0/Db8FLBJN7UXsJuyoNWPJg==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.4.2.tgz", + "integrity": "sha512-oUdEjE0I7JS5AyaAjkD3aOXn9NhO7XKyPyXEyrgFDu++VrVBHUPnV6dgEya9TcMuj5nIJRuCzCm8ZP+c9zCHPw==", "requires": { "cluster-key-slot": "1.1.1", "generic-pool": "3.9.0", @@ -11196,21 +11177,21 @@ "requires": {} }, "@redis/time-series": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.3.tgz", - "integrity": "sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", + "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", "requires": {} }, "@sinclair/typebox": { - "version": "0.24.47", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.47.tgz", - "integrity": "sha512-J4Xw0xYK4h7eC34MNOPQi6IkNxGRck6n4VJpWDzXIFVTW8I/D43Gf+NfWz/v/7NHlzWOPd3+T4PJ4OqklQ2u7A==", + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", "dev": true }, "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -11255,9 +11236,9 @@ "devOptional": true }, "@types/babel__core": { - "version": "7.1.19", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", - "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "version": "7.1.20", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", + "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -11287,9 +11268,9 @@ } }, "@types/babel__traverse": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz", - "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", + "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -11319,9 +11300,9 @@ "dev": true }, "@types/eslint": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.7.tgz", - "integrity": "sha512-ehM7cCt2RSFs42mb+lcmhFT9ouIlV92PuaeRGn8N8c98oMjG4Z5pJHA9b1QiCcuqnbPSHcyfiD3mlhqMaHsQIw==", + "version": "8.4.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", + "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", "dev": true, "requires": { "@types/estree": "*", @@ -11345,12 +11326,12 @@ "dev": true }, "@types/express": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", - "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.15.tgz", + "integrity": "sha512-Yv0k4bXGOH+8a+7bELd2PqHQsuiANB+A8a4gnQrkRWzrkKlb6KHaVvyXhqs04sVW/OWlbPyYxRgYlIXLfrufMQ==", "requires": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", + "@types/express-serve-static-core": "^4.17.31", "@types/qs": "*", "@types/serve-static": "*" } @@ -11423,10 +11404,9 @@ "dev": true }, "@types/jsonwebtoken": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.9.tgz", - "integrity": "sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg==", - "dev": true, + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.8.tgz", + "integrity": "sha512-zm6xBQpFDIDM6o9r6HSgDeIcLy82TKWctCXEPbJJcXb5AKmi5BNNdLXneixK4lplX3PqIVcwLBCGE/kAGnlD4A==", "requires": { "@types/node": "*" } @@ -11446,9 +11426,9 @@ } }, "@types/node": { - "version": "16.11.68", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.68.tgz", - "integrity": "sha512-JkRpuVz3xCNCWaeQ5EHLR/6woMbHZz/jZ7Kmc63AkU+1HxnoUugzSWMck7dsR4DvNYX8jp9wTi9K7WvnxOIQZQ==" + "version": "16.18.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.10.tgz", + "integrity": "sha512-XU1+v7h81p7145ddPfjv7jtWvkSilpcnON3mQ+bDi9Yuf7OI56efOglXRyXWgQ57xH3fEQgh7WOJMncRHVew5w==" }, "@types/parse-json": { "version": "4.0.0", @@ -11466,9 +11446,9 @@ } }, "@types/passport-jwt": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-3.0.7.tgz", - "integrity": "sha512-qRQ4qlww1Yhs3IaioDKrsDNmKy6gLDLgFsGwpCnc2YqWovO2Oxu9yCQdWHMJafQ7UIuOba4C4/TNXcGkQfEjlQ==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-3.0.8.tgz", + "integrity": "sha512-VKJZDJUAHFhPHHYvxdqFcc5vlDht8Q2pL1/ePvKAgqRThDaCc84lSYOTQmnx3+JIkDlN+2KfhFhXIzlcVT+Pcw==", "dev": true, "requires": { "@types/express": "*", @@ -11522,9 +11502,9 @@ } }, "@types/semver": { - "version": "7.3.12", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.12.tgz", - "integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==", + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", "dev": true }, "@types/serve-static": { @@ -11543,9 +11523,9 @@ "dev": true }, "@types/superagent": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", - "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.16.tgz", + "integrity": "sha512-tLfnlJf6A5mB6ddqF159GqcDizfzbMUB1/DeT59/wBNqzRTNNKsaw79A/1TZ84X+f/EwWH8FeuSkjlCLyqS/zQ==", "dev": true, "requires": { "@types/cookiejar": "*", @@ -11562,14 +11542,14 @@ } }, "@types/validator": { - "version": "13.7.9", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.9.tgz", - "integrity": "sha512-y5KJ1PjGXPpU4CZ7lThDu31s+FqvzhqwMOR6Go/x6xaQMFjgzwfzfOvCwABsylr/5n8sB1qFQm1Vi7TaCB8P+A==" + "version": "13.7.10", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.10.tgz", + "integrity": "sha512-t1yxFAR2n0+VO6hd/FJ9F2uezAZVWHLmpmlJzm1eX03+H7+HsuTAp7L8QJs+2pQCfWkP1+EXsGK9Z9v7o/qPVQ==" }, "@types/yargs": { - "version": "17.0.13", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", - "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "version": "17.0.17", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.17.tgz", + "integrity": "sha512-72bWxFKTK6uwWJAVT+3rF6Jo6RTojiJ27FQo8Rf60AL+VZbzoVPnMFhKsUnbjR8A3BTCYQ7Mv3hnl8T0A+CX9g==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -11582,69 +11562,70 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz", - "integrity": "sha512-FsWboKkWdytGiXT5O1/R9j37YgcjO8MKHSUmWnIEjVaz0krHkplPnYi7mwdb+5+cs0toFNQb0HIrN7zONdIEWg==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.46.1.tgz", + "integrity": "sha512-YpzNv3aayRBwjs4J3oz65eVLXc9xx0PDbIRisHj+dYhvBn02MjYOD96P8YGiWEIFBrojaUjxvkaUpakD82phsA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.40.1", - "@typescript-eslint/type-utils": "5.40.1", - "@typescript-eslint/utils": "5.40.1", + "@typescript-eslint/scope-manager": "5.46.1", + "@typescript-eslint/type-utils": "5.46.1", + "@typescript-eslint/utils": "5.46.1", "debug": "^4.3.4", "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" } }, "@typescript-eslint/parser": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.1.tgz", - "integrity": "sha512-IK6x55va5w4YvXd4b3VrXQPldV9vQTxi5ov+g4pMANsXPTXOcfjx08CRR1Dfrcc51syPtXHF5bgLlMHYFrvQtg==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.1.tgz", + "integrity": "sha512-RelQ5cGypPh4ySAtfIMBzBGyrNerQcmfA1oJvPj5f+H4jI59rl9xxpn4bonC0tQvUKOEN7eGBFWxFLK3Xepneg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.40.1", - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/typescript-estree": "5.40.1", + "@typescript-eslint/scope-manager": "5.46.1", + "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/typescript-estree": "5.46.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.1.tgz", - "integrity": "sha512-jkn4xsJiUQucI16OLCXrLRXDZ3afKhOIqXs4R3O+M00hdQLKR58WuyXPZZjhKLFCEP2g+TXdBRtLQ33UfAdRUg==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.46.1.tgz", + "integrity": "sha512-iOChVivo4jpwUdrJZyXSMrEIM/PvsbbDOX1y3UCKjSgWn+W89skxWaYXACQfxmIGhPVpRWK/VWPYc+bad6smIA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/visitor-keys": "5.40.1" + "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/visitor-keys": "5.46.1" } }, "@typescript-eslint/type-utils": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.1.tgz", - "integrity": "sha512-DLAs+AHQOe6n5LRraXiv27IYPhleF0ldEmx6yBqBgBLaNRKTkffhV1RPsjoJBhVup2zHxfaRtan8/YRBgYhU9Q==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.46.1.tgz", + "integrity": "sha512-V/zMyfI+jDmL1ADxfDxjZ0EMbtiVqj8LUGPAGyBkXXStWmCUErMpW873zEHsyguWCuq2iN4BrlWUkmuVj84yng==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.40.1", - "@typescript-eslint/utils": "5.40.1", + "@typescript-eslint/typescript-estree": "5.46.1", + "@typescript-eslint/utils": "5.46.1", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", - "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.46.1.tgz", + "integrity": "sha512-Z5pvlCaZgU+93ryiYUwGwLl9AQVB/PQ1TsJ9NZ/gHzZjN7g9IAn6RSDkpCV8hqTwAiaj6fmCcKSQeBPlIpW28w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz", - "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.46.1.tgz", + "integrity": "sha512-j9W4t67QiNp90kh5Nbr1w92wzt+toiIsaVPnEblB2Ih2U9fqBTyqV9T3pYWZBRt6QoMh/zVWP59EpuCjc4VRBg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/visitor-keys": "5.40.1", + "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/visitor-keys": "5.46.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -11653,28 +11634,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.1.tgz", - "integrity": "sha512-a2TAVScoX9fjryNrW6BZRnreDUszxqm9eQ9Esv8n5nXApMW0zeANUYlwh/DED04SC/ifuBvXgZpIK5xeJHQ3aw==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.46.1.tgz", + "integrity": "sha512-RBdBAGv3oEpFojaCYT4Ghn4775pdjvwfDOfQ2P6qzNVgQOVrnSPe5/Pb88kv7xzYQjoio0eKHKB9GJ16ieSxvA==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.40.1", - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/typescript-estree": "5.40.1", + "@typescript-eslint/scope-manager": "5.46.1", + "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/typescript-estree": "5.46.1", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", - "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.46.1.tgz", + "integrity": "sha512-jczZ9noovXwy59KjRTk1OftT78pwygdcmCuBf8yMoWt/8O8l+6x2LSEze0E4TeepXK4MezW3zGSyoDRZK7Y9cg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/types": "5.46.1", "eslint-visitor-keys": "^3.3.0" } }, @@ -11846,9 +11827,9 @@ } }, "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "devOptional": true }, "acorn-import-assertions": { @@ -11934,9 +11915,9 @@ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" }, "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -12115,9 +12096,9 @@ } }, "body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "requires": { "bytes": "3.1.2", "content-type": "~1.0.4", @@ -12127,7 +12108,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.10.3", + "qs": "6.11.0", "raw-body": "2.5.1", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -12255,9 +12236,9 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "caniuse-lite": { - "version": "1.0.30001422", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001422.tgz", - "integrity": "sha512-hSesn02u1QacQHhaxl/kNMZwqVG35Sz/8DgvmgedxSH8z9UUpcDYSPYgsj3x5dQNRcNp6BwpSfQfVzYUTm+fog==", + "version": "1.0.30001439", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz", + "integrity": "sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A==", "dev": true }, "chalk": { @@ -12305,9 +12286,9 @@ "dev": true }, "ci-info": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", - "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz", + "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==", "dev": true }, "cjs-module-lexer": { @@ -12557,9 +12538,9 @@ } }, "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, "requires": { "@types/parse-json": "^4.0.0", @@ -12637,6 +12618,13 @@ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true }, + "denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "optional": true, + "peer": true + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -12699,9 +12687,9 @@ } }, "dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", + "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==" }, "dotenv-expand": { "version": "8.0.3", @@ -12758,9 +12746,9 @@ } }, "enhanced-resolve": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", - "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "dev": true, "requires": { "graceful-fs": "^4.2.4", @@ -12799,14 +12787,15 @@ "dev": true }, "eslint": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", - "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.30.0.tgz", + "integrity": "sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.10.5", + "@eslint/eslintrc": "^1.4.0", + "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -12822,14 +12811,14 @@ "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "globby": "^11.1.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", @@ -12949,9 +12938,9 @@ "dev": true }, "espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", "dev": true, "requires": { "acorn": "^8.8.0", @@ -13096,25 +13085,6 @@ "vary": "~1.1.2" }, "dependencies": { - "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - } - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -13132,14 +13102,6 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "requires": { - "side-channel": "^1.0.4" - } } } }, @@ -13232,9 +13194,9 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -13392,17 +13354,6 @@ "hexoid": "^1.0.0", "once": "^1.4.0", "qs": "^6.11.0" - }, - "dependencies": { - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - } } }, "forwarded": { @@ -13516,9 +13467,9 @@ "dev": true }, "globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "version": "13.19.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", + "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -13617,9 +13568,9 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", + "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==", "dev": true }, "import-fresh": { @@ -13716,6 +13667,24 @@ "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true }, + "ioredis": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.2.4.tgz", + "integrity": "sha512-qIpuAEt32lZJQ0XyrloCRdlEdUUNGG9i0UOk6zgzK6igyudNWqEBxfH6OlbnOOoBBvr1WB02mm8fR55CnikRng==", + "optional": true, + "peer": true, + "requires": { + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.0.1", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + } + }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -13783,6 +13752,12 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -14185,9 +14160,9 @@ } }, "jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "requires": {} }, @@ -14487,9 +14462,9 @@ } }, "js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", + "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==", "dev": true }, "js-tokens": { @@ -14531,9 +14506,9 @@ "dev": true }, "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.2.tgz", + "integrity": "sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ==", "dev": true }, "jsonc-parser": { @@ -14618,9 +14593,9 @@ } }, "libphonenumber-js": { - "version": "1.10.14", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.14.tgz", - "integrity": "sha512-McGS7GV/WjJ2KjfOGhJU1oJn29RYeo7Q+RpANRbUNMQ9gj5XArpbjurSuyYPTejFwbaUojstQ4XyWCrAzGOUXw==" + "version": "1.10.15", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.15.tgz", + "integrity": "sha512-sLeVLmWX17VCKKulc+aDIRHS95TxoTsKMRJi5s5gJdwlqNzMWcBCtSHHruVyXjqfi67daXM2SnLf2juSrdx5Sg==" }, "lines-and-columns": { "version": "1.2.4", @@ -14648,11 +14623,25 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "optional": true, + "peer": true + }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "optional": true, + "peer": true + }, "lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", @@ -14779,9 +14768,9 @@ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, "memfs": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz", - "integrity": "sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw==", + "version": "3.4.12", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.12.tgz", + "integrity": "sha512-BcjuQn6vfqP+k100e0E9m61Hyqa//Brp+I3f0OBmN0ATHlFA8vx3Lt8z57R3u2bPqe3WGDBC+nF72fTH7isyEw==", "dev": true, "requires": { "fs-monkey": "^1.0.3" @@ -14905,6 +14894,12 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -14951,9 +14946,9 @@ "dev": true }, "node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", + "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", "dev": true }, "normalize-path": { @@ -15416,9 +15411,9 @@ "dev": true }, "prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz", + "integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==", "dev": true }, "prettier-linter-helpers": { @@ -15589,9 +15584,9 @@ } }, "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "requires": { "side-channel": "^1.0.4" } @@ -15678,16 +15673,33 @@ } }, "redis": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.4.0.tgz", - "integrity": "sha512-tQyFG6O9iewLxxHYRyirJNklhe2QI7M/0o8q0jk7D9Z/Cxh/7oZrQyHKyjWz0TkkCls8ool/xvhL9K8zRnkaYQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.5.1.tgz", + "integrity": "sha512-oxXSoIqMJCQVBTfxP6BNTCtDMyh9G6Vi5wjdPdV/sRKkufyZslDqCScSGcOr6XGR/reAWZefz7E4leM31RgdBA==", "requires": { "@redis/bloom": "1.1.0", - "@redis/client": "1.3.1", + "@redis/client": "1.4.2", "@redis/graph": "1.1.0", "@redis/json": "1.0.4", "@redis/search": "1.1.0", - "@redis/time-series": "1.0.3" + "@redis/time-series": "1.0.4" + } + }, + "redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "optional": true, + "peer": true + }, + "redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "optional": true, + "peer": true, + "requires": { + "redis-errors": "^1.0.0" } }, "reflect-metadata": { @@ -15797,9 +15809,9 @@ } }, "rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", + "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", "requires": { "tslib": "^2.1.0" } @@ -16043,9 +16055,9 @@ "dev": true }, "stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "requires": { "escape-string-regexp": "^2.0.0" @@ -16059,6 +16071,13 @@ } } }, + "standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "optional": true, + "peer": true + }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -16131,9 +16150,9 @@ "dev": true }, "superagent": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.0.2.tgz", - "integrity": "sha512-QtYZ9uaNAMexI7XWl2vAXAh0j4q9H7T0WVEI/y5qaUB3QLwxo+voUgCQ217AokJzUTIVOp0RTo7fhZrwhD7A2Q==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.0.6.tgz", + "integrity": "sha512-HqSe6DSIh3hEn6cJvCkaM1BLi466f1LHi4yubR0tpewlMpk4RUFFy35bKz8SsPBwYfIIJy5eclp+3tCYAuX0bw==", "dev": true, "requires": { "component-emitter": "^1.3.0", @@ -16141,11 +16160,11 @@ "debug": "^4.3.4", "fast-safe-stringify": "^2.1.1", "form-data": "^4.0.0", - "formidable": "^2.0.1", + "formidable": "^2.1.1", "methods": "^1.1.2", "mime": "2.6.0", "qs": "^6.11.0", - "semver": "^7.3.7" + "semver": "^7.3.8" }, "dependencies": { "mime": { @@ -16153,26 +16172,17 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } } } }, "supertest": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.0.tgz", - "integrity": "sha512-QgWju1cNoacP81Rv88NKkQ4oXTzGg0eNZtOoxp1ROpbS4OHY/eK5b8meShuFtdni161o5X0VQvgo7ErVyKK+Ow==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.3.tgz", + "integrity": "sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==", "dev": true, "requires": { "methods": "^1.1.2", - "superagent": "^8.0.0" + "superagent": "^8.0.5" } }, "supports-color": { @@ -16222,9 +16232,9 @@ } }, "terser": { - "version": "5.15.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz", - "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", + "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", "dev": true, "requires": { "@jridgewell/source-map": "^0.3.2", @@ -16383,9 +16393,9 @@ } }, "ts-loader": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.1.tgz", - "integrity": "sha512-384TYAqGs70rn9F0VBnh6BPTfhga7yFNdC5gXbQpDrBj9/KsT4iRkGqKXhziofHOlE2j6YEaiTYVGKKvPhGWvw==", + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.2.tgz", + "integrity": "sha512-OmlC4WVmFv5I0PpaxYb+qGeGOdm5giHU7HwDDUjw59emP2UYMHy9fFSDcYgSNoH8sXcj4hGCSEhlDZ9ULeDraA==", "dev": true, "requires": { "chalk": "^4.1.0", @@ -16470,9 +16480,9 @@ } }, "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "tsutils": { "version": "3.21.0", @@ -16527,9 +16537,9 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "typeorm": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.10.tgz", - "integrity": "sha512-VMKiM84EpJQ+Mz9xDIPqnfplWhyUy1d8ccaKdMY9obifxJOTFnv8GYVyPsGwG8Lk7Nb8MlttHyHWENGAhBA3WA==", + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.11.tgz", + "integrity": "sha512-pzdOyWbVuz/z8Ww6gqvBW4nylsM0KLdUCDExr2gR20/x1khGSVxQkjNV/3YqliG90jrWzrknYbYscpk8yxFJVg==", "requires": { "@sqltools/formatter": "^1.2.2", "app-root-path": "^3.0.0", @@ -16581,9 +16591,9 @@ } }, "typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "devOptional": true }, "uid-safe": { @@ -16705,10 +16715,11 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "webpack": { - "version": "5.74.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", - "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", + "version": "5.75.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", + "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", "dev": true, + "peer": true, "requires": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", @@ -16881,9 +16892,9 @@ "dev": true }, "yargs": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", - "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", "requires": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -16891,7 +16902,7 @@ "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" } }, "yargs-parser": { diff --git a/srcs/requirements/nestjs/api_back/src/app.module.ts b/srcs/requirements/nestjs/api_back/src/app.module.ts index 837f8baf..63fa879c 100644 --- a/srcs/requirements/nestjs/api_back/src/app.module.ts +++ b/srcs/requirements/nestjs/api_back/src/app.module.ts @@ -7,13 +7,14 @@ import { ConfigModule } from '@nestjs/config'; import { FriendshipsModule } from './friendship/friendships.module'; import { AuthenticationModule } from './auth/42/authentication.module'; import { PassportModule } from '@nestjs/passport'; -// import { GameModule } from './game/game/game.module'; +import { GameModule } from './game/game.module'; @Module({ imports: [UsersModule, AuthenticationModule, PassportModule.register({ session: true }), FriendshipsModule, + GameModule, ConfigModule.forRoot(), TypeOrmModule.forRoot({ type: 'postgres', @@ -27,7 +28,6 @@ import { PassportModule } from '@nestjs/passport'; //avec une classe pour le module synchronize: true, }), - // GameModule, ], controllers: [AppController], providers: [AppService], diff --git a/srcs/requirements/nestjs/api_back/src/auth/42/strategy/42strategy.ts b/srcs/requirements/nestjs/api_back/src/auth/42/strategy/42strategy.ts index 6b43659c..6670477a 100644 --- a/srcs/requirements/nestjs/api_back/src/auth/42/strategy/42strategy.ts +++ b/srcs/requirements/nestjs/api_back/src/auth/42/strategy/42strategy.ts @@ -18,7 +18,7 @@ import { CreateUsersDto } from "src/users/dto/create-users.dto"; async validate(accessToken: string, refreshToken: string, profile: Profile, callbackURL: string) { console.log("Validate inside strategy.ts"); console.log(profile.id, profile.username, profile.phoneNumbers[0].value, profile.emails[0].value, profile.photos[0].value); - const userDTO: CreateUsersDto = { fortyTwoId: profile.id, username: profile.username, email: profile.emails[0].value, image_url: 'default.png', isEnabledTwoFactorAuth: false , status: "connected" }; + const userDTO: CreateUsersDto = { fortyTwoId: profile.id, username: profile.username, email: profile.emails[0].value, image_url: 'default.png', isEnabledTwoFactorAuth: false , status: "Connected" }; const user = await this.authenticationService.validateUser(userDTO); if (!user) throw new UnauthorizedException(); diff --git a/srcs/requirements/nestjs/api_back/src/game/dto/create-party.dto.ts b/srcs/requirements/nestjs/api_back/src/game/dto/create-party.dto.ts deleted file mode 100644 index 14d2e14c..00000000 --- a/srcs/requirements/nestjs/api_back/src/game/dto/create-party.dto.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { IsBoolean, IsEmail, IsNotEmpty, IsString } from 'class-validator'; - -export class CreateUsersDto { - @IsString() - @IsNotEmpty() - readonly username: string; - readonly fortyTwoId: string; - @IsEmail() - readonly email: string; - @IsString() - readonly image_url: string; - @IsString() - readonly status: string; - @IsBoolean() - readonly isEnabledTwoFactorAuth: boolean; -} diff --git a/srcs/requirements/nestjs/api_back/src/game/dto/createGame.dto.ts b/srcs/requirements/nestjs/api_back/src/game/dto/createGame.dto.ts new file mode 100644 index 00000000..ddce81b3 --- /dev/null +++ b/srcs/requirements/nestjs/api_back/src/game/dto/createGame.dto.ts @@ -0,0 +1,19 @@ +import { IsBoolean, IsNotEmpty, IsNumber, IsString } from "class-validator"; + +export class CreateGameDto { + @IsString() + @IsNotEmpty() + gameServerIdOfTheMatch : string + @IsNumber() + @IsNotEmpty() + gameOptions: number + @IsString() + @IsNotEmpty() + playerOneUsername : string + @IsString() + playerTwoUsername : string + @IsNumber() + playerTwoUsernameResult : number + @IsNumber() + playerOneUsernameResult : number +} diff --git a/srcs/requirements/nestjs/api_back/src/game/dto/grantTicket.dto.ts b/srcs/requirements/nestjs/api_back/src/game/dto/grantTicket.dto.ts new file mode 100644 index 00000000..c010fc11 --- /dev/null +++ b/srcs/requirements/nestjs/api_back/src/game/dto/grantTicket.dto.ts @@ -0,0 +1,14 @@ +import { IsBoolean, IsEmpty, IsInt, IsNotEmpty, IsNumber, IsString } from "class-validator"; +import { IsNull } from "typeorm"; + +export class GrantTicketDto { + @IsString() + @IsNotEmpty() + playerOneUsername : string + @IsString() + playerTwoUsername : string + @IsNumber() + gameOptions : number + @IsBoolean() + isGameIsWithInvitation : boolean +} diff --git a/srcs/requirements/nestjs/api_back/src/game/dto/updateGame.dto.ts b/srcs/requirements/nestjs/api_back/src/game/dto/updateGame.dto.ts new file mode 100644 index 00000000..29f55473 --- /dev/null +++ b/srcs/requirements/nestjs/api_back/src/game/dto/updateGame.dto.ts @@ -0,0 +1,5 @@ +import { OmitType } from "@nestjs/mapped-types"; +import { IsBoolean, IsNotEmpty, IsNumber, IsString } from "class-validator"; +import { CreateGameDto } from "./createGame.dto"; + +export class UpdateGameDto extends OmitType(CreateGameDto, ['playerOneUsername', 'playerTwoUsername', 'gameOptions'] as const){} diff --git a/srcs/requirements/nestjs/api_back/src/game/dto/validateTicket.dto.ts b/srcs/requirements/nestjs/api_back/src/game/dto/validateTicket.dto.ts new file mode 100644 index 00000000..8c594dda --- /dev/null +++ b/srcs/requirements/nestjs/api_back/src/game/dto/validateTicket.dto.ts @@ -0,0 +1,16 @@ +import { IsBase64, IsBoolean, IsEmpty, IsNotEmpty, IsNumber, IsString } from "class-validator"; + +export class ValidateTicketDto { + @IsString() + @IsNotEmpty() + playerOneUsername : string + @IsString() + playerTwoUsername : string + @IsNumber() + gameOptions : number + @IsBoolean() + isGameIsWithInvitation : boolean + @IsBase64() + @IsNotEmpty() + token : string +} diff --git a/srcs/requirements/nestjs/api_back/src/game/entity/game.entity.ts b/srcs/requirements/nestjs/api_back/src/game/entity/game.entity.ts new file mode 100644 index 00000000..1af581b0 --- /dev/null +++ b/srcs/requirements/nestjs/api_back/src/game/entity/game.entity.ts @@ -0,0 +1,25 @@ +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; + +@Entity('game') +export class Game { + @PrimaryGeneratedColumn() + id: number; + + @Column() + playerOneUsername: string + + @Column() + playerTwoUsername: string + + @Column({default : 0, nullable : true}) + playerOneUsernameResult : number + + @Column({default : 0, nullable : true}) + playerTwoUsernameResult : number + + @Column({unique : true}) + gameServerIdOfTheMatch: string + + @Column({default: false, nullable : true}) //éric pourra trouver un meilleur mot : ongoing ? + isMatchIsFinished: boolean +} diff --git a/srcs/requirements/nestjs/api_back/src/game/entity/tokenGame.entity.ts b/srcs/requirements/nestjs/api_back/src/game/entity/tokenGame.entity.ts new file mode 100644 index 00000000..9481b32e --- /dev/null +++ b/srcs/requirements/nestjs/api_back/src/game/entity/tokenGame.entity.ts @@ -0,0 +1,22 @@ +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; + +@Entity('tokenGame') +export class TokenGame { + + @PrimaryGeneratedColumn() + id: number; + @Column() + playerOneUsername : string + @Column({nullable: true}) + playerTwoUsername : string + @Column() + gameOptions : number + @Column() + isGameIsWithInvitation : boolean + @Column({default: 0, nullable: true}) + numberOfRegisteredUser : number + @Column({default : false}) + isSecondUserAcceptedRequest : boolean + @Column() + token : string +} diff --git a/srcs/requirements/nestjs/api_back/src/game/entity/user.entity.ts b/srcs/requirements/nestjs/api_back/src/game/entity/user.entity.ts deleted file mode 100644 index 6c45d3a5..00000000 --- a/srcs/requirements/nestjs/api_back/src/game/entity/user.entity.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; - - - -@Entity('gameParty') -export class gameParty { - - @PrimaryGeneratedColumn() - id: number; - - @Column() - playerOne: string - - @Column() - playerTwo: string - - @Column() - resultOfTheMatch: string - - @Column() - gameServerIdOfTheMatch: string -} diff --git a/srcs/requirements/nestjs/api_back/src/game/game.controller.ts b/srcs/requirements/nestjs/api_back/src/game/game.controller.ts index d86df072..09d1a650 100644 --- a/srcs/requirements/nestjs/api_back/src/game/game.controller.ts +++ b/srcs/requirements/nestjs/api_back/src/game/game.controller.ts @@ -1,4 +1,116 @@ -import { Controller } from '@nestjs/common'; +import { Body, Controller, Get, HttpException, HttpStatus, Post, Req, UseGuards } from '@nestjs/common'; +import { Console } from 'console'; +import { request } from 'http'; +import { use } from 'passport'; +import { AuthenticateGuard, TwoFactorGuard } from 'src/auth/42/guards/42guards'; +import { User } from 'src/users/entities/user.entity'; +import { UsersService } from 'src/users/users.service'; +import { CreateGameDto } from './dto/createGame.dto'; +import { GrantTicketDto } from './dto/grantTicket.dto'; +import { UpdateGameDto } from './dto/updateGame.dto'; +import { ValidateTicketDto } from './dto/validateTicket.dto'; +import { TokenGame } from './entity/tokenGame.entity'; +import { GameService } from './game.service'; @Controller('game') -export class GameController {} +export class GameController { + constructor (private readonly gameService : GameService) { } + + + @Get('ranking') + @UseGuards(AuthenticateGuard) + @UseGuards(TwoFactorGuard) + async getRankingForAllUsers(@Req() req) + { + const currentUser : User = req.user + return this.gameService.getRankingForAllUsers(currentUser); + } + + @Post('ticket') + @UseGuards(AuthenticateGuard) + @UseGuards(TwoFactorGuard) + async grantTicket(@Req() req, @Body() grantTicketDto : GrantTicketDto) + { + const user : User = req.user + if (grantTicketDto.playerOneUsername != user.username) + return new HttpException('You can\'t request a game for another person.', 403 ) + // else if (user.status !== "connected") + // return new HttpException('You must not be in game...', HttpStatus.FORBIDDEN ) + return this.gameService.generateToken(user, grantTicketDto); + } + + @Post('requested') + @UseGuards(AuthenticateGuard) + @UseGuards(TwoFactorGuard) + async requestIfAnotherUserHasRespondToquestForGame(@Req() req, @Body('token') token) + { + const user : User = req.user; + return this.gameService.requestIfAnotherUserHasRespondToquestForGame(user, token); + } + + @Post('decline') + @UseGuards(AuthenticateGuard) + @UseGuards(TwoFactorGuard) + async declineInvitation(@Body('token') token, @Req() req) + { + const user : User = req.user; + return this.gameService.declineInvitation(user, token); + } + + @Post('accept') + @UseGuards(AuthenticateGuard) + @UseGuards(TwoFactorGuard) + async acceptInvitation(@Body('token') token, @Req() req) + { + const user : User = req.user; + return this.gameService.acceptInvitation(user, token); + } + + + @Get('invitations') + @UseGuards(AuthenticateGuard) + @UseGuards(TwoFactorGuard) + async findInvitations(@Req() request) + { + const user : User = request.user; + return this.gameService.findInvitations(user); + } + + // + //N'est valable que pour le game-serveur. + @Post('gameserver/validate') + async validateTicket(@Body() validateTicketDto : ValidateTicketDto, @Req() request) + { + if (await this.gameService.validateToken(validateTicketDto) === false) + return new HttpException("The token is not valid", HttpStatus.NOT_FOUND); + console.log("200 retourné côté nest") + return HttpStatus.OK; + } + + @Post('gameserver/creategame') + async createGame(@Body() creategameDto : CreateGameDto) + { + console.log("On est dans create game") + console.log(creategameDto) + return this.gameService.createGame(creategameDto); + } + + + + + @Post('gameserver/updategame') + async updateGame(@Body() updateGameDto : UpdateGameDto) + { + console.log("On est dans update game") + console.log(updateGameDto) + return this.gameService.updateGame(updateGameDto); + } + + @Post('gameserver/destroysession') + async destroySession(@Body('token') token) + { + return this.gameService.destroySession(token); + } + + +} diff --git a/srcs/requirements/nestjs/api_back/src/game/game.module.ts b/srcs/requirements/nestjs/api_back/src/game/game.module.ts index 17a50c06..e834599f 100644 --- a/srcs/requirements/nestjs/api_back/src/game/game.module.ts +++ b/srcs/requirements/nestjs/api_back/src/game/game.module.ts @@ -1,9 +1,17 @@ import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { Friendship } from 'src/friendship/entities/friendship.entity'; +import { FriendshipService } from 'src/friendship/friendship.service'; +import { User } from 'src/users/entities/user.entity'; +import { UsersService } from 'src/users/users.service'; +import { Game } from './entity/game.entity'; +import { TokenGame } from './entity/tokenGame.entity'; import { GameController } from './game.controller'; import { GameService } from './game.service'; @Module({ - controllers: [GameController], - providers: [GameService] + imports: [TypeOrmModule.forFeature([TokenGame, User, Game, Friendship])], + controllers: [GameController], + providers: [GameService, UsersService, FriendshipService] }) export class GameModule {} diff --git a/srcs/requirements/nestjs/api_back/src/game/game.service.spec.ts b/srcs/requirements/nestjs/api_back/src/game/game.service.spec.ts index f4a1db7e..d91fa17d 100644 --- a/srcs/requirements/nestjs/api_back/src/game/game.service.spec.ts +++ b/srcs/requirements/nestjs/api_back/src/game/game.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { GameService } from './game.service'; +// import { Test, TestingModule } from '@nestjs/testing'; +// // import { GameService } from './game.service'; -describe('GameService', () => { - let service: GameService; +// describe('GameService', () => { +// let service: GameService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [GameService], - }).compile(); +// beforeEach(async () => { +// const module: TestingModule = await Test.createTestingModule({ +// providers: [GameService], +// }).compile(); - service = module.get(GameService); - }); +// service = module.get(GameService); +// }); - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); +// it('should be defined', () => { +// expect(service).toBeDefined(); +// }); +// }); diff --git a/srcs/requirements/nestjs/api_back/src/game/game.service.ts b/srcs/requirements/nestjs/api_back/src/game/game.service.ts index 18ca270d..562ab843 100644 --- a/srcs/requirements/nestjs/api_back/src/game/game.service.ts +++ b/srcs/requirements/nestjs/api_back/src/game/game.service.ts @@ -1,4 +1,277 @@ -import { Injectable } from '@nestjs/common'; +import { ConsoleLogger, HttpException, HttpStatus, Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { createCipheriv, randomBytes, scrypt } from 'crypto'; +import { User } from 'src/users/entities/user.entity'; +import { Repository } from 'typeorm'; +import { promisify } from 'util'; +import { GrantTicketDto } from './dto/grantTicket.dto'; +import { Game } from './entity/game.entity'; +import { ValidateTicketDto } from './dto/validateTicket.dto'; +import { TokenGame } from './entity/tokenGame.entity'; +import { UsersService } from 'src/users/users.service'; +import { CreateGameDto } from './dto/createGame.dto'; +import { UpdateGameDto } from './dto/updateGame.dto'; +import { FriendshipService } from 'src/friendship/friendship.service'; @Injectable() -export class GameService {} +export class GameService { + constructor ( + @InjectRepository(Game) + private readonly gameRepository : Repository, + @InjectRepository(User) + private readonly userRepository : Repository, + @InjectRepository(TokenGame) + private readonly tokenGameRepository : Repository, + private readonly userService : UsersService, + private readonly friendShipService : FriendshipService + ) { } + + async getRankingForAllUsers(currentUser : User) { + const users = await this.userRepository.createQueryBuilder("user") + .leftJoinAndSelect("user.stats", "stats") + .orderBy('stats.winGame', "DESC") + .getMany(); + const partialUser : Partial[] = [] + for (const user of users) + { + if (await this.friendShipService.findIfUserIsBlockedOrHasBlocked(currentUser.id.toString(), user.id.toString()) === false) + partialUser.push({username : user.username, stats : user.stats }) + } + console.log(...partialUser) + return partialUser; + } + + + async encryptToken(toEncrypt : string) : Promise { + const iv = randomBytes(16); + const password = process.env.TICKET_FOR_PLAYING_GAME_SECRET + new Date(); + const key = (await promisify(scrypt)(password, 'salt', 32)) as Buffer; + const cipher = createCipheriv('aes-256-ctr', key, iv); + const encryptedText = Buffer.concat([ + cipher.update(toEncrypt), + cipher.final(), + ]); + const encryptedTextToReturn = encryptedText.toString('base64'); + return encryptedTextToReturn + } + + async generateToken(user : User, grantTicketDto : GrantTicketDto) + { + console.log(user.status); + if (user.status === "In Game" || user.status === "In Pool") + return new HttpException("You can't play two games", HttpStatus.FORBIDDEN); + if (grantTicketDto.isGameIsWithInvitation === true) + { + const secondUser : Partial = await this.userService.findOneByUsername(user.id.toString(), grantTicketDto.playerTwoUsername) + if (!secondUser || secondUser.username === user.username) + return new HttpException("The requested second player does not exist OR you want to play against yourself. :P", HttpStatus.NOT_FOUND); + const encryptedTextToReturn = await this.encryptToken(user.username + '_' + secondUser.username + '_' + + grantTicketDto.gameOptions + '_' + grantTicketDto.isGameIsWithInvitation + '_' + new Date()) + const tok = this.tokenGameRepository.create(grantTicketDto); + tok.isSecondUserAcceptedRequest = false; + tok.numberOfRegisteredUser = 0; + tok.token = encryptedTextToReturn; + this.tokenGameRepository.save(tok); + this.userService.updateStatus(user.id, "In Pool") + return { token : encryptedTextToReturn }; + } + else if (grantTicketDto.isGameIsWithInvitation === false) { + const encryptedTextToReturn = await this.encryptToken(user.username + '_' + + grantTicketDto.gameOptions + '_' + grantTicketDto.isGameIsWithInvitation + '_' + new Date()) + const tok = this.tokenGameRepository.create(grantTicketDto); + tok.numberOfRegisteredUser = 0; + tok.token = encryptedTextToReturn; + this.tokenGameRepository.save(tok); + this.userService.updateStatus(user.id, "In Pool") + return { token : encryptedTextToReturn }; + } + return new HttpException("Something went wrong !", HttpStatus.INTERNAL_SERVER_ERROR) + } + + async validateToken(validateTicketDto : ValidateTicketDto) { + if (validateTicketDto.isGameIsWithInvitation === true) + { + const tokenGame : TokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame') + .where('tokengame.playerOneUsername = :playerOneUsername', {playerOneUsername : validateTicketDto.playerOneUsername}) + .andWhere('tokengame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : validateTicketDto.playerTwoUsername}) + .andWhere('tokengame.gameOptions = :gameOption', {gameOption : validateTicketDto.gameOptions}) + .andWhere('tokengame.isGameIsWithInvitation = :isGameIsWithInvitation', {isGameIsWithInvitation: true}) + .andWhere('tokengame.isSecondUserAcceptedRequest = :choice', {choice : true}) + .andWhere('tokengame.token = :token', {token : validateTicketDto.token}) + .getOne(); + if (tokenGame) + { + tokenGame.numberOfRegisteredUser++; + if (tokenGame.numberOfRegisteredUser === 2) + { + this.tokenGameRepository.remove(tokenGame) + const userOne : User = await this.userRepository.createQueryBuilder('user') + .where("user.username = :username", {username : tokenGame.playerOneUsername}) + .getOne(); + this.userService.updateStatus(userOne.id, "In Game") + const userTwo : User = await this.userRepository.createQueryBuilder('user') + .where("user.username = :username", {username : tokenGame.playerTwoUsername}) + .getOne(); + this.userService.updateStatus(userTwo.id, "In Game") + } + return true; + } + } + else if (validateTicketDto.isGameIsWithInvitation === false) + { + const tokenGame : TokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame') + .where('tokengame.playerOneUsername = :playerOneUsername', {playerOneUsername : validateTicketDto.playerOneUsername}) + .andWhere('tokengame.gameOptions = :gameOption', {gameOption : validateTicketDto.gameOptions}) + .andWhere('tokengame.isGameIsWithInvitation = :isGameIsWithInvitation', {isGameIsWithInvitation: false}) + .andWhere('tokengame.token = :token', {token : validateTicketDto.token}) + .getOne(); + if (tokenGame) + { + this.tokenGameRepository.remove(tokenGame) + console.log("USERNAME : " + tokenGame.playerOneUsername) + const user : User = await this.userRepository.createQueryBuilder('user') + .where("user.username = :username", {username : tokenGame.playerOneUsername}) + .getOne(); + this.userService.updateStatus(user.id, "In Game") + return true; + } + } + return false; + } + + async findInvitations(user : User) { + const game = await this.tokenGameRepository.createQueryBuilder('tokengame') + .where('tokengame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username}) + .andWhere('tokengame.isGameIsWithInvitation = :invit', {invit : true}) + .andWhere('tokengame.isSecondUserAcceptedRequest = :choice', {choice : false}) + .getMany(); + if (!game) + return new HttpException( "No invitations !", HttpStatus.NOT_FOUND); + let partialGame : Partial[] = []; + for (const gameToken of game) { + partialGame.push({ + playerOneUsername : gameToken.playerOneUsername, + playerTwoUsername : gameToken.playerTwoUsername, + gameOptions : gameToken.gameOptions, + token : gameToken.token, + }); + } + return partialGame; + } + + async declineInvitation(user : User, token : string) + { + if (user.status !== "Connected") + return new HttpException("You must finish your game before decline.", HttpStatus.FORBIDDEN) + console.log("On décline l'invitation") + const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame') + .andWhere('tokengame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username}) + .andWhere('tokengame.token = :token', {token : token}) + .getOne(); + if (tokenGame) + return this.tokenGameRepository.remove(tokenGame); + return new HttpException("Invitation not found !", HttpStatus.NOT_FOUND) + } + + async destroySession(token : string) + { + console.log("On détruit le token et la session qui va avec") + const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame') + .where('tokengame.token = :token', {token : token}) + .getOne(); + if (tokenGame) + { + const playerOne = await this.userRepository.findOneBy({username : tokenGame.playerOneUsername}) + const playerTwo = await this.userRepository.findOneBy({username : tokenGame.playerTwoUsername}) + if (playerOne.status !== "Disconnected") + this.userService.updateStatus(playerOne.id, "Connected") + if (playerTwo.status !== "Disconnected") + this.userService.updateStatus(playerTwo.id, "Connected") + return this.tokenGameRepository.remove(tokenGame); + } + return new HttpException("Token not found !", HttpStatus.NOT_FOUND) + } + + async acceptInvitation(user : User, token : string) + { + if (user.status !== "Connected") + return new HttpException("You must finish your game before accept.", HttpStatus.FORBIDDEN) + const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame') + .andWhere('tokenGame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username}) + .andWhere('tokenGame.token = :token', {token : token}) + .getOne(); + if (tokenGame) + { + tokenGame.isSecondUserAcceptedRequest = true; + this.tokenGameRepository.save(tokenGame) + return HttpStatus.OK + } + return new HttpException("Invitation not found !", HttpStatus.NOT_FOUND) + } + + async requestIfAnotherUserHasRespondToquestForGame(user : User, token : string) { + if (user.status !== "Connected") + return new HttpException("You can't do that.", HttpStatus.BAD_REQUEST) + const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame') + .where('tokenGame.token = :token', {token : token}) + .andWhere('tokenGame.isSecondUserAcceptedRequest = :isSecondUserAcceptedRequest', {isSecondUserAcceptedRequest : true}) + .getOne(); + if (tokenGame && tokenGame.isSecondUserAcceptedRequest === true) + return {isSecondUserAcceptedRequest : true} + else if (tokenGame && tokenGame.isSecondUserAcceptedRequest === false) + return {isSecondUserAcceptedRequest : false} + else if (!tokenGame) + return new HttpException("Not Found", HttpStatus.NOT_FOUND) + } + + + async createGame(creategameDto : CreateGameDto) + { + if (creategameDto.playerOneUsername === "" || creategameDto.playerTwoUsername === "" + || creategameDto.playerOneUsername === creategameDto.playerTwoUsername) + return HttpStatus.INTERNAL_SERVER_ERROR + const game = this.gameRepository.create(creategameDto) + game.isMatchIsFinished = false; + this.gameRepository.save(game); + if (!game) + return HttpStatus.INTERNAL_SERVER_ERROR + console.log("200 retourné pour la création de partie") + return HttpStatus.OK + } + + async updateGame(updateGameDto : UpdateGameDto) { + console.log("Updata game" + updateGameDto) + const game = await this.gameRepository.createQueryBuilder('game') + .where("game.gameServerIdOfTheMatch = :gameServerIdOfTheMatch", {gameServerIdOfTheMatch : updateGameDto.gameServerIdOfTheMatch}) + .getOne(); + if (!game) + throw new HttpException(`The game could not be updated.`,HttpStatus.NOT_FOUND); + game.isMatchIsFinished = true; + game.playerOneUsernameResult = updateGameDto.playerOneUsernameResult + game.playerTwoUsernameResult = updateGameDto.playerTwoUsernameResult + this.userRepository.save(game); + const playerOne = await this.userRepository.findOneBy({username : game.playerOneUsername}) + const playerTwo = await this.userRepository.findOneBy({username : game.playerTwoUsername}) + if (!playerOne || !playerTwo) + return new HttpException("Internal Server Error. Impossible to update the database", HttpStatus.INTERNAL_SERVER_ERROR); + if (game.playerOneUsernameResult === game.playerTwoUsernameResult) + { + this.userService.incrementDraws(playerOne.id) + this.userService.incrementDraws(playerTwo.id) + } + else if (game.playerOneUsernameResult < game.playerTwoUsernameResult) + { + this.userService.incrementDefeats(playerOne.id) + this.userService.incrementVictories(playerTwo.id) + } + else + { + this.userService.incrementVictories(playerOne.id) + this.userService.incrementDefeats(playerTwo.id) + } + this.userService.updateStatus(playerOne.id, "Connected") + this.userService.updateStatus(playerTwo.id, "Connected") + return HttpStatus.OK + } +} + diff --git a/srcs/requirements/nestjs/api_back/src/users/dto/update-users.dto.ts b/srcs/requirements/nestjs/api_back/src/users/dto/update-users.dto.ts index 53e00fb3..eaad2c5b 100644 --- a/srcs/requirements/nestjs/api_back/src/users/dto/update-users.dto.ts +++ b/srcs/requirements/nestjs/api_back/src/users/dto/update-users.dto.ts @@ -2,7 +2,7 @@ // et de les mettre comme optionnelles. De plus on peut hériter // des décorateurs de la classe parente (par exemple @IsString()). -import { OmitType, PartialType } from "@nestjs/mapped-types"; +import { OmitType } from "@nestjs/mapped-types"; import { CreateUsersDto } from "./create-users.dto"; export class UpdateUsersDto extends OmitType(CreateUsersDto, ['fortyTwoId', 'email', 'image_url', 'status'] as const){} diff --git a/srcs/requirements/nestjs/api_back/src/users/entities/user.entity.ts b/srcs/requirements/nestjs/api_back/src/users/entities/user.entity.ts index c00427b3..b7ed9f65 100644 --- a/srcs/requirements/nestjs/api_back/src/users/entities/user.entity.ts +++ b/srcs/requirements/nestjs/api_back/src/users/entities/user.entity.ts @@ -28,7 +28,7 @@ export class User { @Column({ nullable: true }) phone: string; - @Column({ default: 'disconnected' }) + @Column({ default: 'Disconnected' }) status: string; // @Column() diff --git a/srcs/requirements/nestjs/api_back/src/users/users.controller.ts b/srcs/requirements/nestjs/api_back/src/users/users.controller.ts index 181b9ac5..9b44bc88 100644 --- a/srcs/requirements/nestjs/api_back/src/users/users.controller.ts +++ b/srcs/requirements/nestjs/api_back/src/users/users.controller.ts @@ -49,11 +49,9 @@ export class UsersController { @Get() findOne(@Query('username') username: string, @Req() req) { if (username === undefined) { - console.log("Backend Getting current user"); return this.usersService.findOne(req.user.id); } else { const user : User = req.user; - console.log('we have a query: ' + username) return this.usersService.findOneByUsername(user.id.toString(),username); } } @@ -64,7 +62,6 @@ export class UsersController { @Get('search') findOneByUsername(@Query('username') username: string, @Req() req) { const user : User = req.user; - console.log('searching for user' + user.username); return this.usersService.findOneByUsername(user.id.toString(),username); } @@ -81,12 +78,9 @@ export class UsersController { @UseGuards(TwoFactorGuard) @Patch() async update(@Req() req, @Body(new ValidationPipe()) usersUpdateDto: UpdateUsersDto, @Res() response : Response) { - console.log("DANS PATCH USERS"); const user = await this.usersService.update(req.user.id, usersUpdateDto); - // const user : User = req.user; if (user.isEnabledTwoFactorAuth === false && user.isTwoFactorAuthenticated === true) this.usersService.setIsTwoFactorAuthenticatedWhenLogout(user.id); - console.log ("Enbale 2FA " + user.isEnabledTwoFactorAuth + " Is authenticated " + user.isTwoFactorAuthenticated); if (user.isEnabledTwoFactorAuth === true && user.isTwoFactorAuthenticated === false) { response.status(201).send('2FA redirect') diff --git a/srcs/requirements/nestjs/api_back/src/users/users.service.ts b/srcs/requirements/nestjs/api_back/src/users/users.service.ts index 929d93d9..be1c19b2 100644 --- a/srcs/requirements/nestjs/api_back/src/users/users.service.ts +++ b/srcs/requirements/nestjs/api_back/src/users/users.service.ts @@ -4,12 +4,9 @@ import { User } from './entities/user.entity'; import { Repository } from 'typeorm'; import { CreateUsersDto } from './dto/create-users.dto'; import { UpdateUsersDto } from './dto/update-users.dto'; -import { Friendship } from '../friendship/entities/friendship.entity'; import { PaginationQueryDto } from 'src/common/dto/pagination-query.dto'; import { UserStats } from './entities/userStat.entities'; import { FriendshipService } from 'src/friendship/friendship.service'; -import { stringify } from 'querystring'; - // On va devoir sûrement trouver un moyen plus simple pour passer l'id, sûrement via des pipes // ou des interceptors, mais pour l'instant on va faire comme ça. @Injectable() diff --git a/srcs/requirements/nginx/conf/default.conf b/srcs/requirements/nginx/conf/default.conf index bbaaa8c5..27e5cb23 100644 --- a/srcs/requirements/nginx/conf/default.conf +++ b/srcs/requirements/nginx/conf/default.conf @@ -10,6 +10,19 @@ server { proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://backend_dev:3000; } + + location /api/v2/game/gameserver { + deny all; + } + + location /pong { + proxy_pass http://game_server:8042/pong; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + } + location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; diff --git a/srcs/requirements/nginx/conf/nginx.conf b/srcs/requirements/nginx/conf/nginx.conf new file mode 100644 index 00000000..df5a4609 --- /dev/null +++ b/srcs/requirements/nginx/conf/nginx.conf @@ -0,0 +1,37 @@ + +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + map $http_upgrade $connection_upgrade { + default upgrade; + '' close; + } + + #gzip on; + + include /etc/nginx/conf.d/*.conf; +} diff --git a/srcs/requirements/svelte/api_front/public/favicon.ico b/srcs/requirements/svelte/api_front/public/favicon.ico new file mode 100644 index 00000000..b7e7e5ca Binary files /dev/null and b/srcs/requirements/svelte/api_front/public/favicon.ico differ diff --git a/srcs/requirements/svelte/api_front/public/favicon.png b/srcs/requirements/svelte/api_front/public/favicon.png deleted file mode 100644 index 7e6f5eb5..00000000 Binary files a/srcs/requirements/svelte/api_front/public/favicon.png and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/game/class/Event.ts b/srcs/requirements/svelte/api_front/public/game/class/Event.ts deleted file mode 100644 index 3f0d440a..00000000 --- a/srcs/requirements/svelte/api_front/public/game/class/Event.ts +++ /dev/null @@ -1,107 +0,0 @@ - -import * as en from "../enums.js" - -/* From Server */ -class ServerEvent { - type: en.EventTypes; - constructor(type: en.EventTypes = 0) { - this.type = type; - } -} - -class EventAssignId extends ServerEvent { - id: string; - constructor(id: string) { - super(en.EventTypes.assignId); - this.id = id; - } -} - -class EventMatchmakingComplete extends ServerEvent { - side: en.PlayerSide; - constructor(side: en.PlayerSide) { - super(en.EventTypes.matchmakingComplete); - this.side = side; - } -} - -class EventGameUpdate extends ServerEvent { - playerLeft = { - y: 0 - }; - playerRight = { - y: 0 - }; - ballsArr: { - x: number, - y: number, - dirX: number, - dirY: number, - speed: number - }[] = []; - wallTop? = { - y: 0 - }; - wallBottom? = { - y: 0 - }; - lastInputId = 0; - constructor() { // TODO: constructor that take GameComponentsServer maybe ? - super(en.EventTypes.gameUpdate); - } -} - -class EventScoreUpdate extends ServerEvent { - scoreLeft: number; - scoreRight: number; - constructor(scoreLeft: number, scoreRight: number) { - super(en.EventTypes.scoreUpdate); - this.scoreLeft = scoreLeft; - this.scoreRight = scoreRight; - } -} - -class EventMatchEnd extends ServerEvent { - winner: en.PlayerSide; - constructor(winner: en.PlayerSide) { - super(en.EventTypes.matchEnd); - this.winner = winner; - } -} - - -/* From Client */ -class ClientEvent { - type: en.EventTypes; // readonly ? - constructor(type: en.EventTypes = 0) { - this.type = type; - } -} - -class ClientAnnounce extends ClientEvent { - role: en.ClientRole; - clientId: string; - matchOptions: en.MatchOptions; - constructor(role: en.ClientRole, matchOptions: en.MatchOptions, clientId: string = "") { - super(en.EventTypes.clientAnnounce); - this.role = role; - this.clientId = clientId; - this.matchOptions = matchOptions; - } -} - -class EventInput extends ClientEvent { - input: en.InputEnum; - id: number; - constructor(input: en.InputEnum = en.InputEnum.noInput, id: number = 0) { - super(en.EventTypes.clientInput); - this.input = input; - this.id = id; - } -} - -export { - ServerEvent, EventAssignId, EventMatchmakingComplete, - EventGameUpdate, EventScoreUpdate, EventMatchEnd, - ClientEvent, ClientAnnounce, EventInput -} diff --git a/srcs/requirements/svelte/api_front/public/game/gameLoop.ts b/srcs/requirements/svelte/api_front/public/game/gameLoop.ts deleted file mode 100644 index 593d1eaa..00000000 --- a/srcs/requirements/svelte/api_front/public/game/gameLoop.ts +++ /dev/null @@ -1,49 +0,0 @@ - -import * as c from "./constants.js"; -import * as en from "../shared_js/enums.js" -import { gc, matchOptions, clientInfo } from "./global.js"; -import { wallsMovements } from "../shared_js/wallsMovement.js"; - -let actual_time: number = Date.now(); -let last_time: number; -let delta_time: number; - -function gameLoop() -{ - /* last_time = actual_time; - actual_time = Date.now(); - delta_time = (actual_time - last_time) / 1000; */ - - delta_time = c.fixedDeltaTime; - // console.log(`delta_gameLoop: ${delta_time}`); - - // interpolation - // console.log(`dir.y: ${clientInfo.opponent.dir.y}, pos.y: ${clientInfo.opponent.pos.y}, opponentNextPos.y: ${clientInfo.opponentNextPos.y}`); - if (clientInfo.opponent.dir.y != 0 ) { - opponentInterpolation(delta_time); - } - - // client prediction - gc.ballsArr.forEach((ball) => { - ball.moveAndBounce(delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]); - }); - - if (matchOptions & en.MatchOptions.movingWalls) { - wallsMovements(delta_time, gc); - } -} - -function opponentInterpolation(delta: number) -{ - // interpolation - clientInfo.opponent.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]); - - if ((clientInfo.opponent.dir.y > 0 && clientInfo.opponent.pos.y > clientInfo.opponentNextPos.y) - || (clientInfo.opponent.dir.y < 0 && clientInfo.opponent.pos.y < clientInfo.opponentNextPos.y)) - { - clientInfo.opponent.dir.y = 0; - clientInfo.opponent.pos.y = clientInfo.opponentNextPos.y; - } -} - -export {gameLoop} diff --git a/srcs/requirements/svelte/api_front/public/game/global.ts b/srcs/requirements/svelte/api_front/public/game/global.ts deleted file mode 100644 index 7d0a7126..00000000 --- a/srcs/requirements/svelte/api_front/public/game/global.ts +++ /dev/null @@ -1,3 +0,0 @@ - -export {pong, gc, matchOptions} from "./pong.js" -export {socket, clientInfo} from "./ws.js" diff --git a/srcs/requirements/svelte/api_front/public/game/pong.ts b/srcs/requirements/svelte/api_front/public/game/pong.ts deleted file mode 100644 index 5c9dcce0..00000000 --- a/srcs/requirements/svelte/api_front/public/game/pong.ts +++ /dev/null @@ -1,99 +0,0 @@ - -initDom(); -function initDom() { - document.getElementById("play_pong_button").addEventListener("click", init); -} - -import * as c from "./constants.js" -import * as en from "../shared_js/enums.js" -import { GameArea } from "./class/GameArea.js"; -import { GameComponentsClient } from "./class/GameComponentsClient.js"; -import { handleInput } from "./handleInput.js"; -// import { sendLoop } from "./handleInput.js"; -import { gameLoop } from "./gameLoop.js" -import { drawLoop } from "./draw.js"; -import { countdown } from "./utils.js"; -import { initWebSocket } from "./ws.js"; -import { initAudio } from "./audio.js"; - - -/* Keys - Racket: W/S OR Up/Down - Grid On-Off: G -*/ - -/* TODO: A way to delay the init of variables, but still use "const" not "let" ? */ -export let pong: GameArea; -export let gc: GameComponentsClient; -export let matchOptions: en.MatchOptions = en.MatchOptions.noOption; - -function init() -{ - console.log("multi_balls:"+(document.getElementById("multi_balls")).checked); - console.log("moving_walls:"+(document.getElementById("moving_walls")).checked); - console.log("sound_on:"+(document.getElementById("sound_on")).checked); - - let soundMutedFlag = false; - if ( (document.getElementById("sound_off")).checked ) { - soundMutedFlag = true; - } - initAudio(soundMutedFlag); - - if ( (document.getElementById("multi_balls")).checked ) { - matchOptions |= en.MatchOptions.multiBalls; - } - if ( (document.getElementById("moving_walls")).checked ) { - matchOptions |= en.MatchOptions.movingWalls; - } - - document.getElementById("div_game_options").hidden = true; - - pong = new GameArea(); - gc = new GameComponentsClient(matchOptions, pong.ctx); - initWebSocket(matchOptions); -} - -function matchmaking() -{ - console.log("Searching an opponent..."); - gc.text1.clear(); - gc.text1.pos.assign(c.w/5, c.h_mid); - gc.text1.text = "Searching..."; - gc.text1.update(); -} - -function matchmakingComplete() -{ - console.log("Match Found !"); - gc.text1.clear(); - gc.text1.pos.assign(c.w/8, c.h_mid); - gc.text1.text = "Match Found !"; - gc.text1.update(); -} - -function startGame() { - gc.text1.pos.assign(c.w_mid, c.h_mid+c.h/4); - countdown(c.matchStartDelay/1000, (count: number) => { - gc.text1.clear(); - gc.text1.text = `${count}`; - gc.text1.update(); - }, resumeGame); -} - -function resumeGame() -{ - gc.text1.text = ""; - window.addEventListener('keydown', function (e) { - pong.addKey(e.key); - }); - window.addEventListener('keyup', function (e) { - pong.deleteKey(e.key); - }); - pong.handleInputInterval = window.setInterval(handleInput, c.handleInputIntervalMS); - // pong.handleInputInterval = window.setInterval(sendLoop, c.sendLoopIntervalMS); - pong.gameLoopInterval = window.setInterval(gameLoop, c.gameLoopIntervalMS); - pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS); -} - - -export {matchmaking, matchmakingComplete, startGame} diff --git a/srcs/requirements/svelte/api_front/public/game/utils copy.ts b/srcs/requirements/svelte/api_front/public/game/utils copy.ts deleted file mode 100644 index e8f7bca3..00000000 --- a/srcs/requirements/svelte/api_front/public/game/utils copy.ts +++ /dev/null @@ -1,27 +0,0 @@ - -import { MovingRectangle } from "./class/Rectangle.js"; - -function random(min: number = 0, max: number = 1) { - return Math.random() * (max - min) + min; -} - -function sleep (ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - -function clamp(n: number, min: number, max: number) : number -{ - if (n < min) - n = min; - else if (n > max) - n = max; - return (n); -} - -// Typescript hack, unused -function assertMovingRectangle(value: unknown): asserts value is MovingRectangle { - // if (value !== MovingRectangle) throw new Error("Not a MovingRectangle"); - return; -} - -export {random, sleep, clamp, assertMovingRectangle} diff --git a/srcs/requirements/svelte/api_front/public/index.html b/srcs/requirements/svelte/api_front/public/index.html index 5da7ed3e..786ea3ad 100644 --- a/srcs/requirements/svelte/api_front/public/index.html +++ b/srcs/requirements/svelte/api_front/public/index.html @@ -4,9 +4,9 @@ - Svelte app + Potato Pong - + diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/0.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/0.ogg deleted file mode 100644 index 93d05409..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/0.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/1.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/1.ogg deleted file mode 100644 index 3a268b34..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/1.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/10.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/10.ogg deleted file mode 100644 index 855ad78b..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/10.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/11.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/11.ogg deleted file mode 100644 index 655917b5..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/11.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/12.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/12.ogg deleted file mode 100644 index 11336a76..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/12.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/13.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/13.ogg deleted file mode 100644 index 71cfead6..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/13.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/14.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/14.ogg deleted file mode 100644 index 066fff69..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/14.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/15.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/15.ogg deleted file mode 100644 index 011f139c..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/15.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/16.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/16.ogg deleted file mode 100644 index 7e852275..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/16.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/17.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/17.ogg deleted file mode 100644 index 9860139d..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/17.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/18.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/18.ogg deleted file mode 100644 index 6ad25391..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/18.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/19.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/19.ogg deleted file mode 100644 index f6fc42d6..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/19.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/2.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/2.ogg deleted file mode 100644 index 0f09bb30..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/2.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/20.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/20.ogg deleted file mode 100644 index 11ac780e..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/20.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/21.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/21.ogg deleted file mode 100644 index 7c724dd4..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/21.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/22.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/22.ogg deleted file mode 100644 index b2ca9758..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/22.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/23.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/23.ogg deleted file mode 100644 index f57724b9..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/23.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/24.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/24.ogg deleted file mode 100644 index 90093efc..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/24.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/25.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/25.ogg deleted file mode 100644 index 27dfe8eb..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/25.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/26.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/26.ogg deleted file mode 100644 index 80cb60fa..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/26.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/27.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/27.ogg deleted file mode 100644 index 13332de6..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/27.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/28.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/28.ogg deleted file mode 100644 index 29615795..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/28.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/29.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/29.ogg deleted file mode 100644 index 41f95343..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/29.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/3.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/3.ogg deleted file mode 100644 index 12448222..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/3.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/30.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/30.ogg deleted file mode 100644 index bd4e4ffd..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/30.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/31.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/31.ogg deleted file mode 100644 index 4447b52a..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/31.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/32.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/32.ogg deleted file mode 100644 index a58240a1..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/32.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/4.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/4.ogg deleted file mode 100644 index 688b1f81..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/4.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/5.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/5.ogg deleted file mode 100644 index d2163268..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/5.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/6.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/6.ogg deleted file mode 100644 index 34bdd117..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/6.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/7.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/7.ogg deleted file mode 100644 index 9c9c994f..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/7.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/8.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/8.ogg deleted file mode 100644 index 0f9acf99..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/8.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/9.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/pong/9.ogg deleted file mode 100644 index 15d82091..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/pong/9.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/public/sounds/sound/roblox-oof.ogg b/srcs/requirements/svelte/api_front/public/sounds/sound/roblox-oof.ogg deleted file mode 100644 index 689946ed..00000000 Binary files a/srcs/requirements/svelte/api_front/public/sounds/sound/roblox-oof.ogg and /dev/null differ diff --git a/srcs/requirements/svelte/api_front/src/App.svelte b/srcs/requirements/svelte/api_front/src/App.svelte index 7a383eb1..5f293b5e 100644 --- a/srcs/requirements/svelte/api_front/src/App.svelte +++ b/srcs/requirements/svelte/api_front/src/App.svelte @@ -2,7 +2,7 @@ // routing // may not need {link} here import Router, { link, replace } from "svelte-spa-router"; - import { primaryRoutes } from "./routes/primaryRoutes.js"; + import { primaryRoutes } from "./routes/primaryRoutes.js"; // import primaryRoutes from "./routes/primaryRoutes.svelte"; const conditionsFailed = (event) => { diff --git a/srcs/requirements/svelte/api_front/src/main.js b/srcs/requirements/svelte/api_front/src/main.js new file mode 100644 index 00000000..34f779eb --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; +const app = new App({ + target: document.body, + props: { + // name: 'world' + } +}); +export default app; +//# sourceMappingURL=main.js.map \ No newline at end of file diff --git a/srcs/requirements/svelte/api_front/src/main.js.map b/srcs/requirements/svelte/api_front/src/main.js.map new file mode 100644 index 00000000..3bd45e8b --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/main.js.map @@ -0,0 +1 @@ +{"version":3,"file":"main.js","sourceRoot":"","sources":["main.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,cAAc,CAAC;AAE/B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC;IACnB,MAAM,EAAE,QAAQ,CAAC,IAAI;IACrB,KAAK,EAAE;IACN,gBAAgB;KAChB;CACD,CAAC,CAAC;AAEH,eAAe,GAAG,CAAC"} \ No newline at end of file diff --git a/srcs/requirements/svelte/api_front/src/pages/GamePage.svelte b/srcs/requirements/svelte/api_front/src/pages/GamePage.svelte deleted file mode 100644 index 5e08c6f4..00000000 --- a/srcs/requirements/svelte/api_front/src/pages/GamePage.svelte +++ /dev/null @@ -1,106 +0,0 @@ - - - -
-
- game options -
- - -
-
- - -
-
- - - - - -
-
- -
-
-
- -
-

--- keys ---

-

move up: 'w' or 'up arrow'

-

move down: 's' OR 'down arrow'

-

grid on/off: 'g'

-
- -
- -
- - - - - \ No newline at end of file diff --git a/srcs/requirements/svelte/api_front/src/pages/SpectatorMatchList.svelte b/srcs/requirements/svelte/api_front/src/pages/SpectatorMatchList.svelte new file mode 100644 index 00000000..9807f136 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/SpectatorMatchList.svelte @@ -0,0 +1,35 @@ + + + +
+ + {#each arr as match} + + {/each} + + + + + diff --git a/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte b/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte index 4a4741b1..b3ffc753 100644 --- a/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte +++ b/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte @@ -1,88 +1,313 @@ - +
+ +
- - - + - -
.
- -
+ {#if showError === true} +
- game options -
- - -
-
- - -
-
- - - - - -
-
- -
+ Error +

{errorMessageWhenAttemptingToGetATicket}

+
-
+
+ {/if} -
- -
+ {#if showWaitPage === true} +
+
+ Connecting to the game... +

{waitingMessage}

+
+
+ {/if} - - + + + {#if optionsAreNotSet} + {#if showGameOption === true} +
+
initGame()}> +
+ +
+ game options +
+ + +
+
+ + +
+
+

sound :

+ + + + +
+
+ + +
+ {#if options.isSomeoneIsInvited === true} + + {/if} +
+ +
+
+
+ +
+
+ {/if} + + {#if showInvitations} +
+
+ +
+ Current invitation(s) + {#if isThereAnyInvitation} + {#each invitations as invitation } +
+ {invitation.playerOneUsername} has invited you to play a pong ! + + +
+ {/each} + {/if} + {#if isThereAnyInvitation === false} +

Currently, no one asked to play with you.

+ + {/if} +
+
+
+ {/if} + {/if} + +
diff --git a/srcs/requirements/svelte/api_front/src/pages/game/Ranking.svelte b/srcs/requirements/svelte/api_front/src/pages/game/Ranking.svelte new file mode 100644 index 00000000..cb5ea123 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/Ranking.svelte @@ -0,0 +1,73 @@ + + +
+ +
+
+
+

Ranking

+
+
+
+
+ + + + + + + + + + + + + {#each allUsers as user, i} + + + {#if user.username === currentUser.username} + + {:else} + + {/if} + + + + + + {/each} + +
#UsernameWinLoseDrawGames Played
{i + 1}You ({user.username}){user.username}{user.stats.winGame}{user.stats.loseGame}{user.stats.drawGame}{user.stats.totalGame}
+
+
+
+ + + diff --git a/srcs/requirements/svelte/api_front/public/game/audio.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/audio.ts similarity index 50% rename from srcs/requirements/svelte/api_front/public/game/audio.ts rename to srcs/requirements/svelte/api_front/src/pages/game/client/audio.ts index 74c73336..07b846d2 100644 --- a/srcs/requirements/svelte/api_front/public/game/audio.ts +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/audio.ts @@ -2,12 +2,17 @@ import * as c from "./constants.js" export const soundPongArr: HTMLAudioElement[] = []; -export const soundRoblox = new Audio("http://localhost:8080/sound/roblox-oof.ogg"); +export const soundRoblox = new Audio("http://transcendance:8080/sound/roblox-oof.ogg"); -export function initAudio(muteFlag: boolean) +export function initAudio(sound: string) { + let muteFlag = true; + if (sound === "on") { + muteFlag = false; + } + for (let i = 0; i <= 32; i++) { - soundPongArr.push(new Audio("http://localhost:8080/sound/pong/"+i+".ogg")); + soundPongArr.push(new Audio("http://transcendance:8080/sound/pong/"+i+".ogg")); soundPongArr[i].volume = c.soundPongVolume; soundPongArr[i].muted = muteFlag; } diff --git a/srcs/requirements/svelte/api_front/public/game/class/GameArea.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/class/GameArea.ts similarity index 72% rename from srcs/requirements/svelte/api_front/public/game/class/GameArea.ts rename to srcs/requirements/svelte/api_front/src/pages/game/client/class/GameArea.ts index e6921e4e..9b90d4e5 100644 --- a/srcs/requirements/svelte/api_front/public/game/class/GameArea.ts +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/class/GameArea.ts @@ -1,21 +1,25 @@ import * as c from ".././constants.js" -class GameArea { +export class GameArea { keys: string[] = []; handleInputInterval: number = 0; gameLoopInterval: number = 0; drawLoopInterval: number = 0; canvas: HTMLCanvasElement; ctx: CanvasRenderingContext2D; - constructor() { - this.canvas = document.createElement("canvas"); + constructor(canvas_id: string) { + const canvas = document.getElementById("game_area"); + if (canvas && canvas instanceof HTMLCanvasElement) { + this.canvas = canvas; + } + else { + console.log("GameArea init error, invalid canvas_id"); + return; + } this.ctx = this.canvas.getContext("2d") as CanvasRenderingContext2D; this.canvas.width = c.CanvasWidth; this.canvas.height = c.CanvasWidth / c.CanvasRatio; - let container = document.getElementById("canvas_container"); - if (container) - container.insertBefore(this.canvas, container.childNodes[0]); } addKey(key: string) { key = key.toLowerCase(); @@ -34,5 +38,3 @@ class GameArea { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); } } - -export {GameArea} diff --git a/srcs/requirements/svelte/api_front/public/game/class/GameComponentsClient.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/class/GameComponentsClient.ts similarity index 92% rename from srcs/requirements/svelte/api_front/public/game/class/GameComponentsClient.ts rename to srcs/requirements/svelte/api_front/src/pages/game/client/class/GameComponentsClient.ts index bf90f66f..63797971 100644 --- a/srcs/requirements/svelte/api_front/public/game/class/GameComponentsClient.ts +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/class/GameComponentsClient.ts @@ -5,7 +5,7 @@ import { Vector, VectorInteger } from "../../shared_js/class/Vector.js"; import { TextElem, TextNumericValue } from "./Text.js"; import { RectangleClient, MovingRectangleClient, RacketClient, BallClient, Line } from "./RectangleClient.js"; import { GameComponents } from "../../shared_js/class/GameComponents.js"; -import { MovingRectangle } from "../../shared_js/class/Rectangle.js"; +import type { MovingRectangle } from "../../shared_js/class/Rectangle.js"; class GameComponentsExtensionForClient extends GameComponents { wallTop: RectangleClient | MovingRectangleClient; @@ -62,12 +62,13 @@ class GameComponentsExtensionForClient extends GameComponents { } } - -class GameComponentsClient extends GameComponentsExtensionForClient { +export class GameComponentsClient extends GameComponentsExtensionForClient { midLine: Line; scoreLeft: TextNumericValue; scoreRight: TextNumericValue; text1: TextElem; + text2: TextElem; + text3: TextElem; w_grid_mid: RectangleClient; w_grid_u1: RectangleClient; @@ -90,6 +91,8 @@ class GameComponentsClient extends GameComponentsExtensionForClient { // Text pos.assign(0, c.h_mid); this.text1 = new TextElem(pos, Math.floor(c.w/8), ctx, "white"); + this.text2 = new TextElem(pos, Math.floor(c.w/24), ctx, "white"); + this.text3 = new TextElem(pos, Math.floor(c.w/24), ctx, "white"); // Dotted Midline pos.assign(c.w_mid-c.midLineSize/2, 0+c.wallSize); @@ -110,5 +113,3 @@ class GameComponentsClient extends GameComponentsExtensionForClient { this.h_grid_d1 = new RectangleClient(pos, c.gridSize, c.h, ctx, "darkgreen"); } } - -export {GameComponentsClient} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/client/class/InitOptions.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/class/InitOptions.ts new file mode 100644 index 00000000..acefe9c8 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/class/InitOptions.ts @@ -0,0 +1,10 @@ + +export class InitOptions { + sound = "off"; + multi_balls = false; + moving_walls = false; + isSomeoneIsInvited = false; + isInvitedPerson = false; + playerOneUsername = ""; + playerTwoUsername = ""; +} diff --git a/srcs/requirements/svelte/api_front/public/game/class/InputHistory.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/class/InputHistory.ts similarity index 59% rename from srcs/requirements/svelte/api_front/public/game/class/InputHistory.ts rename to srcs/requirements/svelte/api_front/src/pages/game/client/class/InputHistory.ts index e4d3b8f1..f8a7fe4f 100644 --- a/srcs/requirements/svelte/api_front/public/game/class/InputHistory.ts +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/class/InputHistory.ts @@ -1,8 +1,8 @@ -import * as en from "../../shared_js/enums.js" -import * as ev from "../../shared_js/class/Event.js" +import type * as en from "../../shared_js/enums.js" +import type * as ev from "../../shared_js/class/Event.js" -class InputHistory { +export class InputHistory { input: en.InputEnum; id: number; deltaTime: number; @@ -12,5 +12,3 @@ class InputHistory { this.deltaTime = deltaTime; } } - -export {InputHistory} diff --git a/srcs/requirements/svelte/api_front/public/game/class/RectangleClient.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/class/RectangleClient.ts similarity index 75% rename from srcs/requirements/svelte/api_front/public/game/class/RectangleClient.ts rename to srcs/requirements/svelte/api_front/src/pages/game/client/class/RectangleClient.ts index 5c251704..e671fb3f 100644 --- a/srcs/requirements/svelte/api_front/public/game/class/RectangleClient.ts +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/class/RectangleClient.ts @@ -1,6 +1,6 @@ import { Vector, VectorInteger } from "../../shared_js/class/Vector.js"; -import { Component, GraphicComponent, Moving } from "../../shared_js/class/interface.js"; +import type { GraphicComponent } from "../../shared_js/class/interface.js"; import { Rectangle, MovingRectangle, Racket, Ball } from "../../shared_js/class/Rectangle.js"; import { soundPongArr } from "../audio.js" import { random } from "../utils.js"; @@ -17,7 +17,7 @@ function clearRectangle(this: RectangleClient, pos?: VectorInteger) { this.ctx.clearRect(this.pos.x, this.pos.y, this.width, this.height); } -class RectangleClient extends Rectangle implements GraphicComponent { +export class RectangleClient extends Rectangle implements GraphicComponent { ctx: CanvasRenderingContext2D; color: string; update: () => void; @@ -31,19 +31,9 @@ class RectangleClient extends Rectangle implements GraphicComponent { this.update = updateRectangle; this.clear = clearRectangle; } - // update() { - // this.ctx.fillStyle = this.color; - // this.ctx.fillRect(this.pos.x, this.pos.y, this.width, this.height); - // } - // clear(pos?: VectorInteger) { - // if (pos) - // this.ctx.clearRect(pos.x, pos.y, this.width, this.height); - // else - // this.ctx.clearRect(this.pos.x, this.pos.y, this.width, this.height); - // } } -class MovingRectangleClient extends MovingRectangle implements GraphicComponent { +export class MovingRectangleClient extends MovingRectangle implements GraphicComponent { ctx: CanvasRenderingContext2D; color: string; update: () => void; @@ -59,7 +49,7 @@ class MovingRectangleClient extends MovingRectangle implements GraphicComponent } } -class RacketClient extends Racket implements GraphicComponent { +export class RacketClient extends Racket implements GraphicComponent { ctx: CanvasRenderingContext2D; color: string; update: () => void; @@ -75,7 +65,7 @@ class RacketClient extends Racket implements GraphicComponent { } } -class BallClient extends Ball implements GraphicComponent { +export class BallClient extends Ball implements GraphicComponent { ctx: CanvasRenderingContext2D; color: string; update: () => void; @@ -91,12 +81,10 @@ class BallClient extends Ball implements GraphicComponent { } bounce(collider?: Rectangle) { this._bounceAlgo(collider); - soundPongArr[ Math.floor(random(0, soundPongArr.length)) ].play(); + let i = Math.floor(random(0, soundPongArr.length)); + soundPongArr[ i ].play(); + console.log(`sound_i=${i}`); // debug log } - /* protected _bounceRacket(collider: Racket) { - this._bounceRacketAlgo(collider); - soundRoblox.play(); - } */ } function updateLine(this: Line) { @@ -105,17 +93,20 @@ function updateLine(this: Line) { let i = 0; while (i < this.segmentCount) { - // for Horizontal Line + /* Horizontal Line */ // pos.y = this.pos.y; // pos.x = this.pos.x + this.segmentWidth * i; + + /* Vertical Line */ pos.x = this.pos.x; pos.y = this.pos.y + this.segmentHeight * i; + this.ctx.fillRect(pos.x, pos.y, this.segmentWidth, this.segmentHeight); i += 2; } } -class Line extends RectangleClient { +export class Line extends RectangleClient { gapeCount: number = 0; segmentCount: number; segmentWidth: number; @@ -129,13 +120,12 @@ class Line extends RectangleClient { this.gapeCount = gapeCount; this.segmentCount = this.gapeCount * 2 + 1; + /* Vertical Line */ this.segmentWidth = this.width; this.segmentHeight = this.height / this.segmentCount; - // for Horizontal Line + /* Horizontal Line */ // this.segmentWidth = this.width / this.segmentCount; // this.segmentHeight = this.height; } } - -export {RectangleClient, MovingRectangleClient, RacketClient, BallClient, Line} diff --git a/srcs/requirements/svelte/api_front/public/game/class/Text.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/class/Text.ts similarity index 89% rename from srcs/requirements/svelte/api_front/public/game/class/Text.ts rename to srcs/requirements/svelte/api_front/src/pages/game/client/class/Text.ts index 88111131..ccdfdc0c 100644 --- a/srcs/requirements/svelte/api_front/public/game/class/Text.ts +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/class/Text.ts @@ -1,9 +1,9 @@ import { Vector, VectorInteger } from "../../shared_js/class/Vector.js"; -import { Component } from "../../shared_js/class/interface.js"; +import type { Component } from "../../shared_js/class/interface.js"; // conflict with Text -class TextElem implements Component { +export class TextElem implements Component { ctx: CanvasRenderingContext2D; pos: VectorInteger; color: string; @@ -39,7 +39,7 @@ class TextElem implements Component { } } -class TextNumericValue extends TextElem { +export class TextNumericValue extends TextElem { private _value: number = 0; constructor(pos: VectorInteger, size: number, ctx: CanvasRenderingContext2D, color: string, font?: string) @@ -54,5 +54,3 @@ class TextNumericValue extends TextElem { this.text = v.toString(); } } - -export {TextElem, TextNumericValue} diff --git a/srcs/requirements/svelte/api_front/public/game/constants.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/constants.ts similarity index 100% rename from srcs/requirements/svelte/api_front/public/game/constants.ts rename to srcs/requirements/svelte/api_front/src/pages/game/client/constants.ts diff --git a/srcs/requirements/svelte/api_front/public/game/draw.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/draw.ts similarity index 84% rename from srcs/requirements/svelte/api_front/public/game/draw.ts rename to srcs/requirements/svelte/api_front/src/pages/game/client/draw.ts index 984c2acb..204c55f5 100644 --- a/srcs/requirements/svelte/api_front/public/game/draw.ts +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/draw.ts @@ -1,10 +1,8 @@ import { pong, gc } from "./global.js" -import * as c from "./constants.js" -import * as en from "../shared_js/enums.js" import { gridDisplay } from "./handleInput.js"; -function drawLoop() +export function drawLoop() { pong.clear(); @@ -15,6 +13,8 @@ function drawLoop() drawStatic(); gc.text1.update(); + gc.text2.update(); + gc.text3.update(); drawDynamic(); } @@ -47,5 +47,3 @@ function drawGrid() gc.h_grid_u1.update(); gc.h_grid_d1.update(); } - -export {drawLoop} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/client/gameLoop.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/gameLoop.ts new file mode 100644 index 00000000..2ba91739 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/gameLoop.ts @@ -0,0 +1,71 @@ + +import * as c from "./constants.js"; +import * as en from "../shared_js/enums.js" +import { gc, matchOptions, clientInfo, clientInfoSpectator} from "./global.js"; +import { wallsMovements } from "../shared_js/wallsMovement.js"; +import type { RacketClient } from "./class/RectangleClient.js"; +import type { VectorInteger } from "../shared_js/class/Vector.js"; + +let actual_time: number = Date.now(); +let last_time: number; +let delta_time: number; + +export function gameLoop() +{ + /* last_time = actual_time; + actual_time = Date.now(); + delta_time = (actual_time - last_time) / 1000; */ + + delta_time = c.fixedDeltaTime; + // console.log(`delta_gameLoop: ${delta_time}`); + + // interpolation + // console.log(`dir.y: ${clientInfo.opponent.dir.y}, pos.y: ${clientInfo.opponent.pos.y}, opponentNextPos.y: ${clientInfo.opponentNextPos.y}`); + if (clientInfo.opponent.dir.y != 0 ) { + racketInterpolation(delta_time, clientInfo.opponent, clientInfo.opponentNextPos); + } + + // client prediction + gc.ballsArr.forEach((ball) => { + ball.moveAndBounce(delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]); + }); + + if (matchOptions & en.MatchOptions.movingWalls) { + wallsMovements(delta_time, gc); + } +} + +export function gameLoopSpectator() +{ + delta_time = c.fixedDeltaTime; + + // interpolation + if (gc.playerLeft.dir.y != 0 ) { + racketInterpolation(delta_time, gc.playerLeft, clientInfoSpectator.playerLeftNextPos); + } + if (gc.playerRight.dir.y != 0 ) { + racketInterpolation(delta_time, gc.playerRight, clientInfoSpectator.playerRightNextPos); + } + + // client prediction + gc.ballsArr.forEach((ball) => { + ball.moveAndBounce(delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]); + }); + + if (matchOptions & en.MatchOptions.movingWalls) { + wallsMovements(delta_time, gc); + } +} + +function racketInterpolation(delta: number, racket: RacketClient, nextPos: VectorInteger) +{ + // interpolation + racket.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]); + + if ((racket.dir.y > 0 && racket.pos.y > nextPos.y) + || (racket.dir.y < 0 && racket.pos.y < nextPos.y)) + { + racket.dir.y = 0; + racket.pos.y = nextPos.y; + } +} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/client/global.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/global.ts new file mode 100644 index 00000000..146803aa --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/global.ts @@ -0,0 +1,29 @@ + +import * as en from "../shared_js/enums.js"; +import type { GameArea } from "./class/GameArea.js"; +import type { GameComponentsClient } from "./class/GameComponentsClient.js"; + +// export {pong, gc, matchOptions} from "./pong.js" +export {socket, clientInfo, clientInfoSpectator} from "./ws.js" + +export let pong: GameArea; +export let gc: GameComponentsClient; +export let matchOptions: en.MatchOptions = en.MatchOptions.noOption; + +export function initPong(value: GameArea) { + pong = value; +} + +export function initGc(value: GameComponentsClient) { + gc = value; +} + +export function initMatchOptions(value: en.MatchOptions) { + matchOptions = value; +} + +export let startFunction: () => void; + +export function initStartFunction(value: () => void) { + startFunction = value; +} diff --git a/srcs/requirements/svelte/api_front/public/game/handleInput.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/handleInput.ts similarity index 93% rename from srcs/requirements/svelte/api_front/public/game/handleInput.ts rename to srcs/requirements/svelte/api_front/src/pages/game/client/handleInput.ts index 164680e1..78a2af47 100644 --- a/srcs/requirements/svelte/api_front/public/game/handleInput.ts +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/handleInput.ts @@ -4,6 +4,7 @@ import * as ev from "../shared_js/class/Event.js" import * as en from "../shared_js/enums.js" import { InputHistory } from "./class/InputHistory.js" import * as c from "./constants.js"; +import { matchEnded } from "./ws.js"; export let gridDisplay = false; @@ -20,7 +21,7 @@ const inputHistoryArr: InputHistory[] = []; socket.send(JSON.stringify(inputState)); } */ -function handleInput() +export function handleInput() { /* last_time = actual_time; actual_time = Date.now(); @@ -43,7 +44,9 @@ function handleInput() playerMovements(delta_time, keys); } - socket.send(JSON.stringify(inputState)); + if (!matchEnded) { + socket.send(JSON.stringify(inputState)); + } // setTimeout(testInputDelay, 100); inputHistoryArr.push(new InputHistory(inputState, delta_time)); @@ -86,7 +89,7 @@ function playerMovePrediction(delta: number, input: en.InputEnum) racket.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]); } -function repeatInput(lastInputId: number) +export function repeatInput(lastInputId: number) { // server reconciliation let i = inputHistoryArr.findIndex((value: InputHistory) => { @@ -106,5 +109,3 @@ function repeatInput(lastInputId: number) } }); } - -export {handleInput, repeatInput} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/client/init.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/init.ts new file mode 100644 index 00000000..ab832e93 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/init.ts @@ -0,0 +1,47 @@ + +import * as c from "./constants.js" +import * as en from "../shared_js/enums.js" +import { GameArea } from "./class/GameArea.js"; +import { GameComponentsClient } from "./class/GameComponentsClient.js"; +import { socket } from "./ws.js"; +import { initAudio } from "./audio.js"; +import type { InitOptions } from "./class/InitOptions.js"; + +import { pong } from "./global.js" +import { initPong, initGc, initMatchOptions } from "./global.js" + +export function computeMatchOptions(options: InitOptions) +{ + let matchOptions = en.MatchOptions.noOption; + + if (options.multi_balls === true) { + matchOptions |= en.MatchOptions.multiBalls + } + if (options.moving_walls === true) { + matchOptions |= en.MatchOptions.movingWalls + } + + return matchOptions; +} + +export function initBase(matchOptions: en.MatchOptions, sound: string, gameAreaId: string) +{ + initMatchOptions(matchOptions); + initAudio(sound); + initPong(new GameArea(gameAreaId)); + initGc(new GameComponentsClient(matchOptions, pong.ctx)); +} + +export function destroyBase() +{ + if (pong) + { + clearInterval(pong.handleInputInterval); + clearInterval(pong.gameLoopInterval); + clearInterval(pong.drawLoopInterval); + initPong(null); + } + if (socket && socket.OPEN) { + socket.close(); + } +} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/client/message.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/message.ts new file mode 100644 index 00000000..c626543b --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/message.ts @@ -0,0 +1,92 @@ + +import * as c from "./constants.js" +import { gc, pong } from "./global.js" +import * as en from "../shared_js/enums.js" + +/* + before game +*/ +export function error(message: string) +{ + console.log("msg.error()"); + pong.clear(); + const text = "error: " + message; + console.log(text); + gc.text2.clear(); + gc.text2.pos.assign(c.w*0.2, c.h*0.5); + gc.text2.text = text; + gc.text2.update(); +} + +export function matchmaking() +{ + const text = "searching..."; + console.log(text); + gc.text1.clear(); + gc.text1.pos.assign(c.w*0.2, c.h*0.5); + gc.text1.text = text; + gc.text1.update(); +} + +export function matchmakingComplete() +{ + const text = "match found !"; + console.log(text); + gc.text1.clear(); + gc.text1.pos.assign(c.w*0.15, c.h*0.5); + gc.text1.text = text; + gc.text1.update(); +} + +export function matchAbort() +{ + const text = "match abort"; + console.log(text); + gc.text1.clear(); + gc.text1.pos.assign(c.w*0.15, c.h*0.5); + gc.text1.text = text; + gc.text1.update(); + + setTimeout(() => { + gc.text2.pos.assign(c.w*0.44, c.h*0.6); + gc.text2.text = "pardon =("; + const oriSize = gc.text2.size; + gc.text2.size = c.w*0.025; + gc.text2.update(); + gc.text2.size = oriSize; + }, 2500); +} + + +/* + in game +*/ +export function win() +{ + gc.text1.pos.assign(c.w*0.415, c.h*0.5); + gc.text1.text = "WIN"; +} + +export function lose() +{ + gc.text1.pos.assign(c.w*0.383, c.h*0.5); + gc.text1.text = "LOSE"; +} + +export function forfeit(playerSide: en.PlayerSide) +{ + if (playerSide === en.PlayerSide.left) { + gc.text2.pos.assign(c.w*0.65, c.h*0.42); + gc.text3.pos.assign(c.w*0.65, c.h*0.52); + } + else { + gc.text2.pos.assign(c.w*0.09, c.h*0.42); + gc.text3.pos.assign(c.w*0.09, c.h*0.52); + } + setTimeout(() => { + gc.text2.text = "par forfait"; + }, 1500); + setTimeout(() => { + gc.text3.text = "calme ta joie"; + }, 3500); +} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/client/pong.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/pong.ts new file mode 100644 index 00000000..cf15df25 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/pong.ts @@ -0,0 +1,60 @@ + +import * as c from "./constants.js" +import { handleInput } from "./handleInput.js"; +import { gameLoop } from "./gameLoop.js" +import { drawLoop } from "./draw.js"; +import { countdown } from "./utils.js"; +import { initWebSocket } from "./ws.js"; +import type { InitOptions } from "./class/InitOptions.js"; +export { InitOptions } from "./class/InitOptions.js"; +import { initBase, destroyBase, computeMatchOptions } from "./init.js"; +export { computeMatchOptions } from "./init.js"; + +/* TODO: A way to delay the init of variables, but still use "const" not "let" ? */ +import { pong, gc } from "./global.js" +import { initStartFunction } from "./global.js" + + +export function init(options: InitOptions, gameAreaId: string, token: string) +{ + const matchOptions = computeMatchOptions(options); + initBase(matchOptions, options.sound, gameAreaId); + + initStartFunction(start); + if (options.isSomeoneIsInvited) { + initWebSocket(matchOptions, token, options.playerOneUsername, true, options.playerTwoUsername, options.isInvitedPerson); + } + else { + initWebSocket(matchOptions, token, options.playerOneUsername); + } +} + +export function destroy() +{ + destroyBase(); +} + +function start() +{ + gc.text1.pos.assign(c.w*0.5, c.h*0.75); + countdown(c.matchStartDelay/1000, (count: number) => { + gc.text1.clear(); + gc.text1.text = `${count}`; + gc.text1.update(); + }, resume); +} + +function resume() +{ + gc.text1.text = ""; + window.addEventListener('keydown', function (e) { + pong.addKey(e.key); + }); + window.addEventListener('keyup', function (e) { + pong.deleteKey(e.key); + }); + pong.handleInputInterval = window.setInterval(handleInput, c.handleInputIntervalMS); + // pong.handleInputInterval = window.setInterval(sendLoop, c.sendLoopIntervalMS); + pong.gameLoopInterval = window.setInterval(gameLoop, c.gameLoopIntervalMS); + pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS); +} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/client/pongSpectator.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/pongSpectator.ts new file mode 100644 index 00000000..e02b776b --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/pongSpectator.ts @@ -0,0 +1,37 @@ + +import * as c from "./constants.js" +import type * as en from "../shared_js/enums.js" +import { gameLoopSpectator } from "./gameLoop.js" +import { drawLoop } from "./draw.js"; +import { initWebSocketSpectator } from "./ws.js"; +import { initBase, destroyBase, computeMatchOptions } from "./init.js"; +export { computeMatchOptions } from "./init.js"; + +/* TODO: A way to delay the init of variables, but still use "const" not "let" ? */ +import { pong, gc } from "./global.js" +import { initStartFunction } from "./global.js" + + +export function init(matchOptions: en.MatchOptions, sound: string, gameAreaId: string, gameSessionId: string) +{ + initBase(matchOptions, sound, gameAreaId); + + initStartFunction(start); + initWebSocketSpectator(gameSessionId); +} + +export function destroy() +{ + destroyBase(); +} + +function start() +{ + resume(); +} + +function resume() +{ + pong.gameLoopInterval = window.setInterval(gameLoopSpectator, c.gameLoopIntervalMS); + pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS); +} diff --git a/srcs/requirements/svelte/api_front/public/game/utils.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/utils.ts similarity index 68% rename from srcs/requirements/svelte/api_front/public/game/utils.ts rename to srcs/requirements/svelte/api_front/src/pages/game/client/utils.ts index db971447..ff45234d 100644 --- a/srcs/requirements/svelte/api_front/public/game/utils.ts +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/utils.ts @@ -1,7 +1,7 @@ export * from "../shared_js/utils.js" -function countdown(count: number, callback?: (count: number) => void, endCallback?: () => void) +export function countdown(count: number, callback?: (count: number) => void, endCallback?: () => void) { console.log("countdown ", count); if (count > 0) { @@ -14,5 +14,3 @@ function countdown(count: number, callback?: (count: number) => void, endCallbac endCallback(); } } - -export {countdown} diff --git a/srcs/requirements/svelte/api_front/public/game/ws.ts b/srcs/requirements/svelte/api_front/src/pages/game/client/ws.ts similarity index 51% rename from srcs/requirements/svelte/api_front/public/game/ws.ts rename to srcs/requirements/svelte/api_front/src/pages/game/client/ws.ts index 60f1ab87..fefb64d1 100644 --- a/srcs/requirements/svelte/api_front/public/game/ws.ts +++ b/srcs/requirements/svelte/api_front/src/pages/game/client/ws.ts @@ -1,15 +1,18 @@ import * as c from "./constants.js" -import { gc, matchOptions } from "./global.js" +import { gc, matchOptions, startFunction } from "./global.js" import * as ev from "../shared_js/class/Event.js" import * as en from "../shared_js/enums.js" -import { matchmaking, matchmakingComplete, startGame } from "./pong.js"; -import { RacketClient } from "./class/RectangleClient.js"; +import * as msg from "./message.js"; +import type { RacketClient } from "./class/RectangleClient.js"; import { repeatInput } from "./handleInput.js"; import { soundRoblox } from "./audio.js" import { sleep } from "./utils.js"; import { Vector, VectorInteger } from "../shared_js/class/Vector.js"; +export let matchEnded = false; +export let matchAbort = false; + class ClientInfo { id = ""; side: en.PlayerSide; @@ -18,18 +21,34 @@ class ClientInfo { opponentNextPos: VectorInteger; } -const wsPort = 8042; -const wsUrl = "ws://" + document.location.hostname + ":" + wsPort + "/pong"; +class ClientInfoSpectator { + // side: en.PlayerSide; + /* WIP: playerLeftNextPos and playerRightNextPos could be in clientInfo for simplicity */ + playerLeftNextPos: VectorInteger; + playerRightNextPos: VectorInteger; +} + +const wsUrl = "ws://transcendance:8080/pong"; export let socket: WebSocket; /* TODO: A way to still use "const" not "let" ? */ export const clientInfo = new ClientInfo(); +export const clientInfoSpectator = new ClientInfoSpectator(); // WIP, could refactor this -export function initWebSocket(options: en.MatchOptions) + +export function initWebSocket(options: en.MatchOptions, token: string, username: string, privateMatch = false, playerTwoUsername?: string, isInvitedPerson? : boolean) { socket = new WebSocket(wsUrl, "json"); + console.log("Infos from ws.ts : options => " + options + " token => " + token + " username => " + username + " priavte match => " + privateMatch + + " player two => " + playerTwoUsername) socket.addEventListener("open", (event) => { - socket.send(JSON.stringify( new ev.ClientAnnounce(en.ClientRole.player, options, clientInfo.id) )); + if (privateMatch) { + socket.send(JSON.stringify( new ev.ClientAnnouncePlayer(options, token, username, privateMatch, playerTwoUsername, isInvitedPerson) )); + } + else { + socket.send(JSON.stringify( new ev.ClientAnnouncePlayer(options, token, username) )); + } }); // socket.addEventListener("message", logListener); // for testing purpose + socket.addEventListener("message", errorListener); socket.addEventListener("message", preMatchListener); } @@ -37,6 +56,15 @@ function logListener(this: WebSocket, event: MessageEvent) { console.log("%i: " + event.data, Date.now()); } +function errorListener(this: WebSocket, event: MessageEvent) { + console.log("errorListener"); + const data: ev.ServerEvent = JSON.parse(event.data); + if (data.type === en.EventTypes.error) { + console.log("actual Error"); + msg.error((data as ev.EventError).message); + } +} + function preMatchListener(this: WebSocket, event: MessageEvent) { const data: ev.ServerEvent = JSON.parse(event.data); @@ -45,7 +73,7 @@ function preMatchListener(this: WebSocket, event: MessageEvent) clientInfo.id = (data).id; break; case en.EventTypes.matchmakingInProgress: - matchmaking(); + msg.matchmaking(); break; case en.EventTypes.matchmakingComplete: clientInfo.side = (data).side; @@ -62,17 +90,22 @@ function preMatchListener(this: WebSocket, event: MessageEvent) clientInfo.opponentNextPos = new VectorInteger(clientInfo.opponent.pos.x, clientInfo.opponent.pos.y); clientInfo.racket.color = "darkgreen"; // for testing purpose socket.send(JSON.stringify( new ev.ClientEvent(en.EventTypes.clientPlayerReady) )); // TODO: set an interval/timeout to resend until matchStart response (in case of network problem) - matchmakingComplete(); + msg.matchmakingComplete(); break; case en.EventTypes.matchStart: socket.removeEventListener("message", preMatchListener); socket.addEventListener("message", inGameListener); - startGame(); + startFunction(); + break; + case en.EventTypes.matchAbort: + matchAbort = true; + socket.removeEventListener("message", preMatchListener); + msg.matchAbort(); break; } } -function inGameListener(event: MessageEvent) +function inGameListener(this: WebSocket, event: MessageEvent) { const data: ev.ServerEvent = JSON.parse(event.data); switch (data.type) { @@ -168,15 +201,122 @@ function scoreUpdate(data: ev.EventScoreUpdate) function matchEnd(data: ev.EventMatchEnd) { + matchEnded = true; + socket.close(); if (data.winner === clientInfo.side) { - gc.text1.pos.assign(c.w*0.415, c.h_mid); - gc.text1.text = "WIN"; + msg.win(); + if (data.forfeit) { + msg.forfeit(clientInfo.side); + } } else { - gc.text1.pos.assign(c.w*0.383, c.h_mid); - gc.text1.text = "LOSE"; + msg.lose(); } - // matchEnded = true; } -// export let matchEnded = false; +/* Spectator */ + +export function initWebSocketSpectator(gameSessionId: string) +{ + socket = new WebSocket(wsUrl, "json"); + socket.addEventListener("open", (event) => { + socket.send(JSON.stringify( new ev.ClientAnnounceSpectator(gameSessionId) )); + }); + // socket.addEventListener("message", logListener); // for testing purpose + socket.addEventListener("message", preMatchListenerSpectator); + + clientInfoSpectator.playerLeftNextPos = new VectorInteger(gc.playerLeft.pos.x, gc.playerLeft.pos.y); + clientInfoSpectator.playerRightNextPos = new VectorInteger(gc.playerRight.pos.x, gc.playerRight.pos.y); + +} + +export function preMatchListenerSpectator(this: WebSocket, event: MessageEvent) +{ + const data: ev.ServerEvent = JSON.parse(event.data); + if (data.type === en.EventTypes.matchStart) + { + socket.removeEventListener("message", preMatchListenerSpectator); + socket.addEventListener("message", inGameListenerSpectator); + startFunction(); + } +} + +function inGameListenerSpectator(this: WebSocket, event: MessageEvent) +{ + const data: ev.ServerEvent = JSON.parse(event.data); + switch (data.type) { + case en.EventTypes.gameUpdate: + gameUpdateSpectator(data as ev.EventGameUpdate); + break; + case en.EventTypes.scoreUpdate: + scoreUpdateSpectator(data as ev.EventScoreUpdate); + break; + case en.EventTypes.matchEnd: + matchEndSpectator(data as ev.EventMatchEnd); + break; + } +} + +function gameUpdateSpectator(data: ev.EventGameUpdate) +{ + console.log("gameUpdateSpectator"); + + if (matchOptions & en.MatchOptions.movingWalls) { + gc.wallTop.pos.y = data.wallTop.y; + gc.wallBottom.pos.y = data.wallBottom.y; + } + + data.ballsArr.forEach((ball, i) => { + gc.ballsArr[i].pos.assign(ball.x, ball.y); + gc.ballsArr[i].dir.assign(ball.dirX, ball.dirY); + gc.ballsArr[i].speed = ball.speed; + }); + + // interpolation + for (const racket of [gc.playerLeft, gc.playerRight]) + { + let nextPos: VectorInteger; + if (racket === gc.playerLeft) { + nextPos = clientInfoSpectator.playerLeftNextPos; + } + else { + nextPos = clientInfoSpectator.playerRightNextPos; + } + + racket.pos.assign(nextPos.x, nextPos.y); + if (racket === gc.playerLeft) { + nextPos.assign(racket.pos.x, data.playerLeft.y); + } + else { + nextPos.assign(racket.pos.x, data.playerRight.y); + } + + racket.dir = new Vector( + nextPos.x - racket.pos.x, + nextPos.y - racket.pos.y + ); + + if (Math.abs(racket.dir.x) + Math.abs(racket.dir.y) !== 0) { + racket.dir = racket.dir.normalized(); + } + } +} + +function scoreUpdateSpectator(data: ev.EventScoreUpdate) +{ + console.log("scoreUpdateSpectator"); + gc.scoreLeft.value = data.scoreLeft; + gc.scoreRight.value = data.scoreRight; +} + +function matchEndSpectator(data: ev.EventMatchEnd) +{ + console.log("matchEndSpectator"); + matchEnded = true; + socket.close(); + // WIP + /* msg.win(); + if (data.forfeit) { + msg.forfeit(clientInfo.side); + } */ +} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/Event.ts b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/Event.ts new file mode 100644 index 00000000..0147ead8 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/Event.ts @@ -0,0 +1,144 @@ + +import * as en from "../enums.js" + +/* From Server */ +export class ServerEvent { + type: en.EventTypes; + constructor(type: en.EventTypes = 0) { + this.type = type; + } +} + +export class EventAssignId extends ServerEvent { + id: string; + constructor(id: string) { + super(en.EventTypes.assignId); + this.id = id; + } +} + +export class EventMatchmakingComplete extends ServerEvent { + side: en.PlayerSide; + constructor(side: en.PlayerSide) { + super(en.EventTypes.matchmakingComplete); + this.side = side; + } +} + +export class EventGameUpdate extends ServerEvent { + playerLeft = { + y: 0 + }; + playerRight = { + y: 0 + }; + ballsArr: { + x: number, + y: number, + dirX: number, + dirY: number, + speed: number + }[] = []; + wallTop? = { + y: 0 + }; + wallBottom? = { + y: 0 + }; + lastInputId = 0; + constructor() { // TODO: constructor that take GameComponentsServer maybe ? + super(en.EventTypes.gameUpdate); + } +} + +export class EventScoreUpdate extends ServerEvent { + scoreLeft: number; + scoreRight: number; + constructor(scoreLeft: number, scoreRight: number) { + super(en.EventTypes.scoreUpdate); + this.scoreLeft = scoreLeft; + this.scoreRight = scoreRight; + } +} + +export class EventMatchEnd extends ServerEvent { + winner: en.PlayerSide; + forfeit: boolean; + constructor(winner: en.PlayerSide, forfeit = false) { + super(en.EventTypes.matchEnd); + this.winner = winner; + this.forfeit = forfeit; + } +} + +export class EventMatchAbort extends ServerEvent { + constructor() { + super(en.EventTypes.matchAbort); + } +} + +export class EventError extends ServerEvent { + message: string; + constructor(message: string) { + super(en.EventTypes.error); + this.message = message; + } +} + + +/* From Client */ +export class ClientEvent { + type: en.EventTypes; // readonly ? + constructor(type: en.EventTypes = 0) { + this.type = type; + } +} + +export class ClientAnnounce extends ClientEvent { + role: en.ClientRole; + constructor(role: en.ClientRole) { + super(en.EventTypes.clientAnnounce); + this.role = role; + } +} + +export class ClientAnnouncePlayer extends ClientAnnounce { + clientId: string; // unused + matchOptions: en.MatchOptions; + token: string; + username: string; + privateMatch: boolean; + playerTwoUsername?: string; + isInvitedPerson? : boolean; + constructor(matchOptions: en.MatchOptions, token: string, username: string, privateMatch: boolean = false, playerTwoUsername?: string, isInvitedPerson? : boolean) { + super(en.ClientRole.player); + this.matchOptions = matchOptions; + this.token = token; + this.username = username; + this.privateMatch = privateMatch; + if (isInvitedPerson) { + this.isInvitedPerson = isInvitedPerson; + } + if (playerTwoUsername) { + this.playerTwoUsername = playerTwoUsername; + } + } +} + +export class ClientAnnounceSpectator extends ClientAnnounce { + gameSessionId: string; + constructor(gameSessionId: string) { + super(en.ClientRole.spectator); + this.gameSessionId = gameSessionId; + } +} + +export class EventInput extends ClientEvent { + input: en.InputEnum; + id: number; + constructor(input: en.InputEnum = en.InputEnum.noInput, id: number = 0) { + super(en.EventTypes.clientInput); + this.input = input; + this.id = id; + } +} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/GameComponents.ts b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/GameComponents.ts new file mode 100644 index 00000000..ec36f15f --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/GameComponents.ts @@ -0,0 +1,63 @@ + +import * as c from "../constants.js" +import * as en from "../../shared_js/enums.js" +import { VectorInteger } from "./Vector.js"; +import { Rectangle, MovingRectangle, Racket, Ball } from "./Rectangle.js"; +import { random } from "../utils.js"; + +export class GameComponents { + wallTop: Rectangle | MovingRectangle; + wallBottom: Rectangle | MovingRectangle; + playerLeft: Racket; + playerRight: Racket; + ballsArr: Ball[] = []; + constructor(options: en.MatchOptions) + { + const pos = new VectorInteger; + + // Rackets + pos.assign(0+c.pw, c.h_mid-c.ph/2); + this.playerLeft = new Racket(pos, c.pw, c.ph, c.racketSpeed); + pos.assign(c.w-c.pw-c.pw, c.h_mid-c.ph/2); + this.playerRight = new Racket(pos, c.pw, c.ph, c.racketSpeed); + + // Balls + let ballsCount = 1; + if (options & en.MatchOptions.multiBalls) { + ballsCount = c.multiBallsCount; + } + pos.assign(-c.ballSize, -c.ballSize); // ball out =) + while (this.ballsArr.length < ballsCount) { + this.ballsArr.push(new Ball(pos, c.ballSize, c.ballSpeed, c.ballSpeedIncrease)) + } + this.ballsArr.forEach((ball) => { + ball.dir.x = 1; + if (random() > 0.5) { + ball.dir.x *= -1; + } + + ball.dir.y = random(0, 0.2); + if (random() > 0.5) { + ball.dir.y *= -1; + } + + ball.dir = ball.dir.normalized(); + }); + + // Walls + if (options & en.MatchOptions.movingWalls) { + pos.assign(0, 0); + this.wallTop = new MovingRectangle(pos, c.w, c.wallSize, c.movingWallSpeed); + (this.wallTop).dir.y = -1; + pos.assign(0, c.h-c.wallSize); + this.wallBottom = new MovingRectangle(pos, c.w, c.wallSize, c.movingWallSpeed); + (this.wallBottom).dir.y = 1; + } + else { + pos.assign(0, 0); + this.wallTop = new Rectangle(pos, c.w, c.wallSize); + pos.assign(0, c.h-c.wallSize); + this.wallBottom = new Rectangle(pos, c.w, c.wallSize); + } + } +} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/Rectangle.ts b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/Rectangle.ts new file mode 100644 index 00000000..d258c553 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/Rectangle.ts @@ -0,0 +1,142 @@ + +import { Vector, VectorInteger } from "./Vector.js"; +import type { Component, Moving } from "./interface.js"; +import * as c from "../constants.js" + +export class Rectangle implements Component { + pos: VectorInteger; + width: number; + height: number; + constructor(pos: VectorInteger, width: number, height: number) { + this.pos = new VectorInteger(pos.x, pos.y); + this.width = width; + this.height = height; + } + collision(collider: Rectangle): boolean { + const thisLeft = this.pos.x; + const thisRight = this.pos.x + this.width; + const thisTop = this.pos.y; + const thisBottom = this.pos.y + this.height; + const colliderLeft = collider.pos.x; + const colliderRight = collider.pos.x + collider.width; + const colliderTop = collider.pos.y; + const colliderBottom = collider.pos.y + collider.height; + if ((thisBottom < colliderTop) + || (thisTop > colliderBottom) + || (thisRight < colliderLeft) + || (thisLeft > colliderRight)) { + return false; + } + else { + return true; + } + } +} + +export class MovingRectangle extends Rectangle implements Moving { + dir: Vector = new Vector(0,0); + speed: number; + readonly baseSpeed: number; + constructor(pos: VectorInteger, width: number, height: number, baseSpeed: number) { + super(pos, width, height); + this.baseSpeed = baseSpeed; + this.speed = baseSpeed; + } + move(delta: number) { // Math.floor WIP until VectorInteger debug + // console.log(`delta: ${delta}, speed: ${this.speed}, speed*delta: ${this.speed * delta}`); + // this.pos.x += Math.floor(this.dir.x * this.speed * delta); + // this.pos.y += Math.floor(this.dir.y * this.speed * delta); + this.pos.x += this.dir.x * this.speed * delta; + this.pos.y += this.dir.y * this.speed * delta; + } + moveAndCollide(delta: number, colliderArr: Rectangle[]) { + this._moveAndCollideAlgo(delta, colliderArr); + } + protected _moveAndCollideAlgo(delta: number, colliderArr: Rectangle[]) { + let oldPos = new VectorInteger(this.pos.x, this.pos.y); + this.move(delta); + if (colliderArr.some(this.collision, this)) { + this.pos = oldPos; + } + } +} + +export class Racket extends MovingRectangle { + constructor(pos: VectorInteger, width: number, height: number, baseSpeed: number) { + super(pos, width, height, baseSpeed); + } + moveAndCollide(delta: number, colliderArr: Rectangle[]) { + // let oldPos = new VectorInteger(this.pos.x, this.pos.y); // debug + this._moveAndCollideAlgo(delta, colliderArr); + // console.log(`y change: ${this.pos.y - oldPos.y}`); + } +} + +export class Ball extends MovingRectangle { + readonly speedIncrease: number; + ballInPlay: boolean = false; + constructor(pos: VectorInteger, size: number, baseSpeed: number, speedIncrease: number) { + super(pos, size, size, baseSpeed); + this.speedIncrease = speedIncrease; + } + moveAndBounce(delta: number, colliderArr: Rectangle[]) { + this.move(delta); + let i = colliderArr.findIndex(this.collision, this); + if (i != -1) + { + this.bounce(colliderArr[i]); + this.move(delta); + } + } + bounce(collider?: Rectangle) { + this._bounceAlgo(collider); + } + protected _bounceAlgo(collider?: Rectangle) { + /* Could be more generic, but testing only Racket is enough, + because in Pong collider can only be Racket or Wall. */ + if (collider instanceof Racket) { + this._bounceRacket(collider); + } + else { + this._bounceWall(); + } + } + protected _bounceWall() { // Should be enough for Wall + this.dir.y = this.dir.y * -1; + } + protected _bounceRacket(racket: Racket) { + this._bounceRacketAlgo(racket); + } + protected _bounceRacketAlgo(racket: Racket) { + this.speed += this.speedIncrease; + + let x = this.dir.x * -1; + + const angleFactorDegree = 60; + const angleFactor = angleFactorDegree / 90; + const racketHalf = racket.height/2; + const ballMid = this.pos.y + this.height/2; + const racketMid = racket.pos.y + racketHalf; + + let impact = ballMid - racketMid; + const horizontalMargin = racketHalf * 0.15; + if (impact < horizontalMargin && impact > -horizontalMargin) { + impact = 0; + } + else if (impact > 0) { + impact = impact - horizontalMargin; + } + else if (impact < 0) { + impact = impact + horizontalMargin; + } + + let y = impact / (racketHalf - horizontalMargin) * angleFactor; + + this.dir.assign(x, y); + // Normalize Vector (for consistency in speed independent of direction) + if (c.normalizedSpeed) { + this.dir = this.dir.normalized(); + } + // console.log(`x: ${this.dir.x}, y: ${this.dir.y}`); + } +} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/Vector.ts b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/Vector.ts new file mode 100644 index 00000000..fbe121e5 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/Vector.ts @@ -0,0 +1,47 @@ + +export class Vector { + x: number; + y: number; + constructor(x: number = 0, y: number = 0) { + this.x = x; + this.y = y; + } + assign(x: number, y: number) { + this.x = x; + this.y = y; + } + normalized() : Vector { + const normalizationFactor = Math.abs(this.x) + Math.abs(this.y); + return new Vector(this.x/normalizationFactor, this.y/normalizationFactor); + } +} + +export class VectorInteger extends Vector { + // PLACEHOLDER + // VectorInteger with set/get dont work (No draw on the screen). Why ? +} + +/* +export class VectorInteger { + // private _x: number = 0; + // private _y: number = 0; + // constructor(x: number = 0, y: number = 0) { + // this._x = x; + // this._y = y; + // } + // get x(): number { + // return this._x; + // } + // set x(v: number) { + // // this._x = Math.floor(v); + // this._x = v; + // } + // get y(): number { + // return this._y; + // } + // set y(v: number) { + // // this._y = Math.floor(v); + // this._y = v; + // } +} +*/ diff --git a/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/interface.ts b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/interface.ts new file mode 100644 index 00000000..0f484da3 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/class/interface.ts @@ -0,0 +1,19 @@ + +import type { Vector, VectorInteger } from "./Vector.js"; + +export interface Component { + pos: VectorInteger; +} + +export interface GraphicComponent extends Component { + ctx: CanvasRenderingContext2D; + color: string; + update: () => void; + clear: (pos?: VectorInteger) => void; +} + +export interface Moving { + dir: Vector; + speed: number; // pixel per second + move(delta: number): void; +} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/shared_js/constants.ts b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/constants.ts new file mode 100644 index 00000000..44c282c2 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/constants.ts @@ -0,0 +1,30 @@ + +export const CanvasWidth = 1500; +export const CanvasRatio = 1.66666; +/* ratio 5/3 (1.66) */ + +export const w = CanvasWidth; +export const h = CanvasWidth / CanvasRatio; +export const w_mid = Math.floor(w/2); +export const h_mid = Math.floor(h/2); +export const pw = Math.floor(w*0.017); +export const ph = pw*6; +export const ballSize = pw; +export const wallSize = Math.floor(w*0.01); +export const racketSpeed = Math.floor(w*0.60); // pixel per second +export const ballSpeed = Math.floor(w*0.55); // pixel per second +export const ballSpeedIncrease = Math.floor(ballSpeed*0.05); // pixel per second + +export const normalizedSpeed = false; // for consistency in speed independent of direction + +export const matchStartDelay = 3000; // millisecond +export const newRoundDelay = 1500; // millisecond + +// Game Variantes +export const multiBallsCount = 3; +export const movingWallPosMax = Math.floor(w*0.12); +export const movingWallSpeed = Math.floor(w*0.08); + + +export const gameSessionIdPLACEHOLDER = "42"; // TESTING SPECTATOR PLACEHOLDER +// for testing, force gameSession.id in wsServer.ts->matchmaking() \ No newline at end of file diff --git a/srcs/requirements/svelte/api_front/src/pages/game/shared_js/enums.ts b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/enums.ts new file mode 100644 index 00000000..b86571e5 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/enums.ts @@ -0,0 +1,47 @@ + +export enum EventTypes { + // Class Implemented + gameUpdate = 1, + scoreUpdate, + matchEnd, + assignId, + matchmakingComplete, + error, + + // Generic + matchmakingInProgress, + matchStart, + matchAbort, + matchNewRound, // unused + matchPause, // unused + matchResume, // unused + + // Client + clientAnnounce, + clientPlayerReady, + clientInput, + +} + +export enum InputEnum { + noInput = 0, + up = 1, + down, +} + +export enum PlayerSide { + left = 1, + right +} + +export enum ClientRole { + player = 1, + spectator +} + +export enum MatchOptions { + // binary flags, can be mixed + noOption = 0b0, + multiBalls = 1 << 0, + movingWalls = 1 << 1 +} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/shared_js/utils.ts b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/utils.ts new file mode 100644 index 00000000..dd3d40d0 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/utils.ts @@ -0,0 +1,25 @@ + +import type { MovingRectangle } from "./class/Rectangle.js"; + +export function random(min: number = 0, max: number = 1) { + return Math.random() * (max - min) + min; +} + +export function sleep (ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +export function clamp(n: number, min: number, max: number) : number +{ + if (n < min) + n = min; + else if (n > max) + n = max; + return (n); +} + +// Typescript hack, unused +export function assertMovingRectangle(value: unknown): asserts value is MovingRectangle { + // if (value !== MovingRectangle) throw new Error("Not a MovingRectangle"); + return; +} diff --git a/srcs/requirements/svelte/api_front/src/pages/game/shared_js/wallsMovement.ts b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/wallsMovement.ts new file mode 100644 index 00000000..b2c2b581 --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/shared_js/wallsMovement.ts @@ -0,0 +1,18 @@ + +import * as c from "./constants.js"; +import type { MovingRectangle } from "../shared_js/class/Rectangle.js"; +import type { GameComponents } from "./class/GameComponents.js"; + +export function wallsMovements(delta: number, gc: GameComponents) +{ + const wallTop = gc.wallTop; + const wallBottom = gc.wallBottom; + if (wallTop.pos.y <= 0 || wallTop.pos.y >= c.movingWallPosMax) { + wallTop.dir.y *= -1; + } + if (wallBottom.pos.y >= c.h-c.wallSize || wallBottom.pos.y <= c.h-c.movingWallPosMax) { + wallBottom.dir.y *= -1; + } + wallTop.moveAndCollide(delta, [gc.playerLeft, gc.playerRight]); + wallBottom.moveAndCollide(delta, [gc.playerLeft, gc.playerRight]); +} diff --git a/srcs/requirements/svelte/api_front/src/pages/profile/ProfileDisplay.svelte b/srcs/requirements/svelte/api_front/src/pages/profile/ProfileDisplay.svelte index 46b7c62b..1ecc18e1 100644 --- a/srcs/requirements/svelte/api_front/src/pages/profile/ProfileDisplay.svelte +++ b/srcs/requirements/svelte/api_front/src/pages/profile/ProfileDisplay.svelte @@ -10,10 +10,10 @@ user = await fetch('http://transcendance:8080/api/v2/user') .then( (x) => x.json() ); - + }) - + @@ -115,7 +115,7 @@ /* Glittery Star Stuff */ - :root { + :root { --purple: rgb(123, 31, 162); --violet: rgb(103, 58, 183); --pink: rgb(244, 143, 177); @@ -126,7 +126,7 @@ from { background-position: 0% center; } - + to { background-position: -200% center; } @@ -136,7 +136,7 @@ from, to { transform: scale(0); } - + 50% { transform: scale(1); } @@ -146,7 +146,7 @@ from { transform: rotate(0deg); } - + to { transform: rotate(180deg); } @@ -191,7 +191,7 @@ var(--purple) ); background-size: 200%; - + /* Keep these for Safari and chrome */ -webkit-background-clip: text; -webkit-text-fill-color: transparent; @@ -203,4 +203,4 @@ white-space: nowrap; } - \ No newline at end of file + diff --git a/srcs/requirements/svelte/api_front/src/pieces/Header.svelte b/srcs/requirements/svelte/api_front/src/pieces/Header.svelte index dee06c62..26e483c6 100644 --- a/srcs/requirements/svelte/api_front/src/pieces/Header.svelte +++ b/srcs/requirements/svelte/api_front/src/pieces/Header.svelte @@ -24,6 +24,9 @@ Potato Pong Logo (push('/'))}>

Potato Pong