8 template-generic skills in .claude/skills/ (new-feature, new-context, value-object, form-machine, bff-endpoint, mutation-command, ui-component, new-ssp), condensed from CLAUDE.md/ARCHITECTURE/fp-tea/ADRs and pointing at this repo's worked examples. CLAUDE.md gains a pointer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1.9 KiB
1.9 KiB
name, description
| name | description |
|---|---|
| value-object | Add a validated input type (postcode, email, hours, id number, …) as a branded value object with a parser — "parse, don't validate". Use whenever a form field or API value has format rules. |
Value object (parse, don't validate)
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.
Skeleton
<context>/domain/value-objects/<name>.ts (pure TS, no Angular):
import { Brand, Result, ok, err } from '@shared/kernel/fp';
export type Postcode = Brand<string, 'Postcode'>;
export function parsePostcode(raw: string): Result<string, Postcode> {
const t = raw.trim().toUpperCase();
if (!/^[1-9]\d{3}\s?[A-Z]{2}$/.test(t)) {
return err($localize`:@@validation.postcode:Voer een geldige postcode in, bijv. 1234 AB.`);
}
// The parser also normalises — callers always hold the canonical form.
return ok(t.replace(/^(\d{4})\s?([A-Z]{2})$/, '$1 $2') as Postcode);
}
Rules:
- The
as Brandcast appears only inside the parser — the type is mintable nowhere else. - Error message is user-facing →
$localizewith a stable@@validation.<name>id. - Trim/normalise before testing; return the cleaned value.
- This is format feedback only. The server re-validates as authority (ADR-0001) — never encode business rules (existence, eligibility) here.
Spec (required)
Co-located <name>.spec.ts: happy path, normalisation, each rejection case. Call the
parser directly — no TestBed.
Wiring into a form
The machine's validate(draft) calls the parsers and collects errors into
StepErrors; the Valid type holds the branded values (see form-machine skill).
Worked examples
src/app/registratie/domain/value-objects/ — postcode.ts, email.ts, uren.ts,
big-nummer.ts, each with a co-located spec.
Verify
npm test && npm run lint