MCPcopy Create free account
hub / github.com/backnotprop/plannotator / handle

Function handle

packages/server/external-annotations.ts:80–205  ·  view source on GitHub ↗
(
      req: Request,
      url: URL,
      options?: { disableIdleTimeout?: () => void },
    )

Source from the content-addressed store, hash-verified

78 },
79
80 async handle(
81 req: Request,
82 url: URL,
83 options?: { disableIdleTimeout?: () => void },
84 ): Promise<Response | null> {
85 // --- SSE stream ---
86 if (url.pathname === STREAM && req.method === "GET") {
87 options?.disableIdleTimeout?.();
88
89 let heartbeatTimer: ReturnType<typeof setInterval> | null = null;
90 let ctrl: ReadableStreamDefaultController;
91
92 const stream = new ReadableStream({
93 start(controller) {
94 ctrl = controller;
95
96 // Send current state as snapshot
97 const snapshot: ExternalAnnotationEvent<StorableAnnotation> = {
98 type: "snapshot",
99 annotations: store.getAll(),
100 };
101 controller.enqueue(encoder.encode(serializeSSEEvent(snapshot)));
102
103 subscribers.add(controller);
104
105 // Heartbeat to keep connection alive
106 heartbeatTimer = setInterval(() => {
107 try {
108 controller.enqueue(encoder.encode(HEARTBEAT_COMMENT));
109 } catch {
110 // Stream closed
111 if (heartbeatTimer) clearInterval(heartbeatTimer);
112 subscribers.delete(controller);
113 }
114 }, HEARTBEAT_INTERVAL_MS);
115 },
116 cancel() {
117 if (heartbeatTimer) clearInterval(heartbeatTimer);
118 subscribers.delete(ctrl);
119 },
120 });
121
122 return new Response(stream, {
123 headers: {
124 "Content-Type": "text/event-stream",
125 "Cache-Control": "no-cache",
126 Connection: "keep-alive",
127 },
128 });
129 }
130
131 // --- GET snapshot (polling fallback) ---
132 if (url.pathname === BASE && req.method === "GET") {
133 const since = url.searchParams.get("since");
134 if (since !== null) {
135 const sinceVersion = parseInt(since, 10);
136 if (!isNaN(sinceVersion) && sinceVersion === store.version) {
137 return new Response(null, { status: 304 });

Callers

nothing calls this directly

Calls 7

getAllMethod · 0.80
addMethod · 0.80
updateMethod · 0.80
clearBySourceMethod · 0.80
clearAllMethod · 0.80
getMethod · 0.65
removeMethod · 0.65

Tested by

no test coverage detected