/** * @factory/database-engine/values — shared codec types + record shapes. * * The codec contract (TASK-0064): one codec per PropertyType with * `fromWire`/`toWire` (JSON round-trip), `display`, `compare`, and * `canConvert`. Values are plain JSON primitives/arrays — never host objects. */ import type { PropertyType } from "@factory/shared/dto"; /** All possible property values (JSON-serializable). */ export type PropertyValue = | string | number | boolean | null | undefined | PropertyValue[] | { start: string; end: string } | { id: string; name: string; url?: string; size?: number }[]; /** Normalized date value (ISO 8601 UTC, `YYYY-MM-DD` or full timestamp). */ export type DateValue = string; /** A date range value (ISO 8601 UTC). */ export interface DateRangeValue { start: string; end: string; } /** A file attachment value (one entry in a `files` property). */ export interface FileValue { id: string; name: string; url?: string; size?: number; } /** A record as the engine sees it (values keyed by property id). */ export interface RecordRow { id: string; pageId: string; position: string; title?: string; values: Record; icon?: string; coverUrl?: string; archivedAt?: number; createdTime: number; lastEditedTime: number; } /** Minimal property description the engine needs (the db's property set). */ export interface PropertyInfo { id: string; name: string; type: PropertyType; config: Record; } export interface EvalContext { now: number; // `| undefined` (not just `?`): `exactOptionalPropertyTypes` — the query // pipeline assigns a `string | undefined` field here. actorUserId?: string | undefined; userTimezone: string; } /** The value codec contract (Phase-6 computed codecs follow the same shape). */ export interface ValueCodec { type: PropertyType; /** Validate + normalize a raw JSON wire value → PropertyValue (throws on bad). */ fromWire(json: unknown): PropertyValue; /** Serialize a PropertyValue for storage/transport (JSON-safe). */ toWire(value: PropertyValue): unknown; /** Human display (cells, chips, group labels). Missing config → plain value. */ display(value: PropertyValue, config: Record, locale?: string): string; /** Sort comparator (nulls handled by sort, not here). */ compare(a: PropertyValue, b: PropertyValue, config: Record): number; }