diff --git a/CLAUDE.md b/CLAUDE.md index 5d2b5248e2ff..4bb483a53281 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,8 @@ Be extremely concise. Sacrifice grammar for concision. Frontend is partially migrated from vanilla JS to SolidJS — new components use `.tsx`, legacy code remains vanilla. Single test file: `pnpm vitest run path/to/test.ts` +When running oxc lint, always use `--format agent`. +For typechecking, use `oxc --type-aware --type-check` instead of `tsc`. For styling, use Tailwind CSS, class property, `cn` utility. Do not use classlist. Only colors available are those defined in Tailwind config. In legacy code, use `i` tags with FontAwesome classes. In new code, use `Fa` component. In plan mode, before writing up a plan, ask clarifying questions if needed. At the end of plan mode, give me a list of unresolved questions to answer, if any. Make them concise. \ No newline at end of file diff --git a/backend/__tests__/__integration__/dal/blocklist.spec.ts b/backend/__tests__/__integration__/dal/blocklist.spec.ts index 1253d7aa0098..b861d03c8ef8 100644 --- a/backend/__tests__/__integration__/dal/blocklist.spec.ts +++ b/backend/__tests__/__integration__/dal/blocklist.spec.ts @@ -26,7 +26,7 @@ describe("BlocklistDal", () => { const now = 1715082588; vi.setSystemTime(now); - const name = "user" + new ObjectId().toHexString(); + const name = `user${new ObjectId().toHexString()}`; const email = `${name}@example.com`; //WHEN @@ -56,7 +56,7 @@ describe("BlocklistDal", () => { const now = 1715082588; vi.setSystemTime(now); - const name = "user" + new ObjectId().toHexString(); + const name = `user${new ObjectId().toHexString()}`; const email = `${name}@example.com`; const discordId = `${name}DiscordId`; @@ -78,7 +78,7 @@ describe("BlocklistDal", () => { const now = 1715082588; vi.setSystemTime(now); - const name = "user" + new ObjectId().toHexString(); + const name = `user${new ObjectId().toHexString()}`; const email = `${name}@example.com`; const email2 = `${name}@otherdomain.com`; await BlacklistDal.add({ name, email }); @@ -114,9 +114,9 @@ describe("BlocklistDal", () => { const now = 1715082588; vi.setSystemTime(now); - const name = "user" + new ObjectId().toHexString(); + const name = `user${new ObjectId().toHexString()}`; const email = `${name}@example.com`; - const name2 = "user" + new ObjectId().toHexString(); + const name2 = `user${new ObjectId().toHexString()}`; await BlacklistDal.add({ name, email }); //WHEN @@ -136,8 +136,8 @@ describe("BlocklistDal", () => { const now = 1715082588; vi.setSystemTime(now); - const name = "user" + new ObjectId().toHexString(); - const name2 = "user" + new ObjectId().toHexString(); + const name = `user${new ObjectId().toHexString()}`; + const name2 = `user${new ObjectId().toHexString()}`; const email = `${name}@example.com`; const discordId = `${name}DiscordId`; @@ -160,7 +160,7 @@ describe("BlocklistDal", () => { describe("contains", () => { it("contains user", async () => { //GIVEN - const name = "user" + new ObjectId().toHexString(); + const name = `user${new ObjectId().toHexString()}`; const email = `${name}@example.com`; const discordId = `${name}DiscordId`; await BlacklistDal.add({ name, email, discordId }); @@ -229,7 +229,7 @@ describe("BlocklistDal", () => { describe("remove", () => { it("removes existing username", async () => { //GIVEN - const name = "user" + new ObjectId().toHexString(); + const name = `user${new ObjectId().toHexString()}`; const email = `${name}@example.com`; await BlacklistDal.add({ name, email }); await BlacklistDal.add({ name: "test", email: "test@example.com" }); @@ -251,7 +251,7 @@ describe("BlocklistDal", () => { }); it("removes existing email", async () => { //GIVEN - const name = "user" + new ObjectId().toHexString(); + const name = `user${new ObjectId().toHexString()}`; const email = `${name}@example.com`; await BlacklistDal.add({ name, email }); await BlacklistDal.add({ name: "test", email: "test@example.com" }); @@ -273,7 +273,7 @@ describe("BlocklistDal", () => { }); it("removes existing discordId", async () => { //GIVEN - const name = "user" + new ObjectId().toHexString(); + const name = `user${new ObjectId().toHexString()}`; const email = `${name}@example.com`; const discordId = `${name}DiscordId`; await BlacklistDal.add({ name, email, discordId }); @@ -304,7 +304,7 @@ describe("BlocklistDal", () => { }); it("removes existing username,email and discordId", async () => { //GIVEN - const name = "user" + new ObjectId().toHexString(); + const name = `user${new ObjectId().toHexString()}`; const email = `${name}@example.com`; const discordId = `${name}DiscordId`; await BlacklistDal.add({ name, email, discordId }); @@ -336,7 +336,7 @@ describe("BlocklistDal", () => { it("does not remove for empty user", async () => { //GIVEN - const name = "user" + new ObjectId().toHexString(); + const name = `user${new ObjectId().toHexString()}`; const email = `${name}@example.com`; const discordId = `${name}DiscordId`; await BlacklistDal.add({ name, email, discordId }); diff --git a/backend/__tests__/__integration__/dal/leaderboards.isolated.spec.ts b/backend/__tests__/__integration__/dal/leaderboards.isolated.spec.ts index 9baeb166033f..17847fe0b345 100644 --- a/backend/__tests__/__integration__/dal/leaderboards.isolated.spec.ts +++ b/backend/__tests__/__integration__/dal/leaderboards.isolated.spec.ts @@ -496,7 +496,7 @@ async function createUser( userProperties?: Partial, ): Promise { const uid = new ObjectId().toHexString(); - await UserDal.addUser("User " + uid, uid + "@example.com", uid); + await UserDal.addUser(`User ${uid}`, `${uid}@example.com`, uid); await DB.getDb() ?.collection("users") @@ -505,8 +505,8 @@ async function createUser( { $set: { timeTyping: 7200, - discordId: "discord " + uid, - discordAvatar: "avatar " + uid, + discordId: `discord ${uid}`, + discordAvatar: `avatar ${uid}`, ...userProperties, lbPersonalBests, }, diff --git a/backend/__tests__/__integration__/dal/user.spec.ts b/backend/__tests__/__integration__/dal/user.spec.ts index 148e4e90b2db..7330dfe8f532 100644 --- a/backend/__tests__/__integration__/dal/user.spec.ts +++ b/backend/__tests__/__integration__/dal/user.spec.ts @@ -128,8 +128,8 @@ describe("UserDal", () => { it("isNameAvailable should correctly check if a username is available", async () => { // given - const name1 = "user" + new ObjectId().toHexString(); - const name2 = "user" + new ObjectId().toHexString(); + const name1 = `user${new ObjectId().toHexString()}`; + const name2 = `user${new ObjectId().toHexString()}`; const { uid: user1 } = await UserTestData.createUser({ name: name1 }); await UserTestData.createUser({ name: name2 }); @@ -160,8 +160,8 @@ describe("UserDal", () => { it("updatename should not allow unavailable usernames", async () => { // given - const name1 = "user" + new ObjectId().toHexString(); - const name2 = "user" + new ObjectId().toHexString(); + const name1 = `user${new ObjectId().toHexString()}`; + const name2 = `user${new ObjectId().toHexString()}`; const user1 = await UserTestData.createUser({ name: name1 }); const user2 = await UserTestData.createUser({ name: name2 }); const _decoy = await UserTestData.createUser(); @@ -173,8 +173,8 @@ describe("UserDal", () => { }); it("same usernames (different casing) should be available only for the same user", async () => { - const name1 = "user" + new ObjectId().toHexString(); - const name2 = "user" + new ObjectId().toHexString(); + const name1 = `user${new ObjectId().toHexString()}`; + const name2 = `user${new ObjectId().toHexString()}`; const user1 = await UserTestData.createUser({ name: name1 }); const user2 = await UserTestData.createUser({ name: name2 }); @@ -192,8 +192,8 @@ describe("UserDal", () => { it("UserDAL.updateName should change the name of a user", async () => { // given - const name = "user" + new ObjectId().toHexString(); - const renamed = "renamed" + new ObjectId().toHexString(); + const name = `user${new ObjectId().toHexString()}`; + const renamed = `renamed${new ObjectId().toHexString()}`; const testUser = await UserTestData.createUser({ name: name }); // when @@ -1696,7 +1696,7 @@ describe("UserDal", () => { it("increments bananas", async () => { //GIVEN - const name = "user" + new ObjectId().toHexString(); + const name = `user${new ObjectId().toHexString()}`; const { uid } = await UserTestData.createUser({ name, bananas: 1, diff --git a/backend/__tests__/__testData__/connections.ts b/backend/__tests__/__testData__/connections.ts index 70fc8b0dfc33..438dec3c653b 100644 --- a/backend/__tests__/__testData__/connections.ts +++ b/backend/__tests__/__testData__/connections.ts @@ -5,7 +5,7 @@ export async function createConnection( data: Partial, maxPerUser = 25, ): Promise { - const defaultName = "user" + new ObjectId().toHexString(); + const defaultName = `user${new ObjectId().toHexString()}`; const result = await ConnectionsDal.create( { uid: data.initiatorUid ?? new ObjectId().toHexString(), diff --git a/backend/__tests__/__testData__/users.ts b/backend/__tests__/__testData__/users.ts index e7f1f4b66c27..98595d335dae 100644 --- a/backend/__tests__/__testData__/users.ts +++ b/backend/__tests__/__testData__/users.ts @@ -7,7 +7,7 @@ export async function createUser( user?: Partial, ): Promise { const uid = new ObjectId().toHexString(); - await UserDAL.addUser("user" + uid, uid + "@example.com", uid); + await UserDAL.addUser(`user${uid}`, `${uid}@example.com`, uid); await DB.collection("users").updateOne({ uid }, { $set: { ...user } }); return await UserDAL.getUser(uid, "test"); } @@ -16,7 +16,7 @@ export async function createUserWithoutMigration( user?: Partial, ): Promise { const uid = new ObjectId().toHexString(); - await UserDAL.addUser("user" + uid, uid + "@example.com", uid); + await UserDAL.addUser(`user${uid}`, `${uid}@example.com`, uid); await DB.collection("users").updateOne({ uid }, { $set: { ...user } }); await DB.collection("users").updateOne( { uid }, diff --git a/backend/__tests__/api/controllers/leaderboard.spec.ts b/backend/__tests__/api/controllers/leaderboard.spec.ts index 9dc146d5234e..1b48ca1a95ea 100644 --- a/backend/__tests__/api/controllers/leaderboard.spec.ts +++ b/backend/__tests__/api/controllers/leaderboard.spec.ts @@ -395,7 +395,7 @@ describe("Loaderboard Controller", () => { await mockApp .get("/leaderboards/rank") .query({ language: "english", mode: "time", mode2: "60" }) - .set("authorization", "ApeKey " + apeKey) + .set("authorization", `ApeKey ${apeKey}`) .expect(200); }); it("should get for mode", async () => { @@ -405,7 +405,7 @@ describe("Loaderboard Controller", () => { .get("/leaderboards/rank") .set("Authorization", `Bearer ${uid}`) .query({ language: "english", mode, mode2: "custom" }); - expect(response.status, "for mode " + mode).toEqual(200); + expect(response.status, `for mode ${mode}`).toEqual(200); } }); @@ -417,7 +417,7 @@ describe("Loaderboard Controller", () => { .set("Authorization", `Bearer ${uid}`) .query({ language: "english", mode: "words", mode2 }); - expect(response.status, "for mode2 " + mode2).toEqual(200); + expect(response.status, `for mode2 ${mode2}`).toEqual(200); } }); it("fails for missing query", async () => { @@ -750,7 +750,7 @@ describe("Loaderboard Controller", () => { const response = await mockApp .get("/leaderboards/daily") .query({ language: "english", mode, mode2: "custom" }); - expect(response.status, "for mode " + mode).toEqual(200); + expect(response.status, `for mode ${mode}`).toEqual(200); } }); @@ -760,7 +760,7 @@ describe("Loaderboard Controller", () => { .get("/leaderboards/daily") .query({ language: "english", mode: "words", mode2 }); - expect(response.status, "for mode2 " + mode2).toEqual(200); + expect(response.status, `for mode2 ${mode2}`).toEqual(200); } }); @@ -963,7 +963,7 @@ describe("Loaderboard Controller", () => { .get("/leaderboards/daily/rank") .set("Authorization", `Bearer ${uid}`) .query({ language: "english", mode, mode2: "custom" }); - expect(response.status, "for mode " + mode).toEqual(200); + expect(response.status, `for mode ${mode}`).toEqual(200); } }); @@ -974,7 +974,7 @@ describe("Loaderboard Controller", () => { .set("Authorization", `Bearer ${uid}`) .query({ language: "english", mode: "words", mode2 }); - expect(response.status, "for mode2 " + mode2).toEqual(200); + expect(response.status, `for mode2 ${mode2}`).toEqual(200); } }); diff --git a/backend/__tests__/api/controllers/public.spec.ts b/backend/__tests__/api/controllers/public.spec.ts index c3501ec99872..d4dc598d81bf 100644 --- a/backend/__tests__/api/controllers/public.spec.ts +++ b/backend/__tests__/api/controllers/public.spec.ts @@ -40,7 +40,7 @@ describe("PublicController", () => { const response = await mockApp .get("/public/speedHistogram") .query({ language: "english", mode, mode2: "custom" }); - expect(response.status, "for mode " + mode).toEqual(200); + expect(response.status, `for mode ${mode}`).toEqual(200); } }); @@ -61,7 +61,7 @@ describe("PublicController", () => { .get("/public/speedHistogram") .query({ language: "english", mode: "words", mode2 }); - expect(response.status, "for mode2 " + mode2).toEqual(200); + expect(response.status, `for mode2 ${mode2}`).toEqual(200); } }); it("fails for missing query", async () => { diff --git a/backend/__tests__/api/controllers/user.spec.ts b/backend/__tests__/api/controllers/user.spec.ts index d9e0cf7610e5..4e066dbb1560 100644 --- a/backend/__tests__/api/controllers/user.spec.ts +++ b/backend/__tests__/api/controllers/user.spec.ts @@ -3349,9 +3349,9 @@ describe("user controller test", () => { socialProfiles: { twitter: new Array(21).fill("x").join(""), github: new Array(40).fill("x").join(""), - website: - "https://" + - new Array(201 - "https://".length).fill("x").join(""), + website: `https://${new Array(201 - "https://".length) + .fill("x") + .join("")}`, }, }) .expect(422); diff --git a/backend/package.json b/backend/package.json index 2706c897a8c1..5c1245450265 100644 --- a/backend/package.json +++ b/backend/package.json @@ -80,8 +80,8 @@ "@vitest/coverage-v8": "4.1.5", "concurrently": "8.2.2", "openapi3-ts": "2.0.2", - "oxlint": "1.60.0", - "oxlint-tsgolint": "0.21.0", + "oxlint": "1.64.0", + "oxlint-tsgolint": "0.22.1", "readline-sync": "1.4.10", "supertest": "7.1.4", "testcontainers": "11.11.0", diff --git a/backend/private/script.js b/backend/private/script.js index 86cf2375b5d0..d10b9ca040af 100644 --- a/backend/private/script.js +++ b/backend/private/script.js @@ -294,7 +294,7 @@ function download(filename, text) { let element = document.createElement("a"); element.setAttribute( "href", - "data:text/plain;charset=utf-8," + encodeURIComponent(text), + `data:text/plain;charset=utf-8,${encodeURIComponent(text)}`, ); element.setAttribute("download", filename); diff --git a/backend/scripts/openapi.ts b/backend/scripts/openapi.ts index 101b350a0cdb..0b9c08905084 100644 --- a/backend/scripts/openapi.ts +++ b/backend/scripts/openapi.ts @@ -259,7 +259,7 @@ function getRateLimitDescription(limit: RateLimiterId | RateLimitIds): string { )} with ApeKeys`; } - return result + ".\n\n"; + return `${result}.\n\n`; } function formatWindow(window: Window): string { @@ -273,7 +273,7 @@ function formatWindow(window: Window): string { return `every ${duration}`; } - return "per " + window; + return `per ${window}`; } function addRequiredConfiguration( diff --git a/backend/src/api/controllers/admin.ts b/backend/src/api/controllers/admin.ts index 2840472de572..85068dc5beb4 100644 --- a/backend/src/api/controllers/admin.ts +++ b/backend/src/api/controllers/admin.ts @@ -132,7 +132,7 @@ export async function handleReports( } else { throw new MonkeyError( 500, - "Error handling reports: " + getErrorMessage(e), + `Error handling reports: ${getErrorMessage(e)}`, ); } } diff --git a/backend/src/api/controllers/dev.ts b/backend/src/api/controllers/dev.ts index 6f3e47166125..f020d0e0f7d0 100644 --- a/backend/src/api/controllers/dev.ts +++ b/backend/src/api/controllers/dev.ts @@ -88,8 +88,8 @@ async function getOrCreateUser( throw new MonkeyError(404, `User ${username} does not exist.`); } - const email = username + "@example.com"; - Logger.success("create user " + username); + const email = `${username}@example.com`; + Logger.success(`create user ${username}`); const { uid } = await FirebaseAdmin().auth().createUser({ displayName: username, password: password, diff --git a/backend/src/api/controllers/quote.ts b/backend/src/api/controllers/quote.ts index 40c64cf0ef8a..1ae0ae4ea19a 100644 --- a/backend/src/api/controllers/quote.ts +++ b/backend/src/api/controllers/quote.ts @@ -50,7 +50,7 @@ export async function isSubmissionEnabled( ): Promise { const { submissionsEnabled } = req.ctx.configuration.quotes; return new MonkeyResponse( - "Quote submission " + (submissionsEnabled ? "enabled" : "disabled"), + `Quote submission ${submissionsEnabled ? "enabled" : "disabled"}`, { isEnabled: submissionsEnabled }, ); } diff --git a/backend/src/api/controllers/result.ts b/backend/src/api/controllers/result.ts index eb9e94875d5b..59396abbd705 100644 --- a/backend/src/api/controllers/result.ts +++ b/backend/src/api/controllers/result.ts @@ -649,7 +649,7 @@ export async function addResult( if (isPb) { void addLog( "user_new_pb", - `${completedEvent.mode + " " + completedEvent.mode2} ${ + `${`${completedEvent.mode} ${completedEvent.mode2}`} ${ completedEvent.wpm } ${completedEvent.acc}% ${completedEvent.rawWpm} ${ completedEvent.consistency diff --git a/backend/src/api/controllers/user.ts b/backend/src/api/controllers/user.ts index 964602852f10..b89a7874515f 100644 --- a/backend/src/api/controllers/user.ts +++ b/backend/src/api/controllers/user.ts @@ -210,8 +210,9 @@ export async function sendVerificationEmail( } else { throw new MonkeyError( 500, - "Firebase failed to generate an email verification link: " + - error.errorInfo.message, + `Firebase failed to generate an email verification link: ${ + error.errorInfo.message + }`, JSON.stringify(error), ); } @@ -231,7 +232,7 @@ export async function sendVerificationEmail( } else { throw new MonkeyError( 500, - "Failed to generate an email verification link: " + message, + `Failed to generate an email verification link: ${message}`, error.stack, ); } diff --git a/backend/src/api/routes/docs.ts b/backend/src/api/routes/docs.ts index bd2befb32744..0c236799a64e 100644 --- a/backend/src/api/routes/docs.ts +++ b/backend/src/api/routes/docs.ts @@ -2,7 +2,7 @@ import { Response, Router } from "express"; const router = Router(); -const root = __dirname + "/../../../dist/static"; +const root = `${__dirname}/../../../dist/static`; router.use("/internal", (req, res) => { setCsp(res); diff --git a/backend/src/api/routes/swagger.ts b/backend/src/api/routes/swagger.ts index cff73fac3c76..9a449391c95c 100644 --- a/backend/src/api/routes/swagger.ts +++ b/backend/src/api/routes/swagger.ts @@ -6,7 +6,7 @@ import Logger from "../../utils/logger"; import { tryCatchSync } from "@monkeytype/util/trycatch"; function addSwaggerMiddlewares(app: Application): void { - const openApiSpec = __dirname + "/../../../dist/static/api/openapi.json"; + const openApiSpec = `${__dirname}/../../../dist/static/api/openapi.json`; const { data: spec, error } = tryCatchSync( () => diff --git a/backend/src/dal/logs.ts b/backend/src/dal/logs.ts index a7fb5641438a..6305d5bd64bc 100644 --- a/backend/src/dal/logs.ts +++ b/backend/src/dal/logs.ts @@ -36,7 +36,7 @@ async function insertIntoDb( Logger.info( `${event}\t${uid}\t${ - stringified.length > 100 ? stringified.slice(0, 100) + "..." : stringified + stringified.length > 100 ? `${stringified.slice(0, 100)}...` : stringified }`, ); diff --git a/backend/src/init/email-client.ts b/backend/src/init/email-client.ts index 39121cba0fcb..4980247112e6 100644 --- a/backend/src/init/email-client.ts +++ b/backend/src/init/email-client.ts @@ -76,8 +76,9 @@ export async function init(): Promise { if (!result) { throw new Error( - `Could not verify email client configuration: ` + - JSON.stringify(result), + `Could not verify email client configuration: ${JSON.stringify( + result, + )}`, ); } diff --git a/backend/src/middlewares/auth.ts b/backend/src/middlewares/auth.ts index a7deffd2c991..3b1530aff37a 100644 --- a/backend/src/middlewares/auth.ts +++ b/backend/src/middlewares/auth.ts @@ -358,7 +358,7 @@ export function authenticateGithubWebhook( } throw new MonkeyError( 500, - "Failed to authenticate Github webhook: " + (error as Error).message, + `Failed to authenticate Github webhook: ${(error as Error).message}`, ); } } diff --git a/backend/src/utils/error.ts b/backend/src/utils/error.ts index 7b0a55fdd77e..a63582ea1ce3 100644 --- a/backend/src/utils/error.ts +++ b/backend/src/utils/error.ts @@ -62,12 +62,12 @@ class MonkeyError extends Error implements MonkeyServerErrorType { if (isDevEnvironment()) { this.message = (stack ?? "") - ? String(message) + "\nStack: " + String(stack) + ? `${String(message)}\nStack: ${String(stack)}` : String(message); } else { if ((this.stack ?? "") && this.status >= 500) { - this.stack = this.message + "\n" + this.stack; - this.message = "Internal Server Error " + this.errorId; + this.stack = `${this.message}\n${this.stack}`; + this.message = `Internal Server Error ${this.errorId}`; } else { this.message = String(message); } diff --git a/frontend/__tests__/elements/test-activity-calendar.spec.ts b/frontend/__tests__/elements/test-activity-calendar.spec.ts index 8caf7afd9ee2..f68e51566f1b 100644 --- a/frontend/__tests__/elements/test-activity-calendar.spec.ts +++ b/frontend/__tests__/elements/test-activity-calendar.spec.ts @@ -1213,7 +1213,7 @@ describe("test-activity-calendar.ts", () => { }); function getDate(date: string): Date { - return new UTCDateMini(Dates.parseISO(date + "T00:00:00Z")); + return new UTCDateMini(Dates.parseISO(`${date}T00:00:00Z`)); } function getData(from: string, to: string): number[] { diff --git a/frontend/__tests__/utils/key-converter.spec.ts b/frontend/__tests__/utils/key-converter.spec.ts index 40be7199bfc3..57a69fde6272 100644 --- a/frontend/__tests__/utils/key-converter.spec.ts +++ b/frontend/__tests__/utils/key-converter.spec.ts @@ -4,13 +4,13 @@ import { layoutKeyToKeycode } from "../../src/ts/utils/key-converter"; const isoDvorak = JSON.parse( readFileSync( - import.meta.dirname + "/../../static/layouts/swedish_dvorak.json", + `${import.meta.dirname}/../../static/layouts/swedish_dvorak.json`, "utf-8", ), ); const dvorak = JSON.parse( readFileSync( - import.meta.dirname + "/../../static/layouts/dvorak.json", + `${import.meta.dirname}/../../static/layouts/dvorak.json`, "utf-8", ), ); diff --git a/frontend/package.json b/frontend/package.json index 59d12ce58300..4becddf31f10 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -109,8 +109,8 @@ "madge": "8.0.0", "magic-string": "0.30.17", "normalize.css": "8.0.1", - "oxlint": "1.60.0", - "oxlint-tsgolint": "0.21.0", + "oxlint": "1.64.0", + "oxlint-tsgolint": "0.22.1", "postcss": "8.5.8", "sass": "1.70.0", "solid-devtools": "0.34.5", diff --git a/frontend/scripts/check-assets.ts b/frontend/scripts/check-assets.ts index a0b267d5ee31..8ba8e7fa9400 100644 --- a/frontend/scripts/check-assets.ts +++ b/frontend/scripts/check-assets.ts @@ -24,7 +24,8 @@ import { QuoteDataSchema, QuoteData } from "@monkeytype/schemas/quotes"; import { clickSoundConfig } from "../src/ts/constants/sounds"; import * as ghCore from "@actions/core"; -const stepSummary = ghCore.summary; +const stepSummary = + process.env["GITHUB_STEP_SUMMARY"] !== undefined ? ghCore.summary : undefined; class Problems { private type: string; @@ -54,33 +55,32 @@ class Problems { return Object.keys(this.problems).length !== 0; } public toString(): string { - stepSummary.addHeading(`${this.type} Checks`, 2); + stepSummary?.addHeading(`${this.type} Checks`, 2); if (!this.hasError()) { - stepSummary.addRaw("✅ all checks passed").addEOL(); + stepSummary?.addRaw("✅ all checks passed").addEOL(); return `${this.type} are all \u001b[32mvalid\u001b[0m`; } Object.entries(this.problems).forEach(([key, problems]) => { let label: string = this.labels[key as T] ?? `${key}`; stepSummary - .addRaw(`❌ ${label}`) + ?.addRaw(`❌ ${label}`) .addEOL() .addList(problems as string[]) .addEOL(); }); - return ( - `${this.type} are \u001b[31minvalid\u001b[0m\n` + - Object.entries(this.problems) - .map(([key, problems]) => { - let label: string = this.labels[key as T] ?? `${key}`; - - return `${label}:\n ${(problems as string[]) - .map((error) => "\t- " + error) - .join("\n")}`; - }) - .join("\n") - ); + return `${this.type} are \u001b[31minvalid\u001b[0m\n${Object.entries( + this.problems, + ) + .map(([key, problems]) => { + let label: string = this.labels[key as T] ?? `${key}`; + + return `${label}:\n ${(problems as string[]) + .map((error) => `\t- ${error}`) + .join("\n")}`; + }) + .join("\n")}`; } } @@ -151,7 +151,7 @@ async function validateLayouts(): Promise { //no files not defined in LayoutsList const additionalLayoutFiles = fs .readdirSync("./static/layouts") - .filter((it) => !LayoutsList.some((layout) => layout + ".json" === it)); + .filter((it) => !LayoutsList.some((layout) => `${layout}.json` === it)); if (additionalLayoutFiles.length !== 0) { additionalLayoutFiles.forEach((it) => problems.add("_additional", it)); } @@ -291,7 +291,7 @@ async function validateLanguages(): Promise { ); if (languageFileData.name !== language) { - problems.add(language, "Name is not " + language); + problems.add(language, `Name is not ${language}`); } const duplicates = findDuplicates(languageFileData.words); const duplicatePercentage = @@ -308,7 +308,7 @@ async function validateLanguages(): Promise { //no files not defined in LanguageList fs.readdirSync("./static/languages") - .filter((it) => !LanguageList.some((language) => language + ".json" === it)) + .filter((it) => !LanguageList.some((language) => `${language}.json` === it)) .forEach((it) => problems.add("_additional", it)); //check groups @@ -405,7 +405,7 @@ async function validateThemes(): Promise { //missing or additional theme files (mismatch in hasCss) ThemesList.filter( - (it) => themeFiles.includes(it.name + ".css") !== (it.hasCss ?? false), + (it) => themeFiles.includes(`${it.name}.css`) !== (it.hasCss ?? false), ).forEach((it) => problems.add( it.name, @@ -415,7 +415,7 @@ async function validateThemes(): Promise { //additional theme files themeFiles - .filter((it) => !ThemesList.some((theme) => theme.name + ".css" === it)) + .filter((it) => !ThemesList.some((theme) => `${theme.name}.css` === it)) .forEach((it) => problems.add("_additional", it)); //validate theme colors are valid hex colors, not covered by typescipt @@ -461,7 +461,7 @@ async function validateSounds(): Promise { .filter((it) => !soundFiles.has(it)) .forEach((file) => problems.add( - "click" + key, + `click${key}`, `missing file frontend/static/sounds/${file}`, ), ); @@ -531,7 +531,7 @@ async function main(): Promise { [...tasks].map(async (validator) => validator()), ); - await stepSummary.write(); + await stepSummary?.write(); if (results.find((it) => it.status === "rejected") !== undefined) { throw new Error("One or more checks failed."); diff --git a/frontend/scripts/import-tree.ts b/frontend/scripts/import-tree.ts index ce1cb6834e76..9ef29535aa72 100644 --- a/frontend/scripts/import-tree.ts +++ b/frontend/scripts/import-tree.ts @@ -217,11 +217,11 @@ function depthColor(depth: number): string { function leavesFolder(filePath: string): boolean { if (boundary === null) return false; if (filePath.startsWith("@monkeytype/")) return true; - return !filePath.startsWith(boundary + "/"); + return !filePath.startsWith(`${boundary}/`); } function displayPath(filePath: string): string { - if (filePath.startsWith(ROOT + "/")) { + if (filePath.startsWith(`${ROOT}/`)) { return path.relative(ROOT, filePath); } return filePath; diff --git a/frontend/src/ts/auth.tsx b/frontend/src/ts/auth.tsx index b0e684ec60bd..f0956823bc59 100644 --- a/frontend/src/ts/auth.tsx +++ b/frontend/src/ts/auth.tsx @@ -97,7 +97,7 @@ async function getDataAndInit(): Promise { ); } - showErrorNotification("Failed to get user data: " + error.message); + showErrorNotification(`Failed to get user data: ${error.message}`); } else { showErrorNotification("Failed to get user data", { error }); } diff --git a/frontend/src/ts/collections/inbox.ts b/frontend/src/ts/collections/inbox.ts index 06bed51c1e01..ea6f9fa6066c 100644 --- a/frontend/src/ts/collections/inbox.ts +++ b/frontend/src/ts/collections/inbox.ts @@ -54,9 +54,9 @@ const inboxCollection = createCollection( const response = await Ape.users.getInbox(); if (response.status !== 200) { showErrorNotification( - "Error fetching user inbox: " + response.body.message, + `Error fetching user inbox: ${response.body.message}`, ); - throw new Error("Error fetching user inbox: " + response.body.message); + throw new Error(`Error fetching user inbox: ${response.body.message}`); } setMaxMailboxSize(response.body.data.maxMail); return response.body.data.inbox.map(addStatus); @@ -157,9 +157,9 @@ async function flushPendingChanges({ if (response.status !== 200) { showErrorNotification( - "Error updating user inbox: " + response.body.message, + `Error updating user inbox: ${response.body.message}`, ); - throw new Error("Error updating user inbox: " + response.body.message); + throw new Error(`Error updating user inbox: ${response.body.message}`); } inboxCollection.utils.writeBatch(() => { diff --git a/frontend/src/ts/collections/presets.ts b/frontend/src/ts/collections/presets.ts index 051497b34340..937fbab9a2ff 100644 --- a/frontend/src/ts/collections/presets.ts +++ b/frontend/src/ts/collections/presets.ts @@ -39,7 +39,7 @@ const presetsCollection = createCollection( const response = await Ape.presets.get(); if (response.status !== 200) { - throw new Error("Error fetching presets:" + response.body.message); + throw new Error(`Error fetching presets:${response.body.message}`); } return response.body.data diff --git a/frontend/src/ts/collections/results.ts b/frontend/src/ts/collections/results.ts index 53133bb829ea..e3841319f411 100644 --- a/frontend/src/ts/collections/results.ts +++ b/frontend/src/ts/collections/results.ts @@ -224,7 +224,7 @@ const resultsCollection = createCollection( }); if (response.status !== 200) { - throw new Error("Error fetching results:" + response.body.message); + throw new Error(`Error fetching results:${response.body.message}`); } const results = response.body.data diff --git a/frontend/src/ts/collections/utils/misc.ts b/frontend/src/ts/collections/utils/misc.ts index bce53db4547a..876dbff7aadc 100644 --- a/frontend/src/ts/collections/utils/misc.ts +++ b/frontend/src/ts/collections/utils/misc.ts @@ -1,7 +1,5 @@ export function tempId(): string { - return ( - "temp_" + Math.random().toString(36).slice(2) + Date.now().toString(36) - ); + return `temp_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`; } /** diff --git a/frontend/src/ts/commandline/commandline.ts b/frontend/src/ts/commandline/commandline.ts index d542fabbe132..709e21559d62 100644 --- a/frontend/src/ts/commandline/commandline.ts +++ b/frontend/src/ts/commandline/commandline.ts @@ -507,8 +507,9 @@ async function showCommands(): Promise { if (command.configValue !== undefined || command.active !== undefined) { display = display.replace( ``, - `` + - configIconHtml, + `${ + configIconHtml + }`, ); } } diff --git a/frontend/src/ts/commandline/lists.ts b/frontend/src/ts/commandline/lists.ts index 4a095f7b4f86..e7e62a75f307 100644 --- a/frontend/src/ts/commandline/lists.ts +++ b/frontend/src/ts/commandline/lists.ts @@ -488,13 +488,13 @@ function buildSingleListCommands( /\s?\.\.\.$/g, "", ); - const singleListDisplay = - parentCommandDisplay + - '' + - command.display; + const singleListDisplay = `${ + parentCommandDisplay + }${ + command.display + }`; - const singleListDisplayNoIcon = - parentCommandDisplay + " " + command.display; + const singleListDisplayNoIcon = `${parentCommandDisplay} ${command.display}`; let newAlias: string | undefined = undefined; diff --git a/frontend/src/ts/commandline/lists/custom-background.ts b/frontend/src/ts/commandline/lists/custom-background.ts index 795f20929695..e59ba73606de 100644 --- a/frontend/src/ts/commandline/lists/custom-background.ts +++ b/frontend/src/ts/commandline/lists/custom-background.ts @@ -59,7 +59,7 @@ const customBackgroundCommand: Command = { await updateUI(); } catch (e) { showNoticeNotification( - "Error uploading background: " + (e as Error).message, + `Error uploading background: ${(e as Error).message}`, ); } cleanup(); @@ -88,7 +88,7 @@ const customBackgroundCommand: Command = { await updateUI(); } catch (e) { showNoticeNotification( - "Error removing background: " + (e as Error).message, + `Error removing background: ${(e as Error).message}`, ); } }, diff --git a/frontend/src/ts/commandline/lists/custom-themes-list.ts b/frontend/src/ts/commandline/lists/custom-themes-list.ts index f513ba2bb84f..6e29fe9e2e06 100644 --- a/frontend/src/ts/commandline/lists/custom-themes-list.ts +++ b/frontend/src/ts/commandline/lists/custom-themes-list.ts @@ -43,7 +43,7 @@ export function update(): void { } for (const theme of snapshot.customThemes) { subgroup.list.push({ - id: "setCustomThemeId" + theme._id, + id: `setCustomThemeId${theme._id}`, display: theme.name.replace(/_/gi, " "), configValue: theme._id, hover: (): void => { diff --git a/frontend/src/ts/commandline/lists/font-family.ts b/frontend/src/ts/commandline/lists/font-family.ts index 231ddc5f043a..60ca8a34b797 100644 --- a/frontend/src/ts/commandline/lists/font-family.ts +++ b/frontend/src/ts/commandline/lists/font-family.ts @@ -80,7 +80,7 @@ if (fromMeta.subgroup) { await updateUI(); } catch (e) { showNoticeNotification( - "Error uploading font: " + (e as Error).message, + `Error uploading font: ${(e as Error).message}`, ); } cleanup(); @@ -106,7 +106,7 @@ if (fromMeta.subgroup) { await applyFontFamily(); } catch (e) { showNoticeNotification( - "Error removing font: " + (e as Error).message, + `Error removing font: ${(e as Error).message}`, ); } }, diff --git a/frontend/src/ts/commandline/lists/funbox.ts b/frontend/src/ts/commandline/lists/funbox.ts index 12ffbfb86b37..5c6e6c5e4021 100644 --- a/frontend/src/ts/commandline/lists/funbox.ts +++ b/frontend/src/ts/commandline/lists/funbox.ts @@ -21,7 +21,7 @@ const list: Command[] = [ for (const funbox of getAllFunboxes()) { list.push({ - id: "changeFunbox" + funbox.name, + id: `changeFunbox${funbox.name}`, display: funbox.name.replace(/_/g, " "), available: () => { const activeNames = getActiveFunboxNames(); diff --git a/frontend/src/ts/commandline/lists/load-challenge.ts b/frontend/src/ts/commandline/lists/load-challenge.ts index 7a22caca1944..c49f1511a298 100644 --- a/frontend/src/ts/commandline/lists/load-challenge.ts +++ b/frontend/src/ts/commandline/lists/load-challenge.ts @@ -22,7 +22,7 @@ const commands: Command[] = [ function update(challenges: Challenge[]): void { challenges.forEach((challenge) => { subgroup.list.push({ - id: "loadChallenge" + capitalizeFirstLetterOfEachWord(challenge.name), + id: `loadChallenge${capitalizeFirstLetterOfEachWord(challenge.name)}`, display: challenge.display, exec: async (): Promise => { await navigate("/"); diff --git a/frontend/src/ts/commandline/lists/presets.ts b/frontend/src/ts/commandline/lists/presets.ts index 5a6f5c4b870b..5e7b94b37450 100644 --- a/frontend/src/ts/commandline/lists/presets.ts +++ b/frontend/src/ts/commandline/lists/presets.ts @@ -33,7 +33,7 @@ function update(): void { if (presets.length === 0) return; presets.forEach((preset) => { subgroup.list.push({ - id: "applyPreset" + preset._id, + id: `applyPreset${preset._id}`, display: preset.name, exec: async (): Promise => { Settings.setEventDisabled(true); diff --git a/frontend/src/ts/commandline/lists/tags.ts b/frontend/src/ts/commandline/lists/tags.ts index 677e993fc10f..689c6a979818 100644 --- a/frontend/src/ts/commandline/lists/tags.ts +++ b/frontend/src/ts/commandline/lists/tags.ts @@ -55,7 +55,7 @@ function update(): void { for (const tag of tags) { subgroup.list.push({ - id: "toggleTag" + tag._id, + id: `toggleTag${tag._id}`, display: tag.name, sticky: true, active: () => { diff --git a/frontend/src/ts/commandline/lists/themes.ts b/frontend/src/ts/commandline/lists/themes.ts index 394ca2c29821..3144f6edf7e7 100644 --- a/frontend/src/ts/commandline/lists/themes.ts +++ b/frontend/src/ts/commandline/lists/themes.ts @@ -18,7 +18,7 @@ const isFavorite = (theme: ThemeWithName): boolean => */ const createThemeCommand = (theme: ThemeWithName): Command => { return { - id: "changeTheme" + capitalizeFirstLetterOfEachWord(theme.name), + id: `changeTheme${capitalizeFirstLetterOfEachWord(theme.name)}`, display: theme.name.replace(/_/g, " "), configValue: theme.name, // customStyle: `color:${theme.main};background:${theme.bg};`, diff --git a/frontend/src/ts/components/common/Advertisement.tsx b/frontend/src/ts/components/common/Advertisement.tsx index 9a55f2bd68e7..37067af6a21e 100644 --- a/frontend/src/ts/components/common/Advertisement.tsx +++ b/frontend/src/ts/components/common/Advertisement.tsx @@ -14,7 +14,7 @@ export function Advertisement(props: { return (