import { z } from "zod"; import { REVIEW_ORIGIN_SERIES_LIMITS, isDiagnosticToken, isDiagnosticPlainRecord, isRealIsoDate, validateReviewOriginSeriesRequest, createReviewOriginSeries, replayReviewOriginSeries, type ReviewOriginSeries, type ReviewOriginSeriesRequest, type DeclaredReviewOriginSeriesRequest, type ModelReviewOriginSeriesRequest } from "@actuarial-ts/core"; import { analysisContextSchema, quantitySemanticsSchema, analysisSnapshotSchema } from "./reviewContracts.js"; import { retainedModelInputSchema } from "./modelCalibrationContracts.js"; import { parseReviewBoundary } from "./reviewBoundary.js"; const token = z.string().refine(isDiagnosticToken), date = z.string().refine(isRealIsoDate); const coordinate = { origin: token, levelDate: date }; const value = z.union([z.object({ ...coordinate, value: z.number().finite(), reason: z.null() }).strict(), z.object({ ...coordinate, value: z.null(), reason: token }).strict()]); const base = { id: token, version: token, rationale: token, limits: z.object({ maximumOrigins: z.number().int().positive().max(REVIEW_ORIGIN_SERIES_LIMITS.maximumOrigins), maximumInputCharacters: z.number().int().positive().max(REVIEW_ORIGIN_SERIES_LIMITS.maximumInputCharacters), maximumOutputCharacters: z.number().int().positive().max(REVIEW_ORIGIN_SERIES_LIMITS.maximumOutputCharacters) }).strict() }; export const declaredReviewOriginSeriesRequestSchema = z.object({ ...base, kind: z.literal("declared"), context: analysisContextSchema, quantity: quantitySemanticsSchema, snapshots: z.array(analysisSnapshotSchema), knownDate: date, declaration: z.object({ actorId: token, knownDate: date, rationale: token }).strict(), rows: z.array(value) }).strict(); export const modelReviewOriginSeriesRequestSchema = z.object({ ...base, kind: z.literal("model"), run: retainedModelInputSchema, seriesKey: z.enum(["ultimate", "unpaid", "additional-incurred-development", "loss-through-development-age", "future-paid-through-development-age", "future-incurred-development-through-development-age", "ultimate-recoveries", "future-recoveries"]), coordinates: z.array(z.object(coordinate).strict()) }).strict(); export const reviewOriginSeriesRequestSchema = z.discriminatedUnion("kind", [declaredReviewOriginSeriesRequestSchema, modelReviewOriginSeriesRequestSchema]); export function parseReviewOriginSeriesRequest(input: unknown): ReviewOriginSeriesRequest { return validateReviewOriginSeriesRequest(parseReviewBoundary(reviewOriginSeriesRequestSchema, input) as ReviewOriginSeriesRequest); } export function createReviewOriginSeriesFromInput(input: unknown): ReviewOriginSeries { return createReviewOriginSeries(parseReviewOriginSeriesRequest(input)); } export function parseDeclaredReviewOriginSeriesRequest(input: unknown): DeclaredReviewOriginSeriesRequest { return validateReviewOriginSeriesRequest(parseReviewBoundary(declaredReviewOriginSeriesRequestSchema, input) as DeclaredReviewOriginSeriesRequest) as DeclaredReviewOriginSeriesRequest; } export function parseModelReviewOriginSeriesRequest(input: unknown): ModelReviewOriginSeriesRequest { return validateReviewOriginSeriesRequest(parseReviewBoundary(modelReviewOriginSeriesRequestSchema, input) as ModelReviewOriginSeriesRequest) as ModelReviewOriginSeriesRequest; } export function replayReviewOriginSeriesFromInput(input: unknown): ReviewOriginSeries { return replayReviewOriginSeries(parseReviewBoundary(z.custom(isDiagnosticPlainRecord), input)); }