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