CI / Server unit tests (push) Successful in 26s
CI / Generate TypeScript types (push) Successful in 10s
CI / Build server (push) Successful in 28s
CI / Build client (push) Successful in 41s
CI / Playwright E2E tests (push) Successful in 2m24s
CI / Build and push Docker image (push) Successful in 44s
CI / Notify (push) Successful in 2s
63 lines
2.1 KiB
TypeScript
63 lines
2.1 KiB
TypeScript
import { Socket } from "socket.io";
|
|
import { getLogin } from "./auth";
|
|
|
|
/** Pomůcky pro websocketové minihry (kreslení). Ostatní minihry jsou v samostatné aplikaci Lobby. */
|
|
|
|
/** Chyba určená hráči — posílá se zpět klientovi, nic se neloguje. */
|
|
export class GameError extends Error { }
|
|
|
|
/** Hodiny a náhoda vyčleněné kvůli testům. */
|
|
export type Clock = {
|
|
now: () => number,
|
|
setTimeout: (fn: () => void, ms: number) => unknown,
|
|
clearTimeout: (handle: unknown) => void,
|
|
random: () => number,
|
|
};
|
|
|
|
export const defaultClock: Clock = {
|
|
now: () => Date.now(),
|
|
setTimeout: (fn, ms) => setTimeout(fn, ms),
|
|
clearTimeout: handle => clearTimeout(handle as NodeJS.Timeout),
|
|
random: () => Math.random(),
|
|
};
|
|
|
|
/** Ověří token z eventu a vrátí login, jinak vyhodí chybu. */
|
|
export function loginFromPayload(payload: unknown): string {
|
|
const token = (payload as { token?: unknown } | undefined)?.token;
|
|
if (typeof token !== 'string') {
|
|
throw new GameError('Chybí přihlášení.');
|
|
}
|
|
try {
|
|
const login = getLogin(token);
|
|
if (!login) throw new Error();
|
|
return login;
|
|
} catch {
|
|
throw new GameError('Neplatné přihlášení.');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Vytvoří handler websocket eventu, který ověří přihlášení a herní chyby
|
|
* pošle zpět jen danému klientovi jako `errorEvent`.
|
|
*/
|
|
export function gameHandler(socket: Socket, errorEvent: string, action: (login: string, payload: unknown) => void | Promise<void>) {
|
|
const onError = (e: unknown) => {
|
|
if (e instanceof GameError) {
|
|
socket.emit(errorEvent, e.message);
|
|
} else {
|
|
console.error(`Chyba minihry (${errorEvent})`, e);
|
|
}
|
|
};
|
|
return (payload: unknown) => {
|
|
try {
|
|
const result = action(loginFromPayload(payload), payload);
|
|
if (result instanceof Promise) result.catch(onError);
|
|
} catch (e) {
|
|
onError(e);
|
|
}
|
|
};
|
|
}
|
|
|
|
/** Minimální počet hráčů — lokálně lze hrát i sám. */
|
|
export const minPlayersForEnv = (prod: number) => process.env.NODE_ENV === 'development' ? 1 : prod;
|