Compare commits
37 Commits
main
...
landing-pa
| Author | SHA1 | Date |
|---|---|---|
|
|
00f22aee28 | |
|
|
e7ea4269d7 | |
|
|
1d777f74ff | |
|
|
e982f782cb | |
|
|
496c68550b | |
|
|
b878beaaff | |
|
|
eff695837b | |
|
|
c0c7a8468e | |
|
|
5fe216dbc0 | |
|
|
9fbfe40f7f | |
|
|
8a4593b542 | |
|
|
10269ec448 | |
|
|
7391d78c03 | |
|
|
8bbfe472c6 | |
|
|
f04f153a0e | |
|
|
44cb010faf | |
|
|
0650f0481b | |
|
|
b7561d804c | |
|
|
949969bda3 | |
|
|
b692caf93d | |
|
|
4db2aa7407 | |
|
|
3525d62c19 | |
|
|
bd6d330226 | |
|
|
6fab2d94a0 | |
|
|
6bb0e1aa74 | |
|
|
87d61278a1 | |
|
|
7a5125ea38 | |
|
|
d90942624b | |
|
|
37a84be3c3 | |
|
|
9f5ec017b7 | |
|
|
47746b5009 | |
|
|
e2bf337b25 | |
|
|
5d55631812 | |
|
|
e323623007 | |
|
|
3a9b88ef55 | |
|
|
d9eafeb71a | |
|
|
74eadacdb2 |
|
|
@ -16,7 +16,8 @@
|
||||||
"@nestjs/websockets": "^10.4.7",
|
"@nestjs/websockets": "^10.4.7",
|
||||||
"interface": "file:../interface",
|
"interface": "file:../interface",
|
||||||
"reflect-metadata": "^0.2.0",
|
"reflect-metadata": "^0.2.0",
|
||||||
"rxjs": "^7.8.1"
|
"rxjs": "^7.8.1",
|
||||||
|
"uuid": "^11.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nestjs/cli": "^10.0.0",
|
"@nestjs/cli": "^10.0.0",
|
||||||
|
|
@ -48,8 +49,7 @@
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"socket.io": "^4.8.1",
|
"socket.io": "^4.8.1",
|
||||||
"socket.io-client": "^4.8.1",
|
"socket.io-client": "^4.8.1"
|
||||||
"uuid": "^11.0.3"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^8.0.0",
|
"@eslint/js": "^8.0.0",
|
||||||
|
|
@ -8949,6 +8949,19 @@
|
||||||
"node": ">= 0.4.0"
|
"node": ">= 0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/uuid": {
|
||||||
|
"version": "11.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz",
|
||||||
|
"integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/esm/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/v8-compile-cache-lib": {
|
"node_modules/v8-compile-cache-lib": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@
|
||||||
"@nestjs/websockets": "^10.4.7",
|
"@nestjs/websockets": "^10.4.7",
|
||||||
"interface": "file:../interface",
|
"interface": "file:../interface",
|
||||||
"reflect-metadata": "^0.2.0",
|
"reflect-metadata": "^0.2.0",
|
||||||
"rxjs": "^7.8.1"
|
"rxjs": "^7.8.1",
|
||||||
|
"uuid": "^11.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nestjs/cli": "^10.0.0",
|
"@nestjs/cli": "^10.0.0",
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { AppService } from './app.service';
|
import { AppService } from './app.service';
|
||||||
import { PlayerService } from './players/player.service';
|
import { PlayerService } from './players/player.service';
|
||||||
|
import { GameService } from './games/game.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [],
|
||||||
providers: [AppService, PlayerService],
|
providers: [AppService, PlayerService, GameService],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger, UseFilters } from '@nestjs/common';
|
||||||
import {
|
import {
|
||||||
ConnectedSocket,
|
ConnectedSocket,
|
||||||
OnGatewayConnection,
|
OnGatewayConnection,
|
||||||
|
|
@ -7,35 +7,81 @@ import {
|
||||||
WebSocketGateway,
|
WebSocketGateway,
|
||||||
} from '@nestjs/websockets';
|
} from '@nestjs/websockets';
|
||||||
import { PlayerService } from './players/player.service';
|
import { PlayerService } from './players/player.service';
|
||||||
|
import { GameService } from 'src/games/game.service';
|
||||||
import { Socket } from 'socket.io';
|
import { Socket } from 'socket.io';
|
||||||
import { ClientEvent, CreateLobbyEvent, JoinLobbyEvent } from 'interface';
|
import {
|
||||||
|
ClientEvent,
|
||||||
|
CreateLobbyEvent,
|
||||||
|
emitUpdateLobbyEvent,
|
||||||
|
JoinLobbyEvent,
|
||||||
|
} from 'interface';
|
||||||
|
import { createWsExceptionFilter } from './websocket-exception-filter';
|
||||||
|
import {
|
||||||
|
GameNotFoundException,
|
||||||
|
InvalidPlayerNameException,
|
||||||
|
MissingPlayerNameException,
|
||||||
|
PlayerNotFoundException,
|
||||||
|
} from './exceptions';
|
||||||
|
|
||||||
@WebSocketGateway({ cors: true })
|
@WebSocketGateway({ cors: true })
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AppService implements OnGatewayConnection {
|
export class AppService implements OnGatewayConnection {
|
||||||
private readonly logger = new Logger(AppService.name);
|
private readonly logger = new Logger(AppService.name);
|
||||||
|
|
||||||
constructor(private readonly playerService: PlayerService) {}
|
constructor(
|
||||||
|
private readonly playerService: PlayerService,
|
||||||
|
private readonly gameService: GameService,
|
||||||
|
) {}
|
||||||
handleConnection(client: Socket) {
|
handleConnection(client: Socket) {
|
||||||
this.playerService.createPlayer(client.id);
|
this.playerService.createPlayer(client);
|
||||||
this.logger.log(client.id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseFilters(
|
||||||
|
createWsExceptionFilter([
|
||||||
|
PlayerNotFoundException,
|
||||||
|
MissingPlayerNameException,
|
||||||
|
InvalidPlayerNameException,
|
||||||
|
]),
|
||||||
|
)
|
||||||
@SubscribeMessage(ClientEvent.CREATE_LOBBY)
|
@SubscribeMessage(ClientEvent.CREATE_LOBBY)
|
||||||
handleCreateLobby(
|
handleCreateLobby(
|
||||||
@ConnectedSocket() client: Socket,
|
@ConnectedSocket() client: Socket,
|
||||||
@MessageBody() event: CreateLobbyEvent,
|
@MessageBody() event: CreateLobbyEvent,
|
||||||
) {
|
) {
|
||||||
this.playerService.addUserName(client.id, event.userName);
|
this.playerService.addUserName(client.id, event.userName);
|
||||||
this.logger.log('Se ha creado un lobby');
|
const game = this.gameService.createLobby(
|
||||||
|
this.playerService.getPlayer(client.id),
|
||||||
|
);
|
||||||
|
emitUpdateLobbyEvent(client, {
|
||||||
|
playerNames: game.players.map((player) => player.userName),
|
||||||
|
gameCode: game.gameCode,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseFilters(
|
||||||
|
createWsExceptionFilter([
|
||||||
|
PlayerNotFoundException,
|
||||||
|
MissingPlayerNameException,
|
||||||
|
InvalidPlayerNameException,
|
||||||
|
GameNotFoundException,
|
||||||
|
]),
|
||||||
|
)
|
||||||
@SubscribeMessage(ClientEvent.JOIN_LOBBY)
|
@SubscribeMessage(ClientEvent.JOIN_LOBBY)
|
||||||
handleJoinLobby(
|
handleJoinLobby(
|
||||||
@ConnectedSocket() client: Socket,
|
@ConnectedSocket() client: Socket,
|
||||||
@MessageBody() event: JoinLobbyEvent,
|
@MessageBody() event: JoinLobbyEvent,
|
||||||
) {
|
) {
|
||||||
this.playerService.addUserName(client.id, event.userName);
|
this.playerService.addUserName(client.id, event.userName);
|
||||||
this.logger.log('Te has unido a un lobby');
|
const game = this.gameService.joinGame(
|
||||||
|
this.playerService.getPlayer(client.id),
|
||||||
|
event.lobbyId,
|
||||||
|
);
|
||||||
|
const playerNames = game.players.map((player) => player.userName);
|
||||||
|
game.players.forEach((player) =>
|
||||||
|
emitUpdateLobbyEvent(player.socket, {
|
||||||
|
playerNames: playerNames,
|
||||||
|
gameCode: game.gameCode,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { WsException } from '@nestjs/websockets';
|
||||||
|
import { ErrorCode } from 'interface';
|
||||||
|
|
||||||
|
export abstract class WebSocketException extends WsException {
|
||||||
|
public readonly errorCode: ErrorCode;
|
||||||
|
|
||||||
|
constructor(message: string, errorCode: ErrorCode) {
|
||||||
|
super(message);
|
||||||
|
this.errorCode = errorCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MissingPlayerNameException extends WebSocketException {
|
||||||
|
constructor() {
|
||||||
|
super('Missing player name', ErrorCode.MISSING_USER_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class InvalidPlayerNameException extends WebSocketException {
|
||||||
|
constructor(userName: string) {
|
||||||
|
super('Invalid player name: ' + userName, ErrorCode.INVALID_USER_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PlayerNotFoundException extends WebSocketException {
|
||||||
|
constructor(playerId: string) {
|
||||||
|
super(
|
||||||
|
'Unable to find player from ID: ' + playerId,
|
||||||
|
ErrorCode.PLAYER_NOT_FOUND,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GameNotFoundException extends WebSocketException {
|
||||||
|
constructor(gameId: string) {
|
||||||
|
super('Unable to find game from ID: ' + gameId, ErrorCode.GAME_NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
import { Game } from './game';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import { Player } from 'src/players/player';
|
||||||
|
import { GameNotFoundException } from 'src/exceptions';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class GameService {
|
||||||
|
private readonly logger = new Logger(GameService.name);
|
||||||
|
private readonly games: Map<string, Game> = new Map();
|
||||||
|
|
||||||
|
createLobby(player: Player): Game {
|
||||||
|
const gameId = uuidv4();
|
||||||
|
const gameCode = uuidv4().slice(-5).toUpperCase();
|
||||||
|
const game: Game = new Game(gameId, gameCode, player);
|
||||||
|
this.games.set(gameCode, game);
|
||||||
|
return game;
|
||||||
|
}
|
||||||
|
|
||||||
|
joinGame(player: Player, gameCode: string): Game {
|
||||||
|
const game = this.games.get(gameCode);
|
||||||
|
if (game === undefined) {
|
||||||
|
throw new GameNotFoundException(gameCode);
|
||||||
|
}
|
||||||
|
game.players.push(player);
|
||||||
|
return game;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { Player } from 'src/players/player';
|
||||||
|
|
||||||
|
export class Game {
|
||||||
|
gameId: string;
|
||||||
|
gameCode: string;
|
||||||
|
players: Player[];
|
||||||
|
constructor(gameId: string, gameCode: string, player: Player) {
|
||||||
|
this.gameId = gameId;
|
||||||
|
this.gameCode = gameCode;
|
||||||
|
this.players = [player];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,19 +1,38 @@
|
||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
import { Player } from './player';
|
import { Player } from './player';
|
||||||
|
import {
|
||||||
|
InvalidPlayerNameException,
|
||||||
|
MissingPlayerNameException,
|
||||||
|
PlayerNotFoundException,
|
||||||
|
} from 'src/exceptions';
|
||||||
|
import { Socket } from 'socket.io/dist/socket';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PlayerService {
|
export class PlayerService {
|
||||||
private readonly logger = new Logger(PlayerService.name);
|
private readonly logger = new Logger(PlayerService.name);
|
||||||
private readonly players: Map<string, Player> = new Map();
|
private readonly players: Map<string, Player> = new Map();
|
||||||
|
private readonly userNameValidator: RegExp = /^[a-zA-Z\s]{1,20}$/;
|
||||||
|
|
||||||
createPlayer(socketId: string) {
|
createPlayer(socket: Socket) {
|
||||||
const player: Player = new Player(socketId);
|
const player: Player = new Player(socket);
|
||||||
this.players.set(socketId, player);
|
this.players.set(player.socketId, player);
|
||||||
this.logger.log([...this.players.entries()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addUserName(socketId: string, userName: string) {
|
addUserName(socketId: string, userName: string) {
|
||||||
|
if (!userName) {
|
||||||
|
throw new MissingPlayerNameException();
|
||||||
|
}
|
||||||
|
if (!this.userNameValidator.test(userName)) {
|
||||||
|
throw new InvalidPlayerNameException(userName);
|
||||||
|
}
|
||||||
this.players.get(socketId).userName = userName;
|
this.players.get(socketId).userName = userName;
|
||||||
this.logger.log([...this.players.entries()]);
|
}
|
||||||
|
|
||||||
|
getPlayer(socketId: string): Player {
|
||||||
|
const player = this.players.get(socketId);
|
||||||
|
if (!player) {
|
||||||
|
throw new PlayerNotFoundException(socketId);
|
||||||
|
}
|
||||||
|
return player;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
|
import { Socket } from 'socket.io';
|
||||||
|
|
||||||
export class Player {
|
export class Player {
|
||||||
socketId: string;
|
socketId: string;
|
||||||
|
socket: Socket;
|
||||||
userName?: string;
|
userName?: string;
|
||||||
constructor(socketId: string) {
|
|
||||||
this.socketId = socketId;
|
constructor(socket: Socket) {
|
||||||
|
this.socket = socket;
|
||||||
|
this.socketId = socket.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { ArgumentsHost, Catch, Logger } from '@nestjs/common';
|
||||||
|
import { BaseWsExceptionFilter } from '@nestjs/websockets';
|
||||||
|
import { WebSocketException } from './exceptions';
|
||||||
|
import { Socket } from 'socket.io';
|
||||||
|
import { ClientEvent } from 'interface';
|
||||||
|
import { emitCreateLobbyError, emitJoinLobbyError } from 'interface';
|
||||||
|
|
||||||
|
export const createWsExceptionFilter: (
|
||||||
|
exceptionList: (typeof WebSocketException)[],
|
||||||
|
) => BaseWsExceptionFilter<WebSocketException> = (handledExceptions) => {
|
||||||
|
@Catch(...handledExceptions)
|
||||||
|
class WsExceptionFilter extends BaseWsExceptionFilter<WebSocketException> {
|
||||||
|
private readonly logger = new Logger(BaseWsExceptionFilter.name);
|
||||||
|
|
||||||
|
catch(exception: WebSocketException, host: ArgumentsHost) {
|
||||||
|
const socket = host.switchToWs().getClient() as Socket;
|
||||||
|
const method = host.switchToWs().getPattern();
|
||||||
|
const data: object = host.switchToWs().getData();
|
||||||
|
this.logger.log(
|
||||||
|
`Caught exception: ${exception}
|
||||||
|
for request to ${method}
|
||||||
|
from client ${socket.id}
|
||||||
|
with input ${JSON.stringify(data)}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (method) {
|
||||||
|
case ClientEvent.CREATE_LOBBY:
|
||||||
|
emitCreateLobbyError(socket, { error: exception.errorCode });
|
||||||
|
break;
|
||||||
|
case ClientEvent.JOIN_LOBBY:
|
||||||
|
emitJoinLobbyError(socket, { error: exception.errorCode });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new WsExceptionFilter();
|
||||||
|
};
|
||||||
|
|
@ -4,6 +4,15 @@ export * from "./constants/ExitType";
|
||||||
export * from "./constants/InternalNodeType";
|
export * from "./constants/InternalNodeType";
|
||||||
export * from "./constants/Pieces";
|
export * from "./constants/Pieces";
|
||||||
export * from "./constants/TrackType";
|
export * from "./constants/TrackType";
|
||||||
|
export * from "./server-events/CreateLobbyError";
|
||||||
|
export * from "./server-events/JoinLobbyError";
|
||||||
|
export * from "./server-events/ServerError";
|
||||||
|
export * from "./server-events/ServerEvent";
|
||||||
|
export * from "./server-events/StartRoundEvent";
|
||||||
|
export * from "./server-events/UpdateLobbyEvent";
|
||||||
|
export * from "./client-events/ClientEvent";
|
||||||
|
export * from "./client-events/CreateLobbyEvent";
|
||||||
|
export * from "./client-events/JoinLobbyEvent";
|
||||||
export * from "./types/Border";
|
export * from "./types/Border";
|
||||||
export * from "./types/Cell";
|
export * from "./types/Cell";
|
||||||
export * from "./types/Exit";
|
export * from "./types/Exit";
|
||||||
|
|
@ -12,10 +21,3 @@ export * from "./types/InternalNode";
|
||||||
export * from "./types/Piece";
|
export * from "./types/Piece";
|
||||||
export * from "./types/PlacedPiece";
|
export * from "./types/PlacedPiece";
|
||||||
export * from "./BoardBuilder";
|
export * from "./BoardBuilder";
|
||||||
export * from "./server-events/ServerError";
|
|
||||||
export * from "./server-events/ServerEvent";
|
|
||||||
export * from "./server-events/StartRoundEvent";
|
|
||||||
export * from "./server-events/UpdateLobbyEvent";
|
|
||||||
export * from "./client-events/ClientEvent";
|
|
||||||
export * from "./client-events/CreateLobbyEvent";
|
|
||||||
export * from "./client-events/JoinLobbyEvent";
|
|
||||||
|
|
|
||||||
|
|
@ -248,12 +248,6 @@
|
||||||
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
|
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/cookie": {
|
|
||||||
"version": "0.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
|
|
||||||
"integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@types/cors": {
|
"node_modules/@types/cors": {
|
||||||
"version": "2.8.17",
|
"version": "2.8.17",
|
||||||
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz",
|
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz",
|
||||||
|
|
@ -272,21 +266,21 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.17.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz",
|
||||||
"integrity": "sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==",
|
"integrity": "sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "8.17.0",
|
"@typescript-eslint/scope-manager": "8.23.0",
|
||||||
"@typescript-eslint/type-utils": "8.17.0",
|
"@typescript-eslint/type-utils": "8.23.0",
|
||||||
"@typescript-eslint/utils": "8.17.0",
|
"@typescript-eslint/utils": "8.23.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.17.0",
|
"@typescript-eslint/visitor-keys": "8.23.0",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^5.3.1",
|
"ignore": "^5.3.1",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
"ts-api-utils": "^1.3.0"
|
"ts-api-utils": "^2.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
|
@ -297,25 +291,21 @@
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
|
"@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
|
||||||
"eslint": "^8.57.0 || ^9.0.0"
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
},
|
"typescript": ">=4.8.4 <5.8.0"
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "8.17.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz",
|
||||||
"integrity": "sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==",
|
"integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.17.0",
|
"@typescript-eslint/scope-manager": "8.23.0",
|
||||||
"@typescript-eslint/types": "8.17.0",
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.17.0",
|
"@typescript-eslint/typescript-estree": "8.23.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.17.0",
|
"@typescript-eslint/visitor-keys": "8.23.0",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
@ -326,23 +316,19 @@
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"eslint": "^8.57.0 || ^9.0.0"
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
},
|
"typescript": ">=4.8.4 <5.8.0"
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "8.17.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.23.0.tgz",
|
||||||
"integrity": "sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==",
|
"integrity": "sha512-OGqo7+dXHqI7Hfm+WqkZjKjsiRtFUQHPdGMXzk5mYXhJUedO7e/Y7i8AK3MyLMgZR93TX4bIzYrfyVjLC+0VSw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.17.0",
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.17.0"
|
"@typescript-eslint/visitor-keys": "8.23.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
|
@ -353,16 +339,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "8.17.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.23.0.tgz",
|
||||||
"integrity": "sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==",
|
"integrity": "sha512-iIuLdYpQWZKbiH+RkCGc6iu+VwscP5rCtQ1lyQ7TYuKLrcZoeJVpcLiG8DliXVkUxirW/PWlmS+d6yD51L9jvA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/typescript-estree": "8.17.0",
|
"@typescript-eslint/typescript-estree": "8.23.0",
|
||||||
"@typescript-eslint/utils": "8.17.0",
|
"@typescript-eslint/utils": "8.23.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^1.3.0"
|
"ts-api-utils": "^2.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
|
@ -372,18 +358,14 @@
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"eslint": "^8.57.0 || ^9.0.0"
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
},
|
"typescript": ">=4.8.4 <5.8.0"
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "8.17.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.23.0.tgz",
|
||||||
"integrity": "sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==",
|
"integrity": "sha512-1sK4ILJbCmZOTt9k4vkoulT6/y5CHJ1qUYxqpF1K/DBAd8+ZUL4LlSCxOssuH5m4rUaaN0uS0HlVPvd45zjduQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
@ -395,45 +377,20 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "8.17.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.23.0.tgz",
|
||||||
"integrity": "sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==",
|
"integrity": "sha512-LcqzfipsB8RTvH8FX24W4UUFk1bl+0yTOf9ZA08XngFwMg4Kj8A+9hwz8Cr/ZS4KwHrmo9PJiLZkOt49vPnuvQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.17.0",
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.17.0",
|
"@typescript-eslint/visitor-keys": "8.23.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
"minimatch": "^9.0.4",
|
"minimatch": "^9.0.4",
|
||||||
"semver": "^7.6.0",
|
"semver": "^7.6.0",
|
||||||
"ts-api-utils": "^1.3.0"
|
"ts-api-utils": "^2.0.1"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@typescript-eslint/utils": {
|
|
||||||
"version": "8.17.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.17.0.tgz",
|
|
||||||
"integrity": "sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@eslint-community/eslint-utils": "^4.4.0",
|
|
||||||
"@typescript-eslint/scope-manager": "8.17.0",
|
|
||||||
"@typescript-eslint/types": "8.17.0",
|
|
||||||
"@typescript-eslint/typescript-estree": "8.17.0"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
|
@ -443,22 +400,41 @@
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"eslint": "^8.57.0 || ^9.0.0"
|
"typescript": ">=4.8.4 <5.8.0"
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "8.17.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.23.0.tgz",
|
||||||
"integrity": "sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==",
|
"integrity": "sha512-uB/+PSo6Exu02b5ZEiVtmY6RVYO7YU5xqgzTIVZwTHvvK3HsL8tZZHFaTLFtRG3CsV4A5mhOv+NZx5BlhXPyIA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.17.0",
|
"@eslint-community/eslint-utils": "^4.4.0",
|
||||||
|
"@typescript-eslint/scope-manager": "8.23.0",
|
||||||
|
"@typescript-eslint/types": "8.23.0",
|
||||||
|
"@typescript-eslint/typescript-estree": "8.23.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
|
"typescript": ">=4.8.4 <5.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
|
"version": "8.23.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.23.0.tgz",
|
||||||
|
"integrity": "sha512-oWWhcWDLwDfu++BGTZcmXWqpwtkwb5o7fxUIGksMQQDSdPW9prsSnfIOZMlsj4vBOSrcnjIUZMiIjODgGosFhQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"eslint-visitor-keys": "^4.2.0"
|
"eslint-visitor-keys": "^4.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
@ -743,12 +719,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/engine.io": {
|
"node_modules/engine.io": {
|
||||||
"version": "6.6.2",
|
"version": "6.6.4",
|
||||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz",
|
||||||
"integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==",
|
"integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/cookie": "^0.4.1",
|
|
||||||
"@types/cors": "^2.8.12",
|
"@types/cors": "^2.8.12",
|
||||||
"@types/node": ">=10.0.0",
|
"@types/node": ">=10.0.0",
|
||||||
"accepts": "~1.3.4",
|
"accepts": "~1.3.4",
|
||||||
|
|
@ -764,9 +739,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/engine.io-client": {
|
"node_modules/engine.io-client": {
|
||||||
"version": "6.6.2",
|
"version": "6.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
|
||||||
"integrity": "sha512-TAr+NKeoVTjEVW8P3iHguO1LO6RlUz9O5Y8o7EY0fU+gY1NYqas7NN3slpFtbXEsLMHk0h90fJMfKjRkQ0qUIw==",
|
"integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@socket.io/component-emitter": "~3.1.0",
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
|
@ -1048,9 +1023,9 @@
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/fast-glob": {
|
"node_modules/fast-glob": {
|
||||||
"version": "3.3.2",
|
"version": "3.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
||||||
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
|
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -1058,7 +1033,7 @@
|
||||||
"@nodelib/fs.walk": "^1.2.3",
|
"@nodelib/fs.walk": "^1.2.3",
|
||||||
"glob-parent": "^5.1.2",
|
"glob-parent": "^5.1.2",
|
||||||
"merge2": "^1.3.0",
|
"merge2": "^1.3.0",
|
||||||
"micromatch": "^4.0.4"
|
"micromatch": "^4.0.8"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.6.0"
|
"node": ">=8.6.0"
|
||||||
|
|
@ -1233,9 +1208,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/globals": {
|
"node_modules/globals": {
|
||||||
"version": "15.13.0",
|
"version": "15.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-15.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz",
|
||||||
"integrity": "sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==",
|
"integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
@ -1668,9 +1643,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prettier": {
|
"node_modules/prettier": {
|
||||||
"version": "3.4.2",
|
"version": "3.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
|
||||||
"integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
|
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
|
|
@ -1791,9 +1766,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.6.3",
|
"version": "7.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||||
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -1959,16 +1934,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ts-api-utils": {
|
"node_modules/ts-api-utils": {
|
||||||
"version": "1.4.3",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz",
|
||||||
"integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
|
"integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=18.12"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": ">=4.2.0"
|
"typescript": ">=4.8.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tslib": {
|
"node_modules/tslib": {
|
||||||
|
|
@ -2018,15 +1993,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript-eslint": {
|
"node_modules/typescript-eslint": {
|
||||||
"version": "8.15.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.23.0.tgz",
|
||||||
"integrity": "sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==",
|
"integrity": "sha512-/LBRo3HrXr5LxmrdYSOCvoAMm7p2jNizNfbIpCgvG4HMsnoprRUOce/+8VJ9BDYWW68rqIENE/haVLWPeFZBVQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "8.15.0",
|
"@typescript-eslint/eslint-plugin": "8.23.0",
|
||||||
"@typescript-eslint/parser": "8.15.0",
|
"@typescript-eslint/parser": "8.23.0",
|
||||||
"@typescript-eslint/utils": "8.15.0"
|
"@typescript-eslint/utils": "8.23.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
|
@ -2036,223 +2011,8 @@
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"eslint": "^8.57.0 || ^9.0.0"
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
},
|
"typescript": ">=4.8.4 <5.8.0"
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": {
|
|
||||||
"version": "8.15.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz",
|
|
||||||
"integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
|
||||||
"@typescript-eslint/scope-manager": "8.15.0",
|
|
||||||
"@typescript-eslint/type-utils": "8.15.0",
|
|
||||||
"@typescript-eslint/utils": "8.15.0",
|
|
||||||
"@typescript-eslint/visitor-keys": "8.15.0",
|
|
||||||
"graphemer": "^1.4.0",
|
|
||||||
"ignore": "^5.3.1",
|
|
||||||
"natural-compare": "^1.4.0",
|
|
||||||
"ts-api-utils": "^1.3.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
|
|
||||||
"eslint": "^8.57.0 || ^9.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": {
|
|
||||||
"version": "8.15.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz",
|
|
||||||
"integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"dependencies": {
|
|
||||||
"@typescript-eslint/scope-manager": "8.15.0",
|
|
||||||
"@typescript-eslint/types": "8.15.0",
|
|
||||||
"@typescript-eslint/typescript-estree": "8.15.0",
|
|
||||||
"@typescript-eslint/visitor-keys": "8.15.0",
|
|
||||||
"debug": "^4.3.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"eslint": "^8.57.0 || ^9.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": {
|
|
||||||
"version": "8.15.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz",
|
|
||||||
"integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@typescript-eslint/types": "8.15.0",
|
|
||||||
"@typescript-eslint/visitor-keys": "8.15.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": {
|
|
||||||
"version": "8.15.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz",
|
|
||||||
"integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@typescript-eslint/typescript-estree": "8.15.0",
|
|
||||||
"@typescript-eslint/utils": "8.15.0",
|
|
||||||
"debug": "^4.3.4",
|
|
||||||
"ts-api-utils": "^1.3.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"eslint": "^8.57.0 || ^9.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/typescript-eslint/node_modules/@typescript-eslint/types": {
|
|
||||||
"version": "8.15.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz",
|
|
||||||
"integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": {
|
|
||||||
"version": "8.15.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz",
|
|
||||||
"integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"dependencies": {
|
|
||||||
"@typescript-eslint/types": "8.15.0",
|
|
||||||
"@typescript-eslint/visitor-keys": "8.15.0",
|
|
||||||
"debug": "^4.3.4",
|
|
||||||
"fast-glob": "^3.3.2",
|
|
||||||
"is-glob": "^4.0.3",
|
|
||||||
"minimatch": "^9.0.4",
|
|
||||||
"semver": "^7.6.0",
|
|
||||||
"ts-api-utils": "^1.3.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": {
|
|
||||||
"version": "8.15.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz",
|
|
||||||
"integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@eslint-community/eslint-utils": "^4.4.0",
|
|
||||||
"@typescript-eslint/scope-manager": "8.15.0",
|
|
||||||
"@typescript-eslint/types": "8.15.0",
|
|
||||||
"@typescript-eslint/typescript-estree": "8.15.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"eslint": "^8.57.0 || ^9.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": {
|
|
||||||
"version": "8.15.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz",
|
|
||||||
"integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@typescript-eslint/types": "8.15.0",
|
|
||||||
"eslint-visitor-keys": "^4.2.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/typescript-eslint/node_modules/eslint-visitor-keys": {
|
|
||||||
"version": "4.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
|
|
||||||
"integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://opencollective.com/eslint"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@
|
||||||
"typescript-eslint": "^8.15.0"
|
"typescript-eslint": "^8.15.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"uuid": "^11.0.3",
|
|
||||||
"socket.io": "^4.8.1",
|
"socket.io": "^4.8.1",
|
||||||
"socket.io-client": "^4.8.1"
|
"socket.io-client": "^4.8.1",
|
||||||
|
"uuid": "^11.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Socket as ServerSocket } from "socket.io";
|
||||||
|
import { Socket as ClientSocket } from "socket.io-client";
|
||||||
|
import { ErrorCode, ServerError } from "./ServerError";
|
||||||
|
|
||||||
|
export type CreateLobbyError = {
|
||||||
|
error: ErrorCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const emitCreateLobbyError = (
|
||||||
|
socket: ServerSocket,
|
||||||
|
payload: CreateLobbyError,
|
||||||
|
) => {
|
||||||
|
socket.emit(ServerError.CREATE_LOBBY_ERROR, payload);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const attachHandlerToCreateLobbyError = (
|
||||||
|
socket: ClientSocket,
|
||||||
|
handler: (payload: CreateLobbyError) => void,
|
||||||
|
): (() => void) => {
|
||||||
|
socket.on(ServerError.CREATE_LOBBY_ERROR, handler);
|
||||||
|
return () => socket.off(ServerError.CREATE_LOBBY_ERROR);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Socket as ServerSocket } from "socket.io";
|
||||||
|
import { Socket as ClientSocket } from "socket.io-client";
|
||||||
|
import { ErrorCode, ServerError } from "./ServerError";
|
||||||
|
|
||||||
|
export type JoinLobbyError = {
|
||||||
|
error: ErrorCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const emitJoinLobbyError = (
|
||||||
|
socket: ServerSocket,
|
||||||
|
payload: JoinLobbyError,
|
||||||
|
) => {
|
||||||
|
socket.emit(ServerError.JOIN_LOBBY_ERROR, payload);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const attachHandlerToJoinLobbyError = (
|
||||||
|
socket: ClientSocket,
|
||||||
|
handler: (payload: JoinLobbyError) => void,
|
||||||
|
): (() => void) => {
|
||||||
|
socket.on(ServerError.JOIN_LOBBY_ERROR, handler);
|
||||||
|
return () => socket.off(ServerError.JOIN_LOBBY_ERROR);
|
||||||
|
};
|
||||||
|
|
@ -2,3 +2,12 @@ export enum ServerError {
|
||||||
CREATE_LOBBY_ERROR = "create-lobby-error",
|
CREATE_LOBBY_ERROR = "create-lobby-error",
|
||||||
JOIN_LOBBY_ERROR = "join-lobby-error",
|
JOIN_LOBBY_ERROR = "join-lobby-error",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ErrorCode {
|
||||||
|
PLAYER_NOT_FOUND = "player-not-found",
|
||||||
|
GAME_NOT_FOUND = "game-not-found",
|
||||||
|
MISSING_USER_NAME = "missing-player-name",
|
||||||
|
INVALID_USER_NAME = "invalid-player-name",
|
||||||
|
DUPLICATE_USER_NAME = "duplicate-player-name",
|
||||||
|
MISSING_GAME_CODE = "missing-game-code",
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,7 @@
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"socket.io": "^4.8.1",
|
"socket.io": "^4.8.1",
|
||||||
"socket.io-client": "^4.8.1",
|
"socket.io-client": "^4.8.1"
|
||||||
"uuid": "^11.0.3"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^8.0.0",
|
"@eslint/js": "^8.0.0",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
@use "node_modules/@picocss/pico/scss/pico" with (
|
@use "node_modules/@picocss/pico/scss/pico" with (
|
||||||
$theme-color: "pumpkin"
|
$theme-color: "pumpkin"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#root, #app {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import React, { useCallback, useState } from "react";
|
||||||
import { Socket } from "socket.io-client";
|
import { Socket } from "socket.io-client";
|
||||||
import LandingPage from "./pages/landing/LandingPage";
|
import LandingPage from "./pages/landing/LandingPage";
|
||||||
import GamePage from "./pages/game/GamePage";
|
import GamePage from "./pages/game/GamePage";
|
||||||
|
import "./App.scss";
|
||||||
import LobbyPage from "./pages/lobby/LobbyPage";
|
import LobbyPage from "./pages/lobby/LobbyPage";
|
||||||
import {
|
import {
|
||||||
attachHandlerToStartRoundEvent,
|
attachHandlerToStartRoundEvent,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ const root = ReactDOM.createRoot(
|
||||||
document.getElementById("root") as HTMLElement,
|
document.getElementById("root") as HTMLElement,
|
||||||
);
|
);
|
||||||
const socket = io("http://localhost:3010");
|
const socket = io("http://localhost:3010");
|
||||||
|
socket.on("exception", console.log);
|
||||||
root.render(
|
root.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<App socket={socket} />
|
<App socket={socket} />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
.landing-page {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
padding: 2%;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
background: linear-gradient(-45deg, #03444a, #00a8a8, #f1bc52, #ff8f4b);
|
||||||
|
background-size: 400% 400%;
|
||||||
|
animation: gradient 15s ease infinite;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
@keyframes gradient {
|
||||||
|
0% {
|
||||||
|
background-position: 0% 50%;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
background-position: 100% 50%;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-position: 0% 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-page-body {
|
||||||
|
margin: auto;
|
||||||
|
width: 20%;
|
||||||
|
min-width: 300px;
|
||||||
|
|
||||||
|
#error-message {
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
padding: 2%;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
font-size: 1rem;
|
||||||
|
width: 70%;
|
||||||
|
margin-bottom: var(--pico-spacing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
import {
|
import {
|
||||||
|
attachHandlerToCreateLobbyError,
|
||||||
|
attachHandlerToJoinLobbyError,
|
||||||
CreateLobbyEvent,
|
CreateLobbyEvent,
|
||||||
|
ErrorCode,
|
||||||
handleCreateLobby,
|
handleCreateLobby,
|
||||||
handleJoinLobby,
|
handleJoinLobby,
|
||||||
JoinLobbyEvent,
|
JoinLobbyEvent,
|
||||||
} from "interface";
|
} from "interface";
|
||||||
import React, { ChangeEvent } from "react";
|
import { ChangeEvent, useEffect, useState } from "react";
|
||||||
import { Socket } from "socket.io-client";
|
import { Socket } from "socket.io-client";
|
||||||
|
import "./LandingPage.scss";
|
||||||
|
|
||||||
export interface LandingPageProps {
|
export interface LandingPageProps {
|
||||||
socket: Socket;
|
socket: Socket;
|
||||||
|
|
@ -14,42 +18,81 @@ export interface LandingPageProps {
|
||||||
const LandingPage = (props: LandingPageProps) => {
|
const LandingPage = (props: LandingPageProps) => {
|
||||||
const { socket } = props;
|
const { socket } = props;
|
||||||
|
|
||||||
const createLobbyPayload: CreateLobbyEvent = { userName: "" };
|
const [userName, setUsername] = useState("");
|
||||||
const joinLobbyPayload: JoinLobbyEvent = { userName: "", lobbyId: "" };
|
const [lobbyId, setLobbyId] = useState("");
|
||||||
const registerUsername = (event: ChangeEvent<HTMLInputElement>) => {
|
const createLobbyPayload: CreateLobbyEvent = { userName };
|
||||||
createLobbyPayload.userName = event.target.value;
|
const joinLobbyPayload: JoinLobbyEvent = { userName, lobbyId };
|
||||||
joinLobbyPayload.userName = event.target.value;
|
const registerUsername = (event: ChangeEvent<HTMLInputElement>) =>
|
||||||
};
|
setUsername(event.target.value);
|
||||||
const registerLobbyId = (event: ChangeEvent<HTMLInputElement>) =>
|
const registerLobbyId = (event: ChangeEvent<HTMLInputElement>) =>
|
||||||
(joinLobbyPayload.lobbyId = event.target.value);
|
setLobbyId(event.target.value);
|
||||||
|
|
||||||
|
const [receivedError, setReceivedError] = useState("" as ErrorCode);
|
||||||
|
const userNameErrorCodesToMessageMap = new Map([
|
||||||
|
[ErrorCode.MISSING_USER_NAME, "Introduce your player name"],
|
||||||
|
[
|
||||||
|
ErrorCode.INVALID_USER_NAME,
|
||||||
|
"Player name must be letters or spaces only and up to 25 characters",
|
||||||
|
],
|
||||||
|
[ErrorCode.DUPLICATE_USER_NAME, "Player name is already under use"],
|
||||||
|
]);
|
||||||
|
const userNameErrorMessage =
|
||||||
|
userNameErrorCodesToMessageMap.get(receivedError);
|
||||||
|
const gameCodeErrorCodesToMessageMap = new Map([
|
||||||
|
[ErrorCode.GAME_NOT_FOUND, "No game found with such lobby ID"],
|
||||||
|
[ErrorCode.MISSING_GAME_CODE, "Introduce a game code"],
|
||||||
|
]);
|
||||||
|
const gameCodeErrorMessage =
|
||||||
|
gameCodeErrorCodesToMessageMap.get(receivedError);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
attachHandlerToCreateLobbyError(socket, (event) =>
|
||||||
|
setReceivedError(event.error),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
useEffect(() =>
|
||||||
|
attachHandlerToJoinLobbyError(socket, (event) =>
|
||||||
|
setReceivedError(event.error),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<div className="landing-page">
|
||||||
<div className="landing-page-title">
|
<div>
|
||||||
<h1>Trains And Roads</h1>
|
<h1>Trains And Roads</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="user-name-input">
|
<div className="landing-page-body">
|
||||||
<input placeholder="Enter username" onChange={registerUsername}></input>
|
<div>
|
||||||
|
<input
|
||||||
|
placeholder="Enter username"
|
||||||
|
onChange={registerUsername}
|
||||||
|
maxLength={20}
|
||||||
|
></input>
|
||||||
|
{userNameErrorMessage && (
|
||||||
|
<small id="error-message">{userNameErrorMessage}</small>
|
||||||
|
)}
|
||||||
|
<button onClick={() => handleCreateLobby(socket, createLobbyPayload)}>
|
||||||
|
Create Lobby
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
placeholder="Enter Lobby Id"
|
||||||
|
onChange={registerLobbyId}
|
||||||
|
maxLength={5}
|
||||||
|
></input>
|
||||||
|
{gameCodeErrorMessage && (
|
||||||
|
<small id="error-message">{gameCodeErrorMessage}</small>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
className="secondary"
|
||||||
|
onClick={() => handleJoinLobby(socket, joinLobbyPayload)}
|
||||||
|
>
|
||||||
|
Join Lobby
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="create-lobby-button">
|
</div>
|
||||||
<button onClick={() => handleCreateLobby(socket, createLobbyPayload)}>
|
|
||||||
Create Lobby
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="join-lobby">
|
|
||||||
<input
|
|
||||||
className="lobby-id-input"
|
|
||||||
placeholder="Enter Lobby Id"
|
|
||||||
onChange={registerLobbyId}
|
|
||||||
></input>
|
|
||||||
<button
|
|
||||||
className="join-lobby-button secondary"
|
|
||||||
onClick={() => handleJoinLobby(socket, joinLobbyPayload)}
|
|
||||||
>
|
|
||||||
Join Lobby
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default LandingPage;
|
export default LandingPage;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue