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};