-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.ts
More file actions
91 lines (73 loc) · 2.39 KB
/
index.ts
File metadata and controls
91 lines (73 loc) · 2.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { SQLite } from "@hocuspocus/extension-sqlite";
import { Document, Server } from "@hocuspocus/server";
import { serve } from "@hono/node-server";
import { createNodeWebSocket } from "@hono/node-ws";
import { Hono } from "hono";
import { cors } from "hono/cors";
import { createMiddleware } from "hono/factory";
import { FAKE_authInfoFromToken } from "./auth.js";
import { threadsRouter } from "./threads.js";
import { RejectUnauthorized } from "./rejectUnauthorized.js";
// Setup Hocuspocus server
const hocuspocusServer = Server.configure({
async onAuthenticate(data) {
const { token } = data;
const authInfo = FAKE_authInfoFromToken(token);
if (authInfo === "unauthorized") {
throw new Error("Not authorized!");
}
data.connection.readOnly = authInfo.role === "COMMENT-ONLY";
},
extensions: [
new SQLite({
database: "db.sqlite",
}),
new RejectUnauthorized("threads"),
],
// TODO: for good security, you'd want to make sure that either:
// - incoming updates to the "thread" map within the Y.Doc are denied (these should only be made via the thread API)
// - alternatively, use a separate Y.Doc for the thread data that can only be written to via the thread API
});
// Setup Hono server
const app = new Hono();
app.use(cors());
const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app });
// We mount HocusPocus in the Hono server
app.get(
"/hocuspocus",
upgradeWebSocket((c) => ({
onOpen(_evt, ws) {
hocuspocusServer.handleConnection(ws.raw, c.req.raw);
},
}))
);
// Simple route for testing
app.get("/", (c) => c.text("Hello World"));
// Middleware so all requests to /documents/:documentId/ have the yjs document available
const documentMiddleware = createMiddleware<{
Variables: {
document: Document;
};
}>(async (c, next) => {
const documentId = c.req.param("documentId");
const document = hocuspocusServer.documents.get(documentId!);
if (!document) {
return c.json({ error: "Document not found" }, 404);
}
c.set("document", document);
await next();
return;
});
app.use("/documents/:documentId/*", documentMiddleware);
// Mount the thread REST API
app.route(
"/documents/:documentId/threads",
threadsRouter({ threadsMapKey: "threads" })
);
// Start server
const server = serve({
fetch: app.fetch,
port: 8787,
});
// Setup WebSocket support (needed for HocusPocus)
injectWebSocket(server);