diff --git a/jsconfig.json b/jsconfig.json deleted file mode 100644 index 17ea4fb..0000000 --- a/jsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "ignoreDeprecations": "6.0", - "paths": { - "@/*": ["./client/*"] - }, - "jsx": "react-jsx", - "module": "ESNext", - "moduleResolution": "bundler", - "resolveJsonModule": true - }, - "include": ["client/**/*"], - "exclude": ["node_modules", "dist"] -} diff --git a/package-lock.json b/package-lock.json index 5a2ce63..f41a4c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,6 +54,8 @@ "@eslint/js": "^9.39.4", "@playwright/test": "^1.50.1", "@testing-library/react": "^16.3.2", + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^4.3.3", "autoprefixer": "^10.4.20", "babel-plugin-react-compiler": "^1.0.0", @@ -65,6 +67,7 @@ "jsdom": "^29.1.1", "postcss": "^8.4.47", "tailwindcss": "^3.4.14", + "typescript": "^6.0.3", "vite": "^5.4.10", "vite-plugin-pwa": "^1.3.0", "vitest": "^4.1.8" @@ -6026,6 +6029,26 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/react": { + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "devOptional": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -7198,6 +7221,13 @@ "node": ">=4" } }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/data-urls": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", @@ -12969,6 +12999,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", diff --git a/package.json b/package.json index f410c6b..0f39f49 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "build": "vite build", "check:server": "find server.js db middleware routes services utils -name '*.js' -print0 | xargs -0 -n1 node --check", "lint": "eslint client", + "typecheck": "tsc --noEmit -p tsconfig.json", "check": "npm run check:server && npm run build", "test": "node --test tests/*.test.js", "test:client": "vitest run", @@ -19,7 +20,7 @@ "test:e2e:update": "node e2e/setup/prepare-db.js && playwright test --project=chromium-desktop --project=chromium-mobile --update-snapshots", "test:e2e:probe": "node e2e/setup/prepare-db.js && playwright test --project=probe", "smoke:prod": "bash scripts/prod-smoke.sh", - "ci": "npm run lint && npm run check:server && npm run test:all && npm run build", + "ci": "npm run lint && npm run typecheck && npm run check:server && npm run test:all && npm run build", "start": "node server.js" }, "dependencies": { @@ -68,6 +69,8 @@ "@eslint/js": "^9.39.4", "@playwright/test": "^1.50.1", "@testing-library/react": "^16.3.2", + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^4.3.3", "autoprefixer": "^10.4.20", "babel-plugin-react-compiler": "^1.0.0", @@ -79,6 +82,7 @@ "jsdom": "^29.1.1", "postcss": "^8.4.47", "tailwindcss": "^3.4.14", + "typescript": "^6.0.3", "vite": "^5.4.10", "vite-plugin-pwa": "^1.3.0", "vitest": "^4.1.8" diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1a95308 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2023", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "paths": { "@/*": ["./client/*"] }, + "resolveJsonModule": true, + "esModuleInterop": true, + "isolatedModules": true, + "skipLibCheck": true, + "noEmit": true, + + // Gradual adoption: existing .js/.jsx still resolve and run untouched + // (checkJs off = not type-checked), while new/converted .ts/.tsx are checked + // under full strict mode. Convert file-by-file; nothing breaks in between. + "allowJs": true, + "checkJs": false, + "strict": true, + "noUncheckedIndexedAccess": true, + + "types": ["vite/client"] + }, + "include": ["client/**/*"], + "exclude": ["node_modules", "dist", "client/**/*.test.*"] +}