diff --git a/lib/community-sync.ts b/lib/community-sync.ts
index f83103f..44239e1 100644
--- a/lib/community-sync.ts
+++ b/lib/community-sync.ts
@@ -699,7 +699,7 @@ export class CommunitySync extends EventTarget {
this.dispatchEvent(new CustomEvent("shape-state-changed", {
detail: { shapeId, state: 'forgotten', data: this.#doc.shapes?.[shapeId] }
}));
- this.#scheduleSave();
+ this.#saveImmediate();
this.#syncToServer();
}
@@ -734,7 +734,7 @@ export class CommunitySync extends EventTarget {
this.dispatchEvent(new CustomEvent("shape-state-changed", {
detail: { shapeId, state: 'present', data: this.#doc.shapes?.[shapeId] }
}));
- this.#scheduleSave();
+ this.#saveImmediate();
this.#syncToServer();
}
@@ -756,7 +756,7 @@ export class CommunitySync extends EventTarget {
this.dispatchEvent(new CustomEvent("shape-state-changed", {
detail: { shapeId, state: 'deleted', data: this.#doc.shapes?.[shapeId] }
}));
- this.#scheduleSave();
+ this.#saveImmediate();
this.#syncToServer();
}
@@ -1013,6 +1013,18 @@ export class CommunitySync extends EventTarget {
}, 2000);
}
+ /** Flush doc to IndexedDB immediately (no debounce). Use for destructive ops. */
+ #saveImmediate(): void {
+ if (!this.#offlineStore) return;
+ if (this.#saveDebounceTimer) {
+ clearTimeout(this.#saveDebounceTimer);
+ this.#saveDebounceTimer = null;
+ }
+ const binary = Automerge.save(this.#doc);
+ this.#offlineStore.saveDocImmediate(this.#communitySlug, binary);
+ this.#offlineStore.saveDocEmergency(this.#communitySlug, binary);
+ }
+
#persistSyncState(): void {
if (!this.#offlineStore) return;
diff --git a/server/shell.ts b/server/shell.ts
index 469a51f..ab66d29 100644
--- a/server/shell.ts
+++ b/server/shell.ts
@@ -228,6 +228,14 @@ export function renderShell(opts: ShellOptions): string {