@inkandswitch/patchwork-pkg-base 0.0.7 → 0.0.8
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/modules.json +4 -0
- package/package.json +1 -1
- package/packages/account-history/dist/assets/HistoryRecorder-HO_sxeuE.js +248 -0
- package/packages/account-history/dist/assets/HistoryRecorder-HO_sxeuE.js.map +1 -0
- package/packages/account-history/dist/assets/HistoryViewer-Ct5g7zek.js +308 -0
- package/packages/account-history/dist/assets/HistoryViewer-Ct5g7zek.js.map +1 -0
- package/packages/account-history/dist/assets/NotebookViewer-BkYJL6Jc.js +504 -0
- package/packages/account-history/dist/assets/NotebookViewer-BkYJL6Jc.js.map +1 -0
- package/packages/account-history/dist/assets/index-CFzuSuJg.js +148 -0
- package/packages/account-history/dist/assets/index-CFzuSuJg.js.map +1 -0
- package/packages/account-history/dist/assets/makeDocumentProjection-DXgEZYyv.js +706 -0
- package/packages/account-history/dist/assets/makeDocumentProjection-DXgEZYyv.js.map +1 -0
- package/packages/account-history/dist/assets/store-CRmRL4Cv.js +1079 -0
- package/packages/account-history/dist/assets/store-CRmRL4Cv.js.map +1 -0
- package/packages/account-history/dist/index.js +5 -0
- package/packages/account-history/dist/index.js.map +1 -0
- package/packages/account-history/package.json +33 -0
- package/packages/chat/dist/ChatRoot-BXsklgz7.js +6113 -0
- package/packages/chat/dist/context-tool-CenQrztX.js +107 -0
- package/packages/chat/dist/datatype-1niKKK-c.js +15 -0
- package/packages/chat/dist/index-DYFHDHZ9.js +368 -0
- package/packages/chat/dist/index.js +5 -0
- package/packages/chat/dist/tool-D9BTS5wc.js +38 -0
- package/packages/chat/package.json +42 -0
- package/packages/comments-view/dist/assets/comments-D9lwpHOh.js +50 -0
- package/packages/comments-view/dist/assets/comments-D9lwpHOh.js.map +1 -0
- package/packages/comments-view/dist/assets/datatype-C4SMwWiO.js +22 -0
- package/packages/comments-view/dist/assets/datatype-C4SMwWiO.js.map +1 -0
- package/packages/comments-view/dist/assets/main-C8GVksuY.js +2973 -0
- package/packages/comments-view/dist/assets/main-C8GVksuY.js.map +1 -0
- package/packages/comments-view/dist/index.js +115 -0
- package/packages/comments-view/dist/index.js.map +1 -0
- package/packages/comments-view/package.json +36 -0
- package/packages/drafts/dist/assets/DraftDatatype-Dn8VF6oC.js +14 -0
- package/packages/drafts/dist/assets/DraftDatatype-Dn8VF6oC.js.map +1 -0
- package/packages/drafts/dist/assets/DraftListProvider-DVhUGU1x.js +362 -0
- package/packages/drafts/dist/assets/DraftListProvider-DVhUGU1x.js.map +1 -0
- package/packages/drafts/dist/assets/DraftOverlayProvider-NMDqnpBV.js +123 -0
- package/packages/drafts/dist/assets/DraftOverlayProvider-NMDqnpBV.js.map +1 -0
- package/packages/drafts/dist/assets/clone-policy-D4XOfZxs.js +15 -0
- package/packages/drafts/dist/assets/clone-policy-D4XOfZxs.js.map +1 -0
- package/packages/drafts/dist/assets/index-DAqs20jZ.js +65 -0
- package/packages/drafts/dist/assets/index-DAqs20jZ.js.map +1 -0
- package/packages/drafts/dist/assets/main-Cdev7z-t.js +2366 -0
- package/packages/drafts/dist/assets/main-Cdev7z-t.js.map +1 -0
- package/packages/drafts/dist/index.js +140 -0
- package/packages/drafts/dist/index.js.map +1 -0
- package/packages/drafts/package.json +34 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { isValidAutomergeUrl, stringifyAutomergeUrl, parseAutomergeUrl } from "@automerge/automerge-repo";
|
|
2
|
+
import { s as subscribe, a as accept } from "./index-DAqs20jZ.js";
|
|
3
|
+
import { c as canonicalUrl, S as SKIPPED_DATATYPES } from "./clone-policy-D4XOfZxs.js";
|
|
4
|
+
const HANDLE_DESCRIPTOR_SELECTOR = "repo:handle-descriptor";
|
|
5
|
+
const CHECKED_OUT_SELECTOR = "draft:checked-out";
|
|
6
|
+
const DraftOverlayProvider = (element) => {
|
|
7
|
+
const rawUrl = element.getAttribute("url");
|
|
8
|
+
let draftUrl = null;
|
|
9
|
+
if (rawUrl) {
|
|
10
|
+
if (!isValidAutomergeUrl(rawUrl)) {
|
|
11
|
+
console.warn(
|
|
12
|
+
`[drafts] <patchwork-view component="patchwork-draft-overlay-provider"> has an invalid url attribute (got ${JSON.stringify(rawUrl)})`
|
|
13
|
+
);
|
|
14
|
+
return () => {
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
draftUrl = rawUrl;
|
|
18
|
+
}
|
|
19
|
+
const repo = "repo" in window ? window.repo : void 0;
|
|
20
|
+
if (!repo) {
|
|
21
|
+
console.warn(
|
|
22
|
+
"[drafts] window.repo is not set; draft overlay provider disabled"
|
|
23
|
+
);
|
|
24
|
+
return () => {
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const liveRepo = repo;
|
|
28
|
+
let disposed = false;
|
|
29
|
+
const cloneResolutions = /* @__PURE__ */ new Map();
|
|
30
|
+
const ready = draftUrl ? (async () => {
|
|
31
|
+
const handle = await liveRepo.find(draftUrl);
|
|
32
|
+
if (disposed) throw new Error("[drafts] provider disposed mid-load");
|
|
33
|
+
return handle;
|
|
34
|
+
})() : null;
|
|
35
|
+
ready?.catch((err) => {
|
|
36
|
+
console.error(`[drafts] failed to load draft overlay for ${draftUrl}:`, err);
|
|
37
|
+
});
|
|
38
|
+
let checkedOutHandle = null;
|
|
39
|
+
const unsubscribeCheckedOut = subscribe(
|
|
40
|
+
element,
|
|
41
|
+
{ type: CHECKED_OUT_SELECTOR },
|
|
42
|
+
(url) => {
|
|
43
|
+
if (disposed || !isValidAutomergeUrl(url)) return;
|
|
44
|
+
void liveRepo.find(url).then((handle) => {
|
|
45
|
+
if (!disposed) checkedOutHandle = handle;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
const onSubscribe = (event) => {
|
|
50
|
+
const selector = event.detail.selector;
|
|
51
|
+
if (selector.type === HANDLE_DESCRIPTOR_SELECTOR) {
|
|
52
|
+
const rawTarget = selector.url;
|
|
53
|
+
if (typeof rawTarget !== "string" || !isValidAutomergeUrl(rawTarget)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const original = canonicalUrl(rawTarget);
|
|
57
|
+
accept(event, (respond) => {
|
|
58
|
+
void resolveDescriptor(original).then((descriptor) => {
|
|
59
|
+
if (disposed) return;
|
|
60
|
+
respond(descriptor);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
element.addEventListener("patchwork:subscribe", onSubscribe);
|
|
67
|
+
return () => {
|
|
68
|
+
disposed = true;
|
|
69
|
+
element.removeEventListener("patchwork:subscribe", onSubscribe);
|
|
70
|
+
unsubscribeCheckedOut();
|
|
71
|
+
cloneResolutions.clear();
|
|
72
|
+
};
|
|
73
|
+
async function resolveDescriptor(original) {
|
|
74
|
+
const to = checkedOutHandle?.doc()?.at?.[original]?.to ?? void 0;
|
|
75
|
+
if (!draftUrl || await isSkippedDoc(original)) {
|
|
76
|
+
return to ? { url: original, cloneUrl: withHeads(original, to) } : { url: original };
|
|
77
|
+
}
|
|
78
|
+
const cloneUrl = await resolveClone(original);
|
|
79
|
+
return { url: original, cloneUrl: withHeads(cloneUrl, to) };
|
|
80
|
+
}
|
|
81
|
+
function withHeads(url, heads) {
|
|
82
|
+
if (!heads) return url;
|
|
83
|
+
return stringifyAutomergeUrl({
|
|
84
|
+
documentId: parseAutomergeUrl(url).documentId,
|
|
85
|
+
heads
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
async function isSkippedDoc(original) {
|
|
89
|
+
try {
|
|
90
|
+
const handle = await liveRepo.find(
|
|
91
|
+
original
|
|
92
|
+
);
|
|
93
|
+
const type = handle.doc()?.["@patchwork"]?.type;
|
|
94
|
+
return type != null && SKIPPED_DATATYPES.has(type);
|
|
95
|
+
} catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function resolveClone(original) {
|
|
100
|
+
const cached = cloneResolutions.get(original);
|
|
101
|
+
if (cached) return cached;
|
|
102
|
+
const promise = (async () => {
|
|
103
|
+
if (!ready) throw new Error("[drafts] resolveClone called without a draft");
|
|
104
|
+
const handle = await ready;
|
|
105
|
+
const existing = handle.doc()?.clones?.[original];
|
|
106
|
+
if (existing) return canonicalUrl(existing.cloneUrl);
|
|
107
|
+
const originalHandle = await liveRepo.find(original);
|
|
108
|
+
const clonedAt = originalHandle.heads();
|
|
109
|
+
const clone = liveRepo.clone(originalHandle);
|
|
110
|
+
const cloneUrl = canonicalUrl(clone.url);
|
|
111
|
+
handle.change((d) => {
|
|
112
|
+
d.clones[original] = { cloneUrl, clonedAt };
|
|
113
|
+
});
|
|
114
|
+
return cloneUrl;
|
|
115
|
+
})();
|
|
116
|
+
cloneResolutions.set(original, promise);
|
|
117
|
+
return promise;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
export {
|
|
121
|
+
DraftOverlayProvider
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=DraftOverlayProvider-NMDqnpBV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DraftOverlayProvider-NMDqnpBV.js","sources":["../../src/providers/DraftOverlayProvider.ts"],"sourcesContent":["import {\n isValidAutomergeUrl,\n parseAutomergeUrl,\n stringifyAutomergeUrl,\n type AutomergeUrl,\n type DocHandle,\n type UrlHeads,\n} from \"@automerge/automerge-repo\";\nimport {\n accept,\n subscribe,\n type SubscribeEvent,\n} from \"@inkandswitch/patchwork-providers\";\n\n// Shape of a `repo:handle-descriptor` answer. The one-shot host's\n// patchwork-providers (0.2.2) does not export this type, so it is declared\n// locally; it must stay in sync with the host's `OverlayRepo`.\ntype DocHandleDescriptor = {\n url: AutomergeUrl;\n cloneUrl?: AutomergeUrl;\n};\n\nimport type { CheckedOutDraft, DraftDoc } from \"../draft-types.js\";\nimport { SKIPPED_DATATYPES, canonicalUrl } from \"../clone-policy.js\";\n\nconst HANDLE_DESCRIPTOR_SELECTOR = \"repo:handle-descriptor\";\nconst CHECKED_OUT_SELECTOR = \"draft:checked-out\";\n\n// Mounts on a draft URL and remaps documents resolved beneath it onto\n// per-draft clones, so edits stay inside the draft.\n//\n// Under the new provider model the host `<patchwork-view>` wraps legacy tool\n// document resolution in an `OverlayRepo` that asks the provider tree for a\n// `repo:handle-descriptor` descriptor. This provider answers with\n// `{ url, cloneUrl }`: the clone is forked eagerly the first time a document is\n// requested in this draft (recorded in `DraftDoc.clones`), and the editor then\n// reads and writes the clone while still reporting the original url. The fork\n// point lives in `DraftDoc.clones[url].clonedAt`; the draft-list provider reads\n// it to serve `draft:baseline` (this provider no longer answers that).\n//\n// On \"main\" (empty `url`) there is no clone remapping, but the provider still\n// answers `repo:handle-descriptor` so that an active checkpoint can pin nested\n// docs: it returns the original url carrying the checkpoint's `to` heads when one\n// is set. Pinning also applies on a draft, baked onto the clone url. The per-doc\n// `to`/`from` heads live on the checked-out draft (`CheckedOutDraft.at`), read\n// here via the `draft:checked-out` subscription. A non-empty but invalid `url`\n// is a misconfiguration and disables the provider.\nexport const DraftOverlayProvider = (element: HTMLElement) => {\n const rawUrl = element.getAttribute(\"url\");\n // Empty `url` = \"main\": no clone remapping, but we still answer\n // `repo:handle-descriptor` so an active checkpoint can pin nested docs.\n let draftUrl: AutomergeUrl | null = null;\n if (rawUrl) {\n if (!isValidAutomergeUrl(rawUrl)) {\n console.warn(\n `[drafts] <patchwork-view component=\"patchwork-draft-overlay-provider\"> ` +\n `has an invalid url attribute (got ${JSON.stringify(rawUrl)})`\n );\n return () => {};\n }\n draftUrl = rawUrl;\n }\n\n const repo = \"repo\" in window ? window.repo : undefined;\n if (!repo) {\n console.warn(\n \"[drafts] window.repo is not set; draft overlay provider disabled\"\n );\n return () => {};\n }\n const liveRepo = repo;\n\n let disposed = false;\n\n // One eager-clone resolution per original url; de-dupes concurrent requests.\n const cloneResolutions = new Map<AutomergeUrl, Promise<AutomergeUrl>>();\n\n // The draft doc backing this overlay (clone bookkeeping). Null on \"main\".\n const ready: Promise<DocHandle<DraftDoc>> | null = draftUrl\n ? (async () => {\n const handle = await liveRepo.find<DraftDoc>(draftUrl);\n if (disposed) throw new Error(\"[drafts] provider disposed mid-load\");\n return handle;\n })()\n : null;\n ready?.catch((err) => {\n console.error(`[drafts] failed to load draft overlay for ${draftUrl}:`, err);\n });\n\n // Track the checked-out draft's checkpoint so descriptors can pin a nested doc\n // to its per-doc `to` heads. The url is served by the ancestor draft-list\n // provider; we read `at[original].to` live at resolve time (one-shot, so we\n // never block on this — absent means render live).\n let checkedOutHandle: DocHandle<CheckedOutDraft> | null = null;\n const unsubscribeCheckedOut = subscribe<AutomergeUrl>(\n element,\n { type: CHECKED_OUT_SELECTOR },\n (url) => {\n if (disposed || !isValidAutomergeUrl(url)) return;\n void liveRepo.find<CheckedOutDraft>(url).then((handle) => {\n if (!disposed) checkedOutHandle = handle;\n });\n }\n );\n\n const onSubscribe = (event: SubscribeEvent) => {\n const selector = event.detail.selector;\n\n if (selector.type === HANDLE_DESCRIPTOR_SELECTOR) {\n const rawTarget = selector.url;\n if (typeof rawTarget !== \"string\" || !isValidAutomergeUrl(rawTarget)) {\n return;\n }\n const original = canonicalUrl(rawTarget);\n accept<DocHandleDescriptor>(event, (respond) => {\n void resolveDescriptor(original).then((descriptor) => {\n if (disposed) return;\n respond(descriptor);\n });\n });\n return;\n }\n };\n\n element.addEventListener(\"patchwork:subscribe\", onSubscribe);\n return () => {\n disposed = true;\n element.removeEventListener(\"patchwork:subscribe\", onSubscribe);\n unsubscribeCheckedOut();\n cloneResolutions.clear();\n };\n\n // Resolve a `repo:handle-descriptor` request. The backing url is pinned to the\n // active checkpoint's `to` heads for this doc (if any) so nested views freeze\n // with the doc they live in; `OverlayRepo` honors heads on the backing url.\n // - On \"main\" (no draft): no clone, just the (maybe pinned) original.\n // - Skipped docs (account, contacts): the real doc, never forked.\n // - Everything else on a draft: the per-draft clone (pinned when checked out).\n async function resolveDescriptor(\n original: AutomergeUrl\n ): Promise<DocHandleDescriptor> {\n const to = checkedOutHandle?.doc()?.at?.[original]?.to ?? undefined;\n if (!draftUrl || (await isSkippedDoc(original))) {\n return to\n ? { url: original, cloneUrl: withHeads(original, to) }\n : { url: original };\n }\n const cloneUrl = await resolveClone(original);\n return { url: original, cloneUrl: withHeads(cloneUrl, to) };\n }\n\n // Stamp `heads` onto `url` (same documentId), or return it unchanged when\n // there is no pin. Heads ride on the url so `OverlayRepo` resolves the doc at\n // that point in time.\n function withHeads(\n url: AutomergeUrl,\n heads: UrlHeads | undefined\n ): AutomergeUrl {\n if (!heads) return url;\n return stringifyAutomergeUrl({\n documentId: parseAutomergeUrl(url).documentId,\n heads,\n });\n }\n\n // A doc is skipped when its `@patchwork.type` is in `SKIPPED_DATATYPES`. On\n // any failure we fall back to cloning (the existing behaviour), which is the\n // safe default — a doc that should be skipped merely keeps forking, it isn't\n // lost.\n async function isSkippedDoc(original: AutomergeUrl): Promise<boolean> {\n try {\n const handle = await liveRepo.find<{ \"@patchwork\"?: { type?: string } }>(\n original\n );\n const type = handle.doc()?.[\"@patchwork\"]?.type;\n return type != null && SKIPPED_DATATYPES.has(type);\n } catch {\n return false;\n }\n }\n\n // Ensure a clone of `original` exists for this draft and return its url.\n // Reuses an existing clone recorded in `DraftDoc.clones`; otherwise forks\n // `original` at its current heads and records the fork point so the baseline\n // and merge-back can find it.\n function resolveClone(original: AutomergeUrl): Promise<AutomergeUrl> {\n const cached = cloneResolutions.get(original);\n if (cached) return cached;\n const promise = (async () => {\n if (!ready) throw new Error(\"[drafts] resolveClone called without a draft\");\n const handle = await ready;\n const existing = handle.doc()?.clones?.[original];\n if (existing) return canonicalUrl(existing.cloneUrl);\n\n const originalHandle = await liveRepo.find<unknown>(original);\n const clonedAt = originalHandle.heads();\n const clone = liveRepo.clone(originalHandle);\n const cloneUrl = canonicalUrl(clone.url);\n\n handle.change((d) => {\n d.clones[original] = { cloneUrl, clonedAt };\n });\n\n return cloneUrl;\n })();\n cloneResolutions.set(original, promise);\n return promise;\n }\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { parseAutomergeUrl, stringifyAutomergeUrl } from "@automerge/automerge-repo";
|
|
2
|
+
const SKIPPED_DATATYPES = /* @__PURE__ */ new Set([
|
|
3
|
+
"account",
|
|
4
|
+
"contact",
|
|
5
|
+
"draft"
|
|
6
|
+
]);
|
|
7
|
+
function canonicalUrl(url) {
|
|
8
|
+
const { documentId } = parseAutomergeUrl(url);
|
|
9
|
+
return stringifyAutomergeUrl({ documentId });
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
SKIPPED_DATATYPES as S,
|
|
13
|
+
canonicalUrl as c
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=clone-policy-D4XOfZxs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone-policy-D4XOfZxs.js","sources":["../../src/clone-policy.ts"],"sourcesContent":["import {\n parseAutomergeUrl,\n stringifyAutomergeUrl,\n type AutomergeUrl,\n} from \"@automerge/automerge-repo\";\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]);\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;AACF,CAAC;AAIM,SAAS,aAAa,KAAiC;AAC5D,QAAM,EAAE,WAAA,IAAe,kBAAkB,GAAG;AAC5C,SAAO,sBAAsB,EAAE,YAAY;AAC7C;"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
function subscribe(element, selector, listener) {
|
|
2
|
+
const view = element.closest("patchwork-view");
|
|
3
|
+
const dispatchEl = view ?? element;
|
|
4
|
+
const channel = new MessageChannel();
|
|
5
|
+
const port = channel.port2;
|
|
6
|
+
const controller = new AbortController();
|
|
7
|
+
const { signal } = controller;
|
|
8
|
+
port.addEventListener("message", (event) => {
|
|
9
|
+
if (event.data?.type === "change")
|
|
10
|
+
listener(event.data.value);
|
|
11
|
+
}, { signal });
|
|
12
|
+
port.start();
|
|
13
|
+
const detail = {
|
|
14
|
+
selector,
|
|
15
|
+
port: channel.port1
|
|
16
|
+
};
|
|
17
|
+
dispatchEl.dispatchEvent(new CustomEvent("patchwork:subscribe", {
|
|
18
|
+
detail,
|
|
19
|
+
bubbles: true,
|
|
20
|
+
composed: true
|
|
21
|
+
}));
|
|
22
|
+
return () => {
|
|
23
|
+
if (signal.aborted)
|
|
24
|
+
return;
|
|
25
|
+
controller.abort();
|
|
26
|
+
port.postMessage({ type: "unsubscribe" });
|
|
27
|
+
port.close();
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function accept(event, producer) {
|
|
31
|
+
event.stopPropagation();
|
|
32
|
+
const port = event.detail.port;
|
|
33
|
+
let alive = true;
|
|
34
|
+
const respond = (value) => {
|
|
35
|
+
if (!alive)
|
|
36
|
+
return;
|
|
37
|
+
port.postMessage({ type: "change", value });
|
|
38
|
+
};
|
|
39
|
+
let teardown;
|
|
40
|
+
try {
|
|
41
|
+
teardown = producer(respond);
|
|
42
|
+
} catch (err) {
|
|
43
|
+
console.error("[patchwork-providers] subscribe producer threw:", err);
|
|
44
|
+
}
|
|
45
|
+
const stop = () => {
|
|
46
|
+
if (!alive)
|
|
47
|
+
return;
|
|
48
|
+
alive = false;
|
|
49
|
+
try {
|
|
50
|
+
teardown?.();
|
|
51
|
+
} catch (err) {
|
|
52
|
+
console.error("[patchwork-providers] subscribe teardown threw:", err);
|
|
53
|
+
}
|
|
54
|
+
port.close();
|
|
55
|
+
};
|
|
56
|
+
port.onmessage = (event2) => {
|
|
57
|
+
if (event2.data?.type === "unsubscribe")
|
|
58
|
+
stop();
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
accept as a,
|
|
63
|
+
subscribe as s
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=index-DAqs20jZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-DAqs20jZ.js","sources":["../../../node_modules/.pnpm/@inkandswitch+patchwork-providers@0.2.2_@automerge+automerge-repo@2.6.0-subduction.34_supports-color@7.2.0_/node_modules/@inkandswitch/patchwork-providers/dist/index.js"],"sourcesContent":["/**\n * Open a streaming subscription. Dispatches a `patchwork:subscribe` for the\n * given `selector` carrying a fresh `MessageChannel` port; the answering\n * provider pushes values back over that channel for as long as the\n * subscription is live. `listener` is invoked once per emission (the first\n * delivery is always async because `MessagePort.postMessage` queues a task).\n *\n * The event is dispatched from the nearest enclosing `<patchwork-view>` so\n * callers can pass any node inside a provider subtree. An unclaimed\n * subscription is never settled: if no provider answers, `listener` simply\n * never fires.\n *\n * Returns an unsubscribe function. Calling it tells the provider to tear down\n * (via an `unsubscribe` message) and closes the consumer's port; any values\n * the provider emits after that are dropped.\n */\nexport function subscribe(element, selector, listener) {\n const view = element.closest(\"patchwork-view\");\n const dispatchEl = view ?? element;\n const channel = new MessageChannel();\n const port = channel.port2;\n const controller = new AbortController();\n const { signal } = controller;\n port.addEventListener(\"message\", (event) => {\n if (event.data?.type === \"change\")\n listener(event.data.value);\n }, { signal });\n // addEventListener (unlike assigning onmessage) does not implicitly start\n // the port, so message delivery has to be kicked off explicitly.\n port.start();\n const detail = {\n selector,\n port: channel.port1,\n };\n dispatchEl.dispatchEvent(new CustomEvent(\"patchwork:subscribe\", {\n detail,\n bubbles: true,\n composed: true,\n }));\n return () => {\n if (signal.aborted)\n return;\n controller.abort();\n port.postMessage({ type: \"unsubscribe\" });\n port.close();\n };\n}\n/**\n * Answer a `patchwork:subscribe`. The `producer` receives a `respond`\n * callback it can call any number of times to push values to the consumer,\n * and may return a teardown that runs when the consumer unsubscribes. Stops\n * propagation so ancestor providers don't double-answer. Values emitted after\n * the consumer unsubscribes are dropped.\n */\nexport function accept(event, producer) {\n event.stopPropagation();\n const port = event.detail.port;\n let alive = true;\n const respond = (value) => {\n if (!alive)\n return;\n port.postMessage({ type: \"change\", value });\n };\n let teardown;\n try {\n teardown = producer(respond);\n }\n catch (err) {\n console.error(\"[patchwork-providers] subscribe producer threw:\", err);\n }\n const stop = () => {\n if (!alive)\n return;\n alive = false;\n try {\n teardown?.();\n }\n catch (err) {\n console.error(\"[patchwork-providers] subscribe teardown threw:\", err);\n }\n port.close();\n };\n port.onmessage = (event) => {\n if (event.data?.type === \"unsubscribe\")\n stop();\n };\n}\n/**\n * One-shot convenience wrapper over {@link subscribe}: opens a subscription\n * for `selector`, resolves with the first value a provider emits, then\n * immediately unsubscribes. Because there is no fallback provider, an\n * unclaimed selector never resolves — use `subscribe` directly if you need to\n * handle the \"no provider\" case.\n */\nexport function request(element, selector) {\n return new Promise((resolve) => {\n const unsubscribe = subscribe(element, selector, (value) => {\n // The first emission is always async (postMessage queues a task), so\n // `unsubscribe` is assigned by the time this fires.\n unsubscribe();\n resolve(value);\n });\n });\n}\nexport { registerRepoProviderElement, } from \"./repo-provider.js\";\n"],"names":["event"],"mappings":"AAgBO,SAAS,UAAU,SAAS,UAAU,UAAU;AACnD,QAAM,OAAO,QAAQ,QAAQ,gBAAgB;AAC7C,QAAM,aAAa,QAAQ;AAC3B,QAAM,UAAU,IAAI,eAAc;AAClC,QAAM,OAAO,QAAQ;AACrB,QAAM,aAAa,IAAI,gBAAe;AACtC,QAAM,EAAE,OAAM,IAAK;AACnB,OAAK,iBAAiB,WAAW,CAAC,UAAU;AACxC,QAAI,MAAM,MAAM,SAAS;AACrB,eAAS,MAAM,KAAK,KAAK;AAAA,EACjC,GAAG,EAAE,QAAQ;AAGb,OAAK,MAAK;AACV,QAAM,SAAS;AAAA,IACX;AAAA,IACA,MAAM,QAAQ;AAAA,EACtB;AACI,aAAW,cAAc,IAAI,YAAY,uBAAuB;AAAA,IAC5D;AAAA,IACA,SAAS;AAAA,IACT,UAAU;AAAA,EAClB,CAAK,CAAC;AACF,SAAO,MAAM;AACT,QAAI,OAAO;AACP;AACJ,eAAW,MAAK;AAChB,SAAK,YAAY,EAAE,MAAM,cAAa,CAAE;AACxC,SAAK,MAAK;AAAA,EACd;AACJ;AAQO,SAAS,OAAO,OAAO,UAAU;AACpC,QAAM,gBAAe;AACrB,QAAM,OAAO,MAAM,OAAO;AAC1B,MAAI,QAAQ;AACZ,QAAM,UAAU,CAAC,UAAU;AACvB,QAAI,CAAC;AACD;AACJ,SAAK,YAAY,EAAE,MAAM,UAAU,MAAK,CAAE;AAAA,EAC9C;AACA,MAAI;AACJ,MAAI;AACA,eAAW,SAAS,OAAO;AAAA,EAC/B,SACO,KAAK;AACR,YAAQ,MAAM,mDAAmD,GAAG;AAAA,EACxE;AACA,QAAM,OAAO,MAAM;AACf,QAAI,CAAC;AACD;AACJ,YAAQ;AACR,QAAI;AACA,iBAAQ;AAAA,IACZ,SACO,KAAK;AACR,cAAQ,MAAM,mDAAmD,GAAG;AAAA,IACxE;AACA,SAAK,MAAK;AAAA,EACd;AACA,OAAK,YAAY,CAACA,WAAU;AACxB,QAAIA,OAAM,MAAM,SAAS;AACrB,WAAI;AAAA,EACZ;AACJ;","x_google_ignoreList":[0]}
|