Skip to content

Commit 543ac92

Browse files
Refactor many things
1 parent e9df1ba commit 543ac92

20 files changed

+85
-75
lines changed

.github/workflows/deno.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ jobs:
2727
deno-version: v1.x
2828

2929
- name: Run linter
30-
run: deno lint --ignore=node_modules,./.*,*.min.*
30+
run: deno lint --ignore=node_modules,./.*,**/*.min.js

assets/data/faq.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type FAQEntry, Tag } from "../types/faq";
1+
import { Tag } from "../types/faq";
22

33
export default {
44
'what-is-techmino': {

assets/scripts/background.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,11 @@ function onResize() {
101101
bgCanvas.width = width;
102102
bgCanvas.height = height;
103103

104-
let starCount = Math.floor(width * height * 6e-4);
104+
const starCount = Math.floor(width * height * 6e-4);
105105
stars = new Array(starCount);
106106

107107
for (let i = 0; i < starCount; i++) {
108-
let size = random(2.6, 4);
108+
const size = random(2.6, 4);
109109
stars[i] = {
110110
size: size,
111111
x: random(-10, width + 10),

assets/scripts/database.ts

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { ref } from 'vue';
22
import {
33
createClient,
44
SupabaseClient,
5-
type PostgrestError,
65
type SupabaseClientOptions,
76
type User
87
} from '@supabase/supabase-js';

assets/scripts/replay/analyzer.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export type KeyDurationStats = {
4040
};
4141

4242
function getEmptyKeyDurationStats(): KeyDurationStats {
43-
let partial: Partial<KeyDurationStats> = {};
43+
const partial: Partial<KeyDurationStats> = {};
4444

4545
for(const key of Object.values(InputKey)) {
4646
partial[key] = {
@@ -69,10 +69,10 @@ function getEmptyKeyDurationStats(): KeyDurationStats {
6969
export function getReplayKeyDurationStats(
7070
replayData: GameReplayData
7171
): KeyDurationStats {
72-
let keyDurationStats = getEmptyKeyDurationStats();
72+
const keyDurationStats = getEmptyKeyDurationStats();
7373

74-
let timeOfPreviousPress: Record<InputKey, number> = (function() {
75-
let partial: Partial<Record<InputKey, number>> = {};
74+
const timeOfPreviousPress: Record<InputKey, number> = (function() {
75+
const partial: Partial<Record<InputKey, number>> = {};
7676

7777
for(const key of Object.values(InputKey)) {
7878
partial[key] = Infinity;
@@ -99,7 +99,7 @@ export function getReplayKeyDurationStats(
9999
}
100100

101101
// Process inputs for additional statistics
102-
for(let key of Object.values(InputKey)) {
102+
for(const key of Object.values(InputKey)) {
103103
// Calculate the 25th, 50th (median), and 75th percentiles
104104
{
105105
const durations = Object.keys(keyDurationStats[key].durations).map(Number);
@@ -116,7 +116,7 @@ export function getReplayKeyDurationStats(
116116

117117
let percentile25Set = false;
118118
let medianSet = false;
119-
let percentile75Set = false
119+
let percentile75Set = false;
120120

121121
for(const duration of durations) {
122122
const durationInstances = keyDurationStats[key].durations[duration] ?? 0;
@@ -385,7 +385,7 @@ export function getReplayLocalKps(replayData: GameReplayData, filter?: InputKey,
385385
* @param replayData The replay data to analyze.
386386
*/
387387
export function getUsedKeys(replayData: GameReplayData) {
388-
let usedKeys = new Set<InputKey>();
388+
const usedKeys = new Set<InputKey>();
389389

390390
for(const input of replayData.inputs) {
391391
if(input.type === InputEventType.Press) {
@@ -402,7 +402,7 @@ export function getUsedKeys(replayData: GameReplayData) {
402402
* @param gameMode The game mode to get the KPS limit for.
403403
* @returns The KPS limit for the given game mode.
404404
*/
405-
function getKpsLimit(gameMode: string) {
405+
export function getKpsLimit(gameMode: string) {
406406
const kpsLimits = {
407407
sprint123: 60,
408408
classic: 30,

assets/types/database.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { createClient, SupabaseClient, type SupabaseClientOptions } from "@supabase/supabase-js";
2-
31
/**
42
* The Profile type represents a user's profile.
53
* This should be what you get from querying from the `public.profiles` table.
@@ -60,7 +58,7 @@ export type Submission = {
6058
* It is different for each game mode, and can even be null.
6159
* Postgres type: jsonb
6260
*/
63-
score: Record<string | number, any> | null;
61+
score: Record<string | number, unknown> | null;
6462

6563
/**
6664
* The timestamp when the submission was uploaded.

assets/types/lang.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/** Language entry type. */
22
export type LangEntry = {
3-
[key: string]: string | string[] | ((...args: any) => string) | LangEntry
3+
[key: string]:
4+
string | string[] | ((...args: unknown[]) => string) | LangEntry
45
};
56

67
/** The prefix of a string if it should be processed in Markdown */

assets/types/map.ts

+37-23
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,33 @@ export type MapData = {
88
starting_mode: string
99
}
1010

11+
function isRecord(candidate: unknown): candidate is Record<string, unknown> {
12+
return !!(typeof candidate === 'object' && candidate);
13+
}
14+
15+
const mapDataSchema = {
16+
modes: 'object',
17+
min_x: 'number',
18+
max_x: 'number',
19+
min_y: 'number',
20+
max_y: 'number',
21+
starting_mode: 'string'
22+
} as const;
23+
24+
function recordFollowsMapDataSchema(rec: Record<string, unknown>): rec is MapData {
25+
for(const key of Object.keys(mapDataSchema) as (keyof typeof mapDataSchema)[]) {
26+
if(!(key in rec) || (typeof rec[key]) !== mapDataSchema[key]) {
27+
return false;
28+
}
29+
30+
if(mapDataSchema[key] === 'object' && !isRecord(rec[key])) {
31+
return false;
32+
}
33+
}
34+
35+
return true;
36+
}
37+
1138
/**
1239
* Checks if the given map data is valid.
1340
*
@@ -20,23 +47,9 @@ export type MapData = {
2047
*
2148
* @returns Whether or not the map data is valid
2249
*/
23-
export function isMapDataValid(mapData: any, strict: boolean = false): mapData is MapData {
24-
if(!mapData || typeof mapData !== 'object') { return false; }
25-
26-
const schema = {
27-
modes: 'object',
28-
min_x: 'number',
29-
max_x: 'number',
30-
min_y: 'number',
31-
max_y: 'number',
32-
starting_mode: 'string'
33-
} as const;
34-
35-
for(const key of Object.keys(schema) as (keyof typeof schema)[]) {
36-
if(!(key in mapData) || (typeof mapData[key]) !== schema[key]) {
37-
return false;
38-
}
39-
}
50+
export function isMapDataValid(mapData: unknown, strict: boolean = false): mapData is MapData {
51+
if(!isRecord(mapData)) return false;
52+
if(!recordFollowsMapDataSchema(mapData)) return false;
4053

4154
if(!mapData.modes[mapData.starting_mode]) {
4255
return false;
@@ -77,8 +90,9 @@ export type Mode = {
7790
* @param mode The candidate mode to be validated.
7891
* @returns Whether or not the mode is valid.
7992
*/
80-
export function isModeValid(mode: any): mode is Mode {
81-
if(!mode || typeof mode !== 'object') { return false; }
93+
// @ts-ignore | "`any` type is not allowed"
94+
export function isModeValid(mode: unknown): mode is Mode {
95+
if(!isRecord(mode)) { return false; }
8296

8397
const schema = {
8498
name: 'string',
@@ -121,19 +135,19 @@ export type Rank = typeof Rank[keyof typeof Rank];
121135

122136

123137
export const modeShapeNames = (() => {
124-
let names = new Map<ModeShape, string>();
138+
const names = new Map<ModeShape, string>();
125139

126-
for(let [key, value] of Object.entries(ModeShape)) {
140+
for(const [key, value] of Object.entries(ModeShape)) {
127141
names.set(value, key);
128142
}
129143

130144
return names as Map<ModeShape, keyof typeof ModeShape>;
131145
})();
132146

133147
export const rankNames = (() => {
134-
let names = new Map<Rank, string>();
148+
const names = new Map<Rank, string>();
135149

136-
for(let [key, value] of Object.entries(Rank)) {
150+
for(const [key, value] of Object.entries(Rank)) {
137151
names.set(value, key);
138152
}
139153

deno.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"lint": {
3+
"rules": {
4+
"tags": ["recommended"],
5+
"exclude": ["no-node-globals"]
6+
}
7+
}
8+
}

i18n.config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ function processLangEntry(entries: LangEntry): LangEntry {
3838
const newEntries: LangEntry = {};
3939

4040
for(const key in entries) {
41-
let entry = entries[key];
41+
const entry = entries[key];
4242

4343
if(typeof entry === 'string') {
4444
newEntries[key] = renderString(entry);

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"generate": "nuxt generate",
99
"preview": "nuxt preview",
1010
"postinstall": "nuxt prepare",
11-
"lint": "deno lint --ignore=node_modules,./.*,*.min.*"
11+
"lint": "deno lint --ignore=node_modules,./.*,**/*.min.js",
12+
"lintless": "npm run lint > lint_output.log 2>&1 || less -R lint_output.log"
1213
},
1314
"dependencies": {
1415
"@nuxt/kit": "^3.13.1",

plugins/thtml-directive.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { type DirectiveBinding } from "vue";
2+
13
// Workaround for v-html not being supported for custom elements
24
// Source: https://github.com/nuxt/nuxt/issues/10333#issuecomment-1842692933
35

@@ -6,10 +8,10 @@
68
// If v-html works, use that instead.
79
export default defineNuxtPlugin((nuxtApp) => {
810
nuxtApp.vueApp.directive('thtml', {
9-
mounted: (el: HTMLElement, binding: any) => {
11+
mounted: (el: HTMLElement, binding: DirectiveBinding) => {
1012
el.innerHTML = binding.value;
1113
},
12-
getSSRProps(binding: any) {
14+
getSSRProps(binding: DirectiveBinding) {
1315
return {
1416
innerHTML: binding.value
1517
};

plugins/tl-with-fallback.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { type TranslateOptions } from 'vue-i18n';
2-
31
/**
42
* Translate with a key if it exists, otherwise fallback to another key.
53
*
@@ -30,7 +28,7 @@ export function translateWithFallback(
3028
}
3129
}
3230

33-
export default defineNuxtPlugin((nuxtApp) => {
31+
export default defineNuxtPlugin(() => {
3432
const tf = translateWithFallback;
3533

3634
return {

server/api/v1/check-avatar.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { useDatabase } from "~/composables/database";
1414
export default defineEventHandler(async (event) => {
1515
const query = getQuery(event);
1616

17-
let id = query.id;
17+
const id = query.id;
1818

1919
if (!id) {
2020
throw createError({
@@ -47,7 +47,7 @@ export default defineEventHandler(async (event) => {
4747
});
4848

4949
return response.ok;
50-
} catch {}
51-
52-
return false;
50+
} catch {
51+
return false;
52+
}
5353
});

server/api/v1/fetch-article.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export default defineEventHandler(async (event) => {
100100
let text = "";
101101

102102
try {
103-
let res = await fetch(path);
103+
const res = await fetch(path);
104104

105105
if(!res.ok) {
106106
throw createError({

server/api/v1/fetch-leaderboard.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { RECORD_SCHEMAS } from '~/assets/data/record-schemas';
2-
import { Submission, SubmissionValidity } from '~/assets/types/database';
2+
import { SubmissionValidity } from '~/assets/types/database';
33
import { useDatabase } from '~/composables/database';
4-
import { type PostgrestError } from '@supabase/supabase-js';
54

65
/**
76
* @api {get} /api/v1/fetch-leaderboard Fetch leaderboard
@@ -26,7 +25,7 @@ import { type PostgrestError } from '@supabase/supabase-js';
2625
export default defineEventHandler(async (event) => {
2726
const query = getQuery(event);
2827

29-
let gameMode = query.gameMode;
28+
const gameMode = query.gameMode;
3029

3130
if(!gameMode) {
3231
throw createError({
@@ -143,7 +142,7 @@ export default defineEventHandler(async (event) => {
143142
let reverse = false;
144143

145144
if(query.reverse) {
146-
let reverseQuery = query.reverse;
145+
const reverseQuery = query.reverse;
147146

148147
if(typeof reverseQuery === 'boolean') {
149148
reverse = reverseQuery;

server/api/v1/fetch-profile-submissions.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { useDatabase } from '~/composables/database';
2121
export default defineEventHandler(async (event) => {
2222
const query = getQuery(event);
2323

24-
let id = query.id;
24+
const id = query.id;
2525

2626
if (!id) {
2727
throw createError({
@@ -58,7 +58,7 @@ export default defineEventHandler(async (event) => {
5858
}
5959

6060
if(typeof limitQuery === 'string') {
61-
let casted = parseInt(limitQuery);
61+
const casted = parseInt(limitQuery);
6262

6363
if(!isFinite(casted)) {
6464
throw createError({
@@ -95,7 +95,7 @@ export default defineEventHandler(async (event) => {
9595
}
9696

9797
if(typeof offsetQuery === 'string') {
98-
let casted = parseInt(offsetQuery);
98+
const casted = parseInt(offsetQuery);
9999

100100
if(!isFinite(casted)) {
101101
throw createError({

server/api/v1/fetch-profile.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ import { useDatabase } from '~/composables/database';
1818
export default defineEventHandler(async (event) => {
1919
const query = getQuery(event);
2020

21-
let uuid = query.uuid;
22-
let username = query.username;
21+
const uuid = query.uuid;
22+
const username = query.username;
2323

2424
if(!uuid && !username) {
2525
throw createError({
@@ -74,7 +74,7 @@ export default defineEventHandler(async (event) => {
7474
});
7575
}
7676

77-
let error = err as PostgrestError | Error;
77+
const error = err as PostgrestError | Error;
7878

7979
if(error.message.toLowerCase().includes("not found")) {
8080
throw createError({

0 commit comments

Comments
 (0)