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