Skip to content

Fix typia - #233

Merged
jho406 merged 3 commits into
v2from
fix-typia
Sep 29, 2026
Merged

jho406 merged 3 commits into
v2from
fix-typia

Conversation

@jho406

@jho406 jho406 commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator

This fixes typia integration which wasn't working because the transformation of useContent took place after the typecheck which end up skipped by typia. This uses a different strategy that takes inspiration from the preamble plugin and the path plugin to inline the change.

jho406 and others added 3 commits September 29, 2026 17:39
The `require` conditions for `./typia` and `./deepkit` pointed at
`dist/*.cjs`, but tsup emits `dist/*.js`, so requiring either subpath
failed with MODULE_NOT_FOUND.

Remove the `superglueTypia` export. It re-exported `@ttsc/unplugin`
through a bare `require`, which is undefined in the ESM build, so it
was always `null` there. Apps can import `@ttsc/unplugin` directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The typia plugin rewrote `useContent<T>()` to pass
`{ validate: typia.createValidate<T>() }`, but typia never expanded it.
Typia only transforms calls the checker resolves to its own
declarations, and the rewrite rebuilt the call and its ancestors after
type-checking, so the checker could not resolve the injected callee.
The emitted code referenced an undefined `typia` at runtime.

Two changes let typia resolve the injected call:

- Add a `SourcePreamble` that prepends
  `import __superglueTypia from "typia"` to every file before parsing,
  so the injected callee refers to a real, checked binding. Files
  without hooks never reference it, so import elision drops it.
- Mutate each hook call in place instead of rebuilding it through a
  visitor, so the injected nodes hang off the original, bound parse
  tree. The injected callee borrows the hook identifier's source range
  because typia reads the callee's text to label its errors.

The ttsc descriptor now raises a clear error when typia is not
installed, since the preamble would otherwise fail to type-check in
every file.

Add end-to-end specs that run the real ttsc CLI with typia hosting the
build, which the existing specs never exercised. ttsc needs the native
TypeScript 7 compiler, so add `@typescript/native-preview` (it ships
`tsgo`, avoiding a clash with TypeScript 5's `tsc`) and point ttsc at
it through `TTSC_TSGO_BINARY`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`useContent` and `useFragment` logged failed validation with
`console.error` and kept rendering. Under SSR, Humid forwards
`console.error` to the Rails logger but drops every argument after the
first, so the errors never appeared and nothing surfaced the failure.

Throw a `ContentValidationError` instead. It keeps the validator's
errors on `error.errors` and lists each one in the message, for both
the typia (`{ path, expected, value }`) and deepkit
(`{ path, message, value }`) shapes. Under SSR Humid raises it as a
`Humid::RenderError`. It only throws when a validator is present,
which the typia and deepkit plugins inject in builds that run them.

Export `ContentValidationError` so apps can match on it, and pass
deepkit's `value` through so its messages include the offending value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jho406
jho406 merged commit 3cad259 into v2 Sep 29, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant