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.
34 lines
1.3 KiB
TypeScript
34 lines
1.3 KiB
TypeScript
import { Injectable, inject, resource } from '@angular/core';
|
|
import { Result, ok, err } from '@shared/kernel/fp';
|
|
import { IntakePolicy } from '@herregistratie/domain/intake.machine';
|
|
import { ApiClient } from '@shared/infrastructure/api-client';
|
|
|
|
/**
|
|
* Infrastructure adapter for the intake policy (the scholing threshold config
|
|
* value). Same shape as every other adapter — a signal `resource` over the
|
|
* generated typed client — so HTTP lives in exactly one place per concern.
|
|
*/
|
|
@Injectable({ providedIn: 'root' })
|
|
export class IntakePolicyAdapter {
|
|
private client = inject(ApiClient);
|
|
|
|
policyResource() {
|
|
return resource({
|
|
loader: async () => {
|
|
const parsed = parseIntakePolicy(await this.client.policy());
|
|
if (!parsed.ok) throw new Error(parsed.error);
|
|
return parsed.value;
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
/** Trust-boundary parse: an unrecognized/missing threshold is an explicit Failure. */
|
|
export function parseIntakePolicy(json: unknown): Result<string, IntakePolicy> {
|
|
if (typeof json !== 'object' || json === null) return err('intake-policy: not an object');
|
|
const dto = json as { scholingThreshold?: unknown };
|
|
if (typeof dto.scholingThreshold !== 'number')
|
|
return err('intake-policy: missing scholingThreshold');
|
|
return ok({ scholingThreshold: dto.scholingThreshold });
|
|
}
|