From fbbfdc6aa86b68e4b5ee6b8287210c0b24cb4cf4 Mon Sep 17 00:00:00 2001 From: Kris Braun Date: Sun, 2 Aug 2026 20:07:47 -0400 Subject: [PATCH 1/2] Add NewNote.deferUntilThread for notes whose thread has not synced yet --- .changeset/defer-until-thread.md | 5 +++++ twister/src/plot.ts | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 .changeset/defer-until-thread.md diff --git a/.changeset/defer-until-thread.md b/.changeset/defer-until-thread.md new file mode 100644 index 00000000..84944405 --- /dev/null +++ b/.changeset/defer-until-thread.md @@ -0,0 +1,5 @@ +--- +"@plotday/twister": minor +--- + +Added: `NewNote.deferUntilThread` holds a note addressed by `{ source }` until a thread with that source exists, instead of returning `null` when it has not synced yet. diff --git a/twister/src/plot.ts b/twister/src/plot.ts index 4c4d4b92..25c513c8 100644 --- a/twister/src/plot.ts +++ b/twister/src/plot.ts @@ -869,6 +869,28 @@ export type NewNote = Partial< */ authoredBySelf?: boolean; + /** + * Keep this note until its thread exists, instead of dropping it. + * + * A note addressed by `{ source }` normally resolves immediately, and + * `saveNote` returns `null` when no thread carries that source — which for + * a connector usually means the item this note belongs to has not synced + * yet. Set this to have the platform hold the note and attach it as soon + * as a thread with that source appears, rather than making you store and + * retry it yourself. + * + * Recommended for any `{ source }`-addressed note whose target is synced + * by a different product or connector and may therefore lag. Leave it + * unset when a miss means the note is genuinely undeliverable: `null` is + * then the signal you want, and holding the note would accumulate payloads + * for a thread that will never arrive. + * + * Held notes are dropped after a bounded retry window. Ordering is not + * guaranteed relative to notes that attached immediately, so set `created` + * (as connectors already should) rather than relying on arrival order. + */ + deferUntilThread?: boolean; + /** * Format of the note content. Determines how the note is processed: * - 'text': Plain text that will be converted to markdown (auto-links URLs, preserves line breaks) From 574e278efeb1e217af8ed15645e3359a23260e3b Mon Sep 17 00:00:00 2001 From: Kris Braun Date: Sun, 2 Aug 2026 22:45:54 -0400 Subject: [PATCH 2/2] Document that deferring two unkeyed notes to one source keeps only the last --- twister/src/plot.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/twister/src/plot.ts b/twister/src/plot.ts index 25c513c8..0b9d6b09 100644 --- a/twister/src/plot.ts +++ b/twister/src/plot.ts @@ -888,6 +888,13 @@ export type NewNote = Partial< * Held notes are dropped after a bounded retry window. Ordering is not * guaranteed relative to notes that attached immediately, so set `created` * (as connectors already should) rather than relying on arrival order. + * + * At most one UNKEYED held note survives per `{ source }`: two deferred + * notes without a `key` addressed to the same still-unresolved source + * collapse onto a single held slot, and the second one you save silently + * replaces the first — it does not queue as a second note. If you may + * defer more than one note to the same unresolved source, give each a + * distinct `key` so they are held separately. */ deferUntilThread?: boolean;