fix(compiler): strip TypeScript from client function bodies
`wrnexus build` failed on any client function whose body used TypeScript:
const requestBody: Record<string, unknown> = {}
error: Expected ";" but found ":"
Codegen copies a client function's body into the browser module verbatim.
It removes the types from the function's *signature*, which is what made
this easy to miss -- the emitted module looked transpiled, and only bodies
carried types through. The artifact is written as .mjs and read back as
plain JavaScript, so the failure surfaced as a syntax error in generated
code rather than at the .wrn line responsible.
Browser modules are now transpiled before they are written, at all three
sites that emit one (the production build and both dev-server paths).
Reproduced end to end: a page with an annotated body failed the build with
the reported errors, and after the fix builds, ships valid minified JS, and
runs -- the handler sets its state correctly in a browser.
Note: the same body is also embedded as a string for the CSP-safe fallback
interpreter, which still receives it untranspiled. The compiled module
shadows the fallback, so this is only reachable in the window before that
module loads. Left alone here because stripping it lives in codegen, which
also runs under Node in the editor bundle where the Bun transpiler is
unavailable.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Strip TypeScript from a generated browser module.
|
||||
*
|
||||
* A client function's body is emitted verbatim, so anything TypeScript-only
|
||||
* inside one -- an annotated local, an `as` cast, a local interface -- reaches
|
||||
* the browser module as TypeScript source. Codegen removes the types from the
|
||||
* function's *signature*, which is what made this easy to miss: the emitted
|
||||
* module looked transpiled, and only bodies carried types through.
|
||||
*
|
||||
* The artifact is written as `.mjs` and read back as plain JavaScript, so the
|
||||
* failure surfaced as a syntax error pointing at generated code rather than at
|
||||
* the `.wrn` line responsible.
|
||||
*/
|
||||
|
||||
let transpiler: { transformSync(code: string): string } | null = null;
|
||||
|
||||
export function stripBrowserTypes(code: string): string {
|
||||
const bun = (
|
||||
globalThis as unknown as {
|
||||
Bun?: { Transpiler: new (options: unknown) => { transformSync(code: string): string } };
|
||||
}
|
||||
).Bun;
|
||||
|
||||
if (!bun?.Transpiler) {
|
||||
throw new Error(
|
||||
"WRN-CLIENT-TS: emitting a browser module needs the Bun transpiler to remove TypeScript from client function bodies.",
|
||||
);
|
||||
}
|
||||
|
||||
transpiler ??= new bun.Transpiler({ loader: "ts", target: "browser" });
|
||||
|
||||
return transpiler.transformSync(code);
|
||||
}
|
||||
@@ -31,6 +31,7 @@ export {
|
||||
export { generate } from "./codegen.ts";
|
||||
export { generateTargets } from "./targets.ts";
|
||||
export { generateBrowserModule } from "./client-codegen.ts";
|
||||
export { stripBrowserTypes } from "./browser-transpile.ts";
|
||||
export { generateServerFunctionsModule, rpcManifest } from "./server-codegen.ts";
|
||||
export { generateDeclarations } from "./type-codegen.ts";
|
||||
export { generateStoreBrowserModule, generateStoreModule } from "./store-codegen.ts";
|
||||
|
||||
Reference in New Issue
Block a user