feat(dx): WP-43 — plop generators (value-object, form-machine)
CI / frontend (push) Successful in 3m11s
CI / backend (push) Successful in 2m27s
CI / storybook-a11y (push) Successful in 9m28s
CI / e2e (push) Successful in 4m38s
CI / semgrep (push) Successful in 1m20s
CI / api-client-drift (push) Successful in 2m13s

Runnable `npm run gen:value-object` / `gen:form-machine` (plop) that scaffold the two
pure-TS house patterns with a co-located spec: a branded value object + parseX (mirrors
postcode/bsn), and an Elm-style form/wizard machine (Draft/Valid/Errors + Editing/
Submitting/Submitted/Failed union + initial/pure reduce/assertNever). Prompts take
context + PascalCase name (positional-arg bypass); a post-action reminds to add the
English target for the generated $localize id. Templates in plop-templates/ (prettier-
ignored). Skills (value-object, form-machine) point at the generators. ui-component +
bff-endpoint stay skill-driven (Angular {{}} / backend + gen:api).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
eho
2026-07-23 18:04:54 +02:00
co-authored by Claude Opus 4.8
parent 00c5faacb9
commit deb5d77e04
12 changed files with 1130 additions and 53 deletions
+5
View File
@@ -9,6 +9,11 @@ If you're about to add a second boolean to track state, stop — model a discrim
union. Fields exist only in the states that need them, so illegal states are
unrepresentable.
**Scaffold it:** `npm run gen:form-machine` (WP-43) emits `<name>.machine.ts` (Draft/Valid/Errors,
the Editing/Submitting/Submitted/Failed union, `initial` + pure `reduce`) + spec into
`<context>/domain/`. Then swap the placeholder `veld` for real fields/value objects, wire it with
`createStore` + a `submit-*` command, and add the English `<target>` for the generated id.
## Skeleton
`<context>/domain/<name>.machine.ts` (pure TS, no Angular imports):
+4
View File
@@ -8,6 +8,10 @@ description: Add a validated input type (postcode, email, hours, id number, …)
Raw input becomes a branded type only via a parser returning `Result`. Once you hold
the type, never re-check it. Never model validity as a boolean flag next to a string.
**Scaffold it:** `npm run gen:value-object` (WP-43) emits the branded type + `parseX` + spec
into `<context>/domain/value-objects/`. Then fill in the real format rule and add the English
`<target>` for the generated `@@validation.<name>` id (the localize gate).
## Skeleton
`<context>/domain/value-objects/<name>.ts` (pure TS, no Angular):