import { createReferenceResource, type ReferenceResource, } from "../domain/reference-resource.ts"; import { mappingFailure, mappingSuccess, type InstalledBoundaryMapper, type MappingResult, } from "../../../contracts/boundary-mapper.ts"; import type { ReferenceResourceDto } from "./reference-schemas.ts"; export type ReferenceResourceView = Readonly<{ resourceId: string; title: string; createdAt: string | null; optimistic?: boolean; }>; /** * Operation-specific mapper. The HTTP contract has already validated the wire * shape, so this mapper owns only wire -> domain construction. */ export function mapReferenceResourcePayload( dto: ReferenceResourceDto, ): MappingResult { try { return mappingSuccess( createReferenceResource({ id: dto.id, displayName: dto.name, createdAt: dto.createdAt ?? null, }), ); } catch { return mappingFailure("MAPPING_INVARIANT_REJECTED"); } } export function mapReferenceResourceListPayload( payload: readonly ReferenceResourceDto[], ): MappingResult { const output: ReferenceResource[] = []; for (const item of payload) { const mapped = mapReferenceResourcePayload(item); if (!mapped.ok) return mapped; output.push(mapped.value); } return mappingSuccess(Object.freeze(output)); } function isReferenceResourceDto(value: unknown): value is ReferenceResourceDto { if (!value || typeof value !== "object" || Array.isArray(value)) return false; const dto = value as Record; return ( typeof dto.id === "string" && typeof dto.name === "string" && (dto.createdAt === undefined || typeof dto.createdAt === "string") ); } function mapUnknownReferenceResourcePayload( value: unknown, ): MappingResult { return isReferenceResourceDto(value) ? mapReferenceResourcePayload(value) : mappingFailure("MAPPING_INVARIANT_REJECTED"); } function mapUnknownReferenceResourceListPayload( value: unknown, ): MappingResult { if ( !Array.isArray(value) || value.length > 100 || !value.every(isReferenceResourceDto) ) { return mappingFailure( Array.isArray(value) && value.length > 100 ? "OUTPUT_LIMIT_EXCEEDED" : "MAPPING_INVARIANT_REJECTED", ); } return mapReferenceResourceListPayload(value); } /** * Registry-facing compatibility projection. The registry is intentionally * untyped, so its adapter performs the defensive shape check. Feature HTTP * bindings use the typed operation-specific mappers above. */ export function mapReferenceOperation( operationId: string, payload: unknown, ): MappingResult { if (operationId === "LIST_REFERENCE_RESOURCES") { return mapUnknownReferenceResourceListPayload(payload); } if ( operationId === "CREATE_REFERENCE_RESOURCE" || operationId === "GET_REFERENCE_RESOURCE" ) { return mapUnknownReferenceResourcePayload(payload); } return mappingFailure("MAPPING_INVARIANT_REJECTED"); } export const REFERENCE_BOUNDARY_MAPPERS = Object.freeze({ ReferenceResourceListMapper: Object.freeze({ mapperId: "ReferenceResourceListMapper", mapperVersion: 1, inputSchemaId: "ReferenceResourceListPayload", outputContractId: "ReferenceResourceList", owner: "feature-frontend-reference-feature-vertical-slice", maxOutputItems: 100, map: mapUnknownReferenceResourceListPayload, }), ReferenceResourceMapper: Object.freeze({ mapperId: "ReferenceResourceMapper", mapperVersion: 1, inputSchemaId: "ReferenceResourcePayload", outputContractId: "ReferenceResource", owner: "feature-frontend-reference-feature-vertical-slice", maxOutputItems: 1, map: mapUnknownReferenceResourcePayload, }), } satisfies Readonly>); export function toReferenceView( resource: ReferenceResource, ): ReferenceResourceView { return Object.freeze({ resourceId: resource.id, title: resource.displayName, createdAt: resource.createdAt, }); }