diff --git a/Makefile b/Makefile index 5ca66a1..19c70ad 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,10 @@ # the user has activated it (or has direnv loaded). `make venv` creates it. export PATH := $(CURDIR)/.venv/bin:$(PATH) -.PHONY: ci lint format format-check test install-dev run venv init build +.PHONY: ci lint format format-check test install-dev run venv init build frontend-lint frontend-type-check # Run all CI checks — called by GitHub Actions. -ci: lint format-check frontend-lint test +ci: lint format-check frontend-lint frontend-type-check test # ── Python ────────────────────────────────────────────────────────────────── @@ -27,6 +27,9 @@ test: frontend-lint: npm --prefix frontend run lint +frontend-type-check: + npm --prefix frontend run type-check + # ── Dev setup ──────────────────────────────────────────────────────────────── venv: diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 0092e46..895524c 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -5,6 +5,7 @@ "packages": { "": { "name": "ceopardy-frontend", + "license": "GPL-3.0-or-later", "dependencies": { "@fortawesome/fontawesome-free": "^6.5.2", "pinia": "^2.2.2", @@ -13,9 +14,13 @@ "vue-router": "^4.4.3" }, "devDependencies": { + "@types/node": "^25.9.1", "@vitejs/plugin-vue": "^6.0.6", + "@vue/tsconfig": "^0.9.1", "prettier": "^3.3.3", - "vite": "^8.0.10" + "typescript": "^6.0.3", + "vite": "^8.0.10", + "vue-tsc": "^3.3.1" } }, "node_modules/@babel/helper-string-parser": { @@ -423,6 +428,16 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/node": { + "version": "25.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", + "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, "node_modules/@vitejs/plugin-vue": { "version": "6.0.6", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.6.tgz", @@ -440,6 +455,35 @@ "vue": "^3.2.25" } }, + "node_modules/@volar/language-core": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.28.tgz", + "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.28" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.28.tgz", + "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.28.tgz", + "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, "node_modules/@vue/compiler-core": { "version": "3.5.34", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.34.tgz", @@ -496,6 +540,22 @@ "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", "license": "MIT" }, + "node_modules/@vue/language-core": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.3.1.tgz", + "integrity": "sha512-NP8g6V7x81NVOXbLupUvYY6i6LqUkjkVowe2epRedmpgaFCOdjgWHE/rQBvEJ4r7koAYODIjGeBWEdt6n7jYXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.2.0", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "picomatch": "^4.0.4" + } + }, "node_modules/@vue/reactivity": { "version": "3.5.34", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.34.tgz", @@ -546,6 +606,32 @@ "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==", "license": "MIT" }, + "node_modules/@vue/tsconfig": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.9.1.tgz", + "integrity": "sha512-buvjm+9NzLCJL29KY1j1991YYJ5e6275OiK+G4jtmfIb+z4POywbdm0wXusT9adVWqe0xqg70TbI7+mRx4uU9w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">= 5.8", + "vue": "^3.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/alien-signals": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.2.1.tgz", + "integrity": "sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==", + "dev": true, + "license": "MIT" + }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", @@ -928,6 +1014,13 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, "node_modules/nanoid": { "version": "3.3.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", @@ -946,6 +1039,13 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -1134,6 +1234,27 @@ "license": "0BSD", "optional": true }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "dev": true, + "license": "MIT" + }, "node_modules/vite": { "version": "8.0.11", "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.11.tgz", @@ -1212,6 +1333,13 @@ } } }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, "node_modules/vue": { "version": "3.5.34", "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.34.tgz", @@ -1274,6 +1402,23 @@ "vue": "^3.5.0" } }, + "node_modules/vue-tsc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.3.1.tgz", + "integrity": "sha512-webBP3jhlxzhELZ2g+11KJ6pg5OVY1xWhWrj7N/yQMi1CrtxJnW+tUACyRVeDK0cQNLP2Va5HNYK8pe+7c+msw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.28", + "@vue/language-core": "3.3.1" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, "node_modules/ws": { "version": "8.18.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", diff --git a/frontend/package.json b/frontend/package.json index 20ac226..310585d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,9 +6,10 @@ "license": "GPL-3.0-or-later", "scripts": { "dev": "vite", - "build": "vite build", + "build": "vue-tsc --noEmit && vite build", "preview": "vite preview", - "lint": "prettier --check \"src/**/*.{js,vue}\"" + "lint": "prettier --check \"src/**/*.{ts,vue}\"", + "type-check": "vue-tsc --noEmit" }, "dependencies": { "@fortawesome/fontawesome-free": "^6.5.2", @@ -18,8 +19,12 @@ "vue-router": "^4.4.3" }, "devDependencies": { + "@types/node": "^25.9.1", "@vitejs/plugin-vue": "^6.0.6", + "@vue/tsconfig": "^0.9.1", "prettier": "^3.3.3", - "vite": "^8.0.10" + "typescript": "^6.0.3", + "vite": "^8.0.10", + "vue-tsc": "^3.3.1" } } diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 352ec61..0f9e0e5 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,5 +1,5 @@ - @@ -58,7 +60,7 @@ function onClick(col, row) {
-

${{ row * game.config.SCORE_TICK }}

+

${{ row * game.scoreTick }}

diff --git a/frontend/src/components/HostControls.vue b/frontend/src/components/HostControls.vue index e2f36a6..4b98c97 100644 --- a/frontend/src/components/HostControls.vue +++ b/frontend/src/components/HostControls.vue @@ -1,21 +1,23 @@ - diff --git a/frontend/src/components/HostFooterDrawer.vue b/frontend/src/components/HostFooterDrawer.vue index 6a790b1..3a7101d 100644 --- a/frontend/src/components/HostFooterDrawer.vue +++ b/frontend/src/components/HostFooterDrawer.vue @@ -1,5 +1,5 @@ - @@ -107,7 +107,7 @@ function toggleCustom() { v-if="customEditing" class="form-color form-edit" contenteditable="true" - @input="customText = $event.target.innerText" + @input="customText = ($event.target as HTMLElement).innerText" > {{ customText }} diff --git a/frontend/src/components/HostHeaderDrawer.vue b/frontend/src/components/HostHeaderDrawer.vue index 88055d1..19f71f3 100644 --- a/frontend/src/components/HostHeaderDrawer.vue +++ b/frontend/src/components/HostHeaderDrawer.vue @@ -1,13 +1,13 @@ - diff --git a/frontend/src/components/QuestionOverlay.vue b/frontend/src/components/QuestionOverlay.vue index 5ef4128..1f9e108 100644 --- a/frontend/src/components/QuestionOverlay.vue +++ b/frontend/src/components/QuestionOverlay.vue @@ -1,5 +1,5 @@ -