decentralised sync engine
1import { OWNER_DID, SERVER_PORT, SERVICE_DID } from "@/lib/env"; 2import { performHandshakes } from "@/lib/setup"; 3import { setRegistrationState } from "@/lib/state"; 4import type { AtUri } from "@/lib/types/atproto"; 5import { getRecordFromAtUri } from "@/lib/utils/atproto"; 6import { newErrorResponse } from "@/lib/utils/http/responses"; 7import { connectToPrism } from "@/lib/utils/prism"; 8import { 9 attachLatticeRegistrationListener, 10 wrapHttpRegistrationCheck, 11 wrapWsRegistrationCheck, 12} from "@/lib/utils/registration"; 13import { routes } from "@/routes"; 14import { setupServer } from "@/server"; 15 16const main = async () => { 17 const server = await setupServer(); 18 for (const [url, route] of Object.entries(routes)) { 19 if (!route.wsHandler) { 20 const { handler, method, skipRegistrationCheck } = route; 21 server.route({ 22 url, 23 method, 24 handler: skipRegistrationCheck 25 ? handler 26 : wrapHttpRegistrationCheck(handler), 27 }); 28 } else { 29 const { 30 wsHandler, 31 method, 32 handler: httpHandler, 33 skipRegistrationCheckHttp, 34 skipRegistrationCheckWs, 35 } = route; 36 const handler = 37 httpHandler ?? 38 (() => 39 newErrorResponse(404, { 40 message: 41 "This is a websocket only route. Did you mean to initiate a websocket connection here?", 42 })); 43 server.route({ 44 url, 45 method: method ?? "GET", 46 handler: skipRegistrationCheckHttp 47 ? handler 48 : wrapHttpRegistrationCheck(handler), 49 wsHandler: skipRegistrationCheckWs 50 ? wsHandler 51 : wrapWsRegistrationCheck(wsHandler), 52 }); 53 } 54 } 55 56 server.listen({ port: SERVER_PORT }).catch((err: unknown) => { 57 server.log.error(err); 58 process.exit(1); 59 }); 60 61 let latticeUrlOrigin = decodeURIComponent( 62 SERVICE_DID.startsWith("did:web:") ? SERVICE_DID.slice(8) : "", 63 ); 64 if (latticeUrlOrigin === "localhost") 65 latticeUrlOrigin += `:${SERVER_PORT.toString()}`; 66 if (latticeUrlOrigin === "") { 67 // TODO: resolve did:plc endpoint to get the origin of the lattice endpoint described by the did:plc doc 68 // for now we just throw. 69 throw new Error( 70 "did:plc support not yet implemented. Provide a did:web for now. did:plc support will come in the future.", 71 ); 72 } 73 74 const latticeAtUri: Required<AtUri> = { 75 // @ts-expect-error alas, template literal weirdness continues uwu 76 authority: OWNER_DID, 77 collection: "systems.gmstn.development.lattice", 78 rKey: latticeUrlOrigin, 79 }; 80 81 const latticeRecord = await getRecordFromAtUri(latticeAtUri); 82 83 if (latticeRecord.ok) { 84 setRegistrationState(true); 85 } 86 87 const prismWebsocket = connectToPrism({ 88 wantedCollections: ["systems.gmstn.development.*"], 89 }); 90 91 // TODO: probably move this to an `attachListeners` hook that attaches the listeners we want. 92 attachLatticeRegistrationListener(prismWebsocket); 93 94 await performHandshakes(latticeAtUri); 95}; 96 97main() 98 .then(() => { 99 console.log(`Server is running on port ${SERVER_PORT.toString()}`); 100 }) 101 .catch((err: unknown) => { 102 console.error("Something went wrong :("); 103 console.error( 104 "=========================== FULL ERROR BELOW ===========================", 105 ); 106 console.error(err); 107 });