1
10
11import type { PropertyValue } from "../values/types.js";
12import type { PropertyInfo } from "../values/types.js";
13import { codec } from "../values/registry.js";
14
15export interface EavRow {
16 recordId: string;
17 propertyId: string;
18 value: unknown;
19}
20
21
22export function pivotValues(
23 eav: readonly EavRow[],
24 properties?: Map<string, PropertyInfo>,
25): Map<string, Record<string, PropertyValue | undefined>> {
26 const out = new Map<string, Record<string, PropertyValue | undefined>>();
27 for (const row of eav) {
28 let rec = out.get(row.recordId);
29 if (!rec) {
30 rec = {};
31 out.set(row.recordId, rec);
32 }
33 const property = properties?.get(row.propertyId);
34 rec[row.propertyId] = property
35 ? codec(property.type).fromWire(row.value)
36 : (row.value as PropertyValue);
37 }
38 return out;
39}
40
41
42export function assembleRows<
43 T extends {
44 id: string;
45 pageId: string;
46 position: string;
47 icon?: string;
48 coverUrl?: string;
49 archivedAt?: number | null;
50 createdTime: number;
51 lastEditedTime: number;
52 },
53>(
54 pages: readonly T[],
55 values: Map<string, Record<string, PropertyValue | undefined>>,
56 titlePropertyId?: string,
57): import("../values/types.js").RecordRow[] {
58 return pages.map((p) => {
59 const vals = values.get(p.id) ?? {};
60 const row: import("../values/types.js").RecordRow = {
61 id: p.id,
62 pageId: p.pageId,
63 position: p.position,
64 values: vals,
65 createdTime: p.createdTime,
66 lastEditedTime: p.lastEditedTime,
67 };
68 if (p.icon !== undefined) row.icon = p.icon;
69 if (p.coverUrl !== undefined) row.coverUrl = p.coverUrl;
70 if (p.archivedAt !== null && p.archivedAt !== undefined) row.archivedAt = p.archivedAt;
71 if (titlePropertyId && typeof vals[titlePropertyId] === "string")
72 row.title = vals[titlePropertyId];
73 return row;
74 });
75}
76