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>
64 lines
2.3 KiB
JavaScript
64 lines
2.3 KiB
JavaScript
/**
|
|
* Runnable house-pattern generators (WP-43). `npm run gen <name>` or the `gen:*` scripts.
|
|
* These emit the boilerplate the skills used to describe by hand; each generated unit ships
|
|
* with its co-located spec so the "domain/pure logic must have a spec" rule holds by default.
|
|
*
|
|
* Generators here are the pure-TS patterns (no Angular-template escaping): value objects and
|
|
* form/wizard state machines. The UI-component and bff-endpoint patterns stay skill-driven —
|
|
* they span the template `{{ }}` syntax / the C# backend + `gen:api` regen, where a generator
|
|
* adds little over the recipe.
|
|
*
|
|
* Positional args skip the prompts, e.g. `npx plop value-object registratie KvkNummer`.
|
|
*/
|
|
export default function (plop) {
|
|
const CONTEXT_PROMPT = {
|
|
type: 'input',
|
|
name: 'context',
|
|
message: 'Context (shared | auth | registratie | herregistratie | brief | beheer):',
|
|
};
|
|
const remindEnXlf = () =>
|
|
'⚠ The generated $localize id needs an English <target> in src/locale/messages.en.xlf before `npm run ci` (the localize gate fails otherwise).';
|
|
|
|
plop.setGenerator('value-object', {
|
|
description: 'Branded value object + parser + spec ("parse, don\'t validate")',
|
|
prompts: [
|
|
CONTEXT_PROMPT,
|
|
{ type: 'input', name: 'name', message: 'Name (PascalCase, e.g. KvkNummer):' },
|
|
],
|
|
actions: [
|
|
{
|
|
type: 'add',
|
|
path: 'src/app/{{context}}/domain/value-objects/{{kebabCase name}}.ts',
|
|
templateFile: 'plop-templates/value-object.hbs',
|
|
},
|
|
{
|
|
type: 'add',
|
|
path: 'src/app/{{context}}/domain/value-objects/{{kebabCase name}}.spec.ts',
|
|
templateFile: 'plop-templates/value-object.spec.hbs',
|
|
},
|
|
remindEnXlf,
|
|
],
|
|
});
|
|
|
|
plop.setGenerator('form-machine', {
|
|
description: 'Elm-style form/wizard state machine (Model/Msg/pure reduce) + spec',
|
|
prompts: [
|
|
CONTEXT_PROMPT,
|
|
{ type: 'input', name: 'name', message: 'Machine name (PascalCase, e.g. Adreswijziging):' },
|
|
],
|
|
actions: [
|
|
{
|
|
type: 'add',
|
|
path: 'src/app/{{context}}/domain/{{kebabCase name}}.machine.ts',
|
|
templateFile: 'plop-templates/form-machine.hbs',
|
|
},
|
|
{
|
|
type: 'add',
|
|
path: 'src/app/{{context}}/domain/{{kebabCase name}}.machine.spec.ts',
|
|
templateFile: 'plop-templates/form-machine.spec.hbs',
|
|
},
|
|
remindEnXlf,
|
|
],
|
|
});
|
|
}
|