MCPcopy Create free account
hub / github.com/Dhravya/notty / getYDoc

Method getYDoc

src/durable-objects/user-notes.ts:176–229  ·  view source on GitHub ↗
(noteId: string)

Source from the content-addressed store, hash-verified

174 // settings (e.g. agent prefs, last-seen versions) doesn't require
175 // a schema migration each time.
176 this.sql.exec(`
177 CREATE TABLE IF NOT EXISTS smfs_config (
178 key TEXT PRIMARY KEY,
179 value TEXT NOT NULL
180 )
181 `);
182 });
183 }
184
185 private getYDoc(noteId: string): Y.Doc {
186 let doc = this.docs.get(noteId);
187 if (doc) return doc;
188
189 doc = new Y.Doc();
190 const rows = this.sql.exec("SELECT yjs_state FROM notes WHERE id = ?", noteId).toArray();
191 if (rows[0]?.yjs_state) {
192 Y.applyUpdate(doc, new Uint8Array(rows[0].yjs_state as ArrayBuffer));
193 }
194
195 doc.on("update", (update: Uint8Array, origin: any) => {
196 // Broadcast to all connected clients except the sender.
197 // origin is the WebSocket that caused this update (null for DB loads).
198 if (origin) {
199 const encoder = encoding.createEncoder();
200 encoding.writeVarUint(encoder, MSG_SYNC);
201 syncProtocol.writeUpdate(encoder, update);
202 const msg = encoding.toUint8Array(encoder);
203 for (const other of this.ctx.getWebSockets(noteId)) {
204 if (other !== origin) {
205 try { other.send(msg); } catch { other.close(); }
206 }
207 }
208 }
209
210 this.scheduleDocPersist(noteId, doc!, 2000);
211 });
212
213 this.docs.set(noteId, doc);
214 return doc;
215 }
216
217 // Persist a live Yjs doc to the notes row: yjs_state always; content +
218 // title when serialization yields a non-empty doc. Never replaces
219 // non-empty column content with an empty doc — if serialization ever
220 // regresses (or the doc is transiently blank), losing the row content is
221 // the worst outcome. Shared by the debounced save and the last-close flush
222 // so the content column can never lag behind yjs_state.
223 private persistDocNow(noteId: string, doc: Y.Doc) {
224 const state = Y.encodeStateAsUpdate(doc);
225 let content = this.extractContentJson(noteId);
226 if (content && isEmptyDoc(content)) {
227 const existing = this.sql.exec("SELECT content FROM notes WHERE id = ?", noteId).toArray()[0] as any;
228 if (existing?.content && !isEmptyDoc(existing.content)) content = null;
229 }
230 if (content && !isEmptyDoc(content)) {
231 // Real content: UPSERT so a brand-new note persists even when the HTTP
232 // autosave never created the row (or failed, e.g. a transient 503).

Callers 3

fetchMethod · 0.95
webSocketMessageMethod · 0.95
extractContentJsonMethod · 0.95

Calls 2

extractContentJsonMethod · 0.95
deriveTitleAndPreviewFunction · 0.90

Tested by

no test coverage detected