Skip to content

Commit ca2373f

Browse files
committed
add comments
1 parent b513a7a commit ca2373f

File tree

4 files changed

+43
-17
lines changed

4 files changed

+43
-17
lines changed

hocuspocus-server/src/auth.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
export function authInfoFromToken(token: string) {
1+
/**
2+
* This is a fake implementation of authentication.
3+
*
4+
* It parses a token (like userid__READ-WRITE) and returns the userId and role.
5+
*/
6+
export function FAKE_authInfoFromToken(token: string) {
27
const parts = token.split("__");
38

49
if (parts.length !== 2) {

hocuspocus-server/src/index.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ import { createNodeWebSocket } from "@hono/node-ws";
66
import { Hono } from "hono";
77
import { cors } from "hono/cors";
88
import { createMiddleware } from "hono/factory";
9-
import { authInfoFromToken } from "./auth.js";
9+
import { FAKE_authInfoFromToken } from "./auth.js";
1010
import { threadsRouter } from "./threads.js";
1111

12+
// Setup Hocuspocus server
1213
const hocuspocusServer = Server.configure({
1314
async onAuthenticate(data) {
1415
const { token } = data;
1516

16-
const authInfo = authInfoFromToken(token);
17+
const authInfo = FAKE_authInfoFromToken(token);
1718

1819
if (authInfo === "unauthorized") {
1920
throw new Error("Not authorized!");
@@ -33,12 +34,13 @@ const hocuspocusServer = Server.configure({
3334
// - alternatively, use a separate Y.Doc for the thread data that can only be written to via the thread API
3435
});
3536

37+
// Setup Hono server
3638
const app = new Hono();
37-
3839
app.use(cors());
3940

4041
const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app });
4142

43+
// We mount HocusPocus in the Hono server
4244
app.get(
4345
"/hocuspocus",
4446
upgradeWebSocket((c) => ({
@@ -48,8 +50,10 @@ app.get(
4850
}))
4951
);
5052

53+
// Simple route for testing
5154
app.get("/", (c) => c.text("Hello World"));
5255

56+
// Middleware so all requests to /documents/:documentId/ have the yjs document available
5357
const documentMiddleware = createMiddleware<{
5458
Variables: {
5559
document: Document;
@@ -69,14 +73,17 @@ const documentMiddleware = createMiddleware<{
6973

7074
app.use("/documents/:documentId/*", documentMiddleware);
7175

76+
// Mount the thread REST API
7277
app.route(
7378
"/documents/:documentId/threads",
7479
threadsRouter({ threadsMapKey: "threads" })
7580
);
7681

82+
// Start server
7783
const server = serve({
7884
fetch: app.fetch,
7985
port: 8787,
8086
});
8187

88+
// Setup WebSocket support (needed for HocusPocus)
8289
injectWebSocket(server);

hocuspocus-server/src/threads.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ import { DefaultThreadStoreAuth, YjsThreadStore } from "@blocknote/core";
22
import { Document } from "@hocuspocus/server";
33
import { Hono, Next } from "hono";
44
import { createMiddleware } from "hono/factory";
5-
import { authInfoFromToken } from "./auth.js";
5+
import { FAKE_authInfoFromToken } from "./auth.js";
66

7+
// Middleware that parses the Authorization header and sets the userId and role
8+
// based on the token.
9+
// NOTE: This is a fake implementation for demo purposes.
710
const authMiddleware = createMiddleware<{
811
Variables: {
912
userId: string;
@@ -18,7 +21,7 @@ const authMiddleware = createMiddleware<{
1821
return c.json({ error: "Unauthorized" });
1922
}
2023

21-
const authInfo = authInfoFromToken(parts[1]);
24+
const authInfo = FAKE_authInfoFromToken(parts[1]);
2225

2326
if (authInfo === "unauthorized") {
2427
c.status(401);
@@ -32,6 +35,7 @@ const authMiddleware = createMiddleware<{
3235
return;
3336
});
3437

38+
// Middleware that based on the auth info creates a YjsThreadStore and makes it available to the request
3539
const threadStoreMiddleware = (options: { threadsMapKey: string }) =>
3640
createMiddleware<{
3741
Variables: {
@@ -55,6 +59,7 @@ const threadStoreMiddleware = (options: { threadsMapKey: string }) =>
5559
await next();
5660
});
5761

62+
// The REST API that handles thread operations and executes them using the threadStore
5863
export const threadsRouter = (options: { threadsMapKey: string }) => {
5964
const router = new Hono<{
6065
Variables: {
@@ -93,7 +98,7 @@ export const threadsRouter = (options: { threadsMapKey: string }) => {
9398
const json = await c.req.json();
9499
// TODO: you'd probably validate the request json here
95100

96-
const comment = await c.get("threadStore").updateComment({
101+
await c.get("threadStore").updateComment({
97102
threadId: c.req.param("threadId"),
98103
commentId: c.req.param("commentId"),
99104
...json,

next-app/components/Editor.tsx

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,45 @@ import "@blocknote/mantine/style.css";
66
import { useCreateBlockNote } from "@blocknote/react";
77
import { HocuspocusProvider } from "@hocuspocus/provider";
88

9+
// Hardcoded settings for demo purposes
910
const USER_ID = "user123";
1011
const USER_ROLE: "COMMENT-ONLY" | "READ-WRITE" = "READ-WRITE";
1112
const DOCUMENT_ID = "mydoc123";
1213
const TOKEN = `${USER_ID}__${USER_ROLE}`;
1314

15+
// Setup Hocuspocus provider
1416
const provider = new HocuspocusProvider({
1517
url: "ws://localhost:8787/hocuspocus",
1618
token: TOKEN,
1719
name: DOCUMENT_ID,
1820
});
1921

20-
// const threadStore = new YjsThreadStore(
21-
// "123",
22-
// provider.document.getMap("threads"),
23-
// new DefaultThreadStoreAuth("123", "editor")
24-
// );
22+
// The thread store auth is used by the BlockNote interface to determine which actions are allowed
23+
// (and which elements should be shown)
24+
const threadStoreAuth = new DefaultThreadStoreAuth(
25+
USER_ID,
26+
USER_ROLE === "READ-WRITE" ? "editor" : "comment"
27+
);
2528

26-
debugger;
29+
// set up the thread store using the REST API
2730
const threadStore = new RESTYjsThreadStore(
2831
`http://localhost:8787/documents/${DOCUMENT_ID}/threads`,
2932
{
3033
Authorization: `Bearer ${TOKEN}`,
3134
},
3235
provider.document.getMap("threads"),
33-
new DefaultThreadStoreAuth(
34-
USER_ID,
35-
USER_ROLE === "READ-WRITE" ? "editor" : "comment"
36-
)
36+
threadStoreAuth
3737
);
3838

39+
// Instead of using the REST API, you could also use a YjsThreadStore
40+
// however, this lacks good authentication on comment operations
41+
//
42+
// const threadStore = new YjsThreadStore(
43+
// USER_ID,
44+
// provider.document.getMap("threads"),
45+
// threadStoreAuth
46+
// );
47+
3948
// Our <Editor> component we can reuse later
4049
export default function Editor() {
4150
// Creates a new editor instance.

0 commit comments

Comments
 (0)