impl/typescript.ts
2,163 bytes · the TypeScript implementation · view raw
Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import { parseIsoDate } from "./dates_add_days.ts"; ← from dates.add-days ^1.0.0 · built alongside by fune
import { addMonths } from "./dates_add_months.ts"; ← from dates.add-months ^1.0.0 · built alongside by fune
import { LIMITATION_PERIODS, LIMITATION_PERIODS_HISTORY } from "./legal_limitation_date_data.ts"; ← this capability’s own data, compiled from data/limitation-periods.json into the same file by fune build
import { type LimitationPeriod } from "./legal_limitation_date_types.ts";
/**
* The last day to bring a claim: the anniversary of the accrual date (or the
* later date of knowledge) the period's number of years on, the accrual day
* itself excluded, and the month's last day where no anniversary exists.
*/
export function limitationDate(claimType: string, accrualDate: string, knowledgeDate: string | null): LimitationPeriod {
parseIsoDate(accrualDate);
const rows = LIMITATION_PERIODS.filter((r) => r.claimType === claimType);
if (rows.length === 0) {
const known = Array.from(new Set(LIMITATION_PERIODS.map((r) => r.claimType))).join(", ");
throw new RangeError(`unknown claim type "${claimType}": expected one of ${known}`);
}
const rule = rows.find((r) => accrualDate >= r.validFrom && (r.validTo === null || accrualDate <= r.validTo));
if (rule === undefined) {
const earliest = rows.map((r) => r.validFrom).reduce((a, b) => (b < a ? b : a));
if (LIMITATION_PERIODS_HISTORY !== "full" && accrualDate < earliest) {
throw new RangeError(
`no limitation rule for ${claimType} accruing on ${accrualDate}: this build was installed with history=${LIMITATION_PERIODS_HISTORY}, so it only carries rules from ${earliest}. Reinstall with history=full for older claims.`,
);
}
throw new RangeError(`no limitation rule for ${claimType} accruing on ${accrualDate}`);
}
let runsFrom = accrualDate;
if (knowledgeDate !== null) {
if (!rule.fromKnowledge) {
throw new RangeError(`a ${claimType} claim runs from accrual under ${rule.section}; knowledgeDate must be null`);
}
parseIsoDate(knowledgeDate);
if (knowledgeDate > accrualDate) runsFrom = knowledgeDate;
}
// The corresponding date rule: the anniversary, clamped to the month end.
const expiry = addMonths(runsFrom, rule.years * 12);
return { claimType, years: rule.years, section: rule.section, runsFrom, expiry };
}