fix: Automerge undefined rejection + thread not synced to server

- tweetImages and imageUrl set to null instead of undefined when empty
  (Automerge rejects undefined as invalid JSON)
- Updated ThreadData schema to allow null for optional fields
- This was the root cause of the 404 on image generation: saveDraft
  threw on undefined, so the thread never synced to the server, and
  the server-side route returned "Thread not found"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-05 17:14:06 -08:00
parent f9bafc8ef0
commit a1b50eb0da
3 changed files with 6 additions and 6 deletions

View File

@ -441,8 +441,8 @@ export class FolkThreadBuilder extends HTMLElement {
handle: handleInput.value || '@yourhandle',
title: titleInput.value || tweets[0].substring(0, 60),
tweets,
tweetImages: Object.keys(this._tweetImages).length ? { ...this._tweetImages } : undefined,
imageUrl: this._thread?.imageUrl,
tweetImages: Object.keys(this._tweetImages).length ? { ...this._tweetImages } : null,
imageUrl: this._thread?.imageUrl || null,
createdAt: this._thread?.createdAt || Date.now(),
updatedAt: Date.now(),
};
@ -716,7 +716,7 @@ export class FolkThreadBuilder extends HTMLElement {
await fetch(this.basePath + 'api/threads/' + this._threadId + '/tweet/' + index + '/image', { method: 'DELETE' });
delete this._tweetImages[index];
if (this._thread) {
this._thread.tweetImages = Object.keys(this._tweetImages).length ? { ...this._tweetImages } : undefined;
this._thread.tweetImages = Object.keys(this._tweetImages).length ? { ...this._tweetImages } : null;
await this.saveToAutomerge(this._thread);
}
this.renderPreview();

View File

@ -216,7 +216,7 @@ routes.post("/api/threads/:id/upload-image", async (c) => {
const ext = safeExtension(file.name);
const filename = `thread-${id}.${ext}`;
await deleteOldImage(thread.imageUrl, filename);
if (thread.imageUrl) await deleteOldImage(thread.imageUrl, filename);
const buffer = Buffer.from(await file.arrayBuffer());
const imageUrl = await saveUploadedFile(buffer, filename);

View File

@ -17,8 +17,8 @@ export interface ThreadData {
handle: string;
title: string;
tweets: string[];
imageUrl?: string;
tweetImages?: Record<string, string>;
imageUrl?: string | null;
tweetImages?: Record<string, string> | null;
createdAt: number;
updatedAt: number;
}