feat(fp): WP-05 — parse-don't-validate closure + MDX
Close the three remaining unvalidated `as <DomainType>` casts at the wire boundary (intake-policy, big-register aantekening type, brief passage scope), each replaced by a Result-returning parser with a rejection-case spec, plus the Foundations/Parse, don't validate curriculum page.
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { parseAantekening } from './big-register.adapter';
|
||||
|
||||
describe('big-register.adapter parse boundary', () => {
|
||||
it('parses known aantekening types', () => {
|
||||
expect(parseAantekening({ type: 'Specialisme', omschrijving: 'x', datum: '2026-01-01' })).toEqual({
|
||||
ok: true,
|
||||
value: { type: 'Specialisme', omschrijving: 'x', datum: '2026-01-01' },
|
||||
});
|
||||
expect(parseAantekening({ type: 'Aantekening' })).toEqual({
|
||||
ok: true,
|
||||
value: { type: 'Aantekening', omschrijving: '', datum: '' },
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects an unknown type', () => {
|
||||
expect(parseAantekening({ type: 'Bogus' }).ok).toBe(false);
|
||||
expect(parseAantekening({}).ok).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Injectable, inject, resource } from '@angular/core';
|
||||
import { Result, ok, err } from '@shared/kernel/fp';
|
||||
import { Aantekening, AantekeningType } from '../domain/registration';
|
||||
import { ApiClient, AantekeningDto } from '@shared/infrastructure/api-client';
|
||||
|
||||
@@ -16,15 +17,30 @@ export class BigRegisterAdapter {
|
||||
private client = inject(ApiClient);
|
||||
|
||||
aantekeningenResource() {
|
||||
return resource({ loader: () => this.client.notes().then((ns) => ns.map(toAantekening)) });
|
||||
return resource({
|
||||
loader: () =>
|
||||
this.client.notes().then((ns) => {
|
||||
const out: Aantekening[] = [];
|
||||
for (const n of ns) {
|
||||
const parsed = parseAantekening(n);
|
||||
if (!parsed.ok) throw new Error(parsed.error);
|
||||
out.push(parsed.value);
|
||||
}
|
||||
return out;
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** Map the wire DTO (all fields optional) onto our domain type. */
|
||||
function toAantekening(n: AantekeningDto): Aantekening {
|
||||
return {
|
||||
const AANTEKENING_TYPES: readonly AantekeningType[] = ['Specialisme', 'Aantekening'];
|
||||
|
||||
/** Trust-boundary parse: an unrecognized type is an explicit Failure, never a silent cast. */
|
||||
export function parseAantekening(n: AantekeningDto): Result<string, Aantekening> {
|
||||
if (!n.type || !AANTEKENING_TYPES.includes(n.type as AantekeningType))
|
||||
return err(`aantekening: unknown type ${n.type}`);
|
||||
return ok({
|
||||
type: n.type as AantekeningType,
|
||||
omschrijving: n.omschrijving ?? '',
|
||||
datum: n.datum ?? '',
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user