leaflet.pub astro loader
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}