Enforce strongly typed API contract in exception filters
parent
5d55631812
commit
e2bf337b25
|
|
@ -10,7 +10,7 @@ import { PlayerService } from './players/player.service';
|
||||||
import { GameService } from 'src/games/game.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, JoinLobbyEvent } from 'interface';
|
||||||
import { WsExceptionFilter } from './websocket-exception-filter';
|
import { createWsExceptionFilter } from './websocket-exception-filter';
|
||||||
import { PlayerNotFoundException } from './exceptions';
|
import { PlayerNotFoundException } from './exceptions';
|
||||||
|
|
||||||
@WebSocketGateway({ cors: true })
|
@WebSocketGateway({ cors: true })
|
||||||
|
|
@ -26,7 +26,7 @@ export class AppService implements OnGatewayConnection {
|
||||||
this.playerService.createPlayer(client.id);
|
this.playerService.createPlayer(client.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseFilters(new WsExceptionFilter([PlayerNotFoundException]))
|
@UseFilters(createWsExceptionFilter([PlayerNotFoundException]))
|
||||||
@SubscribeMessage(ClientEvent.CREATE_LOBBY)
|
@SubscribeMessage(ClientEvent.CREATE_LOBBY)
|
||||||
handleCreateLobby(
|
handleCreateLobby(
|
||||||
@ConnectedSocket() client: Socket,
|
@ConnectedSocket() client: Socket,
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,6 @@ export class PlayerNotFoundException extends WebSocketException {
|
||||||
|
|
||||||
export class GameNotFoundException extends WebSocketException {
|
export class GameNotFoundException extends WebSocketException {
|
||||||
constructor(gameId: string) {
|
constructor(gameId: string) {
|
||||||
super(
|
super('Unable to find game from ID: ' + gameId, ErrorCode.GAME_NOT_FOUND);
|
||||||
'Unable to find game from ID: ' + gameId,
|
|
||||||
ErrorCode.GAME_NOT_FOUND,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,16 @@
|
||||||
import { ArgumentsHost, Catch, Logger } from '@nestjs/common';
|
import { ArgumentsHost, Catch, Logger } from '@nestjs/common';
|
||||||
import { BaseWsExceptionFilter } from '@nestjs/websockets';
|
import { BaseWsExceptionFilter } from '@nestjs/websockets';
|
||||||
import { GameNotFoundException, PlayerNotFoundException, WebSocketException } from './exceptions';
|
import { WebSocketException } from './exceptions';
|
||||||
import { Socket } from 'socket.io';
|
import { Socket } from 'socket.io';
|
||||||
import { ClientEvent } from 'interface';
|
import { ClientEvent } from 'interface';
|
||||||
import { emitCreateLobbyError } from 'interface';
|
import { emitCreateLobbyError } from 'interface';
|
||||||
|
|
||||||
@Catch(PlayerNotFoundException, GameNotFoundException)
|
export const createWsExceptionFilter: (
|
||||||
export class WsExceptionFilter extends BaseWsExceptionFilter<WebSocketException> {
|
exceptionList: (typeof WebSocketException)[],
|
||||||
|
) => BaseWsExceptionFilter<WebSocketException> = (handledExceptions) => {
|
||||||
|
@Catch(...handledExceptions)
|
||||||
|
class WsExceptionFilter extends BaseWsExceptionFilter<WebSocketException> {
|
||||||
private readonly logger = new Logger(BaseWsExceptionFilter.name);
|
private readonly logger = new Logger(BaseWsExceptionFilter.name);
|
||||||
private readonly caughtExceptions: (typeof WebSocketException)[];
|
|
||||||
|
|
||||||
constructor(caughtExceptions: (typeof WebSocketException)[]) {
|
|
||||||
super();
|
|
||||||
this.caughtExceptions = caughtExceptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
catch(exception: WebSocketException, host: ArgumentsHost) {
|
catch(exception: WebSocketException, host: ArgumentsHost) {
|
||||||
const socket = host.switchToWs().getClient() as Socket;
|
const socket = host.switchToWs().getClient() as Socket;
|
||||||
|
|
@ -23,18 +20,9 @@ export class WsExceptionFilter extends BaseWsExceptionFilter<WebSocketException>
|
||||||
`Caught exception: ${exception}
|
`Caught exception: ${exception}
|
||||||
for request to ${method}
|
for request to ${method}
|
||||||
from client ${socket.id}
|
from client ${socket.id}
|
||||||
with input ${data}`,
|
with input ${JSON.stringify(data)}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
|
||||||
!this.caughtExceptions.find(
|
|
||||||
(caughtException) => exception instanceof caughtException,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
this.logger.fatal("Uncaught exception", exception)
|
|
||||||
super.catch(exception, host);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case ClientEvent.CREATE_LOBBY:
|
case ClientEvent.CREATE_LOBBY:
|
||||||
emitCreateLobbyError(socket, { error: exception.errorCode });
|
emitCreateLobbyError(socket, { error: exception.errorCode });
|
||||||
|
|
@ -42,3 +30,5 @@ export class WsExceptionFilter extends BaseWsExceptionFilter<WebSocketException>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return new WsExceptionFilter();
|
||||||
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue