a tool for shared writing and social publishing
1/**
2 * Utilities for normalizing pub.leaflet and site.standard records from database queries.
3 *
4 * These helpers apply the normalization functions from lexicons/src/normalize.ts
5 * to database query results, providing properly typed normalized records.
6 */
7
8import {
9 normalizeDocument,
10 normalizePublication,
11 type NormalizedDocument,
12 type NormalizedPublication,
13} from "lexicons/src/normalize";
14import type { Json } from "supabase/database.types";
15
16/**
17 * Normalizes a document record from a database query result.
18 * Returns the normalized document or null if the record is invalid/unrecognized.
19 *
20 * @param data - The document record data from the database
21 * @param uri - Optional document URI, used to extract the rkey for the path field when normalizing pub.leaflet records
22 *
23 * @example
24 * const doc = normalizeDocumentRecord(dbResult.data, dbResult.uri);
25 * if (doc) {
26 * // doc is NormalizedDocument with proper typing
27 * console.log(doc.title, doc.site, doc.publishedAt);
28 * }
29 */
30export function normalizeDocumentRecord(
31 data: Json | unknown,
32 uri?: string
33): NormalizedDocument | null {
34 return normalizeDocument(data, uri);
35}
36
37/**
38 * Normalizes a publication record from a database query result.
39 * Returns the normalized publication or null if the record is invalid/unrecognized.
40 *
41 * @example
42 * const pub = normalizePublicationRecord(dbResult.record);
43 * if (pub) {
44 * // pub is NormalizedPublication with proper typing
45 * console.log(pub.name, pub.url);
46 * }
47 */
48export function normalizePublicationRecord(
49 record: Json | unknown
50): NormalizedPublication | null {
51 return normalizePublication(record);
52}
53
54/**
55 * Type helper for a document row from the database with normalized data.
56 * Use this when you need the full row but with typed data.
57 */
58export type DocumentRowWithNormalizedData<
59 T extends { data: Json | unknown }
60> = Omit<T, "data"> & {
61 data: NormalizedDocument | null;
62};
63
64/**
65 * Type helper for a publication row from the database with normalized record.
66 * Use this when you need the full row but with typed record.
67 */
68export type PublicationRowWithNormalizedRecord<
69 T extends { record: Json | unknown }
70> = Omit<T, "record"> & {
71 record: NormalizedPublication | null;
72};
73
74/**
75 * Normalizes a document row in place, returning a properly typed row.
76 * If the row has a `uri` field, it will be used to extract the path.
77 */
78export function normalizeDocumentRow<T extends { data: Json | unknown; uri?: string }>(
79 row: T
80): DocumentRowWithNormalizedData<T> {
81 return {
82 ...row,
83 data: normalizeDocumentRecord(row.data, row.uri),
84 };
85}
86
87/**
88 * Normalizes a publication row in place, returning a properly typed row.
89 */
90export function normalizePublicationRow<T extends { record: Json | unknown }>(
91 row: T
92): PublicationRowWithNormalizedRecord<T> {
93 return {
94 ...row,
95 record: normalizePublicationRecord(row.record),
96 };
97}
98
99/**
100 * Type guard for filtering normalized document rows with non-null data.
101 * Use with .filter() after .map(normalizeDocumentRow) to narrow the type.
102 */
103export function hasValidDocument<T extends { data: NormalizedDocument | null }>(
104 row: T
105): row is T & { data: NormalizedDocument } {
106 return row.data !== null;
107}
108
109/**
110 * Type guard for filtering normalized publication rows with non-null record.
111 * Use with .filter() after .map(normalizePublicationRow) to narrow the type.
112 */
113export function hasValidPublication<
114 T extends { record: NormalizedPublication | null }
115>(row: T): row is T & { record: NormalizedPublication } {
116 return row.record !== null;
117}
118
119// Re-export the core types and functions for convenience
120export {
121 normalizeDocument,
122 normalizePublication,
123 type NormalizedDocument,
124 type NormalizedPublication,
125} from "lexicons/src/normalize";
126
127export {
128 isLeafletDocument,
129 isStandardDocument,
130 isLeafletPublication,
131 isStandardPublication,
132 hasLeafletContent,
133 getDocumentPages,
134} from "lexicons/src/normalize";