90 lines
7.1 KiB
Markdown
90 lines
7.1 KiB
Markdown
# Diagnostics guide
|
|
|
|
hemx diagnostics should tell a Rust developer which template fact, generated
|
|
helper, or handler shape is wrong, and what to change next. They should not teach
|
|
raw ids, selector targeting, runtime opcodes, or Cargo internals in the normal
|
|
path. req: diagnostics/001 req: diagnostics/002 req: diagnostics/003
|
|
|
|
Use this guide as the v1 checklist for common mistakes in beginner and
|
|
production-shaped apps. Structured `hemx-build` diagnostics expose a file path,
|
|
directive, target, expected template fact, and repair action so an optional
|
|
editor overlay can share compiler authority without becoming a custom editor
|
|
framework.
|
|
|
|
## Where errors happen
|
|
|
|
- **Template/build diagnostics** come from `hemx_build::app().run()` while reading
|
|
`.heml` files and CSS. Fix the template or generated-surface convention.
|
|
- **Derive/compile diagnostics** come from `#[hemx::surface]`, `#[hemx::form]`,
|
|
`#[hemx::handler]`, `#[hemx::component]`, and `#[hemx::app]`. Fix Rust code so
|
|
it matches the generated surface.
|
|
- **Runtime diagnostics** come from the tiny browser runtime when a deployed page
|
|
and response are incompatible or a target cannot be applied. Fix deployment or
|
|
recover with a full page response. req: failure/005
|
|
|
|
## Common mistakes and fixes
|
|
|
|
| Mistake | Diagnostic shape | Fix |
|
|
| --- | --- | --- |
|
|
| Handler has no matching template handle | `unknown hemx handle \`save\`; add \`data-hemx-handle="save"\`` | Add the handle to the template, rename the function, or put the handler in the matching component. |
|
|
| Component is missing a generated handler | `#[hemx::component] missing handler implementation(s): delete` | Add a `#[hemx::handler] fn delete(...)` in that component, or remove the template handle. |
|
|
| Handler name is ambiguous across components | `ambiguous generated handle name(s): save` | Scope the component with `#[hemx::component("todos")]` or rename handles so the generated path is unique. |
|
|
| Handler misses generated params | `hemx handler \`show\` is missing generated param argument(s): mode` | Add typed handler arguments for every `data-hemx-param-*` fact generated by the template. |
|
|
| Form handler omits the form argument | `handles a generated form and must accept a typed form argument` | Accept `Form<NewThing>`/`hemx::Form<NewThing>`/integration equivalent and derive `#[hemx::form("...")]` for the type. |
|
|
| Form struct misses a control | `hemx form \`new_todo\` is missing field \`title\`` | Add a Rust field matching the form control name, or rename the template control. |
|
|
| Required/multiple form control has wrong Rust shape | `required ... must not be Option<_>` or `accepts multiple values and must be Vec<_>` | Match HTML required/multiple semantics with `T`, `Option<T>`, or `Vec<T>` as appropriate. |
|
|
| Form field type cannot parse submitted values | compiler mentions `T: FormValue` / `T: hemx::FormValue` | Implement `FromStr`/the expected form value trait for the domain newtype, or use a parseable domain type. |
|
|
| Generated resources are unavailable | `could not find generated hemx module` / `could not find generated hemx symbols` plus `add hemx_build::app().run()? to build.rs` | Add or fix `build.rs`, then rerun `cargo check`; do not copy `$OUT_DIR` paths into app code. |
|
|
| Unknown `data-hemx-*` attribute | `unknown hemx attribute ... check the spelling or use a non-hemx data-* attribute` | Fix the spelling, use the supported hemx attribute, or rename app metadata to a non-hemx `data-*` attribute. |
|
|
| Selector-style targeting | ``data-hemx-target` is selector-style targeting; hemx uses generated resources` | Put `data-hemx-slot` on the local target and return a generated slot/page/form effect. |
|
|
| Generated target appears in a loop without a stable key | `inside an h-for without h-key; add a stable h-key="item.id"` | Add a stable `h-key` to the owning loop; use generated keyed helpers for row updates. |
|
|
| Page/SSE attributes are on the wrong element | `expected a real <a href=...>` / `expected placement on the same element as data-hemx-root` | Keep page navigation on anchors and put root-scoped runtime attributes on the root element. |
|
|
| Result handler error type is not mappable | compiler reports the error type does not satisfy `IntoHandlerFailure` | Implement `IntoHandlerFailure` for the app error, or keep expected validation as generated UI effects instead of `Err`. req: failure/004 |
|
|
| Old page talks to a new server/runtime | runtime refuses the partial update on fingerprint mismatch | Serve a self-consistent release or fall back to full page reload/navigation. See `docs/recipes/deploy-versioning.md`. req: abi/004 |
|
|
| Missing runtime target | runtime emits a missing-target diagnostic in development and fails/no-ops according to target kind | Fix the template/generated helper mismatch; do not retarget with selectors. req: failure/001 |
|
|
|
|
## What a good diagnostic should include
|
|
|
|
A v1-quality diagnostic should include:
|
|
|
|
- the user-facing name: handle, form, slot, key, param, class, event, or template
|
|
- the source area: template path, Rust item, or deployment/runtime boundary
|
|
- the concrete expected shape, not an internal representation
|
|
- one next action that preserves generated helpers and the tiny runtime
|
|
|
|
Avoid beginner-facing messages that suggest `ResourceId`, `ResourceRef`, raw
|
|
`Effect`, manual registries, selector strings, or runtime opcodes. If an advanced
|
|
escape hatch is genuinely required, say that it is advanced and name the safer
|
|
normal path first. req: public_api/002 req: public_api/005
|
|
|
|
## Editor overlay boundary
|
|
|
|
A `.heml` editor overlay is optional and subordinate to the compiler. It may read
|
|
`docs/hemplate-syntax.md`, run or reuse `hemx-build` diagnostics, and present
|
|
compiler-shaped diagnostics, completion, hover, and navigation for documented
|
|
syntax and generated targets. It must not define a second template language,
|
|
formatter, selector targeting model, JavaScript expression layer, or custom editor
|
|
framework. If editor feedback disagrees with `hemx-build`, `hemx-build` wins.
|
|
req: diagnostics/004
|
|
|
|
## Verification anchors
|
|
|
|
Current recurring checks cover the most common classes:
|
|
|
|
- `cargo test -p hemx-build` covers template/build diagnostics such as unknown
|
|
hemx attributes, selector-style targeting, invalid runtime attribute values,
|
|
missing keys, and invalid page/SSE placement.
|
|
- `cargo test -p hemx-derive --test compile_fail` covers derive/compile
|
|
diagnostics for missing handlers, form mismatch, params, missing generated
|
|
files, unknown scoped components, ambiguous handles, and generated resource
|
|
lookup.
|
|
- `cargo test -p hemx-js` covers root-scoped runtime behavior, selectorless
|
|
targeting, fingerprint mismatch refusal, SSE application, and recoverable
|
|
runtime events.
|
|
- `cargo test -p hemx-test --test examples_contract` keeps public examples from
|
|
teaching forbidden normal-path constructs.
|
|
|
|
Before claiming the diagnostics story is closed for v1, run those gates plus
|
|
`cargo run -p hemx-xtask -- test`, `cargo check --workspace`, and
|
|
`redgate refs` on a clean tree. The installed CLI's `health` mode additionally requires every historical row to use its newer prescriptive wording, which is not the elected compatibility gate for this corpus. req: test/003 req: test/004
|