Compare commits
31 Commits
landing-pa
...
main
| Author | SHA1 | Date |
|---|---|---|
|
|
10949f30df | |
|
|
09bd13f772 | |
|
|
0b5684f2b9 | |
|
|
7c4a6f5603 | |
|
|
0a0ca65e3b | |
|
|
86d5137857 | |
|
|
b72a74789c | |
|
|
45cbf885a3 | |
|
|
00c365de84 | |
|
|
4f9950c6a9 | |
|
|
98e62180dc | |
|
|
3af9caff9a | |
|
|
5fc02aa6a6 | |
|
|
035b7da335 | |
|
|
b1d57ebfcd | |
|
|
1ab3db8f67 | |
|
|
e7beb85302 | |
|
|
835ce2c62a | |
|
|
39d1ec9a77 | |
|
|
406e4d2f75 | |
|
|
7354586ef5 | |
|
|
163ca86734 | |
|
|
af133bae8b | |
|
|
d72984851e | |
|
|
0945336463 | |
|
|
e9305893cb | |
|
|
4497a0a2f2 | |
|
|
ec6526deb5 | |
|
|
56705d3574 | |
|
|
250325d8d2 | |
|
|
d906cf486b |
|
|
@ -16,8 +16,7 @@
|
|||
"@nestjs/websockets": "^10.4.7",
|
||||
"interface": "file:../interface",
|
||||
"reflect-metadata": "^0.2.0",
|
||||
"rxjs": "^7.8.1",
|
||||
"uuid": "^11.0.3"
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^10.0.0",
|
||||
|
|
@ -49,7 +48,8 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"socket.io": "^4.8.1",
|
||||
"socket.io-client": "^4.8.1"
|
||||
"socket.io-client": "^4.8.1",
|
||||
"uuid": "^11.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^8.0.0",
|
||||
|
|
@ -8949,19 +8949,6 @@
|
|||
"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": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@
|
|||
"@nestjs/websockets": "^10.4.7",
|
||||
"interface": "file:../interface",
|
||||
"reflect-metadata": "^0.2.0",
|
||||
"rxjs": "^7.8.1",
|
||||
"uuid": "^11.0.3"
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^10.0.0",
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { AppService } from './app.service';
|
||||
import { PlayerService } from './players/player.service';
|
||||
import { GameService } from './games/game.service';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
providers: [AppService, PlayerService, GameService],
|
||||
providers: [AppService, PlayerService],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Injectable, Logger, UseFilters } from '@nestjs/common';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import {
|
||||
ConnectedSocket,
|
||||
OnGatewayConnection,
|
||||
|
|
@ -7,81 +7,35 @@ import {
|
|||
WebSocketGateway,
|
||||
} from '@nestjs/websockets';
|
||||
import { PlayerService } from './players/player.service';
|
||||
import { GameService } from 'src/games/game.service';
|
||||
import { Socket } from 'socket.io';
|
||||
import {
|
||||
ClientEvent,
|
||||
CreateLobbyEvent,
|
||||
emitUpdateLobbyEvent,
|
||||
JoinLobbyEvent,
|
||||
} from 'interface';
|
||||
import { createWsExceptionFilter } from './websocket-exception-filter';
|
||||
import {
|
||||
GameNotFoundException,
|
||||
InvalidPlayerNameException,
|
||||
MissingPlayerNameException,
|
||||
PlayerNotFoundException,
|
||||
} from './exceptions';
|
||||
import { ClientEvent, CreateLobbyEvent, JoinLobbyEvent } from 'interface';
|
||||
|
||||
@WebSocketGateway({ cors: true })
|
||||
@Injectable()
|
||||
export class AppService implements OnGatewayConnection {
|
||||
private readonly logger = new Logger(AppService.name);
|
||||
|
||||
constructor(
|
||||
private readonly playerService: PlayerService,
|
||||
private readonly gameService: GameService,
|
||||
) {}
|
||||
constructor(private readonly playerService: PlayerService) {}
|
||||
handleConnection(client: Socket) {
|
||||
this.playerService.createPlayer(client);
|
||||
this.playerService.createPlayer(client.id);
|
||||
this.logger.log(client.id);
|
||||
}
|
||||
|
||||
@UseFilters(
|
||||
createWsExceptionFilter([
|
||||
PlayerNotFoundException,
|
||||
MissingPlayerNameException,
|
||||
InvalidPlayerNameException,
|
||||
]),
|
||||
)
|
||||
@SubscribeMessage(ClientEvent.CREATE_LOBBY)
|
||||
handleCreateLobby(
|
||||
@ConnectedSocket() client: Socket,
|
||||
@MessageBody() event: CreateLobbyEvent,
|
||||
) {
|
||||
this.playerService.addUserName(client.id, event.userName);
|
||||
const game = this.gameService.createLobby(
|
||||
this.playerService.getPlayer(client.id),
|
||||
);
|
||||
emitUpdateLobbyEvent(client, {
|
||||
playerNames: game.players.map((player) => player.userName),
|
||||
gameCode: game.gameCode,
|
||||
});
|
||||
this.logger.log('Se ha creado un lobby');
|
||||
}
|
||||
|
||||
@UseFilters(
|
||||
createWsExceptionFilter([
|
||||
PlayerNotFoundException,
|
||||
MissingPlayerNameException,
|
||||
InvalidPlayerNameException,
|
||||
GameNotFoundException,
|
||||
]),
|
||||
)
|
||||
@SubscribeMessage(ClientEvent.JOIN_LOBBY)
|
||||
handleJoinLobby(
|
||||
@ConnectedSocket() client: Socket,
|
||||
@MessageBody() event: JoinLobbyEvent,
|
||||
) {
|
||||
this.playerService.addUserName(client.id, event.userName);
|
||||
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,
|
||||
}),
|
||||
);
|
||||
this.logger.log('Te has unido a un lobby');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
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,38 +1,19 @@
|
|||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { Player } from './player';
|
||||
import {
|
||||
InvalidPlayerNameException,
|
||||
MissingPlayerNameException,
|
||||
PlayerNotFoundException,
|
||||
} from 'src/exceptions';
|
||||
import { Socket } from 'socket.io/dist/socket';
|
||||
|
||||
@Injectable()
|
||||
export class PlayerService {
|
||||
private readonly logger = new Logger(PlayerService.name);
|
||||
private readonly players: Map<string, Player> = new Map();
|
||||
private readonly userNameValidator: RegExp = /^[a-zA-Z\s]{1,20}$/;
|
||||
|
||||
createPlayer(socket: Socket) {
|
||||
const player: Player = new Player(socket);
|
||||
this.players.set(player.socketId, player);
|
||||
createPlayer(socketId: string) {
|
||||
const player: Player = new Player(socketId);
|
||||
this.players.set(socketId, player);
|
||||
this.logger.log([...this.players.entries()]);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
getPlayer(socketId: string): Player {
|
||||
const player = this.players.get(socketId);
|
||||
if (!player) {
|
||||
throw new PlayerNotFoundException(socketId);
|
||||
}
|
||||
return player;
|
||||
this.logger.log([...this.players.entries()]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,7 @@
|
|||
import { Socket } from 'socket.io';
|
||||
|
||||
export class Player {
|
||||
socketId: string;
|
||||
socket: Socket;
|
||||
userName?: string;
|
||||
|
||||
constructor(socket: Socket) {
|
||||
this.socket = socket;
|
||||
this.socketId = socket.id;
|
||||
constructor(socketId: string) {
|
||||
this.socketId = socketId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
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,15 +4,6 @@ export * from "./constants/ExitType";
|
|||
export * from "./constants/InternalNodeType";
|
||||
export * from "./constants/Pieces";
|
||||
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/Cell";
|
||||
export * from "./types/Exit";
|
||||
|
|
@ -21,3 +12,10 @@ export * from "./types/InternalNode";
|
|||
export * from "./types/Piece";
|
||||
export * from "./types/PlacedPiece";
|
||||
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,6 +248,12 @@
|
|||
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
|
||||
"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": {
|
||||
"version": "2.8.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz",
|
||||
|
|
@ -266,21 +272,21 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz",
|
||||
"integrity": "sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w==",
|
||||
"version": "8.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.17.0.tgz",
|
||||
"integrity": "sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "8.23.0",
|
||||
"@typescript-eslint/type-utils": "8.23.0",
|
||||
"@typescript-eslint/utils": "8.23.0",
|
||||
"@typescript-eslint/visitor-keys": "8.23.0",
|
||||
"@typescript-eslint/scope-manager": "8.17.0",
|
||||
"@typescript-eslint/type-utils": "8.17.0",
|
||||
"@typescript-eslint/utils": "8.17.0",
|
||||
"@typescript-eslint/visitor-keys": "8.17.0",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.3.1",
|
||||
"natural-compare": "^1.4.0",
|
||||
"ts-api-utils": "^2.0.1"
|
||||
"ts-api-utils": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
|
|
@ -291,21 +297,25 @@
|
|||
},
|
||||
"peerDependencies": {
|
||||
"@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
|
||||
"eslint": "^8.57.0 || ^9.0.0",
|
||||
"typescript": ">=4.8.4 <5.8.0"
|
||||
"eslint": "^8.57.0 || ^9.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "8.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz",
|
||||
"integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==",
|
||||
"version": "8.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.17.0.tgz",
|
||||
"integrity": "sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.23.0",
|
||||
"@typescript-eslint/types": "8.23.0",
|
||||
"@typescript-eslint/typescript-estree": "8.23.0",
|
||||
"@typescript-eslint/visitor-keys": "8.23.0",
|
||||
"@typescript-eslint/scope-manager": "8.17.0",
|
||||
"@typescript-eslint/types": "8.17.0",
|
||||
"@typescript-eslint/typescript-estree": "8.17.0",
|
||||
"@typescript-eslint/visitor-keys": "8.17.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
|
|
@ -316,19 +326,23 @@
|
|||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.57.0 || ^9.0.0",
|
||||
"typescript": ">=4.8.4 <5.8.0"
|
||||
"eslint": "^8.57.0 || ^9.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.23.0.tgz",
|
||||
"integrity": "sha512-OGqo7+dXHqI7Hfm+WqkZjKjsiRtFUQHPdGMXzk5mYXhJUedO7e/Y7i8AK3MyLMgZR93TX4bIzYrfyVjLC+0VSw==",
|
||||
"version": "8.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.17.0.tgz",
|
||||
"integrity": "sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.23.0",
|
||||
"@typescript-eslint/visitor-keys": "8.23.0"
|
||||
"@typescript-eslint/types": "8.17.0",
|
||||
"@typescript-eslint/visitor-keys": "8.17.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
|
|
@ -339,16 +353,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "8.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.23.0.tgz",
|
||||
"integrity": "sha512-iIuLdYpQWZKbiH+RkCGc6iu+VwscP5rCtQ1lyQ7TYuKLrcZoeJVpcLiG8DliXVkUxirW/PWlmS+d6yD51L9jvA==",
|
||||
"version": "8.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.17.0.tgz",
|
||||
"integrity": "sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "8.23.0",
|
||||
"@typescript-eslint/utils": "8.23.0",
|
||||
"@typescript-eslint/typescript-estree": "8.17.0",
|
||||
"@typescript-eslint/utils": "8.17.0",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^2.0.1"
|
||||
"ts-api-utils": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
|
|
@ -358,14 +372,18 @@
|
|||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.57.0 || ^9.0.0",
|
||||
"typescript": ">=4.8.4 <5.8.0"
|
||||
"eslint": "^8.57.0 || ^9.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "8.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.23.0.tgz",
|
||||
"integrity": "sha512-1sK4ILJbCmZOTt9k4vkoulT6/y5CHJ1qUYxqpF1K/DBAd8+ZUL4LlSCxOssuH5m4rUaaN0uS0HlVPvd45zjduQ==",
|
||||
"version": "8.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.17.0.tgz",
|
||||
"integrity": "sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
|
@ -377,20 +395,20 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "8.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.23.0.tgz",
|
||||
"integrity": "sha512-LcqzfipsB8RTvH8FX24W4UUFk1bl+0yTOf9ZA08XngFwMg4Kj8A+9hwz8Cr/ZS4KwHrmo9PJiLZkOt49vPnuvQ==",
|
||||
"version": "8.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.17.0.tgz",
|
||||
"integrity": "sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.23.0",
|
||||
"@typescript-eslint/visitor-keys": "8.23.0",
|
||||
"@typescript-eslint/types": "8.17.0",
|
||||
"@typescript-eslint/visitor-keys": "8.17.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": "^2.0.1"
|
||||
"ts-api-utils": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
|
|
@ -399,21 +417,23 @@
|
|||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=4.8.4 <5.8.0"
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "8.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.23.0.tgz",
|
||||
"integrity": "sha512-uB/+PSo6Exu02b5ZEiVtmY6RVYO7YU5xqgzTIVZwTHvvK3HsL8tZZHFaTLFtRG3CsV4A5mhOv+NZx5BlhXPyIA==",
|
||||
"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.23.0",
|
||||
"@typescript-eslint/types": "8.23.0",
|
||||
"@typescript-eslint/typescript-estree": "8.23.0"
|
||||
"@typescript-eslint/scope-manager": "8.17.0",
|
||||
"@typescript-eslint/types": "8.17.0",
|
||||
"@typescript-eslint/typescript-estree": "8.17.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
|
|
@ -423,18 +443,22 @@
|
|||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.57.0 || ^9.0.0",
|
||||
"typescript": ">=4.8.4 <5.8.0"
|
||||
"eslint": "^8.57.0 || ^9.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"version": "8.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.17.0.tgz",
|
||||
"integrity": "sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.23.0",
|
||||
"@typescript-eslint/types": "8.17.0",
|
||||
"eslint-visitor-keys": "^4.2.0"
|
||||
},
|
||||
"engines": {
|
||||
|
|
@ -719,11 +743,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/engine.io": {
|
||||
"version": "6.6.4",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz",
|
||||
"integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==",
|
||||
"version": "6.6.2",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz",
|
||||
"integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/cookie": "^0.4.1",
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/node": ">=10.0.0",
|
||||
"accepts": "~1.3.4",
|
||||
|
|
@ -739,9 +764,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/engine.io-client": {
|
||||
"version": "6.6.3",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
|
||||
"integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
|
||||
"version": "6.6.2",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.2.tgz",
|
||||
"integrity": "sha512-TAr+NKeoVTjEVW8P3iHguO1LO6RlUz9O5Y8o7EY0fU+gY1NYqas7NN3slpFtbXEsLMHk0h90fJMfKjRkQ0qUIw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
|
|
@ -1023,9 +1048,9 @@
|
|||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
||||
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
|
||||
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
|
@ -1033,7 +1058,7 @@
|
|||
"@nodelib/fs.walk": "^1.2.3",
|
||||
"glob-parent": "^5.1.2",
|
||||
"merge2": "^1.3.0",
|
||||
"micromatch": "^4.0.8"
|
||||
"micromatch": "^4.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.6.0"
|
||||
|
|
@ -1208,9 +1233,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/globals": {
|
||||
"version": "15.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz",
|
||||
"integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==",
|
||||
"version": "15.13.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-15.13.0.tgz",
|
||||
"integrity": "sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
|
@ -1643,9 +1668,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
|
||||
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
|
||||
"version": "3.4.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
|
||||
"integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
|
|
@ -1766,9 +1791,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
|
|
@ -1934,16 +1959,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ts-api-utils": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz",
|
||||
"integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==",
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
|
||||
"integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.12"
|
||||
"node": ">=16"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=4.8.4"
|
||||
"typescript": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
|
|
@ -1993,15 +2018,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/typescript-eslint": {
|
||||
"version": "8.23.0",
|
||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.23.0.tgz",
|
||||
"integrity": "sha512-/LBRo3HrXr5LxmrdYSOCvoAMm7p2jNizNfbIpCgvG4HMsnoprRUOce/+8VJ9BDYWW68rqIENE/haVLWPeFZBVQ==",
|
||||
"version": "8.15.0",
|
||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.15.0.tgz",
|
||||
"integrity": "sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "8.23.0",
|
||||
"@typescript-eslint/parser": "8.23.0",
|
||||
"@typescript-eslint/utils": "8.23.0"
|
||||
"@typescript-eslint/eslint-plugin": "8.15.0",
|
||||
"@typescript-eslint/parser": "8.15.0",
|
||||
"@typescript-eslint/utils": "8.15.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
|
|
@ -2011,8 +2036,223 @@
|
|||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.57.0 || ^9.0.0",
|
||||
"typescript": ">=4.8.4 <5.8.0"
|
||||
"eslint": "^8.57.0 || ^9.0.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": {
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@
|
|||
"typescript-eslint": "^8.15.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"uuid": "^11.0.3",
|
||||
"socket.io": "^4.8.1",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"uuid": "^11.0.3"
|
||||
"socket.io-client": "^4.8.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
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);
|
||||
};
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
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,12 +2,3 @@ export enum ServerError {
|
|||
CREATE_LOBBY_ERROR = "create-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,7 +39,8 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"socket.io": "^4.8.1",
|
||||
"socket.io-client": "^4.8.1"
|
||||
"socket.io-client": "^4.8.1",
|
||||
"uuid": "^11.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^8.0.0",
|
||||
|
|
|
|||
|
|
@ -1,9 +1,3 @@
|
|||
@use "node_modules/@picocss/pico/scss/pico" with (
|
||||
$theme-color: "pumpkin"
|
||||
);
|
||||
|
||||
#root, #app {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import React, { useCallback, useState } from "react";
|
|||
import { Socket } from "socket.io-client";
|
||||
import LandingPage from "./pages/landing/LandingPage";
|
||||
import GamePage from "./pages/game/GamePage";
|
||||
import "./App.scss";
|
||||
import LobbyPage from "./pages/lobby/LobbyPage";
|
||||
import {
|
||||
attachHandlerToStartRoundEvent,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ const root = ReactDOM.createRoot(
|
|||
document.getElementById("root") as HTMLElement,
|
||||
);
|
||||
const socket = io("http://localhost:3010");
|
||||
socket.on("exception", console.log);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App socket={socket} />
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
.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,15 +1,11 @@
|
|||
import {
|
||||
attachHandlerToCreateLobbyError,
|
||||
attachHandlerToJoinLobbyError,
|
||||
CreateLobbyEvent,
|
||||
ErrorCode,
|
||||
handleCreateLobby,
|
||||
handleJoinLobby,
|
||||
JoinLobbyEvent,
|
||||
} from "interface";
|
||||
import { ChangeEvent, useEffect, useState } from "react";
|
||||
import React, { ChangeEvent } from "react";
|
||||
import { Socket } from "socket.io-client";
|
||||
import "./LandingPage.scss";
|
||||
|
||||
export interface LandingPageProps {
|
||||
socket: Socket;
|
||||
|
|
@ -18,81 +14,42 @@ export interface LandingPageProps {
|
|||
const LandingPage = (props: LandingPageProps) => {
|
||||
const { socket } = props;
|
||||
|
||||
const [userName, setUsername] = useState("");
|
||||
const [lobbyId, setLobbyId] = useState("");
|
||||
const createLobbyPayload: CreateLobbyEvent = { userName };
|
||||
const joinLobbyPayload: JoinLobbyEvent = { userName, lobbyId };
|
||||
const registerUsername = (event: ChangeEvent<HTMLInputElement>) =>
|
||||
setUsername(event.target.value);
|
||||
const createLobbyPayload: CreateLobbyEvent = { userName: "" };
|
||||
const joinLobbyPayload: JoinLobbyEvent = { userName: "", lobbyId: "" };
|
||||
const registerUsername = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
createLobbyPayload.userName = event.target.value;
|
||||
joinLobbyPayload.userName = event.target.value;
|
||||
};
|
||||
const registerLobbyId = (event: ChangeEvent<HTMLInputElement>) =>
|
||||
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),
|
||||
),
|
||||
);
|
||||
(joinLobbyPayload.lobbyId = event.target.value);
|
||||
|
||||
return (
|
||||
<div className="landing-page">
|
||||
<div>
|
||||
<React.Fragment>
|
||||
<div className="landing-page-title">
|
||||
<h1>Trains And Roads</h1>
|
||||
</div>
|
||||
<div className="landing-page-body">
|
||||
<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 className="user-name-input">
|
||||
<input placeholder="Enter username" onChange={registerUsername}></input>
|
||||
</div>
|
||||
</div>
|
||||
<div className="create-lobby-button">
|
||||
<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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue