@inkandswitch/patchwork-pkg-base 0.0.3 → 0.0.4
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 +0 -2
- package/package.json +1 -1
- package/packages/sync-indicator/dist/assets/SyncIndicator-CCDYatIA.js +0 -3
- package/packages/sync-indicator/dist/assets/SyncIndicator-CCDYatIA.js.map +0 -1
- package/packages/sync-indicator/dist/index.js +0 -72
- package/packages/sync-indicator/dist/index.js.map +0 -1
- package/packages/sync-indicator/package.json +0 -43
- package/packages/tasks/dist/assets/datatype-Pq8jM36X.js +0 -10
- package/packages/tasks/dist/assets/datatype-Pq8jM36X.js.map +0 -1
- package/packages/tasks/dist/assets/index-BbuRtBN3.js +0 -7643
- package/packages/tasks/dist/assets/index-BbuRtBN3.js.map +0 -1
- package/packages/tasks/dist/assets/router-BkeENNWb.js +0 -5112
- package/packages/tasks/dist/assets/router-BkeENNWb.js.map +0 -1
- package/packages/tasks/dist/assets/task-queue-tool-BJuLnyjA.js +0 -56
- package/packages/tasks/dist/assets/task-queue-tool-BJuLnyjA.js.map +0 -1
- package/packages/tasks/dist/assets/titlebar-tool-vaV-wxap.js +0 -123
- package/packages/tasks/dist/assets/titlebar-tool-vaV-wxap.js.map +0 -1
- package/packages/tasks/dist/assets/worker-CwK3e_hu.js +0 -5056
- package/packages/tasks/dist/assets/worker-CwK3e_hu.js.map +0 -1
- package/packages/tasks/dist/assets/worker-pool-Bu52iIe3.js +0 -197
- package/packages/tasks/dist/assets/worker-pool-Bu52iIe3.js.map +0 -1
- package/packages/tasks/dist/index.js +0 -91
- package/packages/tasks/dist/index.js.map +0 -1
- package/packages/tasks/package.json +0 -43
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { c as createRoot, j as jsxRuntimeExports, R as RepoContext, r as reactExports, u as useRepo, a as useDocHandle, b as useDocument } from "./index-BbuRtBN3.js";
|
|
2
|
-
const DEFAULT_INPUT_EXPR = `[
|
|
3
|
-
Math.floor(Math.random() * 10) + 1,
|
|
4
|
-
Math.floor(Math.random() * 10) + 1
|
|
5
|
-
]`, DEFAULT_CODE = `export default async function ([x, y]) {
|
|
6
|
-
await seconds(Math.random() * 3);
|
|
7
|
-
if (Math.random() < 0.1) { throw new Error("Oh no!") }
|
|
8
|
-
return x + y;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async function seconds(s) {
|
|
12
|
-
return new Promise((resolve) => {
|
|
13
|
-
setTimeout(resolve, s * 1000);
|
|
14
|
-
});
|
|
15
|
-
}`, TaskQueueTool = (s, e) => {
|
|
16
|
-
const t = e.repo, r = createRoot(e);
|
|
17
|
-
return r.render(jsxRuntimeExports.jsx(RepoContext.Provider, { value: t, children: jsxRuntimeExports.jsx("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "100%" }, children: jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: "...", children: jsxRuntimeExports.jsx(ITaskQueueBrowserTool, { docUrl: s.url }) }) }) })), () => r.unmount();
|
|
18
|
-
}, ITaskQueueBrowserTool = ({ docUrl }) => {
|
|
19
|
-
const repo = useRepo(), handle = useDocHandle(docUrl, { suspense: true }), { activeRouter, pending, done } = handle.doc(), [workers, setWorkers] = reactExports.useState([]), [inputExpr, setInputExpr] = reactExports.useState(DEFAULT_INPUT_EXPR), [code, setCode] = reactExports.useState(DEFAULT_CODE);
|
|
20
|
-
return reactExports.useEffect(() => {
|
|
21
|
-
const s = (e) => {
|
|
22
|
-
console.log("received ephemeral message", e);
|
|
23
|
-
const t = e.message;
|
|
24
|
-
t && (t.routerUrl !== activeRouter ? console.log("^^ that was a router heartbeat from a different router!") : setWorkers(t.workerUrls));
|
|
25
|
-
};
|
|
26
|
-
return handle.on("ephemeral-message", s), () => {
|
|
27
|
-
handle.off("ephemeral-message", s);
|
|
28
|
-
};
|
|
29
|
-
}, [handle]), jsxRuntimeExports.jsx("div", { className: "task-browser", children: jsxRuntimeExports.jsxs("div", { className: "task-browser-layout", children: [jsxRuntimeExports.jsxs("div", { className: "task-browser-form", children: [jsxRuntimeExports.jsx("div", { style: { flex: 1 }, children: jsxRuntimeExports.jsx("textarea", { className: "task-browser-textarea", rows: 5, value: inputExpr, onChange: (s) => setInputExpr(s.target.value) }) }), jsxRuntimeExports.jsx("div", { style: { flex: 1 }, children: jsxRuntimeExports.jsx("textarea", { className: "task-browser-textarea", rows: 5, value: code, onChange: (s) => setCode(s.target.value) }) }), jsxRuntimeExports.jsx("div", { className: "task-browser-section", children: jsxRuntimeExports.jsx("button", { className: "task-browser-submit", onClick: addTask, children: "add task" }) })] }), activeRouter ? jsxRuntimeExports.jsxs("div", { className: "task-browser-section", children: [jsxRuntimeExports.jsx("div", { className: "task-browser-section-title", children: "Router:" }), jsxRuntimeExports.jsx(Router, { docUrl: activeRouter }, activeRouter)] }) : null, jsxRuntimeExports.jsxs("div", { className: "task-browser-section", children: [jsxRuntimeExports.jsx("div", { className: "task-browser-section-title", children: "Workers:" }), workers.map((s) => jsxRuntimeExports.jsx(Worker, { docUrl: s }, s))] }), jsxRuntimeExports.jsxs("div", { className: "task-browser-section", children: [jsxRuntimeExports.jsxs("div", { className: "task-browser-section-title", children: [pending.length, " pending:"] }), renderTasks(pending.toReversed().slice(0, 20))] }), jsxRuntimeExports.jsxs("div", { className: "task-browser-section", children: [jsxRuntimeExports.jsxs("div", { className: "task-browser-section-title", children: [done.length, " done:"] }), renderTasks(done.toReversed().slice(0, 20))] })] }) });
|
|
30
|
-
function renderTasks(s) {
|
|
31
|
-
return s.length === 0 ? jsxRuntimeExports.jsx("div", { className: "task-muted", children: "(none)" }) : jsxRuntimeExports.jsx("ul", { children: [...new Set(s)].map((e) => jsxRuntimeExports.jsx("li", { children: jsxRuntimeExports.jsx(Task, { docUrl: e, docPath: [] }) }, e)) });
|
|
32
|
-
}
|
|
33
|
-
function addTask() {
|
|
34
|
-
const input = eval(inputExpr), importUrl = `data:application/javascript;base64,${btoa(code)}`, taskDoc = repo.create({ input, importUrl, runs: [] });
|
|
35
|
-
handle.change((s) => s.pending.push(taskDoc.url));
|
|
36
|
-
}
|
|
37
|
-
}, Router = (s) => jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: "...", children: jsxRuntimeExports.jsx(IRouter, { ...s }) }), IRouter = ({ docUrl: s }) => {
|
|
38
|
-
const [{ name: e, contactUrl: t }] = useDocument(s, { suspense: true });
|
|
39
|
-
return jsxRuntimeExports.jsxs("div", { className: "task-router", children: [jsxRuntimeExports.jsx("patchwork-view", { "doc-url": t, "tool-id": "contact-inline" }), " / ", e] });
|
|
40
|
-
}, Worker = (s) => jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: "...", children: jsxRuntimeExports.jsx(IWorker, { ...s }) }), IWorker = ({ docUrl: s }) => {
|
|
41
|
-
const [{ name: e, contactUrl: t, currentTask: r }] = useDocument(s, { suspense: true });
|
|
42
|
-
return jsxRuntimeExports.jsx("div", { className: "task-worker", children: jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsx("patchwork-view", { "doc-url": t, "tool-id": "contact-inline" }), " / ", e, " ", r ? jsxRuntimeExports.jsx(Task, { docUrl: r.taskUrl, docPath: [] }) : "(idle)"] }) });
|
|
43
|
-
}, Task = (s) => jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: "...", children: jsxRuntimeExports.jsx(ITask, { ...s }) }), ITask = ({ docUrl: s }) => {
|
|
44
|
-
const [{ importUrl: e, runs: t, input: r }] = useDocument(s, { suspense: true }), n = t.length === 0, i = t.every((o) => o.status === "failed"), [a, c] = reactExports.useState("");
|
|
45
|
-
return reactExports.useEffect(() => {
|
|
46
|
-
fetch(e).then((o) => o.text()).then((o) => c(o));
|
|
47
|
-
}, [e]), jsxRuntimeExports.jsxs("div", { className: `task-item ${n ? "task-item--pending" : i ? "task-item--failed" : "task-item--success"}`, children: [t.map((o, x) => jsxRuntimeExports.jsx("div", { className: "task-run", children: jsxRuntimeExports.jsx(Run, { input: r, run: o }) }, x)), jsxRuntimeExports.jsx("div", { children: a ? jsxRuntimeExports.jsx("pre", { children: a }) : jsxRuntimeExports.jsx("div", { children: "Loading code..." }) })] });
|
|
48
|
-
}, Run = ({ input: s, run: e }) => {
|
|
49
|
-
const { startTimeMillis: t, endTimeMillis: r, result: n, status: i } = e, a = `${r - t}ms`, [{ contactUrl: c, name: o }] = useDocument(e.workerUrl, { suspense: true });
|
|
50
|
-
return jsxRuntimeExports.jsxs("div", { style: { verticalAlign: "top" }, children: [JSON.stringify(s), jsxRuntimeExports.jsx("div", { children: jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsx("patchwork-view", { "doc-url": c, "tool-id": "contact-inline" }), " / ", o, " ", i === "succeeded" ? n === void 0 ? "" : "\u2192 " + n : "\u2717", " (", a, ")"] }) }), e.logs && e.logs.length > 0 && jsxRuntimeExports.jsxs("details", { children: [jsxRuntimeExports.jsx("summary", { children: "logs" }), e.logs.map(({ timestampMillis: x, message: l }, u) => jsxRuntimeExports.jsxs("div", { children: [new Date(x).toLocaleString(), ": ", l] }, u))] })] });
|
|
51
|
-
};
|
|
52
|
-
export {
|
|
53
|
-
Router,
|
|
54
|
-
TaskQueueTool,
|
|
55
|
-
Worker
|
|
56
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"task-queue-tool-BJuLnyjA.js","sources":["../../src/task-queue-tool.tsx"],"sourcesContent":["import React, { Suspense, useEffect, useState } from 'react';\nimport { createRoot } from 'react-dom/client';\nimport './index.css';\nimport { useRepo, useDocument, useDocHandle } from '@automerge/automerge-repo-react-hooks';\nimport type { AutomergeUrl, DocHandle } from '@automerge/automerge-repo';\nimport { RepoContext } from '@automerge/automerge-repo-react-hooks';\nimport type { RouterDoc, RunInfo, WorkerDoc, TaskDoc, TaskQueueDoc } from './datatype';\nimport type { MessageToTaskQueueChannel } from './protocol';\n\nconst DEFAULT_INPUT_EXPR = `[\n Math.floor(Math.random() * 10) + 1,\n Math.floor(Math.random() * 10) + 1\n]`;\n\nconst DEFAULT_CODE = `export default async function ([x, y]) {\n await seconds(Math.random() * 3);\n if (Math.random() < 0.1) { throw new Error(\"Oh no!\") }\n return x + y;\n}\n \nasync function seconds(s) {\n return new Promise((resolve) => {\n setTimeout(resolve, s * 1000);\n });\n}`;\n\nexport const TaskQueueTool = (handle: DocHandle<unknown>, element: HTMLElement) => {\n const repo = (element as any).repo; // TODO: better way to get the repo\n const root = createRoot(element);\n root.render(\n <RepoContext.Provider value={repo}>\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%' }}>\n <Suspense fallback=\"...\">\n <ITaskQueueBrowserTool docUrl={handle.url} />\n </Suspense>\n </div>\n </RepoContext.Provider>,\n );\n return () => root.unmount();\n};\n\nconst ITaskQueueBrowserTool: React.FC<any> = ({ docUrl }) => {\n const repo = useRepo();\n const handle = useDocHandle<TaskQueueDoc>(docUrl, { suspense: true });\n const { activeRouter, pending, done } = handle.doc();\n\n const [workers, setWorkers] = useState<AutomergeUrl[]>([]);\n const [inputExpr, setInputExpr] = useState(DEFAULT_INPUT_EXPR);\n const [code, setCode] = useState(DEFAULT_CODE);\n\n useEffect(() => {\n const messageHandler = (m: any) => {\n console.log('received ephemeral message', m);\n const msg = m.message as MessageToTaskQueueChannel;\n if (msg) {\n // console.log('received router heartbeat', msg);\n if (msg.routerUrl !== activeRouter) {\n console.log('^^ that was a router heartbeat from a different router!');\n } else {\n setWorkers(msg.workerUrls);\n }\n }\n };\n handle.on('ephemeral-message', messageHandler);\n return () => {\n handle.off('ephemeral-message', messageHandler);\n };\n }, [handle]);\n\n return (\n <div className=\"task-browser\">\n <div className=\"task-browser-layout\">\n <div className=\"task-browser-form\">\n <div style={{ flex: 1 }}>\n <textarea\n className=\"task-browser-textarea\"\n rows={5}\n value={inputExpr}\n onChange={(e) => setInputExpr(e.target.value)}\n />\n </div>\n <div style={{ flex: 1 }}>\n <textarea\n className=\"task-browser-textarea\"\n rows={5}\n value={code}\n onChange={(e) => setCode(e.target.value)}\n />\n </div>\n <div className=\"task-browser-section\">\n <button\n className=\"task-browser-submit\"\n onClick={addTask}\n >\n add task\n </button>\n </div>\n </div>\n {activeRouter ? (\n <div className=\"task-browser-section\">\n <div className=\"task-browser-section-title\">Router:</div>\n <Router key={activeRouter} docUrl={activeRouter} />\n </div>\n ) : null}\n <div className=\"task-browser-section\">\n <div className=\"task-browser-section-title\">Workers:</div>\n {workers.map((url) => (\n <Worker key={url} docUrl={url} />\n ))}\n </div>\n <div className=\"task-browser-section\">\n <div className=\"task-browser-section-title\">{pending.length} pending:</div>\n {renderTasks(pending.toReversed().slice(0, 20))}\n </div>\n <div className=\"task-browser-section\">\n <div className=\"task-browser-section-title\">{done.length} done:</div>\n {renderTasks(done.toReversed().slice(0, 20))}\n </div>\n </div>\n </div>\n );\n\n function renderTasks(urls: AutomergeUrl[]) {\n return urls.length === 0 ? (\n <div className=\"task-muted\">(none)</div>\n ) : (\n <ul>\n {[...new Set(urls)].map((url) => (\n <li key={url}>\n <Task docUrl={url} docPath={[]} />\n </li>\n ))}\n </ul>\n );\n }\n\n function addTask() {\n const input = eval(inputExpr);\n const importUrl = `data:application/javascript;base64,${btoa(code)}`;\n const taskDoc = repo.create<TaskDoc<any, any>>({ input, importUrl, runs: [] });\n handle.change((doc) => doc.pending.push(taskDoc.url));\n }\n};\n\nexport const Router: React.FC<any> = (props) => (\n <Suspense fallback=\"...\">\n <IRouter {...props} />\n </Suspense>\n);\n\nconst IRouter: React.FC<any> = ({ docUrl }: { docUrl: AutomergeUrl }) => {\n const [{ name, contactUrl }] = useDocument<RouterDoc>(docUrl, { suspense: true });\n return (\n <div className=\"task-router\">\n <patchwork-view doc-url={contactUrl} tool-id=\"contact-inline\" /> / {name}\n </div>\n );\n};\n\nexport const Worker: React.FC<any> = (props) => (\n <Suspense fallback=\"...\">\n <IWorker {...props} />\n </Suspense>\n);\n\nconst IWorker: React.FC<any> = ({ docUrl }: { docUrl: AutomergeUrl }) => {\n const [{ name, contactUrl, currentTask }] = useDocument<WorkerDoc>(docUrl, { suspense: true });\n return (\n <div className=\"task-worker\">\n <div>\n <patchwork-view doc-url={contactUrl} tool-id=\"contact-inline\" /> / {name}{' '}\n {currentTask ? <Task docUrl={currentTask.taskUrl} docPath={[]} /> : '(idle)'}\n </div>\n </div>\n );\n};\n\nconst Task: React.FC<any> = (props) => (\n <Suspense fallback=\"...\">\n <ITask {...props} />\n </Suspense>\n);\n\nconst ITask: React.FC<any> = ({ docUrl }) => {\n const [{ importUrl, runs, input }] = useDocument<TaskDoc<any, any>>(docUrl, { suspense: true });\n const hasntRun = runs.length === 0;\n const failed = runs.every((run) => run.status === 'failed');\n const [code, setCode] = useState('');\n\n useEffect(() => {\n fetch(importUrl)\n .then((res) => res.text())\n .then((text) => setCode(text));\n }, [importUrl]);\n\n return (\n <div\n className={`task-item ${\n hasntRun ? 'task-item--pending' : failed ? 'task-item--failed' : 'task-item--success'\n }`}\n >\n {runs.map((run: RunInfo<any>, idx) => (\n <div key={idx} className=\"task-run\">\n <Run input={input} run={run} />\n </div>\n ))}\n <div>{code ? <pre>{code}</pre> : <div>Loading code...</div>}</div>\n </div>\n );\n};\n\nconst Run: React.FC<any> = ({ input, run }: { input: any; run: RunInfo<any> }) => {\n const { startTimeMillis, endTimeMillis, result, status } = run;\n const timeAgo = `${endTimeMillis - startTimeMillis}ms`;\n const [{ contactUrl, name }] = useDocument<WorkerDoc>(run.workerUrl as AutomergeUrl, {\n suspense: true,\n });\n return (\n <div style={{ verticalAlign: 'top' }}>\n {JSON.stringify(input)}\n <div>\n <div>\n <patchwork-view doc-url={contactUrl} tool-id=\"contact-inline\" /> / {name}{' '}\n {status === 'succeeded' ? (result === undefined ? '' : '→ ' + result) : '✗'} ({timeAgo})\n </div>\n </div>\n {run.logs && run.logs.length > 0 && (\n <details>\n <summary>logs</summary>\n {run.logs.map(({ timestampMillis, message }, idx) => (\n <div key={idx}>\n {new Date(timestampMillis).toLocaleString()}: {message}\n </div>\n ))}\n </details>\n )}\n </div>\n );\n};\n"],"names":["handle","element","repo","root","jsx","Suspense","useState","useEffect","messageHandler","m","msg","jsxs","e","url","urls","doc","props","docUrl","name","contactUrl","currentTask","importUrl","runs","input","hasntRun","failed","run","code","setCode","res","text","idx","startTimeMillis","endTimeMillis","result","status","timeAgo","timestampMillis","message"],"mappings":"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"}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import { c as h, j as a, R as w, r as u, b as l } from "./index-BbuRtBN3.js";
|
|
5
|
-
const k = "__taskQueues__";
|
|
6
|
-
async function m(t) {
|
|
7
|
-
const r = p();
|
|
8
|
-
if (!r.startsWith("automerge:")) {
|
|
9
|
-
const e = `account doc url invalid: ${r}`;
|
|
10
|
-
throw console.error(e), new Error(e);
|
|
11
|
-
}
|
|
12
|
-
const n = await t.find(r);
|
|
13
|
-
if (!n) {
|
|
14
|
-
const e = `no doc at account doc url: ${r}`;
|
|
15
|
-
throw console.error(e), new Error(e);
|
|
16
|
-
}
|
|
17
|
-
return n;
|
|
18
|
-
}
|
|
19
|
-
function p() {
|
|
20
|
-
return localStorage.getItem("tinyPatchworkAccountUrl");
|
|
21
|
-
}
|
|
22
|
-
function d(t) {
|
|
23
|
-
return t[k] ?? { "automerge:2xrHArq3QwSGHaeUdquP7ECTpnEL": true };
|
|
24
|
-
}
|
|
25
|
-
function g(t) {
|
|
26
|
-
return new SharedWorker("" + new URL("worker-pool-Bu52iIe3.js", import.meta.url).href, { type: "module", name: t == null ? void 0 : t.name });
|
|
27
|
-
}
|
|
28
|
-
function f(t) {
|
|
29
|
-
return new SharedWorker("" + new URL("worker-CwK3e_hu.js", import.meta.url).href, { type: "module", name: t == null ? void 0 : t.name });
|
|
30
|
-
}
|
|
31
|
-
function b(t) {
|
|
32
|
-
return new SharedWorker("" + new URL("router-BkeENNWb.js", import.meta.url).href, { type: "module", name: t == null ? void 0 : t.name });
|
|
33
|
-
}
|
|
34
|
-
const x = 2;
|
|
35
|
-
class U {
|
|
36
|
-
constructor(r, n, e) {
|
|
37
|
-
__publicField(this, "workerPool");
|
|
38
|
-
__publicField(this, "workers", []);
|
|
39
|
-
__publicField(this, "router");
|
|
40
|
-
this.contactUrl = r, this.workerPool = this.createAndInitializeWorkerPool(n, e);
|
|
41
|
-
for (let o = 0; o < x; o++) this.workers.push(this.createAndInitializeWorker(o, n, e));
|
|
42
|
-
this.router = this.createAndInitializeRouter(n, e);
|
|
43
|
-
}
|
|
44
|
-
createAndInitializeWorkerPool(r, n) {
|
|
45
|
-
const e = new g({ name: "task-worker-pool" });
|
|
46
|
-
return e.onerror = (o) => i(o), this.subscribeToRepoChannel("worker pool", (o) => {
|
|
47
|
-
i("sending init to worker pool"), e.port.postMessage({ type: "init", contactUrl: this.contactUrl, repoPort: o, importMap: r, baseURI: n }, [o]);
|
|
48
|
-
}), e;
|
|
49
|
-
}
|
|
50
|
-
createAndInitializeWorker(r, n, e) {
|
|
51
|
-
var _a, _b;
|
|
52
|
-
const o = `task-worker-${r}`;
|
|
53
|
-
i("creating and initializing worker", o);
|
|
54
|
-
const s = new f({ name: o });
|
|
55
|
-
return s.onerror = (c) => i(`worker ${r} error:`, c), s.port.onmessage = (c) => {
|
|
56
|
-
i("received message from worker that i will forward to the pool", c.data), this.workerPool.port.postMessage(c.data);
|
|
57
|
-
}, s.port.onmessageerror = (c) => {
|
|
58
|
-
i("message error from worker", o, c);
|
|
59
|
-
}, (_b = (_a = s.port).start) == null ? void 0 : _b.call(_a), this.subscribeToRepoChannel(o, (c) => {
|
|
60
|
-
i("sending init message to", o), s.port.postMessage({ type: "init", repoPort: c, contactUrl: this.contactUrl, importMap: n, baseURI: e }, [c]);
|
|
61
|
-
}), s;
|
|
62
|
-
}
|
|
63
|
-
createAndInitializeRouter(r, n) {
|
|
64
|
-
const e = new b({ name: "task-router" });
|
|
65
|
-
return e.onerror = (o) => i(o), this.subscribeToRepoChannel("router", (o) => {
|
|
66
|
-
i("sending init message to router"), e.port.postMessage({ type: "init", repoPort: o, contactUrl: this.contactUrl, importMap: r, baseURI: n }, [o]);
|
|
67
|
-
}), this.setUpTaskQueueSetUpdates(), e;
|
|
68
|
-
}
|
|
69
|
-
async setUpTaskQueueSetUpdates() {
|
|
70
|
-
const r = (e) => {
|
|
71
|
-
const o = { type: "update task queue set", taskQueues: d(e) };
|
|
72
|
-
this.sendToRouter(o), this.workerPool.port.postMessage(o);
|
|
73
|
-
}, n = await m(repo);
|
|
74
|
-
n.on("change", (e) => r(e.handle.doc())), r(n.doc());
|
|
75
|
-
}
|
|
76
|
-
sendToRouter(r) {
|
|
77
|
-
this.router.port.postMessage(r);
|
|
78
|
-
}
|
|
79
|
-
subscribeToRepoChannel(r, n) {
|
|
80
|
-
y().subscribeToRepoChannel(async (e) => {
|
|
81
|
-
n(e);
|
|
82
|
-
}).catch((e) => {
|
|
83
|
-
console.error(`failed to subscribe ${r} to repo channel`, e);
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
function y() {
|
|
88
|
-
var _a;
|
|
89
|
-
const t = (_a = window.patchwork) == null ? void 0 : _a.sw;
|
|
90
|
-
if (!(t == null ? void 0 : t.subscribeToRepoChannel)) throw new Error("patchwork service worker repo channel API is unavailable");
|
|
91
|
-
return t;
|
|
92
|
-
}
|
|
93
|
-
function i(...t) {
|
|
94
|
-
console.log("worker pool proxy:", ...t);
|
|
95
|
-
}
|
|
96
|
-
const S = (t, r) => {
|
|
97
|
-
const n = r.repo, e = h(r);
|
|
98
|
-
return e.render(a.jsx(w.Provider, { value: n, children: a.jsx(u.Suspense, { fallback: null, children: a.jsx(E, { element: r }) }) })), () => e.unmount();
|
|
99
|
-
}, E = ({ element: t }) => {
|
|
100
|
-
const [r] = l(p(), { suspense: true }), n = r.contactUrl, e = d(r), [, o] = u.useState(null);
|
|
101
|
-
return u.useEffect(() => {
|
|
102
|
-
const s = new U(n, W(), document.baseURI);
|
|
103
|
-
console.log("titlebar-tool created worker pool proxy", s), o(s);
|
|
104
|
-
}, [n]), a.jsx("div", { style: { display: "flex", gap: "0.25em", alignItems: "center", height: "100%" }, children: Object.keys(e).map((s) => a.jsx(u.Suspense, { fallback: null, children: a.jsx(T, { element: t, taskQueueUrl: s }) }, s)) });
|
|
105
|
-
}, T = ({ element: t, taskQueueUrl: r }) => {
|
|
106
|
-
const [{ title: n, pending: e, done: o }] = l(r, { suspense: true });
|
|
107
|
-
return a.jsxs("div", { className: "task-titlebar", onClick: () => t.dispatchEvent(R({ url: r })), children: [a.jsx("span", { children: n ?? "TQ" }), a.jsx("span", { children: e.length }), "/", a.jsx("span", { children: o.length })] });
|
|
108
|
-
};
|
|
109
|
-
function R(t) {
|
|
110
|
-
return new CustomEvent("patchwork:open-document", { detail: t, bubbles: true, composed: true });
|
|
111
|
-
}
|
|
112
|
-
function W() {
|
|
113
|
-
const t = document.querySelector('script[type="importmap"]');
|
|
114
|
-
if (!t) return {};
|
|
115
|
-
try {
|
|
116
|
-
return JSON.parse(t.textContent || "{}");
|
|
117
|
-
} catch (r) {
|
|
118
|
-
return console.warn("Failed to parse import map:", r), {};
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
export {
|
|
122
|
-
S as TitlebarTool
|
|
123
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"titlebar-tool-vaV-wxap.js","sources":["../../src/helpers.ts","../../src/worker-pool-proxy.ts","../../src/titlebar-tool.tsx"],"sourcesContent":["import { type AutomergeUrl, type DocHandle, type Repo } from '@automerge/automerge-repo/slim';\nimport { TaskQueueSet } from './datatype';\n\nexport const TASK_QUEUE_URLS_FIELD_NAME = '__taskQueues__';\n\n// TODO: where's the type for account??\nexport async function getAccountHandle(repo: Repo): Promise<DocHandle<any>> {\n const accountDocUrl = getAccountDocUrl();\n // avoid importing isValidAutomergeUrl for BS packaging reasons\n if (!accountDocUrl.startsWith('automerge:')) {\n const errorMsg = `account doc url invalid: ${accountDocUrl}`;\n console.error(errorMsg);\n throw new Error(errorMsg);\n }\n const accountHandle = await repo.find<any>(accountDocUrl);\n if (!accountHandle) {\n const errorMsg = `no doc at account doc url: ${accountDocUrl}`;\n console.error(errorMsg);\n throw new Error(errorMsg);\n }\n return accountHandle;\n}\n\n// TODO: what's the right way to get this??\nexport function getAccountDocUrl(): AutomergeUrl {\n return localStorage.getItem('tinyPatchworkAccountUrl') as AutomergeUrl;\n}\n\nexport async function getSelfContactUrl(repo: Repo): Promise<AutomergeUrl> {\n const accountHandle = await getAccountHandle(repo);\n return accountHandle.doc().contactUrl;\n}\n\nexport type TaskQueues = { [taskQueueUrl: AutomergeUrl]: true };\n\nexport function getTaskQueues(account: any): TaskQueues {\n return account[TASK_QUEUE_URLS_FIELD_NAME] ?? { 'automerge:2xrHArq3QwSGHaeUdquP7ECTpnEL': true };\n}\n\nexport function addTaskQueue(account: any, taskQueueUrl: AutomergeUrl) {\n let taskQueues: TaskQueueSet | null = account[TASK_QUEUE_URLS_FIELD_NAME];\n if (!taskQueues) {\n taskQueues = account[TASK_QUEUE_URLS_FIELD_NAME] = {};\n }\n taskQueues![taskQueueUrl] = true;\n}\n\nexport const seconds = async (s: number) =>\n new Promise((resolve) => {\n setTimeout(resolve, s * 1_000);\n });\n\nexport function notNull<T>(value: T | null): value is T {\n return value !== null;\n}\n\nexport function shuffle<T>(array: T[]): T[] {\n for (let i = array.length - 1; i > 0; i--) {\n // Pick a random index from 0 to i\n const j = Math.floor(Math.random() * (i + 1));\n // Swap elements array[i] and array[j]\n [array[i], array[j]] = [array[j], array[i]];\n }\n return array;\n}\n","import type { AutomergeUrl } from '@automerge/automerge-repo';\nimport type { MessageToRouter, MessageToWorker, MessageToWorkerPool } from './protocol';\n\nimport { getAccountHandle, getTaskQueues } from './helpers';\n\nimport WorkerPool from './worker-pool.ts?sharedworker';\nimport TaskWorker from './worker.ts?sharedworker';\nimport TaskRouter from './router.ts?sharedworker';\n\nconst NUM_WORKERS = 2;\n\nexport class WorkerPoolProxy {\n private readonly workerPool: SharedWorker;\n private readonly workers: SharedWorker[] = [];\n private readonly router: SharedWorker;\n\n constructor(\n readonly contactUrl: AutomergeUrl,\n importMap: any,\n baseURI: string,\n ) {\n this.workerPool = this.createAndInitializeWorkerPool(importMap, baseURI);\n\n for (let workerId = 0; workerId < NUM_WORKERS; workerId++) {\n this.workers.push(this.createAndInitializeWorker(workerId, importMap, baseURI));\n }\n\n this.router = this.createAndInitializeRouter(importMap, baseURI);\n }\n\n private createAndInitializeWorkerPool(importMap: any, baseURI: string) {\n // create the shared worker\n const workerPool = new WorkerPool({ name: `task-worker-pool` });\n workerPool.onerror = (error) => log(error);\n\n this.subscribeToRepoChannel('worker pool', (repoPort) => {\n log('sending init to worker pool');\n workerPool.port.postMessage(\n {\n type: 'init',\n contactUrl: this.contactUrl,\n repoPort,\n importMap,\n baseURI,\n } satisfies MessageToWorkerPool,\n [repoPort],\n );\n });\n\n return workerPool;\n }\n\n private createAndInitializeWorker(id: number, importMap: any, baseURI: string) {\n // create the shared worker\n const name = `task-worker-${id}`;\n log('creating and initializing worker', name);\n const worker = new TaskWorker({ name });\n worker.onerror = (error) => log(`worker ${id} error:`, error);\n\n // forward messages from the worker (type 'add worker') to the worker pool\n worker.port.onmessage = (e: any) => {\n log('received message from worker that i will forward to the pool', e.data);\n this.workerPool.port.postMessage(e.data);\n };\n\n worker.port.onmessageerror = (e) => {\n log('message error from worker', name, e);\n };\n\n (worker.port as any).start?.();\n\n this.subscribeToRepoChannel(name, (repoPort) => {\n log('sending init message to', name);\n worker.port.postMessage(\n {\n type: 'init',\n repoPort,\n contactUrl: this.contactUrl,\n importMap,\n baseURI,\n } satisfies MessageToWorker,\n [repoPort],\n );\n });\n\n return worker;\n }\n\n private createAndInitializeRouter(importMap: any, baseURI: string) {\n // create the shared worker\n const router = new TaskRouter({ name: `task-router` });\n router.onerror = (error) => log(error);\n\n this.subscribeToRepoChannel('router', (repoPort) => {\n log('sending init message to router');\n router.port.postMessage(\n {\n type: 'init',\n repoPort,\n contactUrl: this.contactUrl,\n importMap,\n baseURI,\n } satisfies MessageToRouter,\n [repoPort],\n );\n });\n\n // note: no `await` on purpose\n this.setUpTaskQueueSetUpdates();\n\n return router;\n }\n\n async setUpTaskQueueSetUpdates() {\n const updateTaskQueues = (accountDoc: any) => {\n const message: MessageToWorkerPool = {\n type: 'update task queue set',\n taskQueues: getTaskQueues(accountDoc),\n };\n // Router needs the set so it can join queues, run takeover, and broadcast UI heartbeats.\n this.sendToRouter(message);\n // Worker pool must get the same update: it forwards worker heartbeats to the active\n // router's doc channel; without this it never joins queues and the router sees no workers.\n this.workerPool.port.postMessage(message);\n };\n\n const accountHandle = await getAccountHandle(repo);\n accountHandle.on('change', (payload) => updateTaskQueues(payload.handle.doc()));\n updateTaskQueues(accountHandle.doc());\n }\n\n sendToRouter(message: MessageToRouter) {\n this.router.port.postMessage(message);\n }\n\n private subscribeToRepoChannel(\n label: string,\n listener: (repoPort: MessagePort) => void,\n ) {\n void getPatchworkSw().subscribeToRepoChannel(async (repoPort) => {\n listener(repoPort);\n }).catch((error) => {\n console.error(`failed to subscribe ${label} to repo channel`, error);\n });\n }\n}\n\nfunction getPatchworkSw() {\n const sw = (window as any).patchwork?.sw;\n if (!sw?.subscribeToRepoChannel) {\n throw new Error('patchwork service worker repo channel API is unavailable');\n }\n return sw as {\n subscribeToRepoChannel: (\n listener: (repoPort: MessagePort) => void | Promise<void>,\n ) => Promise<() => void>;\n };\n}\n\nfunction log(...args: any) {\n console.log('worker pool proxy:', ...args);\n}\n","import React, { Suspense, useEffect, useState } from 'react';\nimport { createRoot } from 'react-dom/client';\nimport './index.css';\nimport type { AutomergeUrl, DocHandle } from '@automerge/automerge-repo';\nimport { RepoContext, useDocument } from '@automerge/automerge-repo-react-hooks';\nimport type { OpenDocumentEventDetail } from '@inkandswitch/patchwork-elements';\nimport type { TaskQueueDoc } from './datatype';\nimport { WorkerPoolProxy } from './worker-pool-proxy';\nimport { getAccountDocUrl, getTaskQueues } from './helpers';\n\nexport const TitlebarTool = (handle: DocHandle<unknown>, element: HTMLElement) => {\n const repo = (element as any).repo;\n const root = createRoot(element);\n root.render(\n <RepoContext.Provider value={repo}>\n <Suspense fallback={null}>\n <ITitlebarTool element={element} />\n </Suspense>\n </RepoContext.Provider>,\n );\n return () => root.unmount();\n};\n\nconst ITitlebarTool: React.FC<{ element: HTMLElement }> = ({ element }) => {\n const [accountDoc] = useDocument<any>(getAccountDocUrl(), { suspense: true });\n const selfContactUrl: AutomergeUrl = accountDoc.contactUrl;\n const taskQueueUrls = getTaskQueues(accountDoc);\n\n const [, setWorkerPool] = useState<WorkerPoolProxy | null>(null);\n useEffect(() => {\n const proxy = new WorkerPoolProxy(selfContactUrl, getImportMap(), document.baseURI);\n console.log('titlebar-tool created worker pool proxy', proxy);\n setWorkerPool(proxy);\n }, [selfContactUrl]);\n\n return (\n <div style={{ display: 'flex', gap: '0.25em', alignItems: 'center', height: '100%' }}>\n {Object.keys(taskQueueUrls).map((taskQueueUrl) => (\n <Suspense key={taskQueueUrl} fallback={null}>\n <TaskQueue\n element={element}\n taskQueueUrl={taskQueueUrl as AutomergeUrl}\n />\n </Suspense>\n ))}\n </div>\n );\n};\n\nconst TaskQueue: React.FC<{ element: HTMLElement; taskQueueUrl: AutomergeUrl }> = ({\n element,\n taskQueueUrl,\n}) => {\n const [{ title, pending, done }] = useDocument<TaskQueueDoc>(taskQueueUrl, { suspense: true });\n return (\n <div\n className=\"task-titlebar\"\n onClick={() => element.dispatchEvent(createOpenEvent({ url: taskQueueUrl }))}\n >\n <span>{title ?? 'TQ'}</span>\n <span>{pending.length}</span>/<span>{done.length}</span>\n </div>\n );\n};\n\nfunction createOpenEvent(detail: OpenDocumentEventDetail) {\n const openEvent = new CustomEvent('patchwork:open-document', {\n detail,\n bubbles: true,\n composed: true,\n });\n return openEvent;\n}\n\nfunction getImportMap() {\n const importMapElement = document.querySelector('script[type=\"importmap\"]');\n if (!importMapElement) {\n return {};\n }\n\n try {\n return JSON.parse(importMapElement.textContent || '{}');\n } catch (e) {\n console.warn('Failed to parse import map:', e);\n return {};\n }\n}\n"],"names":["TASK_QUEUE_URLS_FIELD_NAME","getAccountHandle","repo","accountDocUrl","getAccountDocUrl","errorMsg","accountHandle","getTaskQueues","account","NUM_WORKERS","WorkerPoolProxy","contactUrl","importMap","baseURI","workerId","workerPool","WorkerPool","error","log","repoPort","id","name","worker","TaskWorker","e","router","TaskRouter","updateTaskQueues","accountDoc","message","payload","label","listener","getPatchworkSw","sw","args","TitlebarTool","handle","element","root","createRoot","jsx","RepoContext","Suspense","ITitlebarTool","useDocument","selfContactUrl","taskQueueUrls","setWorkerPool","useState","useEffect","proxy","getImportMap","taskQueueUrl","TaskQueue","title","pending","done","jsxs","createOpenEvent","detail","importMapElement"],"mappings":"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"}
|