decentralised message store
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";
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 "Shard 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(1013, "Service unavailable: Shard not yet registered");
35 return;
36 }
37
38 wsHandler(socket, request);
39 };
40
41 return wrappedFunction;
42}
43
44export const attachShardRegistrationListener = (socket: WebSocket) => {
45 socket.on("message", (rawData: RawData) => {
46 const data = rawDataToString(rawData);
47 const jsonData: unknown = JSON.parse(data);
48
49 const { success: prismCommitParseSuccess, data: prismCommit } =
50 prismCommitSchema.safeParse(jsonData);
51 if (!prismCommitParseSuccess) return;
52
53 const { did, commit } = prismCommit;
54 if (did !== OWNER_DID) return;
55
56 const { rkey } = commit;
57
58 // TODO: replace empty string with call to resolve did doc and the endpoint and yadda yadda etc. etc. you get it.
59 // 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
60 // that the domain/origin/whatever matches with the rkey (or record value if we decide to transition to that)
61 const shardDomain = SERVICE_DID.startsWith("did:web:")
62 ? SERVICE_DID.slice(8)
63 : "";
64 if (rkey !== shardDomain) return;
65
66 setRegistrationState(true);
67 });
68};