From 5eb761ddf4ae952f2281423e5ed02c648c791456 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 15:35:04 +0000 Subject: [PATCH 1/3] fix(deps): update dependency type-fest to v5.5.0 --- package.json | 2 +- pnpm-lock.yaml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 05c22f19..749ab439 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "steamapi": "3.1.5", "steamid": "2.1.0", "tailwindcss": "4.2.2", - "type-fest": "5.4.4", + "type-fest": "5.5.0", "umzug": "3.8.2", "ws": "8.19.0", "zod": "4.3.6" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 06292e54..c66c4c17 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -240,8 +240,8 @@ importers: specifier: 4.2.2 version: 4.2.2 type-fest: - specifier: 5.4.4 - version: 5.4.4 + specifier: 5.5.0 + version: 5.5.0 umzug: specifier: 3.8.2 version: 3.8.2(@types/node@24.12.0) @@ -260,7 +260,7 @@ importers: version: 1.58.2 '@release-it/conventional-changelog': specifier: 10.0.6 - version: 10.0.6(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.3.0)(release-it@19.2.4(@types/node@24.12.0)) + version: 10.0.6(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1)(release-it@19.2.4(@types/node@24.12.0)) '@tsconfig/strictest': specifier: 2.0.8 version: 2.0.8 @@ -4896,8 +4896,8 @@ packages: resolution: {integrity: sha512-G6zXWS1dLj6eagy6sVhOMQiLtJdxQBHIA9Z6HFUNLOlr6MFOgzV8wvmidtPONfPtEUv0uZsy77XJNzTAfwPDaA==} engines: {node: '>=16'} - type-fest@5.4.4: - resolution: {integrity: sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==} + type-fest@5.5.0: + resolution: {integrity: sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==} engines: {node: '>=20'} type-is@2.0.1: @@ -6643,9 +6643,9 @@ snapshots: '@protobufjs/utf8@1.1.0': {} - '@release-it/conventional-changelog@10.0.6(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.3.0)(release-it@19.2.4(@types/node@24.12.0))': + '@release-it/conventional-changelog@10.0.6(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1)(release-it@19.2.4(@types/node@24.12.0))': dependencies: - '@conventional-changelog/git-client': 2.6.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.3.0) + '@conventional-changelog/git-client': 2.6.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1) concat-stream: 2.0.0 conventional-changelog: 7.2.0(conventional-commits-filter@5.0.0) conventional-changelog-angular: 8.3.0 @@ -9864,7 +9864,7 @@ snapshots: type-fest@4.30.0: {} - type-fest@5.4.4: + type-fest@5.5.0: dependencies: tagged-tag: 1.0.0 From f9dd3c45ecd97188557f741171e2291a5d8b337e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Garapich?= Date: Fri, 20 Mar 2026 16:57:41 +0100 Subject: [PATCH 2/3] fix(games): resolve TS2590 union type error after type-fest 5.5.0 upgrade Extract actor to a local variable and add explicit field pluck to findOne to avoid the overly complex union type that type-fest 5.5.0 introduced in GamePage. Co-Authored-By: Claude Sonnet 4.6 --- src/games/views/html/game.page.tsx | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/games/views/html/game.page.tsx b/src/games/views/html/game.page.tsx index 3279579a..02914a0f 100644 --- a/src/games/views/html/game.page.tsx +++ b/src/games/views/html/game.page.tsx @@ -16,7 +16,20 @@ import { requestContext } from '@fastify/request-context' export async function GamePage(props: { number: GameNumber }) { const user = requestContext.get('user') - const game = await findOne({ number: props.number }) + const game = await findOne({ number: props.number }, [ + 'number', + 'map', + 'state', + 'slots', + 'events', + 'gameServer', + 'logsUrl', + 'demoUrl', + 'score', + 'connectString', + 'stvConnectString', + ]) + const actor = user?.player.steamId return (
- - + + {user?.player.roles.includes(PlayerRole.admin) && } From 6c0bfcf5dd33a7f72e1ee0aed097d39fdeb866d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Garapich?= Date: Fri, 20 Mar 2026 17:26:49 +0100 Subject: [PATCH 3/3] refactor(games): narrow gameToDto input type and add field projections Use PickDeep to constrain the gameToDto parameter to only the fields it reads, and add matching pluck/projection arguments to all findOne/find call sites to avoid fetching unused fields. Also fixes a TS2590 union-too-complex build error in the game server assignment route. Co-Authored-By: Claude Sonnet 4.6 --- src/games/views/json/game-to-dto.ts | 16 +++++++++++++++- src/routes/api/v1/games/:id/events/index.ts | 2 +- src/routes/api/v1/games/:id/index.ts | 12 +++++++++++- src/routes/api/v1/games/index.ts | 14 +++++++++++++- .../api/v1/players/:steamId/games/index.ts | 14 +++++++++++++- src/routes/games/:number/index.tsx | 15 ++++++++++++++- 6 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/games/views/json/game-to-dto.ts b/src/games/views/json/game-to-dto.ts index 6829c647..66986175 100644 --- a/src/games/views/json/game-to-dto.ts +++ b/src/games/views/json/game-to-dto.ts @@ -1,7 +1,21 @@ import { GameEventType } from '../../../database/models/game-event.model' import type { GameModel } from '../../../database/models/game.model' +import type { PickDeep } from 'type-fest' -export function gameToDto(game: GameModel) { +type Game = PickDeep< + GameModel, + | 'number' + | 'map' + | 'state' + | 'score' + | 'logsUrl' + | 'demoUrl' + | 'events' + | 'gameServer.name' + | 'gameServer.provider' +> + +export function gameToDto(game: Game) { const endedEvent = game.events.find(e => e.event === GameEventType.gameEnded) return { diff --git a/src/routes/api/v1/games/:id/events/index.ts b/src/routes/api/v1/games/:id/events/index.ts index 643f5a50..20a269ec 100644 --- a/src/routes/api/v1/games/:id/events/index.ts +++ b/src/routes/api/v1/games/:id/events/index.ts @@ -14,7 +14,7 @@ export default routes(async app => { }, }, async (request, reply) => { - const game = await games.findOne({ number: request.params.id }) + const game = await games.findOne({ number: request.params.id }, ['number', 'events']) const events = game.events.map(gameEventToPublicDto).filter(isNotNil) return reply diff --git a/src/routes/api/v1/games/:id/index.ts b/src/routes/api/v1/games/:id/index.ts index fcc7c970..4d162b70 100644 --- a/src/routes/api/v1/games/:id/index.ts +++ b/src/routes/api/v1/games/:id/index.ts @@ -13,7 +13,17 @@ export default routes(async app => { }, }, async (request, reply) => { - const game = await games.findOne({ number: request.params.id }) + const game = await games.findOne({ number: request.params.id }, [ + 'number', + 'map', + 'state', + 'score', + 'logsUrl', + 'demoUrl', + 'events', + 'gameServer.name', + 'gameServer.provider', + ]) return reply.type('application/hal+json').status(200).send(gameToDto(game)) }, ) diff --git a/src/routes/api/v1/games/index.ts b/src/routes/api/v1/games/index.ts index 3c5fb05e..cf717e64 100644 --- a/src/routes/api/v1/games/index.ts +++ b/src/routes/api/v1/games/index.ts @@ -17,7 +17,19 @@ export default routes(async app => { const filter = state ? { state } : {} const total = await collections.games.countDocuments(filter) const gamesList = await collections.games - .find(filter) + .find(filter, { + projection: { + number: 1, + map: 1, + state: 1, + score: 1, + logsUrl: 1, + demoUrl: 1, + events: 1, + 'gameServer.name': 1, + 'gameServer.provider': 1, + }, + }) .sort({ number: -1 }) .skip(offset) .limit(limit) diff --git a/src/routes/api/v1/players/:steamId/games/index.ts b/src/routes/api/v1/players/:steamId/games/index.ts index 8da59ce2..cb4f8c02 100644 --- a/src/routes/api/v1/players/:steamId/games/index.ts +++ b/src/routes/api/v1/players/:steamId/games/index.ts @@ -35,7 +35,19 @@ export default routes(async app => { const filter = { 'slots.player': steamId } const total = await collections.games.countDocuments(filter) const gamesList = await collections.games - .find(filter) + .find(filter, { + projection: { + number: 1, + map: 1, + state: 1, + score: 1, + logsUrl: 1, + demoUrl: 1, + events: 1, + 'gameServer.name': 1, + 'gameServer.provider': 1, + }, + }) .sort({ number: -1 }) .skip(offset) .limit(limit) diff --git a/src/routes/games/:number/index.tsx b/src/routes/games/:number/index.tsx index 77df5fed..663e4c5a 100644 --- a/src/routes/games/:number/index.tsx +++ b/src/routes/games/:number/index.tsx @@ -127,7 +127,20 @@ export default routes(async app => { async (request, reply) => { const { number } = request.params const { gameServer } = request.body - const game = await games.findOne({ number }) + const game = await games.findOne({ number }, [ + 'number', + 'map', + 'state', + 'slots', + 'events', + 'gameServer', + 'logsUrl', + 'demoUrl', + 'score', + 'logSecret', + 'connectString', + 'stvConnectString', + ]) await gameServers.assign(game, gameServer, request.user!.player.steamId) await reply .trigger({ close: { target: '#choose-game-server-dialog' } })