build(web): use @tsconfig/bases for tsconfig presets

Quentin Gliech and Claude Opus 4.6 (1M context) created

extend @tsconfig/vite-react and @tsconfig/strictest to replace
hand-rolled compiler options:

tsconfig.app.json:
- extends @tsconfig/strictest + @tsconfig/vite-react
- adds verbatimModuleSyntax, erasableSyntaxOnly, noUncheckedIndexedAccess,
  noImplicitOverride, noImplicitReturns, etc.
- disable exactOptionalPropertyTypes and noPropertyAccessFromIndexSignature
  (incompatible with generated GraphQL types)

tsconfig.node.json:
- extends @tsconfig/strictest for strict checks
- keeps bundler-specific options inline (no base covers this)

fix code issues caught by stricter settings:
- guard suggestions[acIndex] access (noUncheckedIndexedAccess)
- use optional chaining for nodes[0] access

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Change summary

webui2/package.json                       |  2 ++
webui2/pnpm-lock.yaml                     | 16 ++++++++++++++++
webui2/src/components/bugs/QueryInput.tsx |  3 ++-
webui2/src/routes/index.tsx               |  2 +-
webui2/tsconfig.app.json                  | 15 +++------------
webui2/tsconfig.node.json                 |  8 +++-----
6 files changed, 27 insertions(+), 19 deletions(-)

Detailed changes

webui2/package.json 🔗

@@ -46,6 +46,8 @@
     "@tailwindcss/typography": "^0.5.19",
     "@tailwindcss/vite": "^4.2.2",
     "@tanstack/router-plugin": "^1.167.9",
+    "@tsconfig/strictest": "^2.0.8",
+    "@tsconfig/vite-react": "^7.0.2",
     "@types/react": "^19.1.0",
     "@types/react-dom": "^19.1.0",
     "@vitejs/plugin-react": "^6.0.1",

webui2/pnpm-lock.yaml 🔗

@@ -96,6 +96,12 @@ importers:
       '@tanstack/router-plugin':
         specifier: ^1.167.9
         version: 1.167.9(@tanstack/react-router@1.168.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))
+      '@tsconfig/strictest':
+        specifier: ^2.0.8
+        version: 2.0.8
+      '@tsconfig/vite-react':
+        specifier: ^7.0.2
+        version: 7.0.2
       '@types/react':
         specifier: ^19.1.0
         version: 19.2.14
@@ -2078,6 +2084,12 @@ packages:
     engines: {node: '>=20.19'}
     hasBin: true
 
+  '@tsconfig/strictest@2.0.8':
+    resolution: {integrity: sha512-XnQ7vNz5HRN0r88GYf1J9JJjqtZPiHt2woGJOo2dYqyHGGcd6OLGqSlBB6p1j9mpzja6Oe5BoPqWmeDx6X9rLw==}
+
+  '@tsconfig/vite-react@7.0.2':
+    resolution: {integrity: sha512-lEj4y5SPRcH+bjw0tyuxrEnPqQUwfQzBKgd1YamD9xyet9zLwh2gwy5F8w/Nxg5DjdgYVjjKo5aLJUf0BTDz4w==}
+
   '@tybys/wasm-util@0.10.1':
     resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
 
@@ -5657,6 +5669,10 @@ snapshots:
 
   '@tanstack/virtual-file-routes@1.161.7': {}
 
+  '@tsconfig/strictest@2.0.8': {}
+
+  '@tsconfig/vite-react@7.0.2': {}
+
   '@tybys/wasm-util@0.10.1':
     dependencies:
       tslib: 2.8.1

webui2/src/components/bugs/QueryInput.tsx 🔗

@@ -256,7 +256,8 @@ export function QueryInput({ value, onChange, onSubmit, placeholder, className }
       setAcIndex((i) => (i - 1 + suggestions.length) % suggestions.length);
     } else if (e.key === "Enter" || e.key === "Tab") {
       e.preventDefault();
-      applySuggestion(suggestions[acIndex]);
+      const suggestion = suggestions[acIndex];
+      if (suggestion) applySuggestion(suggestion);
     } else if (e.key === "Escape") {
       setCompletion(null);
     }

webui2/src/routes/index.tsx 🔗

@@ -34,7 +34,7 @@ function RouteComponent() {
     if (data?.repositories.nodes.length === 1) {
       void navigate({
         to: "/$repo",
-        params: { repo: repoSlug(data.repositories.nodes[0].name) },
+        params: { repo: repoSlug(data.repositories.nodes[0]?.name) },
         search: { ref: "", path: "", type: "tree" as const },
         replace: true,
       });

webui2/tsconfig.app.json 🔗

@@ -1,17 +1,8 @@
 {
+  "extends": ["@tsconfig/strictest/tsconfig.json", "@tsconfig/vite-react/tsconfig.json"],
   "compilerOptions": {
-    "target": "ES2022",
-    "lib": ["ES2022", "DOM"],
-    "skipLibCheck": true,
-    "moduleResolution": "bundler",
-    "allowImportingTsExtensions": true,
-    "isolatedModules": true,
-    "moduleDetection": "force",
-    "noEmit": true,
-    "jsx": "react-jsx",
-    "noUnusedLocals": true,
-    "noUnusedParameters": true,
-    "noFallthroughCasesInSwitch": true,
+    "exactOptionalPropertyTypes": false,
+    "noPropertyAccessFromIndexSignature": false,
     "paths": {
       "@/*": ["./src/*"]
     }

webui2/tsconfig.node.json 🔗

@@ -1,17 +1,15 @@
 {
+  "extends": "@tsconfig/strictest/tsconfig.json",
   "compilerOptions": {
     "target": "ES2022",
     "lib": ["ES2023"],
     "types": ["node"],
     "moduleResolution": "bundler",
     "allowImportingTsExtensions": true,
-    "isolatedModules": true,
     "moduleDetection": "force",
     "noEmit": true,
-    "skipLibCheck": true,
-    "noUnusedLocals": true,
-    "noUnusedParameters": true,
-    "noFallthroughCasesInSwitch": true
+    "verbatimModuleSyntax": true,
+    "noPropertyAccessFromIndexSignature": false
   },
   "include": ["vite.config.ts", "codegen.ts"]
 }