examples/live-notes Public
// The live-notes Worker. It routes each note to its own NoteRoom by name, so every editor of// "groceries" reaches the same object wherever they are.//// GET /notes/:id the note as JSON: { id, text, version }// GET /notes/:id/ws upgrade to a WebSocket and edit the note (protocol.ts)// GET /notes/:id/snapshots?after=n the note's saved snapshots, oldest first (snapshots.ts)// GET /notes/:id/snapshots/:version the note's text at that version, as text/plain//// Snapshots are read straight from R2, so looking at a note's history never wakes its room.import type { NoteRoom } from "./note-room.ts";import { route } from "./routes.ts";import { listSnapshots, readSnapshot } from "./snapshots.ts";export { NoteRoom } from "./note-room.ts";export interface Env { NOTES: DurableObjectNamespace<NoteRoom>; SNAPSHOTS: R2Bucket;}export default { async fetch(request, env): Promise<Response> { const url = new URL(request.url); const r = route(url.pathname); if (!r) return new Response("not found", { status: 404 }); if (request.method !== "GET") return new Response("method not allowed", { status: 405, headers: { allow: "GET" } }); const objectId = env.NOTES.idFromName(r.id); if (r.kind === "snapshots") { const after = Number(url.searchParams.get("after") ?? 0); if (!Number.isSafeInteger(after) || after < 0) return new Response("after is a version number", { status: 400 }); return Response.json({ id: r.id, ...(await listSnapshots(env.SNAPSHOTS, objectId.toString(), after)) }); } if (r.kind === "snapshot") { const text = await readSnapshot(env.SNAPSHOTS, objectId.toString(), r.version); if (text === null) return new Response("no snapshot of that version", { status: 404 }); return new Response(text, { headers: { "content-type": "text/plain; charset=utf-8", "cache-control": "public, max-age=31536000, immutable" } }); } const room = env.NOTES.get(objectId); if (r.kind === "socket") { if (request.headers.get("Upgrade") !== "websocket") return new Response("expected a WebSocket upgrade", { status: 426 }); return room.fetch(request); } const note = await room.read(); return Response.json({ id: r.id, text: note.text, version: note.version }); },} satisfies ExportedHandler<Env>;