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 let latticeUrlOrigin = decodeURIComponent( 18 SERVICE_DID.startsWith("did:web:") ? SERVICE_DID.slice(8) : "", 19 ); 20 if (latticeUrlOrigin === "localhost") 21 latticeUrlOrigin += `:${SERVER_PORT.toString()}`; 22 if (latticeUrlOrigin === "") { 23 // TODO: resolve did:plc endpoint to get the origin of the lattice endpoint described by the did:plc doc 24 // for now we just throw. 25 throw new Error( 26 "did:plc support not yet implemented. Provide a did:web for now. did:plc support will come in the future.", 27 ); 28 } 29 30 const latticeAtUri: Required<AtUri> = { 31 // @ts-expect-error alas, template literal weirdness continues uwu 32 authority: OWNER_DID, 33 collection: "systems.gmstn.development.lattice", 34 rKey: latticeUrlOrigin, 35 }; 36 37 const latticeRecord = await getRecordFromAtUri(latticeAtUri); 38 39 if (latticeRecord.ok) { 40 setRegistrationState(true); 41 } 42 43 const prismWebsocket = connectToPrism({ 44 wantedCollections: ["systems.gmstn.development.*"], 45 }); 46 47 // TODO: probably move this to an `attachListeners` hook that attaches the listeners we want. 48 attachLatticeRegistrationListener(prismWebsocket); 49 50 await performHandshakes(latticeAtUri); 51 52 const server = await setupServer(); 53 for (const [url, route] of Object.entries(routes)) { 54 if (!route.wsHandler) { 55 const { handler, method, skipRegistrationCheck } = route; 56 server.route({ 57 url, 58 method, 59 handler: skipRegistrationCheck 60 ? handler 61 : wrapHttpRegistrationCheck(handler), 62 }); 63 } else { 64 const { 65 wsHandler, 66 method, 67 handler: httpHandler, 68 skipRegistrationCheckHttp, 69 skipRegistrationCheckWs, 70 } = route; 71 const handler = 72 httpHandler ?? 73 (() => 74 newErrorResponse(404, { 75 message: 76 "This is a websocket only route. Did you mean to initiate a websocket connection here?", 77 })); 78 server.route({ 79 url, 80 method: method ?? "GET", 81 handler: skipRegistrationCheckHttp 82 ? handler 83 : wrapHttpRegistrationCheck(handler), 84 wsHandler: skipRegistrationCheckWs 85 ? wsHandler 86 : wrapWsRegistrationCheck(wsHandler), 87 }); 88 } 89 } 90 91 server.listen({ port: SERVER_PORT }).catch((err: unknown) => { 92 server.log.error(err); 93 process.exit(1); 94 }); 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 });