feat: add a webjs typecheck command (tsc --noEmit wrapper) - #307
Conversation
webjs ships erasable TypeScript as a first-class authoring mode (strict + noEmit + erasableSyntaxOnly + @webjsdev/ts-plugin) but had no command to run the type checker. The runtime only catches strip-time failures (non-erasable syntax) with a 500; genuine type errors were surfaced by nothing, since webjs check is correctness-only and explicitly does not type-check. Add `webjs typecheck`: it resolves the project's OWN typescript/bin/tsc (via createRequire from the app cwd, so it reads the app's tsconfig) and spawns it with --noEmit, passing extra args through, exiting non-zero on a type error so it works as a CI gate. When TypeScript is not installed it prints a clear message and exits non-zero. The framework runs the standard compiler, it does not embed one. The scaffold now ships a typecheck npm script and typescript as a devDependency, with CONVENTIONS.md documenting it as the separate is-my-TypeScript-valid gate to add to CI once the app type-checks cleanly. Not auto-added to the scaffold CI to avoid a day-one failure before the app is verified to type-check. Closes #265
vivek7405
left a comment
There was a problem hiding this comment.
Reviewed the command logic, the test, and the one judgment call. The command is right: it resolves the project's own typescript/bin/tsc via createRequire from the app cwd (so it reads the app's tsconfig), spawns it with --noEmit and a passthrough for extra args, and propagates the child exit code so it works as a CI gate; tsc with a bare flag still reads tsconfig, confirmed by the clean-exits-0 and type-error-exits-nonzero fixtures. Graceful degradation prints the npm install -D typescript fix and exits non-zero. The test spawns the real CLI for all three paths and cleans its fixtures (no stray dirs in git status, the no-typescript fixture lives in the OS tmpdir outside the repo tree so typescript is genuinely unresolvable).
The one decision worth checking was omitting the scaffold CI gate, and it is correct: @webjsdev/server ships no .d.ts, so a fresh scaffold importing createRequestHandler from it would emit TS7016 under strict, meaning a hard typecheck gate in the scaffold CI would fail on day one. Shipping the script and documenting it, while leaving the gate to the author once the app type-checks, is the right out-of-box posture. Full suite 1944 (the known flaky CSP-nonce test passed). Good to merge once CI is green.
Closes #265
What
webjs ships erasable TypeScript as a first-class authoring mode (strict + noEmit + erasableSyntaxOnly +
@webjsdev/ts-plugin) but had no command to run the type checker. The runtime only catches strip-time failures (non-erasable syntax) with a 500; genuine type errors were surfaced by nothing, sincewebjs checkis correctness-only and explicitly does not type-check.Add
webjs typecheck: it resolves the project's OWNtypescript/bin/tsc(viacreateRequirefrom the app cwd, so it reads the app'stsconfig) and spawns it with--noEmit, passing extra args through (e.g.webjs typecheck --watch), exiting non-zero on a type error so it works as a CI gate. When TypeScript is not installed it prints a clear message and exits non-zero. The framework runs the standard compiler, it does not embed one.The scaffold now ships a
typechecknpm script andtypescriptas a devDependency, withCONVENTIONS.mddocumenting it as the separate is-my-TypeScript-valid gate.A deliberate scope decision
I did NOT add
npm run typecheckas a hard step in the scaffold's CI workflow. A CI gate that fails on a fresh scaffold (before the app's example code is verified to type-check cleanly, and@webjsdev/serverships no.d.ts) would be a day-one out-of-box failure, which is worse than a missing gate. The script and the docs make it one line away once the app type-checks.Tests
test/cli/typecheck.test.mjsspawns the real CLI: a clean TS app exits 0, a type error exits non-zero with thetscerror reported, and a project without TypeScript prints the clear message and exits non-zero. (The success/error fixtures live under the repo sotypescriptresolves; the no-typescript fixture lives in the OS tmpdir, outside the repo tree.) Scaffold-integration 5/5, full suite 1944.Docs
Root
AGENTS.mdCLI reference,packages/cli/AGENTS.mdcommand table, scaffoldCONVENTIONS.md.Scope
CLI + scaffold + docs. No version bump (next release batch).