index.ts (3598B)
1 import { _env } from "$lib/utils/_env"; 2 import { type FetchJsonResult, type HttpFetch, fetch_json } from "@radroots/apps-lib"; 3 import type { PageLoadProfileData } from "@radroots/apps-lib-market"; 4 import type { 5 RadrootsCommentEventMetadata, 6 RadrootsListingEventMetadata, 7 RadrootsProfileEventMetadata 8 } from "@radroots/events-bindings"; 9 import type { RadrootsEventsIndexedManifest as radroots_events_indexed_manifest } from "@radroots/events-indexed-bindings"; 10 import { nostr_npub_encode } from "@radroots/nostr"; 11 12 type ProfileRoutesKind = "author" | "npub" | "nip05"; 13 14 type CommentsByRoot = Record<string, RadrootsCommentEventMetadata[]>; 15 16 export type PageLoadProfileDataWithComments = PageLoadProfileData & { 17 events: PageLoadProfileData["events"] & { 18 listing_comments: CommentsByRoot; 19 }; 20 }; 21 22 const { RADROOTS_MARKET_INDEXES_URL: idx_url } = _env; 23 24 async function fetch_listings( 25 fetch_fn: HttpFetch, 26 kind: ProfileRoutesKind, 27 key: string 28 ): Promise<FetchJsonResult<RadrootsListingEventMetadata[]>> { 29 const manifest_res = await fetch_json<radroots_events_indexed_manifest>( 30 fetch_fn, 31 `${idx_url}/events/30402/${kind}/${encodeURIComponent(key)}/manifest.json` 32 ); 33 34 if (!manifest_res.ok) return manifest_res; 35 36 if (!manifest_res.data.shards.length) return { ok: true, data: [] }; 37 38 const shard = manifest_res.data.shards[0]; 39 const shard_url = `${idx_url}/events/30402/${kind}/${encodeURIComponent( 40 key 41 )}/${shard.file}?v=${shard.sha256}`; 42 const events_res = await fetch_json<RadrootsListingEventMetadata[]>(fetch_fn, shard_url); 43 if (!events_res.ok) return events_res; 44 return { ok: true, data: events_res.data }; 45 } 46 47 async function fetch_comments_for_roots( 48 fetch_fn: HttpFetch, 49 rootIds: readonly string[] 50 ): Promise<CommentsByRoot> { 51 const unique = Array.from(new Set(rootIds.map((id) => id.toLowerCase()))); 52 53 const entries: [string, RadrootsCommentEventMetadata[]][] = await Promise.all( 54 unique.map(async (id): Promise<[string, RadrootsCommentEventMetadata[]]> => { 55 const url = `${idx_url}/events/1111/root/${encodeURIComponent( 56 id 57 )}/metadata.json`; 58 const metas_res = await fetch_json<RadrootsCommentEventMetadata[]>( 59 fetch_fn, 60 url 61 ); 62 return [id, metas_res.ok ? metas_res.data : []]; 63 }) 64 ); 65 66 const out: CommentsByRoot = {}; 67 for (const [id, metas] of entries) { 68 out[id] = metas; 69 } 70 71 return out; 72 } 73 74 export async function load_profile_indexed( 75 fetch_fn: HttpFetch, 76 kind: ProfileRoutesKind, 77 key: string 78 ): Promise<FetchJsonResult<PageLoadProfileDataWithComments>> { 79 const profile_res = await fetch_json<RadrootsProfileEventMetadata>( 80 fetch_fn, 81 `${idx_url}/events/0/${kind}/${encodeURIComponent(key)}/metadata.json` 82 ); 83 if (!profile_res.ok) return profile_res; 84 85 const listings_res = await fetch_listings(fetch_fn, kind, key); 86 if (!listings_res.ok) return listings_res; 87 88 const listing_ids = listings_res.data.map((m) => m.id.toLowerCase()); 89 const listing_comments = await fetch_comments_for_roots(fetch_fn, listing_ids); 90 91 const public_key = profile_res.data.author; 92 const npub = nostr_npub_encode(public_key); 93 94 return { 95 ok: true, 96 data: { 97 public_key, 98 npub, 99 events: { 100 profile: profile_res.data, 101 listings: listings_res.data, 102 listing_comments 103 } 104 } 105 }; 106 }