1import { Client, simpleFetchHandler } from "@atcute/client"; 2import { isHandle } from "@atcute/lexicons/syntax"; 3import type { Loader, LoaderContext } from "astro/loaders"; 4import { LeafletDocumentSchema } from "schema.js"; 5import type { 6 LeafletDocumentRecord, 7 StaticLeafletLoaderOptions, 8} from "types.js"; 9import { 10 getLeafletDocuments, 11 isPlcDid, 12 leafletBlocksToHTML, 13 leafletDocumentRecordToView, 14 LiveLoaderError, 15 resolveMiniDoc, 16 uriToRkey, 17} from "utils.js"; 18 19export function leafletStaticLoader( 20 options: StaticLeafletLoaderOptions, 21): Loader { 22 const { repo, limit, reverse } = options; 23 24 if (!repo || typeof repo !== "string") { 25 throw new LiveLoaderError( 26 "missing or invalid did", 27 "MISSING_OR_INVALID_DID", 28 ); 29 } 30 31 // not a valid handle, check if valid did 32 if (!isHandle(repo)) { 33 // not a valid handle or did, throw 34 if (!isPlcDid(repo)) { 35 throw new LiveLoaderError( 36 "invalid handle or did", 37 "INVALID_HANDLE_OR_DID", 38 ); 39 } 40 } 41 42 return { 43 name: "static-leaflet-loader-astro", 44 schema: LeafletDocumentSchema, 45 load: async ({ 46 store, 47 logger, 48 generateDigest, 49 parseData, 50 }: LoaderContext) => { 51 try { 52 logger.info("fetching latest leaflet documents"); 53 const { pds, did } = await resolveMiniDoc(repo); 54 const handler = simpleFetchHandler({ service: pds }); 55 const rpc = new Client({ handler }); 56 57 let cursor: string | undefined; 58 let count = 0; 59 60 fetching: do { 61 const { documents, cursor: documentsCursor } = 62 await getLeafletDocuments({ 63 rpc, 64 repo, 65 cursor, 66 reverse, 67 limit: 50, 68 }); 69 for (const document of documents) { 70 if (limit && count >= limit) { 71 count++; 72 break fetching; 73 } 74 count++; 75 76 const id = uriToRkey(document.uri); 77 const digest = generateDigest(document.value); 78 store.set({ 79 id, 80 data: await parseData({ 81 id, 82 data: JSON.parse( 83 JSON.stringify( 84 leafletDocumentRecordToView({ 85 uri: document.uri, 86 cid: document.cid, 87 value: document.value as unknown as LeafletDocumentRecord, 88 }), 89 ), 90 ), 91 }), 92 digest, 93 rendered: { 94 html: leafletBlocksToHTML({ 95 record: document.value as unknown as LeafletDocumentRecord, 96 did, 97 }), 98 }, 99 }); 100 } 101 cursor = documentsCursor; 102 logger.info(`Fetched ${count} posts`); 103 } while (cursor); 104 } catch (error) { 105 logger.error( 106 `There was an error fetching the leaflet documents: ${(error as Error).message}`, 107 ); 108 } 109 }, 110 }; 111}