frontend client for gemstone. decentralised workplace app
1import type { Did } from "@/lib/types/atproto";
2import type { SystemsGmstnDevelopmentLattice } from "@/lib/types/lexicon/systems.gmstn.development.lattice";
3import { systemsGmstnDevelopmentLatticeRecordSchema } from "@/lib/types/lexicon/systems.gmstn.development.lattice";
4import type { Result } from "@/lib/utils/result";
5import { Client, simpleFetchHandler } from "@atcute/client";
6import { z } from "zod";
7
8// TODO: use prism instead of direct PDS lookup
9export const getUserLattices = async ({
10 pdsEndpoint,
11 did,
12}: {
13 pdsEndpoint: string;
14 did: Did;
15}): Promise<
16 Result<
17 Array<{
18 uri: string;
19 value: SystemsGmstnDevelopmentLattice;
20 }>,
21 unknown
22 >
23> => {
24 const handler = simpleFetchHandler({ service: pdsEndpoint });
25 const client = new Client({ handler });
26 const shardRecordsResult = await fetchRecords({
27 client,
28 did,
29 });
30 if (!shardRecordsResult.ok)
31 return { ok: false, error: shardRecordsResult.error };
32 return { ok: true, data: shardRecordsResult.data };
33};
34
35const fetchRecords = async ({
36 client,
37 did,
38}: {
39 client: Client;
40 did: Did;
41}): Promise<
42 Result<
43 Array<{
44 uri: string;
45 value: SystemsGmstnDevelopmentLattice;
46 }>,
47 unknown
48 >
49> => {
50 const allRecords: Array<{
51 uri: string;
52 value: SystemsGmstnDevelopmentLattice;
53 }> = [];
54 let cursor: string | undefined;
55
56 let continueLoop = true;
57
58 while (continueLoop) {
59 const results = await client.get("com.atproto.repo.listRecords", {
60 params: {
61 repo: did,
62 collection: "systems.gmstn.development.lattice",
63 limit: 100,
64 cursor,
65 },
66 });
67 if (!results.ok)
68 return {
69 ok: false,
70 error: "Failed to fetch records. Check the response from PDS.",
71 };
72 const { records, cursor: nextCursor } = results.data;
73
74 const {
75 success,
76 error,
77 data: responses,
78 } = z
79 .array(
80 z.object({
81 cid: z.string(),
82 uri: z.string(),
83 value: systemsGmstnDevelopmentLatticeRecordSchema,
84 }),
85 )
86 .safeParse(records);
87
88 if (!success) return { ok: false, error: z.treeifyError(error) };
89
90 allRecords.push(
91 ...responses.map((data) => {
92 return { uri: data.uri, value: data.value };
93 }),
94 );
95
96 if (records.length < 100) continueLoop = false;
97 cursor = nextCursor;
98 }
99 return { ok: true, data: allRecords };
100};