@inkandswitch/patchwork-bootloader 0.2.5 → 0.2.7
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/CHANGELOG.md +14 -0
- package/dist/automerge-worker.d.ts +1 -0
- package/dist/automerge-worker.js +505 -0
- package/dist/externals.js +0 -1
- package/dist/service-worker.js +98 -205
- package/dist/setup.d.ts +1 -0
- package/dist/setup.js +89 -106
- package/dist/site.d.ts +12 -7
- package/dist/site.js +61 -53
- package/dist/sync-config.d.ts +8 -0
- package/dist/sync-config.js +13 -0
- package/dist/types.d.ts +90 -0
- package/dist/types.js +7 -1
- package/dist/vite/importmap-plugin.js +9 -3
- package/dist/vite/service-worker-plugin.js +25 -9
- package/package.json +20 -19
- package/src/automerge-worker.ts +647 -0
- package/src/externals.ts +0 -1
- package/src/service-worker.ts +123 -248
- package/src/setup.ts +105 -118
- package/src/site.ts +89 -65
- package/src/sync-config.ts +23 -0
- package/src/types.ts +98 -0
- package/src/vite/importmap-plugin.ts +13 -3
- package/src/vite/service-worker-plugin.ts +26 -11
- package/tsconfig.json +1 -1
- package/dist/sw-logger.d.ts +0 -105
- package/dist/sw-logger.js +0 -366
- package/src/sw-logger.ts +0 -463
package/dist/site.d.ts
CHANGED
|
@@ -2,37 +2,36 @@
|
|
|
2
2
|
* High-level browser-app boot sequence for a Patchwork site.
|
|
3
3
|
*
|
|
4
4
|
* Layers on top of {@link setupServiceWorker} (the package default export) to
|
|
5
|
-
* construct the Repo, wire up the
|
|
5
|
+
* construct the Repo, wire up the automerge-worker port, load plugins via the
|
|
6
6
|
* ModuleWatcher, resolve the user's account document, and hand control to the
|
|
7
7
|
* configured root tool.
|
|
8
8
|
*
|
|
9
9
|
* This entry point pulls in DOM- and plugin-layer dependencies (patchwork
|
|
10
10
|
* elements, plugins, filesystem) and is intended for use only from a browser
|
|
11
11
|
* site's `main.ts`. Non-UI consumers should import the package default (which
|
|
12
|
-
* only does SW registration and
|
|
12
|
+
* only does SW registration and the automerge-worker handoff).
|
|
13
13
|
*/
|
|
14
14
|
import { type DocHandle, Repo, type AutomergeUrl, type StorageId } from "@automerge/vanillajs/slim";
|
|
15
|
+
import { type AutomergeRepoKeyhive } from "@automerge/automerge-repo-keyhive";
|
|
15
16
|
import { ModuleWatcher } from "@inkandswitch/patchwork-filesystem";
|
|
16
17
|
import { type AccountDoc } from "@inkandswitch/patchwork-plugins";
|
|
17
18
|
import * as plugins from "@inkandswitch/patchwork-plugins";
|
|
18
19
|
import type { ServiceWorkerRepoChannelListener } from "./types.js";
|
|
19
|
-
import { SwLogReader } from "./sw-logger.js";
|
|
20
20
|
declare global {
|
|
21
21
|
interface Window {
|
|
22
22
|
accountDocHandle: DocHandle<AccountDoc>;
|
|
23
23
|
Automerge: typeof import("@automerge/automerge");
|
|
24
24
|
AutomergeRepo: typeof import("@automerge/automerge-repo");
|
|
25
25
|
repo: Repo;
|
|
26
|
+
hive?: AutomergeRepoKeyhive;
|
|
27
|
+
getRepoChannel: () => MessagePort;
|
|
26
28
|
patchwork: {
|
|
27
29
|
repo: Repo;
|
|
28
30
|
packages: ModuleWatcher;
|
|
29
31
|
plugins: typeof plugins;
|
|
30
32
|
accountDocHandle: DocHandle<AccountDoc>;
|
|
31
33
|
sw: {
|
|
32
|
-
|
|
33
|
-
tailLogs: (n?: number) => ReturnType<typeof SwLogReader.tail>;
|
|
34
|
-
exportLogs: () => Promise<string>;
|
|
35
|
-
clearLogs: () => Promise<void>;
|
|
34
|
+
connectClassicSync: (server?: string) => Promise<void>;
|
|
36
35
|
subscribeToRepoChannel: (listener: ServiceWorkerRepoChannelListener) => Promise<() => void>;
|
|
37
36
|
};
|
|
38
37
|
};
|
|
@@ -72,6 +71,12 @@ export interface SiteConfig {
|
|
|
72
71
|
* Ink & Switch's production Subduction storage.
|
|
73
72
|
*/
|
|
74
73
|
remoteStorageIds?: StorageId[];
|
|
74
|
+
/**
|
|
75
|
+
* When true, initialize keyhive for access control.
|
|
76
|
+
* The Repo will use keyhive's network adapter, peerId, and idFactory
|
|
77
|
+
* instead of a sharePolicy.
|
|
78
|
+
*/
|
|
79
|
+
keyhive?: boolean;
|
|
75
80
|
}
|
|
76
81
|
export interface BootResult {
|
|
77
82
|
repo: Repo;
|
package/dist/site.js
CHANGED
|
@@ -2,28 +2,29 @@
|
|
|
2
2
|
* High-level browser-app boot sequence for a Patchwork site.
|
|
3
3
|
*
|
|
4
4
|
* Layers on top of {@link setupServiceWorker} (the package default export) to
|
|
5
|
-
* construct the Repo, wire up the
|
|
5
|
+
* construct the Repo, wire up the automerge-worker port, load plugins via the
|
|
6
6
|
* ModuleWatcher, resolve the user's account document, and hand control to the
|
|
7
7
|
* configured root tool.
|
|
8
8
|
*
|
|
9
9
|
* This entry point pulls in DOM- and plugin-layer dependencies (patchwork
|
|
10
10
|
* elements, plugins, filesystem) and is intended for use only from a browser
|
|
11
11
|
* site's `main.ts`. Non-UI consumers should import the package default (which
|
|
12
|
-
* only does SW registration and
|
|
12
|
+
* only does SW registration and the automerge-worker handoff).
|
|
13
13
|
*/
|
|
14
14
|
import { IndexedDBStorageAdapter, initializeWasm, isValidAutomergeUrl, isValidDocumentId, MessageChannelNetworkAdapter, parseAutomergeUrl, Repo, stringifyAutomergeUrl, } from "@automerge/vanillajs/slim";
|
|
15
15
|
import * as Automerge from "@automerge/automerge/slim";
|
|
16
16
|
import * as AutomergeRepo from "@automerge/automerge-repo/slim";
|
|
17
|
+
import { initKeyhiveWasm, initializeAutomergeRepoKeyhive, } from "@automerge/automerge-repo-keyhive";
|
|
17
18
|
// eslint-disable-next-line
|
|
18
19
|
// @ts-ignore — initSync is a wasm-bindgen runtime helper not in the .d.ts
|
|
19
20
|
import { initSync as initSubductionSync } from "@automerge/automerge-subduction/slim";
|
|
21
|
+
const siteName = typeof __SITE_NAME__ !== "undefined" ? __SITE_NAME__ : "tiny-patchwork";
|
|
20
22
|
import { ModuleWatcher } from "@inkandswitch/patchwork-filesystem";
|
|
21
23
|
import { openDocument, registerPatchworkViewElement, } from "@inkandswitch/patchwork-elements";
|
|
22
|
-
import {
|
|
24
|
+
import { registerRepoProviderElement } from "@inkandswitch/patchwork-providers";
|
|
23
25
|
import { getRegistry, registerPlugins, resolveAccountHandle, unregisterPlugins, } from "@inkandswitch/patchwork-plugins";
|
|
24
26
|
import * as plugins from "@inkandswitch/patchwork-plugins";
|
|
25
27
|
import setupServiceWorker from "./setup.js";
|
|
26
|
-
import { SwLogReader } from "./sw-logger.js";
|
|
27
28
|
import debug from "debug";
|
|
28
29
|
const log = debug("patchwork:bootloader:site");
|
|
29
30
|
const DEFAULT_REMOTE_STORAGE_ID = "3760df37-a4c6-4f66-9ecd-732039a9385d";
|
|
@@ -48,51 +49,72 @@ export async function bootPatchworkSite(config) {
|
|
|
48
49
|
log(`booting`, config);
|
|
49
50
|
await initializeWasm(automergeWasm);
|
|
50
51
|
initSubductionSync(subductionWasm);
|
|
51
|
-
const repo = new Repo({
|
|
52
|
-
storage: new IndexedDBStorageAdapter(),
|
|
53
|
-
async sharePolicy(peerId) {
|
|
54
|
-
return peerId.includes("service-worker");
|
|
55
|
-
},
|
|
56
|
-
enableRemoteHeadsGossiping: true,
|
|
57
|
-
peerId: `${config.titleSuffix}-tab-${crypto.randomUUID()}`,
|
|
58
|
-
});
|
|
59
|
-
repo.subscribeToRemotes(config.remoteStorageIds ?? [DEFAULT_REMOTE_STORAGE_ID]);
|
|
60
52
|
const sw = await setupServiceWorker();
|
|
61
53
|
if (!sw)
|
|
62
54
|
throw new Error("Failed to set up service worker");
|
|
63
|
-
let
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
55
|
+
let hive;
|
|
56
|
+
// Get the initial automerge-worker port via subscribeToRepoChannel,
|
|
57
|
+
// then pass it to keyhive init which wraps it in its own network adapter.
|
|
58
|
+
let resolvePort;
|
|
59
|
+
const portPromise = new Promise((r) => {
|
|
60
|
+
resolvePort = r;
|
|
61
|
+
});
|
|
62
|
+
await sw.subscribeToRepoChannel(resolvePort);
|
|
63
|
+
const workerPort = await portPromise;
|
|
64
|
+
if (config.keyhive) {
|
|
65
|
+
initKeyhiveWasm();
|
|
66
|
+
hive = await initializeAutomergeRepoKeyhive({
|
|
67
|
+
storage: new IndexedDBStorageAdapter(`${siteName}-keyhive`),
|
|
68
|
+
peerIdSuffix: siteName + Math.random().toString(36).slice(2),
|
|
69
|
+
networkAdapter: new MessageChannelNetworkAdapter(workerPort),
|
|
70
|
+
automaticArchiveIngestion: true,
|
|
71
|
+
cachingMode: "periodic",
|
|
72
|
+
onlyShareWithHardcodedServerPeerId: false,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
const repo = hive
|
|
76
|
+
? new Repo({
|
|
77
|
+
storage: new IndexedDBStorageAdapter(),
|
|
78
|
+
enableRemoteHeadsGossiping: true,
|
|
79
|
+
network: [hive.networkAdapter],
|
|
80
|
+
peerId: hive.peerId,
|
|
81
|
+
idFactory: hive.idFactory,
|
|
82
|
+
})
|
|
83
|
+
: new Repo({
|
|
84
|
+
network: [new MessageChannelNetworkAdapter(workerPort)],
|
|
85
|
+
storage: new IndexedDBStorageAdapter(),
|
|
86
|
+
async sharePolicy(peerId) {
|
|
87
|
+
return peerId.includes("automerge-worker");
|
|
88
|
+
},
|
|
89
|
+
enableRemoteHeadsGossiping: true,
|
|
90
|
+
peerId: `${config.titleSuffix}-tab-${crypto.randomUUID()}`,
|
|
91
|
+
});
|
|
92
|
+
repo.subscribeToRemotes(config.remoteStorageIds ?? [DEFAULT_REMOTE_STORAGE_ID]);
|
|
93
|
+
await repo.networkSubsystem.whenReady();
|
|
94
|
+
if (hive) {
|
|
95
|
+
hive.networkAdapter.syncKeyhive?.();
|
|
96
|
+
}
|
|
97
|
+
installDevConsoleGlobals(repo, hive, sw.getRepoChannel);
|
|
74
98
|
registerRepoProviderElement(repo);
|
|
75
|
-
registerFallbackProviderElement();
|
|
76
99
|
const rootElement = document.getElementById(config.rootElementId ?? "root");
|
|
77
100
|
if (!rootElement) {
|
|
78
101
|
throw new Error(`bootPatchworkSite: no element with id="${config.rootElementId ?? "root"}"`);
|
|
79
102
|
}
|
|
80
103
|
const repoProvider = document.createElement("repo-provider");
|
|
81
|
-
|
|
82
|
-
rootElement.parentElement.insertBefore(fallbackProvider, rootElement);
|
|
83
|
-
fallbackProvider.appendChild(repoProvider);
|
|
104
|
+
rootElement.parentElement.insertBefore(repoProvider, rootElement);
|
|
84
105
|
repoProvider.appendChild(rootElement);
|
|
85
|
-
|
|
86
|
-
// delegates to in one go.
|
|
87
|
-
registerPatchworkViewElement();
|
|
106
|
+
registerPatchworkViewElement(hive ? { hive } : {});
|
|
88
107
|
// The watcher is started with the site's default-tools bundle alone so that
|
|
89
108
|
// `resolveAccountHandle` below has something to await on (the `account`
|
|
90
109
|
// datatype lives in that bundle today). The user's own module-settings URL
|
|
91
110
|
// is added lazily once it appears on the account doc — see below.
|
|
92
111
|
const moduleWatcher = new ModuleWatcher(repo, { system: defaultModulesUrl }, onModuleLoaded, unregisterPlugins);
|
|
93
|
-
const accountDocHandle = await resolveAccountHandle(repo, {
|
|
112
|
+
const accountDocHandle = (await resolveAccountHandle(repo, {
|
|
94
113
|
storageKey: config.accountStorageKey,
|
|
95
|
-
|
|
114
|
+
hive,
|
|
115
|
+
}));
|
|
116
|
+
// TODO: something we (Orion & pvh) changed in the types made this necessary
|
|
117
|
+
// fix this before merging to main!
|
|
96
118
|
window.accountDocHandle = accountDocHandle;
|
|
97
119
|
wireModuleSettingsWhenReady(accountDocHandle, moduleWatcher);
|
|
98
120
|
primeRootElement(rootElement, accountDocHandle);
|
|
@@ -103,7 +125,7 @@ export async function bootPatchworkSite(config) {
|
|
|
103
125
|
plugins,
|
|
104
126
|
accountDocHandle,
|
|
105
127
|
sw: {
|
|
106
|
-
|
|
128
|
+
connectClassicSync: sw.connectClassicSync,
|
|
107
129
|
subscribeToRepoChannel: sw.subscribeToRepoChannel,
|
|
108
130
|
},
|
|
109
131
|
};
|
|
@@ -131,10 +153,14 @@ function resolveDefaultModulesUrl(builtin) {
|
|
|
131
153
|
console.warn(`ignoring invalid defaultToolsUrl in localStorage: ${override}; using built-in default`);
|
|
132
154
|
return builtin;
|
|
133
155
|
}
|
|
134
|
-
function installDevConsoleGlobals(repo) {
|
|
156
|
+
function installDevConsoleGlobals(repo, hive, getRepoChannel) {
|
|
135
157
|
window.repo = repo;
|
|
136
158
|
window.Automerge = Automerge;
|
|
137
159
|
window.AutomergeRepo = AutomergeRepo;
|
|
160
|
+
if (hive) {
|
|
161
|
+
window.hive = hive;
|
|
162
|
+
}
|
|
163
|
+
window.getRepoChannel = getRepoChannel;
|
|
138
164
|
}
|
|
139
165
|
function onModuleLoaded(name, mod) {
|
|
140
166
|
if (Array.isArray(mod.plugins)) {
|
|
@@ -196,24 +222,6 @@ function logToolRegistryWhenLoaded(moduleWatcher) {
|
|
|
196
222
|
console.error("doneLoading rejected:", err);
|
|
197
223
|
});
|
|
198
224
|
}
|
|
199
|
-
function buildSwLogApi() {
|
|
200
|
-
return {
|
|
201
|
-
printLogs: async (n = 200) => {
|
|
202
|
-
const entries = await SwLogReader.tail(n);
|
|
203
|
-
for (const e of entries) {
|
|
204
|
-
const prefix = `[${e.ts}] [${e.level}]`;
|
|
205
|
-
if (e.data !== undefined)
|
|
206
|
-
log(prefix, e.msg, e.data);
|
|
207
|
-
else
|
|
208
|
-
log(prefix, e.msg);
|
|
209
|
-
}
|
|
210
|
-
log(`--- ${entries.length} entries ---`);
|
|
211
|
-
},
|
|
212
|
-
tailLogs: (n = 200) => SwLogReader.tail(n),
|
|
213
|
-
exportLogs: () => SwLogReader.exportAll(),
|
|
214
|
-
clearLogs: () => SwLogReader.clear(),
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
225
|
const LOADING_STYLE_ID = "pw-bootloader-loading-styles";
|
|
218
226
|
const LOADING_ELEMENT_ID = "pw-bootloader-loading";
|
|
219
227
|
function showLoadingAnimation() {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** localStorage key: optional override for the classic sync WebSocket URL. */
|
|
2
|
+
export declare const CLASSIC_SYNC_SERVER_KEY = "patchworkClassicSyncServer";
|
|
3
|
+
export declare const DEFAULT_CLASSIC_SYNC_SERVER = "wss://sync3.automerge.org";
|
|
4
|
+
export declare function readClassicSyncServer(storage?: Pick<Storage, "getItem">): string;
|
|
5
|
+
export type ConnectClassicSyncMessage = {
|
|
6
|
+
type: "connect-classic-sync";
|
|
7
|
+
server: string;
|
|
8
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** localStorage key: optional override for the classic sync WebSocket URL. */
|
|
2
|
+
export const CLASSIC_SYNC_SERVER_KEY = "patchworkClassicSyncServer";
|
|
3
|
+
export const DEFAULT_CLASSIC_SYNC_SERVER = "wss://sync3.automerge.org";
|
|
4
|
+
export function readClassicSyncServer(storage = globalThis.localStorage) {
|
|
5
|
+
const override = storage.getItem(CLASSIC_SYNC_SERVER_KEY)?.trim();
|
|
6
|
+
if (!override)
|
|
7
|
+
return DEFAULT_CLASSIC_SYNC_SERVER;
|
|
8
|
+
if (!/^wss?:\/\//.test(override)) {
|
|
9
|
+
console.warn(`ignoring invalid ${CLASSIC_SYNC_SERVER_KEY} in localStorage: ${override}; using ${DEFAULT_CLASSIC_SYNC_SERVER}`);
|
|
10
|
+
return DEFAULT_CLASSIC_SYNC_SERVER;
|
|
11
|
+
}
|
|
12
|
+
return override;
|
|
13
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,11 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The BroadcastChannel the service worker and the automerge shared worker
|
|
3
|
+
* use to hand requests off to each other. Broadcast (rather than a
|
|
4
|
+
* MessagePort handed from one to the other) so the two never need to be
|
|
5
|
+
* reintroduced when either of them restarts — and so tabs can listen in.
|
|
6
|
+
*/
|
|
7
|
+
export declare const HANDOFF_CHANNEL = "@patchwork/handoff";
|
|
8
|
+
/**
|
|
9
|
+
* The special URL to resolve, plus enough of the {@link Request} the service
|
|
10
|
+
* worker is holding that the automerge worker can construct one that
|
|
11
|
+
* `cache.match`es it.
|
|
12
|
+
*
|
|
13
|
+
* Stale workers on either side of the channel can outlive a deploy, so the
|
|
14
|
+
* shape can only ever change additively: `url` must stay the http request
|
|
15
|
+
* URL old automerge workers decode the special URL out of, and new meaning
|
|
16
|
+
* goes in new fields old receivers ignore.
|
|
17
|
+
*/
|
|
18
|
+
export interface HandoffRequest {
|
|
19
|
+
/**
|
|
20
|
+
* The URL of the request the service worker is holding (the encoded
|
|
21
|
+
* `https://…/automerge%3Aabc/…` form) — the cache key.
|
|
22
|
+
*/
|
|
23
|
+
url: string;
|
|
24
|
+
/** the decoded special URL, e.g. `automerge:abc/some/path` */
|
|
25
|
+
handoffURL: string;
|
|
26
|
+
/**
|
|
27
|
+
* @deprecated A briefly-deployed shape put the special URL in `url` and
|
|
28
|
+
* the cache key here. Only read, never sent.
|
|
29
|
+
*/
|
|
30
|
+
cacheKey?: string;
|
|
31
|
+
headers: Record<string, string>;
|
|
32
|
+
method: string;
|
|
33
|
+
destination: RequestDestination;
|
|
34
|
+
referrer: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Service worker → automerge worker: please resolve this request and put
|
|
38
|
+
* the response in my cache.
|
|
39
|
+
*/
|
|
40
|
+
export interface HandoffRequestMessage {
|
|
41
|
+
id: string;
|
|
42
|
+
type: "request";
|
|
43
|
+
/** the current name of the service worker cache */
|
|
44
|
+
cachename: string;
|
|
45
|
+
request: HandoffRequest;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Automerge worker → service worker: the response is stored in the cache
|
|
49
|
+
* under the request you're holding. Serve `cache.match`.
|
|
50
|
+
*/
|
|
51
|
+
export interface HandoffCachedMessage {
|
|
52
|
+
id: string;
|
|
53
|
+
type: "cached";
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* An inline response for things that shouldn't be cached: errors, redirects
|
|
57
|
+
* &c.
|
|
58
|
+
*/
|
|
59
|
+
export interface HandoffResponse {
|
|
60
|
+
body?: string | Uint8Array<ArrayBuffer>;
|
|
61
|
+
/** defaults to 200 */
|
|
62
|
+
status?: number;
|
|
63
|
+
headers?: Record<string, string>;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Automerge worker → service worker: don't cache anything, serve this
|
|
67
|
+
* response directly.
|
|
68
|
+
*/
|
|
69
|
+
export interface HandoffResponseMessage {
|
|
70
|
+
id: string;
|
|
71
|
+
type: "response";
|
|
72
|
+
response: HandoffResponse;
|
|
73
|
+
}
|
|
74
|
+
export type HandoffReplyMessage = HandoffCachedMessage | HandoffResponseMessage;
|
|
75
|
+
/**
|
|
76
|
+
* Automerge worker → world: broadcast once on startup so the service worker
|
|
77
|
+
* can re-send any handoff requests that raced the worker's boot.
|
|
78
|
+
*/
|
|
79
|
+
export interface HandoffOnlineMessage {
|
|
80
|
+
type: "online";
|
|
81
|
+
}
|
|
1
82
|
export type SetupServiceWorkerOptions = {
|
|
2
83
|
/**
|
|
3
84
|
* The public path to the service worker file.
|
|
4
85
|
* Defaults to `/service-worker.js`
|
|
5
86
|
*/
|
|
6
87
|
path?: string;
|
|
88
|
+
/**
|
|
89
|
+
* The public path to the automerge shared worker file.
|
|
90
|
+
* Defaults to `/automerge-worker.js`
|
|
91
|
+
*/
|
|
92
|
+
workerPath?: string;
|
|
7
93
|
};
|
|
8
94
|
export type ServiceWorkerRepoChannelListener = (port: MessagePort) => void | Promise<void>;
|
|
9
95
|
export type SetupServiceWorkerResult = {
|
|
96
|
+
/** Open a classic Automerge sync WebSocket from the automerge worker. */
|
|
97
|
+
connectClassicSync: (server?: string) => Promise<void>;
|
|
10
98
|
subscribeToRepoChannel: (listener: ServiceWorkerRepoChannelListener) => Promise<() => void>;
|
|
99
|
+
/** Open a fresh repo sync port to the automerge worker (dev console). */
|
|
100
|
+
getRepoChannel: () => MessagePort;
|
|
11
101
|
};
|
package/dist/types.js
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The BroadcastChannel the service worker and the automerge shared worker
|
|
3
|
+
* use to hand requests off to each other. Broadcast (rather than a
|
|
4
|
+
* MessagePort handed from one to the other) so the two never need to be
|
|
5
|
+
* reintroduced when either of them restarts — and so tabs can listen in.
|
|
6
|
+
*/
|
|
7
|
+
export const HANDOFF_CHANNEL = "@patchwork/handoff";
|
|
@@ -30,12 +30,18 @@ export function importmap(options) {
|
|
|
30
30
|
preserveSignature: "strict",
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
|
-
// Emit automerge wasm so the service worker can fetch
|
|
34
|
-
const
|
|
33
|
+
// Emit automerge, keyhive, and subduction wasm so the service worker can fetch them
|
|
34
|
+
const automergeWasmPath = require.resolve("@automerge/automerge/automerge.wasm");
|
|
35
35
|
this.emitFile({
|
|
36
36
|
type: "asset",
|
|
37
37
|
fileName: "automerge.wasm",
|
|
38
|
-
source: readFileSync(
|
|
38
|
+
source: readFileSync(automergeWasmPath),
|
|
39
|
+
});
|
|
40
|
+
const keyhiveWasmPath = require.resolve("@keyhive/keyhive/keyhive_wasm.wasm");
|
|
41
|
+
this.emitFile({
|
|
42
|
+
type: "asset",
|
|
43
|
+
fileName: "keyhive_wasm.wasm",
|
|
44
|
+
source: readFileSync(keyhiveWasmPath),
|
|
39
45
|
});
|
|
40
46
|
// Emit subduction wasm so the service worker can fetch it
|
|
41
47
|
const subdWasmPath = require.resolve("@automerge/automerge-subduction/wasm");
|
|
@@ -1,20 +1,36 @@
|
|
|
1
1
|
import { builtins } from "./importmap-plugin.js";
|
|
2
|
+
// The service worker and the automerge shared worker are emitted as their
|
|
3
|
+
// own chunks. Their heavy imports are marked external and resolved to
|
|
4
|
+
// /packages/... URLs (both workers are created with type:"module", so the
|
|
5
|
+
// browser fetches those as regular network requests).
|
|
6
|
+
const workers = [
|
|
7
|
+
{
|
|
8
|
+
specifier: "@inkandswitch/patchwork-bootloader/service-worker",
|
|
9
|
+
fileName: "service-worker.js",
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
specifier: "@inkandswitch/patchwork-bootloader/automerge-worker",
|
|
13
|
+
fileName: "automerge-worker.js",
|
|
14
|
+
},
|
|
15
|
+
];
|
|
2
16
|
export function serviceworker() {
|
|
3
|
-
|
|
17
|
+
const entryIds = new Set();
|
|
4
18
|
return {
|
|
5
19
|
name: "@patchwork/service-worker",
|
|
6
20
|
enforce: "pre",
|
|
7
21
|
async buildStart() {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
22
|
+
for (const { specifier, fileName } of workers) {
|
|
23
|
+
const resolved = await this.resolve(specifier);
|
|
24
|
+
entryIds.add(resolved.id);
|
|
25
|
+
this.emitFile({
|
|
26
|
+
type: "chunk",
|
|
27
|
+
id: resolved.id,
|
|
28
|
+
fileName,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
15
31
|
},
|
|
16
32
|
resolveId(source, importer) {
|
|
17
|
-
if (importer &&
|
|
33
|
+
if (importer && entryIds.has(importer) && source in builtins) {
|
|
18
34
|
return { id: builtins[source], external: true };
|
|
19
35
|
}
|
|
20
36
|
},
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inkandswitch/patchwork-bootloader",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"author": "chee",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"devDependencies": {
|
|
8
|
-
"@automerge/automerge-repo-keyhive": "0.
|
|
8
|
+
"@automerge/automerge-repo-keyhive": "0.3.0-alpha.sub.1c",
|
|
9
9
|
"esbuild": "^0.23.1",
|
|
10
|
-
"rollup": "^4.
|
|
10
|
+
"rollup": "^4.61.1"
|
|
11
11
|
},
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
@@ -26,6 +26,10 @@
|
|
|
26
26
|
"import": "./dist/service-worker.js",
|
|
27
27
|
"types": "./dist/service-worker.d.ts"
|
|
28
28
|
},
|
|
29
|
+
"./automerge-worker": {
|
|
30
|
+
"import": "./dist/automerge-worker.js",
|
|
31
|
+
"types": "./dist/automerge-worker.d.ts"
|
|
32
|
+
},
|
|
29
33
|
"./site": {
|
|
30
34
|
"import": "./dist/site.js",
|
|
31
35
|
"types": "./dist/site.d.ts"
|
|
@@ -33,35 +37,32 @@
|
|
|
33
37
|
"./types": {
|
|
34
38
|
"import": "./dist/types.js",
|
|
35
39
|
"types": "./dist/types.d.ts"
|
|
36
|
-
},
|
|
37
|
-
"./sw-logger": {
|
|
38
|
-
"import": "./dist/sw-logger.js",
|
|
39
|
-
"types": "./dist/sw-logger.d.ts"
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@automerge/automerge": "3.3.0-fragments.1",
|
|
44
|
-
"@automerge/automerge-repo": "2.6.0-subduction.
|
|
45
|
-
"@automerge/automerge-
|
|
46
|
-
"@automerge/automerge-repo-network-
|
|
47
|
-
"@automerge/automerge-repo-
|
|
48
|
-
"@automerge/automerge-
|
|
49
|
-
"@automerge/vanillajs": "2.6.0-subduction.
|
|
50
|
-
"@
|
|
44
|
+
"@automerge/automerge-repo": "2.6.0-subduction.29",
|
|
45
|
+
"@automerge/automerge-repo-network-messagechannel": "2.6.0-subduction.29",
|
|
46
|
+
"@automerge/automerge-repo-network-websocket": "2.6.0-subduction.29",
|
|
47
|
+
"@automerge/automerge-repo-storage-indexeddb": "2.6.0-subduction.29",
|
|
48
|
+
"@automerge/automerge-subduction": "0.15.0",
|
|
49
|
+
"@automerge/vanillajs": "2.6.0-subduction.29",
|
|
50
|
+
"@keyhive/keyhive": "0.0.0-alpha.56",
|
|
51
|
+
"@types/debug": "^4.1.13",
|
|
51
52
|
"debug": "^4.4.3",
|
|
52
53
|
"resolve.exports": "^2.0.3",
|
|
53
54
|
"service-worker-types": "npm:@types/serviceworker@^0.0.153",
|
|
54
55
|
"tinyargs": "^0.1.4",
|
|
55
|
-
"@inkandswitch/patchwork-elements": "^0.
|
|
56
|
+
"@inkandswitch/patchwork-elements": "^1.0.0",
|
|
56
57
|
"@inkandswitch/patchwork-filesystem": "^0.0.8",
|
|
57
58
|
"@inkandswitch/patchwork-plugins": "^0.0.11",
|
|
58
|
-
"@inkandswitch/patchwork-providers": "^0.
|
|
59
|
+
"@inkandswitch/patchwork-providers": "^0.2.2"
|
|
59
60
|
},
|
|
60
61
|
"peerDependencies": {
|
|
61
62
|
"@automerge/automerge": "3.3.0-fragments.1",
|
|
62
|
-
"@automerge/automerge-repo": "2.6.0-subduction.
|
|
63
|
-
"@automerge/automerge-repo-keyhive": "0.
|
|
64
|
-
"@automerge/vanillajs": "2.6.0-subduction.
|
|
63
|
+
"@automerge/automerge-repo": "2.6.0-subduction.29",
|
|
64
|
+
"@automerge/automerge-repo-keyhive": "0.3.0-alpha.sub.1c",
|
|
65
|
+
"@automerge/vanillajs": "2.6.0-subduction.29"
|
|
65
66
|
},
|
|
66
67
|
"scripts": {
|
|
67
68
|
"build": "tsc",
|