Keep one sanitiser for pillar ids

The scorer and the stored composition both had to answer what a valid
pillar list looks like, and both had their own copy of the answer. One
function next to the catalogue now, used by both.
This commit is contained in:
Marc-André Bombeck committed 2026-07-31 15:37:04 +02:00
1 parent 2f6f3573a2
commit 956746fe7d
3 files changed
+19 -14

No files matched your search

+2 -7
View File
@@ -6,7 +6,7 @@ import {
import type { Derived } from "@/lib/insights/derived/types";
import {
SCORE_PILLAR_IDS,
orderedUniquePillars,
SCORE_VERSION,
type CompositeValue,
type HealthScoreReport,
@@ -36,15 +36,10 @@ export interface CompositeInput {
asOf: Date;
}
function orderedUnique(ids: readonly ScorePillarId[]): ScorePillarId[] {
const present = new Set(ids);
return SCORE_PILLAR_IDS.filter((id) => present.has(id));
}
export function computeComposite(
input: CompositeInput,
): Derived<CompositeValue> {
const available = orderedUnique(input.availablePillars);
const available = orderedUniquePillars(input.availablePillars);
const byId = new Map(input.pillars.map((pillar) => [pillar.id, pillar]));
const eligible = available
.map((id) => byId.get(id))
+5 -7
View File
@@ -34,13 +34,11 @@
*/
import { z } from "zod";
import { SCORE_PILLAR_IDS, type ScorePillarId } from "./types";
/** Ordered, de-duplicated, unknown ids dropped. Registry order is the score's own. */
export function orderedUniquePillars(ids: readonly unknown[]): ScorePillarId[] {
const present = new Set(ids);
return SCORE_PILLAR_IDS.filter((id) => present.has(id));
}
import {
orderedUniquePillars,
SCORE_PILLAR_IDS,
type ScorePillarId,
} from "./types";
export const scorePillarIdSchema = z.enum(SCORE_PILLAR_IDS);
+12
View File
@@ -20,6 +20,18 @@ export const SCORE_PILLAR_IDS = [
] as const;
export type ScorePillarId = (typeof SCORE_PILLAR_IDS)[number];
/**
* Sanitise a list of pillar ids: registry order, no duplicates, and
* anything outside the catalogue dropped. Everything that narrows the
* score's composition goes through here, so a stored blob, a caller's
* argument and the scorer itself cannot disagree about what a valid
* pillar set looks like.
*/
export function orderedUniquePillars(ids: readonly unknown[]): ScorePillarId[] {
const present = new Set(ids);
return SCORE_PILLAR_IDS.filter((id) => present.has(id));
}
export type ScoreBand = "green" | "yellow" | "red";
export type ScoreDomain =
| "cardiometabolic"