refactor(app): migrate main + preload to TypeScript with typed seams (Phase 5d-3c-ii)

Convert the app's main and preload source from .js to .ts (git mv preserves
history), adding types where they carry value: the core-consumption seam
(BuildIndexOptions/BuildIndexResult, FileInfo), the indexer service/worker
factories, and the preload IPC bridge. Module-to-module specifiers use the
real .ts extension (mirroring scripts/, since Node type-stripping does not
rewrite .js->.ts); the worker's runtime path stays indexer-worker.js because
that is the built output.

Toolchain:
- Add app/tsconfig.json: strict but noImplicitAny:false (the app orchestrates
  the already-strict core; annotating every SQLite-handle helper is low-value
  churn) + allowImportingTsExtensions (safe under noEmit).
- Add @types/better-sqlite3 for the injected binding.
- electron.vite.config.ts inputs -> .ts; refresh the stale CommonJS comment.
- typecheck script runs root + app projects. Root tsconfig excludes the
  app-importing tests (app-*.test.mjs, recap-capture-query.test.mjs) so the
  lenient app files are not dragged into the strict root program; the app
  source is covered by app/tsconfig.json instead. See docs/adr/0005.

Verified: npm run typecheck (root + app) clean; suite 121/121; electron-vite
build emits all 6 main entries + preload with no .ts/node:sqlite residue in
the bundles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tommy0103
2026-07-09 16:25:59 +08:00
co-authored by Claude Opus 4.8
parent 60d47a852e
commit 01a390fa10
21 changed files with 299 additions and 151 deletions
+10 -10
View File
@@ -2,22 +2,22 @@ import { resolve } from 'node:path';
import { defineConfig, externalizeDepsPlugin } from 'electron-vite';
import vue from '@vitejs/plugin-vue';
// Kept CommonJS for the first electron-vite boot (no "type":"module" yet); the
// TS + ESM migration is a later stage. Each main-process module is its own input
// so it is emitted to out/main/<name>.js and the CommonJS require("./x") calls
// between them (and `new Worker(__dirname/indexer-worker.js)`) resolve at runtime.
// The app main/preload/renderer are TypeScript + ESM. Each main-process module
// is its own rollup input so it is emitted to out/main/<name>.js and the
// relative imports between them (and `new Worker(__dirname/indexer-worker.js)`)
// resolve to the built .js at runtime.
export default defineConfig({
main: {
plugins: [externalizeDepsPlugin()],
build: {
rollupOptions: {
input: {
index: resolve('src/main/index.js'),
indexer: resolve('src/main/indexer.js'),
'indexer-service': resolve('src/main/indexer-service.js'),
'indexer-worker': resolve('src/main/indexer-worker.js'),
'indexer-worker-client': resolve('src/main/indexer-worker-client.js'),
'recap-capture-query': resolve('src/main/recap-capture-query.js'),
index: resolve('src/main/index.ts'),
indexer: resolve('src/main/indexer.ts'),
'indexer-service': resolve('src/main/indexer-service.ts'),
'indexer-worker': resolve('src/main/indexer-worker.ts'),
'indexer-worker-client': resolve('src/main/indexer-worker-client.ts'),
'recap-capture-query': resolve('src/main/recap-capture-query.ts'),
},
},
},