Browse Source

fix: Resolve postMessage serialization error in event publishing

Events now publish successfully but don't appear in feed yet. Fixed the
"Failed to execute 'postMessage' on 'Window'" error by ensuring all
event data is properly serialized before passing between components.

Changes:
- Remove non-serializable tree property from exported events
- Convert all NDKEvent properties to primitives in eventToPublishableObject
- Add JSON deep cloning in handlePublish to ensure full serializability
- Add debug logging to track event structure and serialization issues

Status: Publishing works (events are sent to relays) but feed display
needs investigation for relay read/write configuration mismatch.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
master
limina1 6 months ago
parent
commit
716012ee63
  1. 38
      src/lib/components/ZettelEditor.svelte
  2. 22
      src/lib/utils/asciidoc_publication_parser.ts

38
src/lib/components/ZettelEditor.svelte

@ -70,7 +70,7 @@ import Asciidoctor from "asciidoctor";
}); });
// Effect to create PublicationTree when content changes // Effect to create PublicationTree when content changes
// Uses tree processor extension as Michael envisioned: // Uses tree processor:
// "register a tree processor extension in our Asciidoctor instance" // "register a tree processor extension in our Asciidoctor instance"
// "use the AST that Asciidoctor generates during parsing" // "use the AST that Asciidoctor generates during parsing"
// "publication tree side-loads into memory as AsciiDoc is parsed" // "publication tree side-loads into memory as AsciiDoc is parsed"
@ -93,6 +93,16 @@ import Asciidoctor from "asciidoctor";
return exportEventsFromTree(result); return exportEventsFromTree(result);
}) })
.then(events => { .then(events => {
// Debug: Check what we're getting from exportEventsFromTree
console.log("Events from exportEventsFromTree:", events);
console.log("Event keys:", Object.keys(events));
if (events.indexEvent) {
console.log("Index event keys:", Object.keys(events.indexEvent));
}
if (events.contentEvents?.[0]) {
console.log("First content event keys:", Object.keys(events.contentEvents[0]));
}
generatedEvents = events; generatedEvents = events;
console.log("Tree factory result:", { console.log("Tree factory result:", {
@ -225,16 +235,36 @@ import Asciidoctor from "asciidoctor";
function handlePublish() { function handlePublish() {
if (!generatedEvents) return; if (!generatedEvents) return;
if (contentType === 'article' && generatedEvents.indexEvent) { try {
// Deep clone the events to ensure they're fully serializable
// This prevents postMessage cloning errors
const serializableEvents = JSON.parse(JSON.stringify(generatedEvents));
if (contentType === 'article' && serializableEvents.indexEvent) {
// Full article: publish both index event (30040) and content events (30041) // Full article: publish both index event (30040) and content events (30041)
onPublishArticle(generatedEvents); onPublishArticle(serializableEvents);
} else if (contentType === 'scattered-notes') { } else if (contentType === 'scattered-notes') {
// Only notes: publish just the content events (30041) // Only notes: publish just the content events (30041)
const notesOnly = { const notesOnly = {
contentEvents: generatedEvents.contentEvents contentEvents: serializableEvents.contentEvents
}; };
onPublishScatteredNotes(notesOnly); onPublishScatteredNotes(notesOnly);
} }
} catch (error) {
console.error("Failed to serialize events:", error);
console.error("generatedEvents structure:", generatedEvents);
// Try to identify the non-serializable part
if (generatedEvents) {
console.error("Keys in generatedEvents:", Object.keys(generatedEvents));
if (generatedEvents.indexEvent) {
console.error("indexEvent type:", typeof generatedEvents.indexEvent, generatedEvents.indexEvent?.constructor?.name);
}
if (generatedEvents.contentEvents?.[0]) {
console.error("First contentEvent type:", typeof generatedEvents.contentEvents[0], generatedEvents.contentEvents[0]?.constructor?.name);
}
}
alert("Error: Events contain non-serializable data. Check console for details.");
}
} }
// Tutorial sidebar state // Tutorial sidebar state

22
src/lib/utils/asciidoc_publication_parser.ts

@ -109,23 +109,27 @@ async function buildTreeRelationships(result: ProcessorResult): Promise<void> {
export function exportEventsFromTree(result: PublicationTreeResult) { export function exportEventsFromTree(result: PublicationTreeResult) {
return { return {
indexEvent: result.indexEvent ? eventToPublishableObject(result.indexEvent) : undefined, indexEvent: result.indexEvent ? eventToPublishableObject(result.indexEvent) : undefined,
contentEvents: result.contentEvents.map(eventToPublishableObject), contentEvents: result.contentEvents.map(eventToPublishableObject)
tree: result.tree // Note: Deliberately omitting 'tree' to ensure the object is serializable for postMessage
}; };
} }
/** /**
* Convert NDKEvent to publishable object format * Convert NDKEvent to publishable object format
* Ensures all properties are serializable for postMessage
*/ */
function eventToPublishableObject(event: any) { function eventToPublishableObject(event: any) {
// Extract only primitive values to ensure serializability
return { return {
kind: event.kind, kind: Number(event.kind),
content: event.content, content: String(event.content || ''),
tags: event.tags, tags: Array.isArray(event.tags) ? event.tags.map((tag: any) =>
created_at: event.created_at, Array.isArray(tag) ? tag.map(t => String(t)) : []
pubkey: event.pubkey, ) : [],
id: event.id, created_at: Number(event.created_at || Math.floor(Date.now() / 1000)),
title: event.tags.find((t: string[]) => t[0] === "title")?.[1] || "Untitled" pubkey: String(event.pubkey || ''),
id: String(event.id || ''),
title: event.tags?.find?.((t: string[]) => t[0] === "title")?.[1] || "Untitled"
}; };
} }

Loading…
Cancel
Save