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"; @@ -70,7 +70,7 @@ import Asciidoctor from "asciidoctor";
});
// 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"
// "use the AST that Asciidoctor generates during parsing"
// "publication tree side-loads into memory as AsciiDoc is parsed"
@ -93,6 +93,16 @@ import Asciidoctor from "asciidoctor"; @@ -93,6 +93,16 @@ import Asciidoctor from "asciidoctor";
return exportEventsFromTree(result);
})
.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;
console.log("Tree factory result:", {
@ -225,16 +235,36 @@ import Asciidoctor from "asciidoctor"; @@ -225,16 +235,36 @@ import Asciidoctor from "asciidoctor";
function handlePublish() {
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)
onPublishArticle(generatedEvents);
onPublishArticle(serializableEvents);
} else if (contentType === 'scattered-notes') {
// Only notes: publish just the content events (30041)
const notesOnly = {
contentEvents: generatedEvents.contentEvents
contentEvents: serializableEvents.contentEvents
};
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

22
src/lib/utils/asciidoc_publication_parser.ts

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

Loading…
Cancel
Save