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