islandflow/docs/turns/2026-05-29-add-typecheck-command.html
dirtydishes e9e2723c28
Some checks are pending
CI / Validate (push) Waiting to run
add repo-wide typechecking
2026-05-29 02:19:30 -04:00

260 lines
8.4 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Add repository typecheck command</title>
<style>
:root {
color-scheme: light;
--bg: oklch(0.985 0.006 235);
--ink: oklch(0.22 0.018 245);
--muted: oklch(0.46 0.018 245);
--line: oklch(0.88 0.012 245);
--panel: oklch(0.998 0.003 245);
--accent: oklch(0.48 0.11 235);
--accent-soft: oklch(0.93 0.035 235);
--code: oklch(0.25 0.025 245);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background: var(--bg);
color: var(--ink);
font-family:
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
line-height: 1.58;
}
main {
width: min(1080px, calc(100% - 40px));
margin: 0 auto;
padding: 56px 0 72px;
}
header {
border-bottom: 1px solid var(--line);
margin-bottom: 36px;
padding-bottom: 28px;
}
.eyebrow {
color: var(--accent);
font-size: 0.78rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
h1 {
font-size: clamp(2rem, 5vw, 4.25rem);
line-height: 1;
margin: 10px 0 18px;
max-width: 900px;
}
h2 {
border-top: 1px solid var(--line);
font-size: 1.15rem;
margin: 34px 0 10px;
padding-top: 22px;
}
p,
li {
color: var(--muted);
max-width: 76ch;
}
strong {
color: var(--ink);
}
code {
color: var(--code);
font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
font-size: 0.92em;
}
pre {
background: var(--panel);
border: 1px solid var(--line);
border-radius: 8px;
color: var(--code);
overflow-x: auto;
padding: 16px;
}
.summary {
background: var(--accent-soft);
border: 1px solid oklch(0.83 0.04 235);
border-radius: 8px;
padding: 18px 20px;
}
.meta {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 20px;
}
.pill {
background: var(--panel);
border: 1px solid var(--line);
border-radius: 999px;
color: var(--muted);
font-size: 0.85rem;
padding: 6px 10px;
}
</style>
</head>
<body>
<main>
<header>
<div class="eyebrow">Turn document</div>
<h1>Add repository typecheck command</h1>
<p class="summary">
Added a root <code>bun run typecheck</code> command that scans the monorepo workspaces and runs
TypeScript checks for every workspace with a <code>tsconfig.json</code>. The command now passes across apps,
packages, and services.
</p>
<div class="meta">
<span class="pill">Created: 2026-05-29 02:18 EDT</span>
<span class="pill">Beads: islandflow-wvz</span>
<span class="pill">Validation: typecheck and test suite passed</span>
</div>
</header>
<section>
<h2>Summary</h2>
<p>
The repository now has a first-class typecheck gate. Running <code>bun run typecheck</code> checks every
workspace TypeScript project under <code>apps</code>, <code>services</code>, and <code>packages</code>, reports
failures per workspace, and exits non-zero if any project fails.
</p>
</section>
<section>
<h2>Changes Made</h2>
<ul>
<li>Added <code>scripts/typecheck.ts</code>, a Bun runner that discovers workspace <code>tsconfig.json</code> files.</li>
<li>Added the root <code>typecheck</code> package script.</li>
<li>Added root development dependencies for <code>typescript</code>, <code>@types/bun</code>, and <code>@types/ws</code>.</li>
<li>Updated workspace <code>tsconfig.json</code> files to include Bun runtime types instead of stripping all globals.</li>
<li>Fixed type errors exposed by the new gate in tests, JetStream config, storage JSON decoding, API live fanout, and WebSocket payload decoding.</li>
</ul>
</section>
<section>
<h2>Context</h2>
<p>
Before this change, the desktop app had a local typecheck script, but the repository did not have a single
command for checking the whole Bun and TypeScript monorepo. The first run surfaced both configuration issues
and real type mismatches that were not visible from existing validation commands.
</p>
</section>
<section>
<h2>Important Implementation Details</h2>
<p>
The typecheck runner intentionally discovers workspace projects from the existing folder structure rather than
maintaining a hard-coded list. It passes <code>--incremental false</code> so checking the Next.js workspace does
not leave tracked <code>tsconfig.tsbuildinfo</code> churn behind.
</p>
<p>
Workspace configs now use <code>"types": ["bun"]</code>. This matches the runtime and test environment used by
the repo while preserving explicit control over global types.
</p>
</section>
<section>
<h2>Relevant Diff Snippets</h2>
<p>
Attempted to use <code>@pierre/diffs</code> as requested by the repository instructions, but the installed
package exposes library exports and no executable CLI. The snippets below are therefore the documented plain
diff fallback.
</p>
<pre><code>diff --git a/package.json b/package.json
@@
"deploy:current-branch": "./deploy current-branch",
+ "typecheck": "bun run scripts/typecheck.ts",
@@
"devDependencies": {
+ "@types/bun": "^1.3.3",
+ "@types/ws": "^8.18.1",
+ "typescript": "^5.9.3",
"typescript-language-server": "^5.1.3"
}</code></pre>
<pre><code>diff --git a/scripts/typecheck.ts b/scripts/typecheck.ts
+const workspaceRoots = ["apps", "services", "packages"];
+const tsconfigs = workspaceRoots.flatMap((root) =&gt; findTsconfigs(root)).sort();
+
+for (const tsconfig of tsconfigs) {
+ const result = Bun.spawnSync([
+ "bunx",
+ "tsc",
+ "-p",
+ tsconfig,
+ "--noEmit",
+ "--incremental",
+ "false",
+ "--pretty",
+ "false"
+ ]);
+}</code></pre>
<pre><code>diff --git a/packages/bus/src/jetstream.ts b/packages/bus/src/jetstream.ts
@@
- retention: "limits",
- storage: "file",
- discard: "old",
+ retention: RetentionPolicy.Limits,
+ storage: StorageType.File,
+ discard: DiscardPolicy.Old,</code></pre>
<pre><code>diff --git a/packages/bus/tsconfig.json b/packages/bus/tsconfig.json
@@
- "types": []
+ "types": ["bun"]</code></pre>
</section>
<section>
<h2>Expected Impact for End-Users</h2>
<p>
Developers now have one obvious command to validate TypeScript correctness before handoff or deployment:
<code>bun run typecheck</code>. This should catch drift across shared packages and services earlier, especially
when changes cross workspace boundaries.
</p>
</section>
<section>
<h2>Validation</h2>
<ul>
<li><code>bun run typecheck</code> passed across all discovered workspace <code>tsconfig.json</code> files.</li>
<li><code>bun test</code> passed: 250 tests, 0 failures, 994 assertions.</li>
<li>Confirmed the typecheck script no longer modifies <code>apps/web/tsconfig.tsbuildinfo</code>.</li>
</ul>
</section>
<section>
<h2>Issues, Limitations, and Mitigations</h2>
<p>
The command checks workspace TypeScript projects that already have a <code>tsconfig.json</code>. If a new
workspace is added without a config file, it will not be checked until that config exists. The runner prints
each checked config path to make coverage visible during validation.
</p>
</section>
<section>
<h2>Follow-up Work</h2>
<p>
No required follow-up remains for this task. A useful future improvement would be adding the new typecheck
command to CI once the Forgejo pipeline is ready for a broader quality gate.
</p>
</section>
</main>
</body>
</html>