@inkandswitch/patchwork-pkg-base 0.0.41 → 0.0.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/account/dist/{InlineContactAvatar-TVDLE2AV.js → InlineContactAvatar-6UAAJ73R.js} +2 -1
- package/packages/account/dist/InlineContactAvatar-6UAAJ73R.js.map +7 -0
- package/packages/account/dist/index.js +1 -1
- package/packages/chat/dist/{ChatRoot-DQkQQvPO.js → ChatRoot-WdCS4aLg.js} +3001 -2807
- package/packages/chat/dist/{context-tool-BuY29sJF.js → context-tool-KkwLFr2k.js} +2 -2
- package/packages/chat/dist/{index-NiYOPQzY.js → index-P8UuZ1jj.js} +3 -3
- package/packages/chat/dist/index.js +1 -1
- package/packages/chat/dist/{tool-He3mRTzT.js → tool-DWqQOW59.js} +2 -2
- package/packages/chat/package.json +1 -1
- package/packages/codemirror-base/dist/chunk-H5POLO74.js +2658 -0
- package/packages/codemirror-base/dist/chunk-H5POLO74.js.map +7 -0
- package/packages/codemirror-base/dist/lib/codemirror.js +1 -1
- package/packages/codemirror-base/dist/tool.js +9 -5
- package/packages/codemirror-base/dist/tool.js.map +2 -2
- package/packages/codemirror-base/package.json +1 -1
- package/packages/codemirror-markdown/dist/extensions/markdown.js +0 -94
- package/packages/codemirror-markdown/dist/extensions/markdown.js.map +3 -3
- package/packages/drafts/dist/assets/{DraftOverlayProvider-B0Mtq1UF.js → DraftOverlayProvider-VYKlzOy1.js} +85 -25
- package/packages/drafts/dist/assets/DraftOverlayProvider-VYKlzOy1.js.map +1 -0
- package/packages/drafts/dist/assets/{DraftListProvider-D41q9O5B.js → DraftStateProvider-DX8b_RgQ.js} +270 -39
- package/packages/drafts/dist/assets/DraftStateProvider-DX8b_RgQ.js.map +1 -0
- package/packages/drafts/dist/assets/{clone-policy-C4pVv5sr.js → clone-policy-CIdEhg7W.js} +5 -2
- package/packages/drafts/dist/assets/{clone-policy-C4pVv5sr.js.map → clone-policy-CIdEhg7W.js.map} +1 -1
- package/packages/drafts/dist/assets/draft-docs-Bi8K1y3a.js +554 -0
- package/packages/drafts/dist/assets/draft-docs-Bi8K1y3a.js.map +1 -0
- package/packages/drafts/dist/assets/main-BR_tW0sp.js +3105 -0
- package/packages/drafts/dist/assets/main-BR_tW0sp.js.map +1 -0
- package/packages/drafts/dist/index.js +14 -14
- package/packages/drafts/dist/index.js.map +1 -1
- package/packages/drafts/package.json +1 -1
- package/packages/raw/raw-editor.js +26 -11
- package/packages/threepane/dist/IsolatedDocumentArea-2JIBFDOX.js +2 -0
- package/packages/threepane/dist/{PatchworkFrame-4AEBOBRE.js → PatchworkFrame-P5P6JTJE.js} +2 -2
- package/packages/threepane/dist/chunk-CGHYPNSB.js +972 -0
- package/packages/threepane/dist/chunk-CGHYPNSB.js.map +7 -0
- package/packages/threepane/dist/index.js +1 -1
- package/packages/tldraw4/dist/tool.js +61 -10
- package/packages/tldraw4/dist/tool.js.map +2 -2
- package/packages/tldraw4/package.json +2 -2
- package/packages/account/dist/InlineContactAvatar-TVDLE2AV.js.map +0 -7
- package/packages/codemirror-base/dist/chunk-5IG5TKXV.js +0 -795
- package/packages/codemirror-base/dist/chunk-5IG5TKXV.js.map +0 -7
- package/packages/drafts/dist/assets/DraftListProvider-D41q9O5B.js.map +0 -1
- package/packages/drafts/dist/assets/DraftOverlayProvider-B0Mtq1UF.js.map +0 -1
- package/packages/drafts/dist/assets/main-Cp8VsNHh.js +0 -2331
- package/packages/drafts/dist/assets/main-Cp8VsNHh.js.map +0 -1
- package/packages/threepane/dist/IsolatedDocumentArea-MZBBRFMY.js +0 -2
- package/packages/threepane/dist/chunk-HNLVJAZZ.js +0 -972
- package/packages/threepane/dist/chunk-HNLVJAZZ.js.map +0 -7
- /package/packages/threepane/dist/{IsolatedDocumentArea-MZBBRFMY.js.map → IsolatedDocumentArea-2JIBFDOX.js.map} +0 -0
- /package/packages/threepane/dist/{PatchworkFrame-4AEBOBRE.js.map → PatchworkFrame-P5P6JTJE.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DraftStateProvider-DX8b_RgQ.js","sources":["../../src/actor-attribution.ts","../../src/draft-routing.ts","../../src/providers/DraftStateProvider.ts"],"sourcesContent":["import {\n isValidAutomergeUrl,\n type AutomergeUrl,\n type DocHandle,\n type Repo,\n} from \"@automerge/automerge-repo/slim\";\nimport * as Automerge from \"@automerge/automerge/slim\";\nimport { subscribe } from \"@inkandswitch/patchwork-providers\";\n\nimport type { ActorAttributionDoc, DraftDoc } from \"./draft-types.js\";\n\n// Only the writing client knows which Automerge actor ids are its own. Each\n// local change reveals one id, which the ActorRecorder attributes to the\n// current user's contact. Changes seen before dependencies resolve are\n// buffered.\nexport function createActorRecorder(element: HTMLElement): ActorRecorder {\n let contactUrl: AutomergeUrl | null = null;\n let attributionHandle: DocHandle<ActorAttributionDoc> | null = null;\n const recordedActorIds = new Set<string>();\n const pendingActorIds = new Set<string>();\n let disposed = false;\n\n const unsubscribe = subscribe<AutomergeUrl>(\n element,\n { type: CONTACT_SELECTOR },\n (value) => {\n if (disposed || contactUrl) return;\n if (typeof value === \"string\" && isValidAutomergeUrl(value)) {\n contactUrl = value;\n flushPendingActors();\n }\n }\n );\n\n return {\n recordLocalChange(doc) {\n if (disposed) return;\n let actorId: string;\n try {\n actorId = Automerge.getActorId(doc);\n } catch {\n return;\n }\n if (recordedActorIds.has(actorId)) return;\n pendingActorIds.add(actorId);\n flushPendingActors();\n },\n setAttributionHandle(handle) {\n if (disposed) return;\n attributionHandle = handle;\n flushPendingActors();\n },\n dispose() {\n disposed = true;\n pendingActorIds.clear();\n unsubscribe();\n },\n };\n\n function flushPendingActors(): void {\n if (!attributionHandle || !contactUrl || pendingActorIds.size === 0) return;\n const url = contactUrl;\n const actorIds = [...pendingActorIds];\n pendingActorIds.clear();\n for (const id of actorIds) recordedActorIds.add(id);\n const existing = attributionHandle.doc()?.actors ?? {};\n const missing = actorIds.filter((id) => existing[id] !== url);\n if (missing.length === 0) return;\n attributionHandle.change((d) => {\n for (const id of missing) d.actors[id] = url;\n });\n }\n}\n\n// Resolve the host doc's actor-attribution doc, creating it and stamping\n// `actorAttributionUrl` on the main draft the first time. One per host doc\n// (actor ids span main and every draft), following the same check-then-create\n// pattern as `ensureChangeGroupDoc`: the rare concurrent-create orphan is\n// accepted.\nexport async function ensureActorAttribution(\n repo: Repo,\n mainDraftHandle: DocHandle<DraftDoc>\n): Promise<DocHandle<ActorAttributionDoc>> {\n const existingUrl = mainDraftHandle.doc()?.actorAttributionUrl;\n if (existingUrl && isValidAutomergeUrl(existingUrl)) {\n return repo.find<ActorAttributionDoc>(existingUrl);\n }\n\n const attribution = repo.create<ActorAttributionDoc>({\n \"@patchwork\": { type: \"actor-attribution\" },\n actors: {},\n });\n mainDraftHandle.change((d) => {\n if (!d.actorAttributionUrl) d.actorAttributionUrl = attribution.url;\n });\n // A concurrent creator may have won the stamp; honor whichever pointer\n // settled (our fresh doc is then an accepted orphan, like a group doc).\n const settled = mainDraftHandle.doc()?.actorAttributionUrl;\n if (settled && settled !== attribution.url && isValidAutomergeUrl(settled)) {\n return repo.find<ActorAttributionDoc>(settled);\n }\n return attribution;\n}\n\nexport type ActorRecorder = {\n recordLocalChange: (doc: Automerge.Doc<unknown>) => void;\n setAttributionHandle: (handle: DocHandle<ActorAttributionDoc>) => void;\n dispose: () => void;\n};\n\nconst CONTACT_SELECTOR = \"patchwork:contact\";\n","import {\n isValidAutomergeUrl,\n type AutomergeUrl,\n type DocHandle,\n} from \"@automerge/automerge-repo/slim\";\n\nimport type { CheckedOutDraft } from \"./draft-types.js\";\n\n// Keeps the ephemeral checkout selection and the `draft=` URL parameter in\n// sync. Deep links remain pending until their draft appears in the synced tree.\nexport function createDraftRouter(\n checkedOutHandle: DocHandle<CheckedOutDraft>\n): DraftRouter {\n let availableDrafts = new Set<AutomergeUrl>();\n let pendingUrlDraft: AutomergeUrl | null = readDraftParam();\n let lastCheckedOut: AutomergeUrl | null = null;\n let disposed = false;\n\n checkedOutHandle.on(\"change\", syncSelectionToUrl);\n window.addEventListener(\"hashchange\", onHashChange);\n\n return {\n updateAvailableDrafts(draftUrls) {\n if (disposed) return;\n availableDrafts = new Set(draftUrls);\n reconcileSelection();\n },\n dispose() {\n disposed = true;\n checkedOutHandle.off(\"change\", syncSelectionToUrl);\n window.removeEventListener(\"hashchange\", onHashChange);\n },\n };\n\n function onHashChange(): void {\n if (disposed) return;\n const urlDraft = readDraftParam();\n const selected = checkedOutHandle.doc()?.checkedOut ?? null;\n if (urlDraft === selected) {\n pendingUrlDraft = null;\n return;\n }\n if (urlDraft === null) {\n pendingUrlDraft = null;\n selectDraft(null);\n return;\n }\n if (availableDrafts.has(urlDraft)) {\n pendingUrlDraft = null;\n selectDraft(urlDraft);\n return;\n }\n pendingUrlDraft = urlDraft;\n }\n\n function reconcileSelection(): void {\n if (pendingUrlDraft && availableDrafts.has(pendingUrlDraft)) {\n const target = pendingUrlDraft;\n pendingUrlDraft = null;\n selectDraft(target);\n return;\n }\n const selected = checkedOutHandle.doc()?.checkedOut ?? null;\n if (selected && !availableDrafts.has(selected)) selectDraft(null);\n }\n\n function selectDraft(selected: AutomergeUrl | null): void {\n if (checkedOutHandle.doc()?.checkedOut === selected) return;\n checkedOutHandle.change((d) => {\n d.checkedOut = selected;\n });\n }\n\n function syncSelectionToUrl(): void {\n if (disposed) return;\n const selected = checkedOutHandle.doc()?.checkedOut ?? null;\n if (selected === lastCheckedOut) return;\n lastCheckedOut = selected;\n if (pendingUrlDraft && selected !== pendingUrlDraft) pendingUrlDraft = null;\n writeDraftParam(selected);\n }\n}\n\nexport type DraftRouter = {\n updateAvailableDrafts: (draftUrls: readonly AutomergeUrl[]) => void;\n dispose: () => void;\n};\n\nconst DRAFT_PARAM = \"draft\";\nconst RAW_HASH_KEYS = new Set([\"doc\", DRAFT_PARAM]);\n\nfunction readDraftParam(): AutomergeUrl | null {\n const raw = new URLSearchParams(window.location.hash.slice(1)).get(\n DRAFT_PARAM\n );\n return raw && isValidAutomergeUrl(raw) ? raw : null;\n}\n\nfunction writeDraftParam(selected: AutomergeUrl | null): void {\n const params = new URLSearchParams(window.location.hash.slice(1));\n if ((params.get(DRAFT_PARAM) ?? null) === selected) return;\n if (selected) params.set(DRAFT_PARAM, selected);\n else params.delete(DRAFT_PARAM);\n try {\n history.replaceState(null, \"\", \"#\" + serializeHash(params));\n } catch {\n // Sandboxed realms can refuse replaceState; the URL is cosmetic there.\n }\n}\n\nfunction serializeHash(params: URLSearchParams): string {\n const parts: string[] = [];\n params.forEach((value, key) => {\n if (!value) return;\n parts.push(\n `${key}=${RAW_HASH_KEYS.has(key) ? value : encodeURIComponent(value)}`\n );\n });\n return parts.join(\"&\");\n}\n","import {\n encodeHeads,\n isValidAutomergeUrl,\n type AutomergeUrl,\n type DocHandle,\n type Repo,\n type UrlHeads,\n} from \"@automerge/automerge-repo/slim\";\nimport { accept, type SubscribeEvent } from \"@inkandswitch/patchwork-providers\";\nimport type {\n MountedEvent,\n UnmountedEvent,\n} from \"@inkandswitch/patchwork-elements\";\n\nimport type {\n Baseline,\n CheckedOutDraft,\n CloneEntry,\n DraftDoc,\n DraftList,\n DraftMemberDoc,\n DraftSummary,\n HasDrafts,\n} from \"../draft-types.js\";\nimport { SKIPPED_DATATYPES, canonicalUrl } from \"../clone-policy.js\";\nimport {\n createChangeGrouper,\n type TimelineGroupingSpec,\n} from \"../change-group-cache.js\";\nimport {\n createActorRecorder,\n ensureActorAttribution,\n} from \"../actor-attribution.js\";\nimport { createDraftRouter, type DraftRouter } from \"../draft-routing.js\";\nimport { ensureMainDraft } from \"../draft-docs.js\";\n\nconst ROOT_DOC_SELECTOR = \"draft:root-doc\";\nconst CHECKED_OUT_SELECTOR = \"draft:checked-out\";\nconst DRAFT_LIST_SELECTOR = \"draft:list\";\nconst BASELINE_SELECTOR = \"draft:baseline\";\n\nconst ATTR_DOC_URL = \"doc-url\";\n\n// Fork point recorded for the main draft's identity clones: empty heads means\n// \"from the start\", so `getChangesMetaSince(doc, [])` yields the full history.\nconst EMPTY_HEADS: UrlHeads = encodeHeads([]);\n\n// Mounts on a document URL and exposes that document's draft state via three\n// subscriptions:\n// - `draft:root-doc` → AutomergeUrl of the doc this provider is on\n// - `draft:checked-out` → AutomergeUrl of the ephemeral, writeable\n// CheckedOutDraft doc; holds only the selection (`checkedOut = null` = main)\n// - `draft:list` → DraftList: the read-only main entry plus one\n// `DraftSummary` per non-merged draft, each carrying its member docs (on a\n// draft, the forked docs from `DraftDoc.clones`; on main, the main draft's\n// identity clones, or — before the first draft — the docs mounted beneath\n// this provider observed via `patchwork:mounted`, fork fields `null`).\n//\n// Consumers recover the live `DocHandle`s from the realm-local `window.repo`,\n// so member entries carry only plain `AutomergeUrl`s. The link from a host doc\n// to its drafts is `@patchwork.mainDraftUrl` → the main draft, whose `drafts`\n// roots the tree; each `DraftDoc` may have its own sub-drafts via\n// `DraftDoc.drafts`.\nexport const DraftStateProvider = (element: HTMLElement) => {\n const rawUrl = element.getAttribute(ATTR_DOC_URL);\n if (!rawUrl || !isValidAutomergeUrl(rawUrl)) {\n console.warn(\n `[drafts] <patchwork-view component=\"patchwork-draft-state-provider\"> ` +\n `is missing a valid ${ATTR_DOC_URL} attribute (got ${JSON.stringify(rawUrl)})`\n );\n return () => {};\n }\n const docUrl: AutomergeUrl = rawUrl;\n\n const maybeRepo = \"repo\" in window ? window.repo : undefined;\n if (!maybeRepo) {\n console.warn(\n \"[drafts] window.repo is not set; draft-state provider disabled\"\n );\n return () => {};\n }\n const repo: Repo = maybeRepo;\n\n let hostDocHandle: DocHandle<HasDrafts> | null = null;\n let checkedOutHandle: DocHandle<CheckedOutDraft> | null = null;\n let draftRouter: DraftRouter | null = null;\n const trackedDrafts = new Map<AutomergeUrl, DocHandle<DraftDoc>>();\n // The host doc's single main draft (bookkeeping only). Resolved lazily from\n // `@patchwork.mainDraftUrl`; its `drafts` roots the draft tree and its\n // identity `clones` back the \"main\" member list.\n let mainDraftHandle: DocHandle<DraftDoc> | null = null;\n\n // `draft:checked-out` subscribers that arrived before the ephemeral\n // CheckedOutDraft doc was created; flushed once it exists.\n const pendingCheckedOutSubscribers = new Set<(url: AutomergeUrl) => void>();\n\n // `draft:baseline` subscribers, keyed by canonical target url. This provider\n // is the sole answerer (the overlay no longer claims it), serving the\n // checkpoint's per-doc `from` (see `currentBaseline`). Re-emitted whenever\n // the checkout doc changes.\n const baselineSubscribers = new Map<\n AutomergeUrl,\n Set<(baseline: Baseline) => void>\n >();\n\n // `draft:list` bookkeeping: the last computed list, its live subscribers, and\n // the draft order from the most recent rewalk.\n const listSubscribers = new Set<(list: DraftList) => void>();\n let orderedDraftUrls: AutomergeUrl[] = [];\n let draftList: DraftList = {\n main: {\n url: docUrl,\n parent: null,\n members: [],\n childCount: 0,\n name: null,\n changeGroupDocUrl: null,\n },\n drafts: [],\n actorAttributionUrl: null,\n };\n // Author attribution: stamps actor ids from local member-doc changes into\n // the host doc's shared ActorAttributionDoc.\n const actorRecorder = createActorRecorder(element);\n // Keep every timeline's ChangeGroupDoc current whether or not the sidebar\n // is open. Member-doc listeners drive updates between list recomputes.\n const changeGrouper = createChangeGrouper(repo, {\n onLocalChange: actorRecorder.recordLocalChange,\n });\n // Main-case membership: docs mounted beneath this provider, ref-counted so a\n // doc shown in several views is only dropped on its last unmount. Populated\n // even while a draft is selected (where it goes unused) so switching back to\n // main is instant.\n const mountCounts = new Map<AutomergeUrl, number>();\n // Cached \"is this an app-global datatype we skip?\" verdict per mounted url,\n // resolved lazily since reading `@patchwork.type` means loading the doc.\n // Absent = unresolved, treated as not-skipped (visible) until known.\n const skipVerdicts = new Map<AutomergeUrl, boolean>();\n\n let disposed = false;\n let rewalkInFlight = false;\n let rewalkPending = false;\n // A tracked draft changing can mean either its sub-draft list moved (needs a\n // rewalk) or its clone map grew (needs a list recompute), so do both.\n const onTrackedChange = () => {\n scheduleRewalk();\n recomputeList();\n };\n const onHostDocChange = () => scheduleRewalk();\n // The checkout doc changed: its checkpoint may have moved, so re-publish\n // every live `draft:baseline` subscriber.\n const onCheckedOutChange = () => notifyBaselines();\n\n const onMounted = (event: MountedEvent) => {\n const detail = event.detail;\n if (!(\"url\" in detail)) return;\n const url = canonicalUrl(detail.url);\n mountCounts.set(url, (mountCounts.get(url) ?? 0) + 1);\n ensureSkipVerdict(url);\n syncMainDraftClones();\n recomputeList();\n };\n\n const onUnmounted = (event: UnmountedEvent) => {\n const detail = event.detail;\n if (!(\"url\" in detail)) return;\n const url = canonicalUrl(detail.url);\n const count = mountCounts.get(url) ?? 0;\n if (count <= 1) mountCounts.delete(url);\n else mountCounts.set(url, count - 1);\n recomputeList();\n };\n\n const ready: Promise<void> = (async () => {\n const handle = await repo.find<HasDrafts>(docUrl);\n if (disposed) return;\n hostDocHandle = handle;\n\n // Eagerly create the main draft (a real doc, not the virtual fallback) so\n // its ChangeGroupDoc has a persistent home even if the sidebar is never\n // opened. Main's clones are identity mappings — nothing is forked;\n // the only host-doc side effect is the `mainDraftUrl` scalar, which the\n // timeline's `@patchwork` path skip filters out. App-global datatypes the\n // draft machinery never treats as content are left alone.\n const hostType = handle.doc()?.[\"@patchwork\"]?.type;\n if (hostType == null || !SKIPPED_DATATYPES.has(hostType)) {\n try {\n const mainDraft = await ensureMainDraft(repo, handle);\n if (disposed) return;\n // The attribution doc is shared by every timeline on this host doc;\n // once it resolves the ActorRecorder starts stamping local actor ids.\n const attribution = await ensureActorAttribution(repo, mainDraft);\n if (disposed) return;\n actorRecorder.setAttributionHandle(attribution);\n } catch (err) {\n console.warn(\"[drafts] failed to eagerly create main draft:\", err);\n }\n }\n\n // Eagerly create the ephemeral CheckedOutDraft so the sidebar can render\n // its \"Main\" card and write `checkedOut` even before any drafts exist on\n // the host doc.\n checkedOutHandle = repo.create<CheckedOutDraft>({ checkedOut: null });\n checkedOutHandle.on(\"change\", onCheckedOutChange);\n draftRouter = createDraftRouter(checkedOutHandle);\n const checkedOutUrl = checkedOutHandle.url;\n for (const respond of pendingCheckedOutSubscribers) {\n respond(checkedOutUrl);\n }\n pendingCheckedOutSubscribers.clear();\n // A checkpoint may already have synced in before this provider mounted.\n notifyBaselines();\n\n handle.on(\"change\", onHostDocChange);\n scheduleRewalk();\n recomputeList();\n })();\n ready.catch((err) => {\n console.error(`[drafts] failed to initialize draft-state provider:`, err);\n });\n\n const onSubscribe = (event: SubscribeEvent) => {\n const { type } = event.detail.selector;\n\n if (type === ROOT_DOC_SELECTOR) {\n accept<AutomergeUrl>(event, (respond) => {\n respond(docUrl);\n });\n return;\n }\n\n if (type === CHECKED_OUT_SELECTOR) {\n accept<AutomergeUrl>(event, (respond) => {\n if (checkedOutHandle) {\n respond(checkedOutHandle.url);\n return;\n }\n pendingCheckedOutSubscribers.add(respond);\n return () => pendingCheckedOutSubscribers.delete(respond);\n });\n return;\n }\n\n if (type === DRAFT_LIST_SELECTOR) {\n // `draft:list` answers with a DraftList *object*, never an AutomergeUrl, so\n // consumers must use `subscribe` (not `subscribeDoc`, which would feed this\n // object into `repo.find` and crash with \"Invalid AutomergeUrl\").\n accept<DraftList>(event, (respond) => {\n respond(draftList);\n listSubscribers.add(respond);\n return () => listSubscribers.delete(respond);\n });\n return;\n }\n\n if (type === BASELINE_SELECTOR) {\n // Sole answerer for `draft:baseline` (the overlay no longer claims it):\n // serves the checkpoint's per-doc `from` for `target` (see\n // `currentBaseline`).\n const rawTarget = (event.detail.selector as { url?: unknown }).url;\n if (typeof rawTarget !== \"string\" || !isValidAutomergeUrl(rawTarget)) {\n return;\n }\n const target = canonicalUrl(rawTarget);\n accept<Baseline>(event, (respond) => {\n respond(currentBaseline(target));\n let set = baselineSubscribers.get(target);\n if (!set) baselineSubscribers.set(target, (set = new Set()));\n set.add(respond);\n return () => {\n set!.delete(respond);\n if (set!.size === 0) baselineSubscribers.delete(target);\n };\n });\n return;\n }\n\n };\n\n element.addEventListener(\"patchwork:subscribe\", onSubscribe);\n element.addEventListener(\"patchwork:mounted\", onMounted);\n element.addEventListener(\"patchwork:unmounted\", onUnmounted);\n\n return () => {\n disposed = true;\n changeGrouper.dispose();\n actorRecorder.dispose();\n draftRouter?.dispose();\n draftRouter = null;\n element.removeEventListener(\"patchwork:subscribe\", onSubscribe);\n element.removeEventListener(\"patchwork:mounted\", onMounted);\n element.removeEventListener(\"patchwork:unmounted\", onUnmounted);\n if (hostDocHandle) hostDocHandle.off(\"change\", onHostDocChange);\n if (mainDraftHandle) mainDraftHandle.off(\"change\", onTrackedChange);\n for (const [, h] of trackedDrafts) h.off(\"change\", onTrackedChange);\n mainDraftHandle = null;\n trackedDrafts.clear();\n pendingCheckedOutSubscribers.clear();\n listSubscribers.clear();\n baselineSubscribers.clear();\n mountCounts.clear();\n skipVerdicts.clear();\n if (checkedOutHandle) {\n checkedOutHandle.off(\"change\", onCheckedOutChange);\n repo.delete(checkedOutHandle.url);\n }\n checkedOutHandle = null;\n hostDocHandle = null;\n };\n\n function scheduleRewalk(): void {\n if (disposed) return;\n if (!hostDocHandle || !checkedOutHandle) return;\n if (rewalkInFlight) {\n rewalkPending = true;\n return;\n }\n rewalkInFlight = true;\n void (async () => {\n try {\n // Drafts hang off the main draft (`mainDraft.drafts`), which is created\n // on the first draft; until then there are none.\n const mainDraft = await ensureMainDraftTracked();\n if (disposed) return;\n const roots = (mainDraft?.doc()?.drafts ?? []).filter(\n isValidAutomergeUrl\n );\n const allDrafts = await collectAllDrafts(\n repo,\n roots,\n trackedDrafts,\n onTrackedChange\n );\n if (disposed) return;\n orderedDraftUrls = allDrafts;\n draftRouter?.updateAvailableDrafts(allDrafts);\n } catch (err) {\n console.error(\"[drafts] rewalk failed:\", err);\n } finally {\n rewalkInFlight = false;\n // A rewalk may have just started tracking a draft (whose clones won't\n // fire their own change event), so refresh the list.\n recomputeList();\n if (rewalkPending) {\n rewalkPending = false;\n scheduleRewalk();\n }\n }\n })();\n }\n\n // Recompute the `draft:list` value and push it to subscribers when it\n // actually changed. The ChangeGrouper follows the same triggers.\n function recomputeList(): void {\n if (disposed) return;\n updateChangeGrouping();\n const next = computeList();\n if (draftListsEqual(draftList, next)) return;\n draftList = next;\n for (const respond of listSubscribers) respond(next);\n }\n\n // Hand the ChangeGrouper the current timelines, priority-ordered: main,\n // checked-out draft, then the remaining drafts in tree order. Main reads\n // the main draft's identity clones rather than the mounted-doc fallback.\n function updateChangeGrouping(): void {\n if (disposed) return;\n const specs: TimelineGroupingSpec[] = [];\n if (mainDraftHandle) {\n specs.push({\n draftHandle: mainDraftHandle,\n members: clonesToMembers(mainDraftHandle.doc()?.clones ?? {}),\n rootDocUrl: docUrl,\n });\n }\n const selected = checkedOutHandle?.doc()?.checkedOut ?? null;\n const ordered =\n selected && orderedDraftUrls.includes(selected)\n ? [selected, ...orderedDraftUrls.filter((u) => u !== selected)]\n : orderedDraftUrls;\n for (const url of ordered) {\n const handle = trackedDrafts.get(url);\n const doc = handle?.doc();\n if (!handle || !doc || doc.mergedAt !== undefined) continue;\n specs.push({\n draftHandle: handle,\n members: clonesToMembers(doc.clones),\n rootDocUrl: docUrl,\n });\n }\n changeGrouper.setTimelines(specs);\n }\n\n // The full read-only list: the main entry plus one summary per non-merged\n // draft, in rewalk (tree) order.\n function computeList(): DraftList {\n const drafts: DraftSummary[] = [];\n for (const url of orderedDraftUrls) {\n const doc = trackedDrafts.get(url)?.doc();\n if (!doc || doc.mergedAt !== undefined) continue;\n drafts.push({\n url,\n parent: effectiveParent(doc.parent),\n members: clonesToMembers(doc.clones),\n childCount: doc.drafts.length,\n name: doc.name ?? null,\n changeGroupDocUrl: doc.changeGroupDocUrl ?? null,\n });\n }\n return {\n main: computeMainSummary(),\n drafts,\n actorAttributionUrl:\n mainDraftHandle?.doc()?.actorAttributionUrl ?? null,\n };\n }\n\n // The parent a summary should point at: the nearest non-merged ancestor.\n // Merging normally re-parents children, but drafts orphaned before that\n // existed (or by a concurrent merge on another peer) still resolve to the\n // draft their parent was merged into instead of dangling under a hidden\n // one. Unknown urls (not tracked, e.g. the main draft) pass through as-is.\n function effectiveParent(\n parentUrl: AutomergeUrl | undefined\n ): AutomergeUrl | null {\n const seen = new Set<AutomergeUrl>();\n let cursor = parentUrl ?? null;\n while (cursor && !seen.has(cursor)) {\n seen.add(cursor);\n const doc = trackedDrafts.get(cursor)?.doc();\n if (!doc || doc.mergedAt === undefined) return cursor;\n cursor = doc.parent ?? null;\n }\n return cursor;\n }\n\n // Main's summary. Its members come from the main draft's identity clones once\n // it exists; before the first draft is created (no main draft) we fall back to\n // the docs mounted beneath us, minus the app-global datatypes the overlay\n // would never fork. Members are sorted by url so the diff above is positional.\n function computeMainSummary(): DraftSummary {\n const url = mainDraftHandle?.url ?? docUrl;\n const childCount = mainDraftHandle?.doc()?.drafts.length ?? 0;\n const name = mainDraftHandle?.doc()?.name ?? null;\n const changeGroupDocUrl =\n mainDraftHandle?.doc()?.changeGroupDocUrl ?? null;\n\n const mainClones = mainDraftHandle?.doc()?.clones;\n if (mainClones && Object.keys(mainClones).length > 0) {\n return {\n url,\n parent: null,\n members: clonesToMembers(mainClones),\n childCount,\n name,\n changeGroupDocUrl,\n };\n }\n\n const members = [...mountCounts.keys()]\n .filter((u) => skipVerdicts.get(u) !== true)\n .map((u) => ({ url: u, cloneUrl: null, clonedAt: null }))\n .sort(byMemberUrl);\n return { url, parent: null, members, childCount, name, changeGroupDocUrl };\n }\n\n // The diff baseline for `target`: the checkpoint's per-doc `from`, written\n // by the sidebar (its eye toggle and scrubber). `null` — no entry, or an\n // entry without `from` — means no diff. There is deliberately no implicit\n // fork-point fallback: baselines exist only when explicitly written into\n // the checkpoint, so \"diffs hidden\" is simply their absence.\n function currentBaseline(target: AutomergeUrl): Baseline {\n const entry = checkedOutHandle?.doc()?.at?.[target];\n return { heads: entry?.from ?? null };\n }\n\n function notifyBaselines(): void {\n for (const [target, set] of baselineSubscribers) {\n const baseline = currentBaseline(target);\n for (const respond of [...set]) respond(baseline);\n }\n }\n\n // Resolve (once, cached) whether a mounted doc is an app-global datatype we\n // exclude from the main-case membership. On failure we leave it unresolved,\n // so the doc stays visible — mirroring the overlay's \"fall back to forking\".\n function ensureSkipVerdict(url: AutomergeUrl): void {\n if (skipVerdicts.has(url)) return;\n void (async () => {\n try {\n const handle = await repo.find<HasDrafts>(url);\n if (disposed) return;\n const type = handle.doc()?.[\"@patchwork\"]?.type;\n const skipped = type != null && SKIPPED_DATATYPES.has(type);\n if (skipVerdicts.get(url) === skipped) return;\n skipVerdicts.set(url, skipped);\n // A now-confirmed not-skipped doc may belong in the main draft.\n syncMainDraftClones();\n recomputeList();\n } catch {\n // Leave unresolved: the doc keeps showing up, which is the safe default.\n }\n })();\n }\n\n // Resolve and start tracking the host doc's main draft, if any. Returns the\n // handle, or null when the host doc has no `mainDraftUrl` yet. Re-resolves\n // when the pointer changes and attaches `onTrackedChange` so the main draft's\n // `drafts` (tree shape) and `clones` (main membership) stay live.\n async function ensureMainDraftTracked(): Promise<DocHandle<DraftDoc> | null> {\n if (!hostDocHandle) return null;\n const mainDraftUrl = hostDocHandle.doc()?.[\"@patchwork\"]?.mainDraftUrl;\n if (!mainDraftUrl || !isValidAutomergeUrl(mainDraftUrl)) return null;\n if (mainDraftHandle && mainDraftHandle.url === mainDraftUrl) {\n return mainDraftHandle;\n }\n if (mainDraftHandle) mainDraftHandle.off(\"change\", onTrackedChange);\n const handle = await repo.find<DraftDoc>(mainDraftUrl);\n if (disposed) return null;\n mainDraftHandle = handle;\n handle.on(\"change\", onTrackedChange);\n syncMainDraftClones();\n return handle;\n }\n\n // Keep the main draft's identity clone map in step with the live mounted set:\n // every confirmed not-skipped mounted doc gets an identity entry (`cloneUrl\n // === url`, empty fork heads). Additive only — entries are never removed, so\n // main's membership (and history) is stable across unmounts. Writes are\n // diffed, so this is a no-op once everything mounted is already recorded.\n function syncMainDraftClones(): void {\n if (disposed || !mainDraftHandle) return;\n const existing = mainDraftHandle.doc()?.clones ?? {};\n const toAdd = [...mountCounts.keys()].filter(\n (url) => skipVerdicts.get(url) === false && !existing[url]\n );\n if (toAdd.length === 0) return;\n mainDraftHandle.change((d) => {\n for (const url of toAdd) {\n if (!d.clones[url]) {\n d.clones[url] = { cloneUrl: url, clonedAt: EMPTY_HEADS };\n }\n }\n });\n }\n};\n\n// Depth-first pre-order, so a fork lists directly beneath the draft it was\n// forked off (the sidebar indents by parent depth).\nasync function collectAllDrafts(\n repo: Repo,\n roots: readonly AutomergeUrl[],\n tracked: Map<AutomergeUrl, DocHandle<DraftDoc>>,\n onNewChange: () => void\n): Promise<AutomergeUrl[]> {\n const visited = new Set<AutomergeUrl>();\n const order: AutomergeUrl[] = [];\n const queue: AutomergeUrl[] = [...roots];\n while (queue.length) {\n const url = queue.shift()!;\n if (visited.has(url)) continue;\n visited.add(url);\n order.push(url);\n\n let h = tracked.get(url);\n if (!h) {\n h = await repo.find<DraftDoc>(url);\n tracked.set(url, h);\n h.on(\"change\", onNewChange);\n }\n const drafts = (h.doc()?.drafts ?? []).filter(isValidAutomergeUrl);\n queue.unshift(...drafts);\n }\n return order;\n}\n\n// Project a clone map into member-doc entries, sorted by url so the positional\n// equality checks below stay valid.\nfunction clonesToMembers(\n clones: Record<AutomergeUrl, CloneEntry>\n): DraftMemberDoc[] {\n return Object.entries(clones)\n .map(([url, entry]) => ({\n url: url as AutomergeUrl,\n cloneUrl: entry.cloneUrl,\n clonedAt: entry.clonedAt,\n }))\n .sort(byMemberUrl);\n}\n\nfunction draftListsEqual(a: DraftList, b: DraftList): boolean {\n if (a.actorAttributionUrl !== b.actorAttributionUrl) return false;\n if (!summariesEqual(a.main, b.main)) return false;\n if (a.drafts.length !== b.drafts.length) return false;\n for (let i = 0; i < a.drafts.length; i++) {\n if (!summariesEqual(a.drafts[i], b.drafts[i])) return false;\n }\n return true;\n}\n\nfunction summariesEqual(a: DraftSummary, b: DraftSummary): boolean {\n return (\n a.url === b.url &&\n a.parent === b.parent &&\n a.childCount === b.childCount &&\n a.name === b.name &&\n a.changeGroupDocUrl === b.changeGroupDocUrl &&\n memberListsEqual(a.members, b.members)\n );\n}\n\nfunction byMemberUrl(a: DraftMemberDoc, b: DraftMemberDoc): number {\n return a.url < b.url ? -1 : a.url > b.url ? 1 : 0;\n}\n\nfunction memberListsEqual(a: DraftMemberDoc[], b: DraftMemberDoc[]): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i].url !== b[i].url) return false;\n if (a[i].cloneUrl !== b[i].cloneUrl) return false;\n if (!sameHeads(a[i].clonedAt, b[i].clonedAt)) return false;\n }\n return true;\n}\n\nfunction sameHeads(a: UrlHeads | null, b: UrlHeads | null): boolean {\n if (a === b) return true;\n if (!a || !b || a.length !== b.length) return false;\n const set = new Set(b);\n return a.every((h) => set.has(h));\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,10 @@ import { parseAutomergeUrl, stringifyAutomergeUrl } from "@automerge/automerge-r
|
|
|
2
2
|
const SKIPPED_DATATYPES = /* @__PURE__ */ new Set([
|
|
3
3
|
"account",
|
|
4
4
|
"contact",
|
|
5
|
-
"draft"
|
|
5
|
+
"draft",
|
|
6
|
+
"change-group",
|
|
7
|
+
// Legacy marker retained while existing ChangeGroupDocs are migrated.
|
|
8
|
+
"change-group-cache"
|
|
6
9
|
]);
|
|
7
10
|
function canonicalUrl(url) {
|
|
8
11
|
const { documentId } = parseAutomergeUrl(url);
|
|
@@ -12,4 +15,4 @@ export {
|
|
|
12
15
|
SKIPPED_DATATYPES as S,
|
|
13
16
|
canonicalUrl as c
|
|
14
17
|
};
|
|
15
|
-
//# sourceMappingURL=clone-policy-
|
|
18
|
+
//# sourceMappingURL=clone-policy-CIdEhg7W.js.map
|
package/packages/drafts/dist/assets/{clone-policy-C4pVv5sr.js.map → clone-policy-CIdEhg7W.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clone-policy-
|
|
1
|
+
{"version":3,"file":"clone-policy-CIdEhg7W.js","sources":["../../src/clone-policy.ts"],"sourcesContent":["import {\n parseAutomergeUrl,\n stringifyAutomergeUrl,\n type AutomergeUrl,\n} from \"@automerge/automerge-repo/slim\";\n\n// HACK: datatypes the draft machinery must never treat as draft content.\n//\n// The overlay forks *every* document resolved beneath it so edits stay scoped\n// to the draft. But some docs pulled through the overlay are app-global rather\n// than part of the document being drafted: the account doc (read by the context\n// sidebar, which renders inside the overlay) and contact docs (resolved per\n// comment author). Forking those branches global state — account config, user\n// profiles — into a draft, which is wrong and could even merge back into main.\n//\n// The same list filters the \"main\" branch of `draft:member-docs`, so the set\n// of documents reported there matches the docs a draft would actually fork.\n//\n// The principled fix is to know which documents actually belong to the draft\n// and fork only those — nothing should be treated as draft content just because\n// it was resolved beneath the overlay. Until we have that notion of draft\n// membership we invert the problem with a blunt skip-list: it bakes app-level\n// datatype names into otherwise-generic machinery and relies on each doc\n// carrying a matching `@patchwork.type`.\nexport const SKIPPED_DATATYPES: ReadonlySet<string> = new Set([\n \"account\",\n \"contact\",\n \"draft\",\n \"change-group\",\n // Legacy marker retained while existing ChangeGroupDocs are migrated.\n \"change-group-cache\",\n]);\n\n// Reduce a url to its bare document identity by stripping any path/heads\n// suffix, so urls arriving from different traversals dedupe to the same key.\nexport function canonicalUrl(url: AutomergeUrl): AutomergeUrl {\n const { documentId } = parseAutomergeUrl(url);\n return stringifyAutomergeUrl({ documentId });\n}\n"],"names":[],"mappings":";AAwBO,MAAM,wCAA6C,IAAI;AAAA,EAC5D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AACF,CAAC;AAIM,SAAS,aAAa,KAAiC;AAC5D,QAAM,EAAE,WAAA,IAAe,kBAAkB,GAAG;AAC5C,SAAO,sBAAsB,EAAE,YAAY;AAC7C;"}
|