lib.ts (3407B)
1 import { 2 NostrRelayInformationDocument, 3 NostrRelayInformationDocumentFields, 4 } from "../types/lib.js"; 5 6 type NostrRelayInformationDocumentInput = Record<string, unknown> | string | null | undefined; 7 8 const is_record = (value: unknown): value is Record<string, unknown> => { 9 if (!value) return false; 10 if (typeof value !== "object") return false; 11 if (Array.isArray(value)) return false; 12 return true; 13 }; 14 15 const parse_supported_nips = (value: unknown): number[] | undefined => { 16 if (!Array.isArray(value)) return undefined; 17 const nips = value.filter((nip): nip is number => typeof nip === "number"); 18 if (nips.length !== value.length) return undefined; 19 return nips; 20 }; 21 22 const parse_limitation = ( 23 limitation: Record<string, unknown> | undefined, 24 ): Pick<NostrRelayInformationDocument, "limitation_payment_required" | "limitation_restricted_writes"> => { 25 const payment_required = 26 limitation && typeof limitation.payment_required === "string" 27 ? limitation.payment_required 28 : undefined; 29 const restricted_writes = 30 limitation && typeof limitation.restricted_writes === "boolean" 31 ? limitation.restricted_writes 32 : undefined; 33 return { 34 limitation_payment_required: payment_required, 35 limitation_restricted_writes: restricted_writes, 36 }; 37 }; 38 39 export const nostr_relay_information_document_parse = ( 40 data: NostrRelayInformationDocumentInput, 41 ): NostrRelayInformationDocument | undefined => { 42 const obj = typeof data === "string" ? JSON.parse(data) : data; 43 if (!is_record(obj)) return undefined; 44 45 const limitation = is_record(obj.limitation) ? obj.limitation : undefined; 46 const parsed_limitation = parse_limitation(limitation); 47 48 return { 49 id: typeof obj.id === "string" ? obj.id : undefined, 50 name: typeof obj.name === "string" ? obj.name : undefined, 51 description: typeof obj.description === "string" ? obj.description : undefined, 52 pubkey: typeof obj.pubkey === "string" ? obj.pubkey : undefined, 53 contact: typeof obj.contact === "string" ? obj.contact : undefined, 54 supported_nips: parse_supported_nips(obj.supported_nips), 55 software: typeof obj.software === "string" ? obj.software : undefined, 56 version: typeof obj.version === "string" ? obj.version : undefined, 57 limitation_payment_required: parsed_limitation.limitation_payment_required, 58 limitation_restricted_writes: parsed_limitation.limitation_restricted_writes, 59 }; 60 }; 61 62 export const nostr_relay_information_document_build = ( 63 data: NostrRelayInformationDocumentInput, 64 ): NostrRelayInformationDocumentFields | undefined => { 65 const doc = nostr_relay_information_document_parse(data); 66 if (!doc) return undefined; 67 const result: Partial<NostrRelayInformationDocumentFields> = {}; 68 for (const [key, value] of Object.entries(doc)) { 69 if (typeof value === "boolean") result[key as keyof NostrRelayInformationDocument] = value ? "1" : "0"; 70 else if (Array.isArray(value)) result[key as keyof NostrRelayInformationDocument] = value.join(", "); 71 else if (value === null || value === undefined) result[key as keyof NostrRelayInformationDocument] = ""; 72 else result[key as keyof NostrRelayInformationDocument] = String(value); 73 } 74 return result as NostrRelayInformationDocumentFields; 75 };