style: format frontend, docs and skills with prettier; add .prettierignore
One-time prettier --write so the new format:check CI gate starts green. .prettierignore excludes generated (api-client.ts, documentation.json), vendored (public/cibg-huisstijl), and backend (dotnet format owns it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,33 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { parseAanvraagStatus, parseApplicationSummary, parseApplications, parseApplicationDetail } from './applications.adapter';
|
||||
import {
|
||||
parseAanvraagStatus,
|
||||
parseApplicationSummary,
|
||||
parseApplications,
|
||||
parseApplicationDetail,
|
||||
} from './applications.adapter';
|
||||
|
||||
const concept = { id: 'a1', type: 'registratie', status: { tag: 'Concept', stepIndex: 1, stepCount: 4 }, documentIds: [], createdAt: '2026-07-01T10:00:00Z', updatedAt: '2026-07-01T10:05:00Z' };
|
||||
const concept = {
|
||||
id: 'a1',
|
||||
type: 'registratie',
|
||||
status: { tag: 'Concept', stepIndex: 1, stepCount: 4 },
|
||||
documentIds: [],
|
||||
createdAt: '2026-07-01T10:00:00Z',
|
||||
updatedAt: '2026-07-01T10:05:00Z',
|
||||
};
|
||||
|
||||
describe('parseAanvraagStatus', () => {
|
||||
it('parses each tag with its required fields', () => {
|
||||
expect(parseAanvraagStatus({ tag: 'Concept', stepIndex: 2, stepCount: 4 })).toEqual({ ok: true, value: { tag: 'Concept', stepIndex: 2, stepCount: 4 } });
|
||||
expect(parseAanvraagStatus({ tag: 'InBehandeling', referentie: 'BIG-1', manual: true }).ok).toBe(true);
|
||||
expect(parseAanvraagStatus({ tag: 'Concept', stepIndex: 2, stepCount: 4 })).toEqual({
|
||||
ok: true,
|
||||
value: { tag: 'Concept', stepIndex: 2, stepCount: 4 },
|
||||
});
|
||||
expect(
|
||||
parseAanvraagStatus({ tag: 'InBehandeling', referentie: 'BIG-1', manual: true }).ok,
|
||||
).toBe(true);
|
||||
expect(parseAanvraagStatus({ tag: 'Goedgekeurd', referentie: 'BIG-1' }).ok).toBe(true);
|
||||
expect(parseAanvraagStatus({ tag: 'Afgewezen', referentie: 'BIG-1', reden: 'geen uren' }).ok).toBe(true);
|
||||
expect(
|
||||
parseAanvraagStatus({ tag: 'Afgewezen', referentie: 'BIG-1', reden: 'geen uren' }).ok,
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('rejects a missing status, unknown tag, and wrong-typed fields', () => {
|
||||
|
||||
@@ -9,7 +9,12 @@ import {
|
||||
SubmitApplicationRequest,
|
||||
SubmitApplicationResponse,
|
||||
} from '@shared/infrastructure/api-client';
|
||||
import { Aanvraag, AanvraagDetail, AanvraagStatus, AanvraagType } from '@registratie/domain/aanvraag';
|
||||
import {
|
||||
Aanvraag,
|
||||
AanvraagDetail,
|
||||
AanvraagStatus,
|
||||
AanvraagType,
|
||||
} from '@registratie/domain/aanvraag';
|
||||
|
||||
/**
|
||||
* Infrastructure adapter for the backend-owned Aanvraag aggregate — the only place
|
||||
@@ -54,20 +59,25 @@ export class ApplicationsAdapter {
|
||||
const AANVRAAG_TYPES: readonly string[] = ['registratie', 'herregistratie', 'intake'];
|
||||
|
||||
/** Trust-boundary parse of the status union — the tag drives which fields must exist. */
|
||||
export function parseAanvraagStatus(s: AanvraagStatusDto | undefined): Result<string, AanvraagStatus> {
|
||||
export function parseAanvraagStatus(
|
||||
s: AanvraagStatusDto | undefined,
|
||||
): Result<string, AanvraagStatus> {
|
||||
if (!s || typeof s.tag !== 'string') return err('aanvraag: missing status');
|
||||
switch (s.tag) {
|
||||
case 'Concept':
|
||||
if (typeof s.stepIndex !== 'number' || typeof s.stepCount !== 'number') return err('aanvraag: bad Concept status');
|
||||
if (typeof s.stepIndex !== 'number' || typeof s.stepCount !== 'number')
|
||||
return err('aanvraag: bad Concept status');
|
||||
return ok({ tag: 'Concept', stepIndex: s.stepIndex, stepCount: s.stepCount });
|
||||
case 'InBehandeling':
|
||||
if (typeof s.referentie !== 'string' || typeof s.manual !== 'boolean') return err('aanvraag: bad InBehandeling status');
|
||||
if (typeof s.referentie !== 'string' || typeof s.manual !== 'boolean')
|
||||
return err('aanvraag: bad InBehandeling status');
|
||||
return ok({ tag: 'InBehandeling', referentie: s.referentie, manual: s.manual });
|
||||
case 'Goedgekeurd':
|
||||
if (typeof s.referentie !== 'string') return err('aanvraag: bad Goedgekeurd status');
|
||||
return ok({ tag: 'Goedgekeurd', referentie: s.referentie });
|
||||
case 'Afgewezen':
|
||||
if (typeof s.referentie !== 'string' || typeof s.reden !== 'string') return err('aanvraag: bad Afgewezen status');
|
||||
if (typeof s.referentie !== 'string' || typeof s.reden !== 'string')
|
||||
return err('aanvraag: bad Afgewezen status');
|
||||
return ok({ tag: 'Afgewezen', referentie: s.referentie, reden: s.reden });
|
||||
default:
|
||||
return err(`aanvraag: unknown status tag ${s.tag}`);
|
||||
@@ -76,8 +86,10 @@ export function parseAanvraagStatus(s: AanvraagStatusDto | undefined): Result<st
|
||||
|
||||
function parseCommon(dto: ApplicationSummaryDto): Result<string, Aanvraag> {
|
||||
if (typeof dto.id !== 'string') return err('aanvraag: missing id');
|
||||
if (typeof dto.type !== 'string' || !AANVRAAG_TYPES.includes(dto.type)) return err(`aanvraag: bad type ${dto.type}`);
|
||||
if (typeof dto.createdAt !== 'string' || typeof dto.updatedAt !== 'string') return err('aanvraag: missing timestamps');
|
||||
if (typeof dto.type !== 'string' || !AANVRAAG_TYPES.includes(dto.type))
|
||||
return err(`aanvraag: bad type ${dto.type}`);
|
||||
if (typeof dto.createdAt !== 'string' || typeof dto.updatedAt !== 'string')
|
||||
return err('aanvraag: missing timestamps');
|
||||
const status = parseAanvraagStatus(dto.status);
|
||||
if (!status.ok) return status;
|
||||
return ok({
|
||||
|
||||
@@ -22,5 +22,9 @@ export class BigRegisterAdapter {
|
||||
|
||||
/** Map the wire DTO (all fields optional) onto our domain type. */
|
||||
function toAantekening(n: AantekeningDto): Aantekening {
|
||||
return { type: n.type as AantekeningType, omschrijving: n.omschrijving ?? '', datum: n.datum ?? '' };
|
||||
return {
|
||||
type: n.type as AantekeningType,
|
||||
omschrijving: n.omschrijving ?? '',
|
||||
datum: n.datum ?? '',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ import { parseBrpAddress } from './brp.adapter';
|
||||
|
||||
describe('parseBrpAddress (trust boundary)', () => {
|
||||
it('accepts a found address', () => {
|
||||
const r = parseBrpAddress({ gevonden: true, adres: { straat: 'Lange Voorhout 9', postcode: '2514 EA', woonplaats: 'Den Haag' } });
|
||||
const r = parseBrpAddress({
|
||||
gevonden: true,
|
||||
adres: { straat: 'Lange Voorhout 9', postcode: '2514 EA', woonplaats: 'Den Haag' },
|
||||
});
|
||||
expect(r.ok).toBe(true);
|
||||
if (r.ok) expect(r.value.adres?.postcode).toBe('2514 EA');
|
||||
});
|
||||
|
||||
@@ -27,7 +27,12 @@ export function parseBrpAddress(json: unknown): Result<string, BrpAddressDto> {
|
||||
if (typeof dto.gevonden !== 'boolean') return err('brp-address: missing/invalid gevonden');
|
||||
if (dto.gevonden) {
|
||||
const a = dto.adres;
|
||||
if (!a || typeof a.straat !== 'string' || typeof a.postcode !== 'string' || typeof a.woonplaats !== 'string') {
|
||||
if (
|
||||
!a ||
|
||||
typeof a.straat !== 'string' ||
|
||||
typeof a.postcode !== 'string' ||
|
||||
typeof a.woonplaats !== 'string'
|
||||
) {
|
||||
return err('brp-address: missing/invalid adres');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,11 @@ const valid = {
|
||||
geboortedatum: '1985-03-14',
|
||||
status: { tag: 'Geregistreerd', herregistratieDatum: '2027-03-01' },
|
||||
},
|
||||
person: { naam: 'Dr. A. de Vries', geboortedatum: '1985-03-14', adres: { straat: 'X 1', postcode: '2514 EA', woonplaats: 'Den Haag' } },
|
||||
person: {
|
||||
naam: 'Dr. A. de Vries',
|
||||
geboortedatum: '1985-03-14',
|
||||
adres: { straat: 'X 1', postcode: '2514 EA', woonplaats: 'Den Haag' },
|
||||
},
|
||||
decisions: { eligibleForHerregistratie: true, herregistratieReason: 'within window' },
|
||||
};
|
||||
|
||||
@@ -27,6 +31,8 @@ describe('parseDashboardView (trust boundary)', () => {
|
||||
it('rejects malformed responses instead of trusting them', () => {
|
||||
expect(parseDashboardView(null).ok).toBe(false);
|
||||
expect(parseDashboardView({ ...valid, registration: undefined }).ok).toBe(false);
|
||||
expect(parseDashboardView({ ...valid, decisions: { eligibleForHerregistratie: 'yes' } }).ok).toBe(false);
|
||||
expect(
|
||||
parseDashboardView({ ...valid, decisions: { eligibleForHerregistratie: 'yes' } }).ok,
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { Injectable, inject, resource } from '@angular/core';
|
||||
import { Result, ok, err } from '@shared/kernel/fp';
|
||||
import { DashboardViewDto, HerregistratieDecisions } from '@registratie/contracts/dashboard-view.dto';
|
||||
import {
|
||||
DashboardViewDto,
|
||||
HerregistratieDecisions,
|
||||
} from '@registratie/contracts/dashboard-view.dto';
|
||||
import { Registration } from '@registratie/domain/registration';
|
||||
import { Person } from '@registratie/domain/person';
|
||||
import { BigProfile } from '@registratie/domain/big-profile';
|
||||
@@ -49,7 +52,12 @@ export function parseDashboardView(json: unknown): Result<string, DashboardView>
|
||||
const dto = json as Partial<DashboardViewDto>;
|
||||
|
||||
const reg = dto.registration;
|
||||
if (!reg || typeof reg.bigNummer !== 'string' || !reg.status || typeof reg.status.tag !== 'string') {
|
||||
if (
|
||||
!reg ||
|
||||
typeof reg.bigNummer !== 'string' ||
|
||||
!reg.status ||
|
||||
typeof reg.status.tag !== 'string'
|
||||
) {
|
||||
return err('dashboard-view: missing/invalid registration');
|
||||
}
|
||||
const person = dto.person;
|
||||
@@ -72,10 +80,17 @@ export function parseDashboardView(json: unknown): Result<string, DashboardView>
|
||||
geboortedatum: reg.geboortedatum,
|
||||
status: reg.status,
|
||||
};
|
||||
const persoon: Person = { naam: person.naam, geboortedatum: person.geboortedatum, adres: person.adres };
|
||||
const persoon: Person = {
|
||||
naam: person.naam,
|
||||
geboortedatum: person.geboortedatum,
|
||||
adres: person.adres,
|
||||
};
|
||||
|
||||
return ok({
|
||||
profile: { registration, person: persoon },
|
||||
decisions: { eligibleForHerregistratie: d.eligibleForHerregistratie, herregistratieReason: d.herregistratieReason },
|
||||
decisions: {
|
||||
eligibleForHerregistratie: d.eligibleForHerregistratie,
|
||||
herregistratieReason: d.herregistratieReason,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,8 +3,22 @@ import { parseDuoLookup } from './duo.adapter';
|
||||
|
||||
const valid = {
|
||||
diplomas: [
|
||||
{ id: 'd1', naam: 'Geneeskunde', instelling: 'Universiteit Leiden', jaar: 2011, beroep: 'Arts', policyQuestions: [] },
|
||||
{ id: 'd2', naam: 'Medicine', instelling: 'University of Edinburgh', jaar: 2013, beroep: 'Arts', policyQuestions: [{ id: 'nl-taal', vraag: 'Toon taalvaardigheid', type: 'ja-nee' }] },
|
||||
{
|
||||
id: 'd1',
|
||||
naam: 'Geneeskunde',
|
||||
instelling: 'Universiteit Leiden',
|
||||
jaar: 2011,
|
||||
beroep: 'Arts',
|
||||
policyQuestions: [],
|
||||
},
|
||||
{
|
||||
id: 'd2',
|
||||
naam: 'Medicine',
|
||||
instelling: 'University of Edinburgh',
|
||||
jaar: 2013,
|
||||
beroep: 'Arts',
|
||||
policyQuestions: [{ id: 'nl-taal', vraag: 'Toon taalvaardigheid', type: 'ja-nee' }],
|
||||
},
|
||||
],
|
||||
handmatig: {
|
||||
beroepen: ['Arts', 'Verpleegkundige'],
|
||||
@@ -34,6 +48,14 @@ describe('parseDuoLookup (trust boundary)', () => {
|
||||
expect(parseDuoLookup({}).ok).toBe(false); // no diplomas
|
||||
expect(parseDuoLookup({ diplomas: [] }).ok).toBe(false); // no handmatig
|
||||
expect(parseDuoLookup({ diplomas: [{ id: 'd1' }], handmatig: valid.handmatig }).ok).toBe(false); // bad diploma
|
||||
expect(parseDuoLookup({ diplomas: [], handmatig: { beroepen: ['Arts'], policyQuestions: [{ id: 'x', vraag: 'y', type: 'bogus' }] } }).ok).toBe(false); // bad question type
|
||||
expect(
|
||||
parseDuoLookup({
|
||||
diplomas: [],
|
||||
handmatig: {
|
||||
beroepen: ['Arts'],
|
||||
policyQuestions: [{ id: 'x', vraag: 'y', type: 'bogus' }],
|
||||
},
|
||||
}).ok,
|
||||
).toBe(false); // bad question type
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { Injectable, inject, resource } from '@angular/core';
|
||||
import { Result, ok, err } from '@shared/kernel/fp';
|
||||
import { DuoLookupDto, DuoDiplomaDto, PolicyQuestionDto, ManualDiplomaPolicyDto } from '@registratie/contracts/duo-diplomas.dto';
|
||||
import {
|
||||
DuoLookupDto,
|
||||
DuoDiplomaDto,
|
||||
PolicyQuestionDto,
|
||||
ManualDiplomaPolicyDto,
|
||||
} from '@registratie/contracts/duo-diplomas.dto';
|
||||
import { ApiClient } from '@shared/infrastructure/api-client';
|
||||
|
||||
/**
|
||||
@@ -25,7 +30,12 @@ function parseQuestions(json: unknown): PolicyQuestionDto[] | null {
|
||||
for (const q of json) {
|
||||
if (typeof q !== 'object' || q === null) return null;
|
||||
const p = q as Partial<PolicyQuestionDto>;
|
||||
if (typeof p.id !== 'string' || typeof p.vraag !== 'string' || (p.type !== 'ja-nee' && p.type !== 'tekst')) return null;
|
||||
if (
|
||||
typeof p.id !== 'string' ||
|
||||
typeof p.vraag !== 'string' ||
|
||||
(p.type !== 'ja-nee' && p.type !== 'tekst')
|
||||
)
|
||||
return null;
|
||||
out.push({ id: p.id, vraag: p.vraag, type: p.type });
|
||||
}
|
||||
return out;
|
||||
@@ -43,10 +53,22 @@ export function parseDuoLookup(json: unknown): Result<string, DuoLookupDto> {
|
||||
if (typeof item !== 'object' || item === null) return err('duo-lookup: invalid diploma');
|
||||
const d = item as Partial<DuoDiplomaDto>;
|
||||
const vragen = parseQuestions(d.policyQuestions);
|
||||
if (typeof d.id !== 'string' || typeof d.naam !== 'string' || typeof d.beroep !== 'string' || vragen === null) {
|
||||
if (
|
||||
typeof d.id !== 'string' ||
|
||||
typeof d.naam !== 'string' ||
|
||||
typeof d.beroep !== 'string' ||
|
||||
vragen === null
|
||||
) {
|
||||
return err('duo-lookup: missing/invalid diploma fields');
|
||||
}
|
||||
diplomas.push({ id: d.id, naam: d.naam, instelling: d.instelling ?? '', jaar: typeof d.jaar === 'number' ? d.jaar : 0, beroep: d.beroep, policyQuestions: vragen });
|
||||
diplomas.push({
|
||||
id: d.id,
|
||||
naam: d.naam,
|
||||
instelling: d.instelling ?? '',
|
||||
jaar: typeof d.jaar === 'number' ? d.jaar : 0,
|
||||
beroep: d.beroep,
|
||||
policyQuestions: vragen,
|
||||
});
|
||||
}
|
||||
|
||||
const hm = dto.handmatig;
|
||||
|
||||
Reference in New Issue
Block a user