decentralised sync engine
1import { OWNER_DID, SERVER_PORT, SERVICE_DID } from "@/lib/env"; 2import { connectToShards, performHandshakes } from "@/lib/setup"; 3import { handshakeTokens, 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 // least tested. will probably have nuances we need to work on in the future 93 attachLatticeRegistrationListener(prismWebsocket); 94 95 await performHandshakes(latticeAtUri); 96 97 const test = await connectToShards(); 98 console.log( 99 "connected to", 100 test.map((socket) => socket.url), 101 ); 102 103 // TODO: change this to the actual WS sessions 104 const handshakeTokenEntries = handshakeTokens.entries().toArray(); 105 106 if (handshakeTokenEntries.length === 0) { 107 console.warn( 108 "Warning: there are zero handshake tokens on this Lattice.", 109 ); 110 console.warn( 111 "If you're hacking locally, you might want to make sure that there's a running Shard as well.", 112 ); 113 // NOTE: might change in the future 114 console.warn( 115 "Channel records connecting a local Lattice to a production Shard are not supported (for now). Local Lattices must point to a local Shard.", 116 ); 117 } 118}; 119 120main() 121 .then(() => { 122 console.log(`Server is running on port ${SERVER_PORT.toString()}`); 123 }) 124 .catch((err: unknown) => { 125 console.error("Something went wrong :("); 126 console.error( 127 "=========================== FULL ERROR BELOW ===========================", 128 ); 129 console.error(err); 130 });