decentralised sync engine
1import { OWNER_DID, SERVICE_DID } from "@/lib/env";
2import { getRegistrationState, setRegistrationState } from "@/lib/state";
3import { prismCommitSchema } from "@/lib/types/prism";
4import type { RouteHandler, WsRouteHandler } from "@/lib/types/routes";
5import { newErrorResponse } from "@/lib/utils/http/responses";
6import { rawDataToString } from "@/lib/utils/ws/validate";
7import type { RawData } from "ws";
8import type WebSocket from "ws";
9
10export const wrapHttpRegistrationCheck = (
11 routeHandler: RouteHandler,
12): RouteHandler => {
13 const registrationState = getRegistrationState();
14 const wrappedFunction: RouteHandler = (req, rep) => {
15 if (!registrationState.registered) {
16 return newErrorResponse(503, {
17 message:
18 "Lattice has not been registered for use. Register it in the dashboard or make the record yourself using the bootstrapper if you're doing local development.",
19 });
20 }
21
22 return routeHandler(req, rep);
23 };
24
25 return wrappedFunction;
26};
27
28export function wrapWsRegistrationCheck(
29 wsHandler: WsRouteHandler,
30): WsRouteHandler {
31 const registrationState = getRegistrationState();
32 const wrappedFunction: WsRouteHandler = (socket, request) => {
33 if (!registrationState.registered) {
34 socket.close(
35 1013,
36 "Service unavailable: Lattice not yet registered",
37 );
38 return;
39 }
40
41 wsHandler(socket, request);
42 };
43
44 return wrappedFunction;
45}
46
47export const attachLatticeRegistrationListener = (socket: WebSocket) => {
48 socket.on("message", (rawData: RawData) => {
49 const data = rawDataToString(rawData);
50 const jsonData: unknown = JSON.parse(data);
51
52 const { success: prismCommitParseSuccess, data: prismCommit } =
53 prismCommitSchema.safeParse(jsonData);
54 if (!prismCommitParseSuccess) return;
55
56 const { did, commit } = prismCommit;
57 if (did !== OWNER_DID) return;
58
59 const { rkey } = commit;
60
61 // TODO: replace empty string with call to resolve did doc and the endpoint and yadda yadda etc. etc. you get it.
62 // if you don't, then the tl;dr is you need to resolve the did:plc document to get the service endpoint describing this lattice and ensure
63 // that the domain/origin/whatever matches with the rkey (or record value if we decide to transition to that)
64 const latticeDomain = SERVICE_DID.startsWith("did:web:")
65 ? SERVICE_DID.slice(8)
66 : "";
67 if (rkey !== latticeDomain) return;
68
69 setRegistrationState(true);
70 });
71};