Enable @total-typescript/ts-reset (#1761)

## Description:

Enable `@total-typescript/ts-reset`

Fixes #1760

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [ ] I have read and accepted the CLA agreement (only required once).
This commit is contained in:
Scott Anderson
2025-08-09 02:13:56 -04:00
committed by GitHub
parent 2b0701c132
commit 7e25f6b910
31 changed files with 248 additions and 76 deletions
+1 -1
View File
@@ -229,7 +229,7 @@ export class ClientGameRunner {
players,
// Not saving turns locally
[],
startTime(),
startTime() ?? 0,
Date.now(),
update.winner,
this.lobby.serverConfig,
+14 -2
View File
@@ -1,4 +1,8 @@
import { UserMeResponse } from "../core/ApiSchemas";
import { z } from "zod";
import {
StripeCreateCheckoutSessionResponseSchema,
UserMeResponse,
} from "../core/ApiSchemas";
import { Cosmetics, CosmeticsSchema, Pattern } from "../core/CosmeticSchemas";
import { getApiBase, getAuthHeader } from "./jwt";
@@ -59,7 +63,15 @@ export async function handlePurchase(priceId: string) {
return;
}
const { url } = await response.json();
const json = await response.json();
const parsed = StripeCreateCheckoutSessionResponseSchema.safeParse(json);
if (!parsed.success) {
const error = z.prettifyError(parsed.error);
console.error("Invalid checkout session response:", error);
alert("Checkout failed. Please try again later.");
return;
}
const { url } = parsed.data;
// Redirect to Stripe checkout
window.location.href = url;
+1 -1
View File
@@ -159,7 +159,7 @@ export class InputHandler {
groundAttack: "KeyG",
modifierKey: "ControlLeft",
altKey: "AltLeft",
...JSON.parse(localStorage.getItem("settings.keybinds") ?? "{}"),
...(JSON.parse(localStorage.getItem("settings.keybinds") ?? "{}") ?? {}),
};
// Mac users might have different keybinds
+10 -6
View File
@@ -1,8 +1,12 @@
import { LitElement, html } from "lit";
import { customElement, query, state } from "lit/decorators.js";
import { translateText } from "../client/Utils";
import { GameInfo, GameRecord } from "../core/Schemas";
import { GameInfo } from "../core/Schemas";
import { generateID } from "../core/Util";
import {
WorkerApiArchivedGameLobbySchema,
WorkerApiGameIdExistsSchema,
} from "../core/WorkerSchemas";
import { getServerConfigFromClient } from "../core/configuration/ConfigLoader";
import { JoinLobbyEvent } from "./Main";
import "./components/baseComponents/Button";
@@ -198,7 +202,8 @@ export class JoinPrivateLobbyModal extends LitElement {
headers: { "Content-Type": "application/json" },
});
const gameInfo = await response.json();
const json = await response.json();
const gameInfo = WorkerApiGameIdExistsSchema.parse(json);
if (gameInfo.exists) {
this.message = translateText("private_lobby.joined_waiting");
@@ -231,7 +236,8 @@ export class JoinPrivateLobbyModal extends LitElement {
headers: { "Content-Type": "application/json" },
});
const archiveData = await archiveResponse.json();
const json = await archiveResponse.json();
const archiveData = WorkerApiArchivedGameLobbySchema.parse(json);
if (
archiveData.success === false &&
@@ -247,13 +253,11 @@ export class JoinPrivateLobbyModal extends LitElement {
}
if (archiveData.exists) {
const gameRecord = archiveData.gameRecord as GameRecord;
this.dispatchEvent(
new CustomEvent("join-lobby", {
detail: {
gameID: lobbyId,
gameRecord: gameRecord,
gameRecord: archiveData.gameRecord,
clientID: generateID(),
} as JoinLobbyEvent,
bubbles: true,
+25 -10
View File
@@ -1,19 +1,34 @@
import { GameConfig, GameID, GameRecord } from "../core/Schemas";
import { z } from "zod";
import {
GameConfig,
GameConfigSchema,
GameID,
GameRecord,
GameRecordSchema,
ID,
} from "../core/Schemas";
import { replacer } from "../core/Util";
export interface LocalStatsData {
[key: GameID]: {
lobby: Partial<GameConfig>;
const LocalStatsDataSchema = z.record(
ID,
z.object({
lobby: GameConfigSchema.partial(),
// Only once the game is over
gameRecord?: GameRecord;
};
}
gameRecord: GameRecordSchema.optional(),
}),
);
type LocalStatsData = z.infer<typeof LocalStatsDataSchema>;
let _startTime: number;
let _startTime: number | undefined;
function getStats(): LocalStatsData {
const statsStr = localStorage.getItem("game-records");
return statsStr ? JSON.parse(statsStr) : {};
try {
return LocalStatsDataSchema.parse(
JSON.parse(localStorage.getItem("game-records") ?? "{}"),
);
} catch (e) {
return {};
}
}
function save(stats: LocalStatsData) {
+9 -2
View File
@@ -1,3 +1,10 @@
import { z } from "zod";
const LockSchema = z.object({
owner: z.string(),
timestamp: z.number(),
});
export class MultiTabDetector {
private readonly tabId = `${Date.now()}-${Math.random()}`;
private readonly lockKey = "multi-tab-lock";
@@ -60,7 +67,7 @@ export class MultiTabDetector {
if (e.key === this.lockKey && e.newValue) {
let other: { owner: string; timestamp: number };
try {
other = JSON.parse(e.newValue);
other = LockSchema.parse(JSON.parse(e.newValue));
} catch (e) {
console.error("Failed to parse lock", e);
return;
@@ -99,7 +106,7 @@ export class MultiTabDetector {
const raw = localStorage.getItem(this.lockKey);
if (!raw) return null;
try {
return JSON.parse(raw);
return LockSchema.parse(JSON.parse(raw));
} catch (e) {
console.error("Failed to parse lock", raw, e);
return null;
+3 -1
View File
@@ -1,6 +1,7 @@
import { LitElement, html } from "lit";
import { customElement, state } from "lit/decorators.js";
import { translateText } from "../client/Utils";
import { ApiPublicLobbiesResponseSchema } from "../core/ExpressSchemas";
import { GameMapType, GameMode } from "../core/game/Game";
import { GameID, GameInfo } from "../core/Schemas";
import { generateID } from "../core/Util";
@@ -77,7 +78,8 @@ export class PublicLobby extends LitElement {
const response = await fetch(`/api/public_lobbies`);
if (!response.ok)
throw new Error(`HTTP error! status: ${response.status}`);
const data = await response.json();
const json = await response.json();
const data = ApiPublicLobbiesResponseSchema.parse(json);
return data.lobbies;
} catch (error) {
console.error("Error fetching lobbies:", error);
+4 -1
View File
@@ -1,5 +1,6 @@
import { LitElement, html } from "lit";
import { customElement, query, state } from "lit/decorators.js";
import { z } from "zod";
import { translateText } from "../client/Utils";
import { UserSettings } from "../core/game/UserSettings";
import "./components/baseComponents/setting/SettingKeybind";
@@ -8,6 +9,8 @@ import "./components/baseComponents/setting/SettingNumber";
import "./components/baseComponents/setting/SettingSlider";
import "./components/baseComponents/setting/SettingToggle";
const KeybindSchema = z.record(z.string(), z.string());
@customElement("user-setting")
export class UserSettingModal extends LitElement {
private userSettings: UserSettings = new UserSettings();
@@ -25,7 +28,7 @@ export class UserSettingModal extends LitElement {
const savedKeybinds = localStorage.getItem("settings.keybinds");
if (savedKeybinds) {
try {
this.keybinds = JSON.parse(savedKeybinds);
this.keybinds = KeybindSchema.parse(JSON.parse(savedKeybinds));
} catch (e) {
console.warn("Invalid keybinds JSON:", e);
}