@inkandswitch/patchwork-bootloader 0.4.4 → 0.5.2

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 CHANGED
@@ -1,5 +1,43 @@
1
1
  # @inkandswitch/patchwork-bootloader
2
2
 
3
+ ## 0.5.2
4
+
5
+ ### Patch Changes
6
+
7
+ - f00dcb8: Add `repository` metadata pointing at inkandswitch/patchwork-system, so npm links each package to its source directory and can attest provenance when published from CI.
8
+ - Updated dependencies [f00dcb8]
9
+ - @inkandswitch/patchwork-filesystem@0.2.5
10
+ - @inkandswitch/patchwork-elements@4.0.4
11
+ - @inkandswitch/patchwork-plugins@1.0.3
12
+
13
+ ## 0.5.1
14
+
15
+ ### Patch Changes
16
+
17
+ - 5f70c14: Add `repository` metadata pointing at inkandswitch/patchwork-next, so npm links each package to its source directory and can attest provenance when published from CI.
18
+ - Updated dependencies [5f70c14]
19
+ - @inkandswitch/patchwork-filesystem@0.2.4
20
+ - @inkandswitch/patchwork-elements@4.0.3
21
+ - @inkandswitch/patchwork-plugins@1.0.2
22
+
23
+ ## 0.5.0
24
+
25
+ ### Minor Changes
26
+
27
+ - bd63259: Move the site boot sequence and the vite plugin out to `@inkandswitch/patchwork`. The `./site` and `./vite` exports are gone; import from `@inkandswitch/patchwork` and `@inkandswitch/patchwork/vite` instead.
28
+
29
+ Split the externals list into `./externals-list` so the list can be read without pulling in node builtins, and export `resolveExternal` and the wasm asset emitter so another package's vite plugin can resolve the bootloader's own dependencies from the bootloader's `node_modules`. Export `./global.css` and `./module-loader`.
30
+
31
+ Fall back to a url-keyed cache lookup in the service worker when the request-keyed one misses, so a cors request (the wasm `<link rel=preload crossorigin>`) still hits the cache offline.
32
+
33
+ ### Patch Changes
34
+
35
+ - 0aa315d: Configure Subduction or Keyhive with exclusive `syncServers` configuration. `syncServers.keyhive` replaces the `keyhive` and `keyhiveSyncServer` site options and the runtime `setup({ keyhive })` option. Selecting a named ARK relay or providing a custom relay identity and URL enables Keyhive, and configured server URLs now control worker connections as well as connection hints.
36
+ - Updated dependencies [bd63259]
37
+ - Updated dependencies [bd63259]
38
+ - @inkandswitch/patchwork-elements@4.0.2
39
+ - @inkandswitch/patchwork-filesystem@0.2.3
40
+
3
41
  ## 0.4.4
4
42
 
5
43
  ### Patch Changes
@@ -23,19 +23,9 @@ import { HANDOFF_CHANNEL, SYNCSTATE_CHANNEL, } from "./types.js";
23
23
  const siteName = typeof __SITE_NAME__ !== "undefined"
24
24
  ? __SITE_NAME__
25
25
  : "patchwork.inkandswitch.com";
26
- const useKeyhive = typeof __KEYHIVE__ !== "undefined" && __KEYHIVE__;
27
- const useKeyhiveSyncServer = typeof __KEYHIVE_SYNC_SERVER__ !== "undefined" && __KEYHIVE_SYNC_SERVER__;
28
- const SUBDUCTION_SYNC_URL = useKeyhiveSyncServer
29
- ? "wss://keyhive.sync.automerge.org"
30
- : "wss://subduction.sync.inkandswitch.com";
31
- if (useKeyhiveSyncServer) {
32
- const g = globalThis;
33
- g.process ??= {};
34
- g.process.env = {
35
- ...(g.process.env ?? {}),
36
- KEYHIVE_SERVER_IDENTITY: "keyhive-sync",
37
- };
38
- }
26
+ const syncServer = typeof __SYNC_SERVER__ !== "undefined"
27
+ ? __SYNC_SERVER__
28
+ : { url: "wss://subduction.sync.inkandswitch.com" };
39
29
  const RESOLVE_TIMEOUT_MS = 30_000;
40
30
  const CACHEABLE_STATUSES = [200, 203, 204];
41
31
  // A fresh instance means a new repo peerId and cold in-memory state, so a tab
@@ -153,7 +143,7 @@ const subductionPortProvider = makePortProvider();
153
143
  let subductionEndpoints = null;
154
144
  function getSubductionEndpoints() {
155
145
  return (subductionEndpoints ??= [
156
- new WorkerWebSocketEndpoint(SUBDUCTION_SYNC_URL, {
146
+ new WorkerWebSocketEndpoint(syncServer.url, {
157
147
  worker: subductionPortProvider.source,
158
148
  }),
159
149
  ]);
@@ -179,8 +169,8 @@ async function setUpRepoHive() {
179
169
  initSubductionSync(new Uint8Array(subductionWasm));
180
170
  await initializeWasm(new Uint8Array(automergeWasm));
181
171
  log("wasm initialized");
182
- const built = useKeyhive
183
- ? await buildKeyhiveRepo()
172
+ const built = syncServer.keyhive
173
+ ? await buildKeyhiveRepo(syncServer.keyhive)
184
174
  : await buildPlainRepo();
185
175
  self.repo = built.repo;
186
176
  if (built.hive)
@@ -216,7 +206,7 @@ async function buildPlainRepo() {
216
206
  console.log("[patchwork] shared-worker subduction identity:", identity);
217
207
  return { repo, identity };
218
208
  }
219
- async function buildKeyhiveRepo() {
209
+ async function buildKeyhiveRepo(keyhiveSyncServer) {
220
210
  initKeyhiveWasm();
221
211
  const { hive, repo } = await initializeAutomergeRepoKeyhiveRustWithRepo({
222
212
  createRepo: (config) => new Repo(config),
@@ -226,7 +216,7 @@ async function buildKeyhiveRepo() {
226
216
  cachingMode: "periodic",
227
217
  // ARK selects the relay via `syncServer`, which pairs the contact card with
228
218
  // the matching peer id. Omitting it defaults to "subduction".
229
- ...(useKeyhiveSyncServer ? { syncServer: "keyhive" } : {}),
219
+ syncServer: keyhiveSyncServer,
230
220
  repo: {
231
221
  storage: new IndexedDBWorkerStorageAdapter(),
232
222
  subductionWebsocketEndpoints: getSubductionEndpoints(),
@@ -0,0 +1,5 @@
1
+ /**
2
+ * these dependencies will be built into the outdir, and injected into the importmap
3
+ */
4
+ declare const externals: string[];
5
+ export default externals;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * these dependencies will be built into the outdir, and injected into the importmap
3
+ */
4
+ const externals = [
5
+ "@automerge/automerge",
6
+ "@automerge/automerge/slim",
7
+ "@automerge/automerge-repo",
8
+ "@automerge/automerge-repo/slim",
9
+ // Port-donation plumbing for WorkerWebSocketEndpoint: tabs spawn the shared
10
+ // proxy entry and donate its port to the automerge worker (Chrome can't
11
+ // spawn workers from inside a SharedWorker). See setup.ts/automerge-worker.ts.
12
+ "@automerge/automerge-repo/worker-port",
13
+ "@automerge/automerge-repo/subduction-websocket-worker-shared",
14
+ "@automerge/automerge-repo-network-messagechannel",
15
+ "@automerge/automerge-repo-network-websocket",
16
+ "@automerge/automerge-repo-storage-indexeddb",
17
+ "@automerge/automerge-repo-keyhive",
18
+ "@automerge/automerge-subduction",
19
+ "@automerge/automerge-subduction/slim",
20
+ "@keyhive/keyhive",
21
+ "@keyhive/keyhive/slim",
22
+ "@inkandswitch/patchwork-bootloader",
23
+ "@inkandswitch/patchwork-elements",
24
+ "@inkandswitch/patchwork-filesystem",
25
+ "@inkandswitch/patchwork-plugins",
26
+ "@inkandswitch/patchwork-providers",
27
+ "@inkandswitch/patchwork",
28
+ // sad
29
+ "@codemirror/state",
30
+ "@codemirror/view",
31
+ "@codemirror/language",
32
+ "@codemirror/commands",
33
+ // rip
34
+ "solid-js",
35
+ "solid-js/html",
36
+ "solid-js/web",
37
+ "solid-js/h",
38
+ "solid-js/store",
39
+ "solid-js/jsx-runtime",
40
+ ];
41
+ export default externals;
@@ -1,5 +1,16 @@
1
+ export { default } from "./externals-list.js";
1
2
  /**
2
- * these dependencies will be built into the outdir, and injected into the importmap
3
+ * Resolve one of this package's own dependencies from its node_modules
4
+ * rather than the site's, so a vite plugin bundling it never needs the site
5
+ * to install it or agree on a version. Exported so `@inkandswitch/patchwork`'s
6
+ * vite plugin (which lives in a different package) can reuse this for the
7
+ * externals bootloader actually owns, while resolving itself separately.
8
+ *
9
+ * This goes through rollup's resolver rather than import.meta.resolve or
10
+ * require.resolve because those apply node's conditions: subduction (and
11
+ * others) would hand us `dist/esm/node.js`, which imports node:path and blows
12
+ * up at bundle time. rollup applies the browser conditions vite configured.
3
13
  */
4
- declare const externals: string[];
5
- export default externals;
14
+ export declare function resolveExternal(this: import("rollup").PluginContext, name: string): Promise<string>;
15
+ /** Emits automerge/keyhive/subduction's wasm binaries as build assets, so the service worker can fetch them. */
16
+ export declare function emitWasmAssets(this: import("rollup").PluginContext): void;
package/dist/externals.js CHANGED
@@ -1,40 +1,52 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import { fileURLToPath } from "node:url";
4
+ const require = createRequire(import.meta.url);
5
+ export { default } from "./externals-list.js";
1
6
  /**
2
- * these dependencies will be built into the outdir, and injected into the importmap
7
+ * pretend the import came from inside this package, so node_modules resolution
8
+ * walks up from *our* directory and finds our copy of each external. that's why
9
+ * a consuming site never has to install them or agree with us about versions.
3
10
  */
4
- const externals = [
5
- "@automerge/automerge",
6
- "@automerge/automerge/slim",
7
- "@automerge/automerge-repo",
8
- "@automerge/automerge-repo/slim",
9
- // Port-donation plumbing for WorkerWebSocketEndpoint: tabs spawn the shared
10
- // proxy entry and donate its port to the automerge worker (Chrome can't
11
- // spawn workers from inside a SharedWorker). See setup.ts/automerge-worker.ts.
12
- "@automerge/automerge-repo/worker-port",
13
- "@automerge/automerge-repo/subduction-websocket-worker-shared",
14
- "@automerge/automerge-repo-network-messagechannel",
15
- "@automerge/automerge-repo-network-websocket",
16
- "@automerge/automerge-repo-storage-indexeddb",
17
- "@automerge/automerge-repo-keyhive",
18
- "@automerge/automerge-subduction",
19
- "@automerge/automerge-subduction/slim",
20
- "@keyhive/keyhive",
21
- "@keyhive/keyhive/slim",
22
- "@inkandswitch/patchwork-bootloader",
23
- "@inkandswitch/patchwork-elements",
24
- "@inkandswitch/patchwork-filesystem",
25
- "@inkandswitch/patchwork-plugins",
26
- "@inkandswitch/patchwork-providers",
27
- // sad
28
- "@codemirror/state",
29
- "@codemirror/view",
30
- "@codemirror/language",
31
- "@codemirror/commands",
32
- // rip
33
- "solid-js",
34
- "solid-js/html",
35
- "solid-js/web",
36
- "solid-js/h",
37
- "solid-js/store",
38
- "solid-js/jsx-runtime",
39
- ];
40
- export default externals;
11
+ const self = fileURLToPath(import.meta.url);
12
+ /**
13
+ * Resolve one of this package's own dependencies from its node_modules
14
+ * rather than the site's, so a vite plugin bundling it never needs the site
15
+ * to install it or agree on a version. Exported so `@inkandswitch/patchwork`'s
16
+ * vite plugin (which lives in a different package) can reuse this for the
17
+ * externals bootloader actually owns, while resolving itself separately.
18
+ *
19
+ * This goes through rollup's resolver rather than import.meta.resolve or
20
+ * require.resolve because those apply node's conditions: subduction (and
21
+ * others) would hand us `dist/esm/node.js`, which imports node:path and blows
22
+ * up at bundle time. rollup applies the browser conditions vite configured.
23
+ */
24
+ export async function resolveExternal(name) {
25
+ const resolved = await this.resolve(name, self, { skipSelf: true });
26
+ if (!resolved) {
27
+ throw new Error(`@inkandswitch/patchwork-bootloader: couldn't resolve the external ` +
28
+ `"${name}". it should be one of the bootloader's own dependencies.`);
29
+ }
30
+ return resolved.id;
31
+ }
32
+ /** Emits automerge/keyhive/subduction's wasm binaries as build assets, so the service worker can fetch them. */
33
+ export function emitWasmAssets() {
34
+ const automergeWasmPath = require.resolve("@automerge/automerge/automerge.wasm");
35
+ this.emitFile({
36
+ type: "asset",
37
+ fileName: "automerge.wasm",
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),
45
+ });
46
+ const subdWasmPath = require.resolve("@automerge/automerge-subduction/wasm");
47
+ this.emitFile({
48
+ type: "asset",
49
+ fileName: "subduction.wasm",
50
+ source: readFileSync(subdWasmPath),
51
+ });
52
+ }
@@ -0,0 +1,30 @@
1
+ html,
2
+ body {
3
+ overscroll-behavior: none;
4
+ font-family: system-ui, sans-serif;
5
+ font-size: 16px;
6
+ height: 100%;
7
+ height: 100vh;
8
+ height: 100dvh;
9
+
10
+ @media all and (display-mode: standalone) {
11
+ height: 100lvh;
12
+ }
13
+ }
14
+
15
+ patchwork-view {
16
+ display: block;
17
+ height: 100%;
18
+ width: 100%;
19
+ contain: layout;
20
+ }
21
+
22
+ @media (prefers-reduced-motion: reduce) {
23
+ *,
24
+ *:before,
25
+ *:after {
26
+ animation-duration: 0.001s !important;
27
+ transition-duration: 0.001s !important;
28
+ animation-iteration-count: 1 !important;
29
+ }
30
+ }
@@ -255,7 +255,11 @@ async function servePassthrough(fetchEvent, cache, cached) {
255
255
  }
256
256
  async function respond(fetchEvent, handoffURL) {
257
257
  const cache = await caches.open(cachename);
258
- const cached = await cache.match(fetchEvent.request);
258
+ // A cors request (e.g. the wasm `<link rel=preload crossorigin>`) can miss
259
+ // an entry that a url-keyed lookup finds, so fall back to the bare url —
260
+ // offline boot depends on this hitting.
261
+ const cached = (await cache.match(fetchEvent.request)) ??
262
+ (await cache.match(fetchEvent.request.url));
259
263
  try {
260
264
  return handoffURL
261
265
  ? await serveHandoff(fetchEvent, cache, handoffURL, cached)
@@ -1,6 +1,6 @@
1
1
  /** localStorage key: optional override for the classic sync WebSocket URL. */
2
2
  export declare const CLASSIC_SYNC_SERVER_KEY = "patchworkClassicSyncServer";
3
- export declare const DEFAULT_CLASSIC_SYNC_SERVER = "wss://sync3.automerge.org";
3
+ export declare const DEFAULT_CLASSIC_SYNC_SERVER: string;
4
4
  export declare function readClassicSyncServer(storage?: Pick<Storage, "getItem">): string;
5
5
  export type ConnectClassicSyncMessage = {
6
6
  type: "connect-classic-sync";
@@ -1,6 +1,8 @@
1
1
  /** localStorage key: optional override for the classic sync WebSocket URL. */
2
2
  export const CLASSIC_SYNC_SERVER_KEY = "patchworkClassicSyncServer";
3
- export const DEFAULT_CLASSIC_SYNC_SERVER = "wss://sync3.automerge.org";
3
+ export const DEFAULT_CLASSIC_SYNC_SERVER = typeof __CLASSIC_SYNC_SERVER__ !== "undefined"
4
+ ? __CLASSIC_SYNC_SERVER__
5
+ : "wss://sync3.automerge.org";
4
6
  export function readClassicSyncServer(storage = globalThis.localStorage) {
5
7
  const override = storage.getItem(CLASSIC_SYNC_SERVER_KEY)?.trim();
6
8
  if (!override)
package/package.json CHANGED
@@ -1,6 +1,11 @@
1
1
  {
2
2
  "name": "@inkandswitch/patchwork-bootloader",
3
- "version": "0.4.4",
3
+ "repository": {
4
+ "type": "git",
5
+ "url": "git+https://github.com/inkandswitch/patchwork-system.git",
6
+ "directory": "core/bootloader"
7
+ },
8
+ "version": "0.5.2",
4
9
  "author": "chee",
5
10
  "type": "module",
6
11
  "license": "MIT",
@@ -17,9 +22,9 @@
17
22
  "import": "./dist/externals.js",
18
23
  "types": "./dist/externals.d.ts"
19
24
  },
20
- "./vite": {
21
- "import": "./dist/vite/patchwork-plugin.js",
22
- "types": "./dist/vite/patchwork-plugin.d.ts"
25
+ "./externals-list": {
26
+ "import": "./dist/externals-list.js",
27
+ "types": "./dist/externals-list.d.ts"
23
28
  },
24
29
  "./service-worker": {
25
30
  "import": "./dist/service-worker.js",
@@ -29,18 +34,19 @@
29
34
  "import": "./dist/automerge-worker.js",
30
35
  "types": "./dist/automerge-worker.d.ts"
31
36
  },
37
+ "./module-loader": {
38
+ "import": "./dist/module-loader.js",
39
+ "types": "./dist/module-loader.d.ts"
40
+ },
32
41
  "./module-loader-worker": {
33
42
  "import": "./dist/module-loader-worker.js",
34
43
  "types": "./dist/module-loader-worker.d.ts"
35
44
  },
36
- "./site": {
37
- "import": "./dist/site.js",
38
- "types": "./dist/site.d.ts"
39
- },
40
45
  "./types": {
41
46
  "import": "./dist/types.js",
42
47
  "types": "./dist/types.d.ts"
43
- }
48
+ },
49
+ "./global.css": "./dist/global.css"
44
50
  },
45
51
  "dependencies": {
46
52
  "@automerge/automerge": "3.3.2",
@@ -62,10 +68,10 @@
62
68
  "service-worker-types": "npm:@types/serviceworker@^0.0.153",
63
69
  "solid-js": "^1.9.13",
64
70
  "tinyargs": "^0.1.4",
65
- "@inkandswitch/patchwork-elements": "^4.0.1",
66
- "@inkandswitch/patchwork-filesystem": "^0.2.2",
67
- "@inkandswitch/patchwork-plugins": "^1.0.1",
68
- "@inkandswitch/patchwork-providers": "^0.4.2"
71
+ "@inkandswitch/patchwork-elements": "^4.0.4",
72
+ "@inkandswitch/patchwork-plugins": "^1.0.3",
73
+ "@inkandswitch/patchwork-providers": "^0.4.2",
74
+ "@inkandswitch/patchwork-filesystem": "^0.2.5"
69
75
  },
70
76
  "peerDependencies": {
71
77
  "@automerge/automerge": "3.3.2",
@@ -88,7 +94,7 @@
88
94
  }
89
95
  },
90
96
  "scripts": {
91
- "build": "tsc",
97
+ "build": "tsc && cp src/global.css dist/global.css",
92
98
  "dev": "tsc -w --preserveWatchOutput"
93
99
  }
94
100
  }
@@ -34,6 +34,7 @@ import {
34
34
  initializeAutomergeRepoKeyhiveRustWithRepo,
35
35
  initKeyhiveWasm,
36
36
  type AutomergeRepoKeyhiveRust,
37
+ type SyncServerSelection,
37
38
  } from "@automerge/automerge-repo-keyhive";
38
39
 
39
40
  import { DEFAULT_CLASSIC_SYNC_SERVER } from "./sync-config.js";
@@ -52,29 +53,19 @@ import {
52
53
  } from "./types.js";
53
54
 
54
55
  declare const __SITE_NAME__: string;
55
- declare const __KEYHIVE__: boolean;
56
- declare const __KEYHIVE_SYNC_SERVER__: boolean;
56
+ declare const __SYNC_SERVER__: {
57
+ url: string;
58
+ keyhive?: SyncServerSelection;
59
+ };
57
60
 
58
61
  const siteName =
59
62
  typeof __SITE_NAME__ !== "undefined"
60
63
  ? __SITE_NAME__
61
64
  : "patchwork.inkandswitch.com";
62
- const useKeyhive = typeof __KEYHIVE__ !== "undefined" && __KEYHIVE__;
63
- const useKeyhiveSyncServer =
64
- typeof __KEYHIVE_SYNC_SERVER__ !== "undefined" && __KEYHIVE_SYNC_SERVER__;
65
-
66
- const SUBDUCTION_SYNC_URL = useKeyhiveSyncServer
67
- ? "wss://keyhive.sync.automerge.org"
68
- : "wss://subduction.sync.inkandswitch.com";
69
-
70
- if (useKeyhiveSyncServer) {
71
- const g = globalThis as any;
72
- g.process ??= {};
73
- g.process.env = {
74
- ...(g.process.env ?? {}),
75
- KEYHIVE_SERVER_IDENTITY: "keyhive-sync",
76
- };
77
- }
65
+ const syncServer =
66
+ typeof __SYNC_SERVER__ !== "undefined"
67
+ ? __SYNC_SERVER__
68
+ : { url: "wss://subduction.sync.inkandswitch.com" };
78
69
 
79
70
  const RESOLVE_TIMEOUT_MS = 30_000;
80
71
 
@@ -213,7 +204,7 @@ const subductionPortProvider = makePortProvider();
213
204
  let subductionEndpoints: WorkerWebSocketEndpoint[] | null = null;
214
205
  function getSubductionEndpoints(): WorkerWebSocketEndpoint[] {
215
206
  return (subductionEndpoints ??= [
216
- new WorkerWebSocketEndpoint(SUBDUCTION_SYNC_URL, {
207
+ new WorkerWebSocketEndpoint(syncServer.url, {
217
208
  worker: subductionPortProvider.source,
218
209
  }),
219
210
  ]);
@@ -246,8 +237,8 @@ async function setUpRepoHive(): Promise<RepoHive> {
246
237
  await initializeWasm(new Uint8Array(automergeWasm));
247
238
  log("wasm initialized");
248
239
 
249
- const built: BuiltRepo = useKeyhive
250
- ? await buildKeyhiveRepo()
240
+ const built: BuiltRepo = syncServer.keyhive
241
+ ? await buildKeyhiveRepo(syncServer.keyhive)
251
242
  : await buildPlainRepo();
252
243
 
253
244
  (self as any).repo = built.repo;
@@ -291,7 +282,9 @@ async function buildPlainRepo(): Promise<BuiltRepo> {
291
282
  return { repo, identity };
292
283
  }
293
284
 
294
- async function buildKeyhiveRepo(): Promise<BuiltRepo> {
285
+ async function buildKeyhiveRepo(
286
+ keyhiveSyncServer: SyncServerSelection
287
+ ): Promise<BuiltRepo> {
295
288
  initKeyhiveWasm();
296
289
  const { hive, repo } = await initializeAutomergeRepoKeyhiveRustWithRepo({
297
290
  createRepo: (config) => new Repo(config),
@@ -301,7 +294,7 @@ async function buildKeyhiveRepo(): Promise<BuiltRepo> {
301
294
  cachingMode: "periodic",
302
295
  // ARK selects the relay via `syncServer`, which pairs the contact card with
303
296
  // the matching peer id. Omitting it defaults to "subduction".
304
- ...(useKeyhiveSyncServer ? { syncServer: "keyhive" as const } : {}),
297
+ syncServer: keyhiveSyncServer,
305
298
  repo: {
306
299
  storage: new IndexedDBWorkerStorageAdapter(),
307
300
  subductionWebsocketEndpoints: getSubductionEndpoints(),
@@ -0,0 +1,43 @@
1
+ /**
2
+ * these dependencies will be built into the outdir, and injected into the importmap
3
+ */
4
+ const externals = [
5
+ "@automerge/automerge",
6
+ "@automerge/automerge/slim",
7
+ "@automerge/automerge-repo",
8
+ "@automerge/automerge-repo/slim",
9
+ // Port-donation plumbing for WorkerWebSocketEndpoint: tabs spawn the shared
10
+ // proxy entry and donate its port to the automerge worker (Chrome can't
11
+ // spawn workers from inside a SharedWorker). See setup.ts/automerge-worker.ts.
12
+ "@automerge/automerge-repo/worker-port",
13
+ "@automerge/automerge-repo/subduction-websocket-worker-shared",
14
+ "@automerge/automerge-repo-network-messagechannel",
15
+ "@automerge/automerge-repo-network-websocket",
16
+ "@automerge/automerge-repo-storage-indexeddb",
17
+ "@automerge/automerge-repo-keyhive",
18
+ "@automerge/automerge-subduction",
19
+ "@automerge/automerge-subduction/slim",
20
+ "@keyhive/keyhive",
21
+ "@keyhive/keyhive/slim",
22
+ "@inkandswitch/patchwork-bootloader",
23
+ "@inkandswitch/patchwork-elements",
24
+ "@inkandswitch/patchwork-filesystem",
25
+ "@inkandswitch/patchwork-plugins",
26
+ "@inkandswitch/patchwork-providers",
27
+ "@inkandswitch/patchwork",
28
+
29
+ // sad
30
+ "@codemirror/state",
31
+ "@codemirror/view",
32
+ "@codemirror/language",
33
+ "@codemirror/commands",
34
+
35
+ // rip
36
+ "solid-js",
37
+ "solid-js/html",
38
+ "solid-js/web",
39
+ "solid-js/h",
40
+ "solid-js/store",
41
+ "solid-js/jsx-runtime",
42
+ ];
43
+ export default externals;
package/src/externals.ts CHANGED
@@ -1,42 +1,68 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ const require = createRequire(import.meta.url);
6
+
7
+ export { default } from "./externals-list.js";
8
+
1
9
  /**
2
- * these dependencies will be built into the outdir, and injected into the importmap
10
+ * pretend the import came from inside this package, so node_modules resolution
11
+ * walks up from *our* directory and finds our copy of each external. that's why
12
+ * a consuming site never has to install them or agree with us about versions.
3
13
  */
4
- const externals = [
5
- "@automerge/automerge",
6
- "@automerge/automerge/slim",
7
- "@automerge/automerge-repo",
8
- "@automerge/automerge-repo/slim",
9
- // Port-donation plumbing for WorkerWebSocketEndpoint: tabs spawn the shared
10
- // proxy entry and donate its port to the automerge worker (Chrome can't
11
- // spawn workers from inside a SharedWorker). See setup.ts/automerge-worker.ts.
12
- "@automerge/automerge-repo/worker-port",
13
- "@automerge/automerge-repo/subduction-websocket-worker-shared",
14
- "@automerge/automerge-repo-network-messagechannel",
15
- "@automerge/automerge-repo-network-websocket",
16
- "@automerge/automerge-repo-storage-indexeddb",
17
- "@automerge/automerge-repo-keyhive",
18
- "@automerge/automerge-subduction",
19
- "@automerge/automerge-subduction/slim",
20
- "@keyhive/keyhive",
21
- "@keyhive/keyhive/slim",
22
- "@inkandswitch/patchwork-bootloader",
23
- "@inkandswitch/patchwork-elements",
24
- "@inkandswitch/patchwork-filesystem",
25
- "@inkandswitch/patchwork-plugins",
26
- "@inkandswitch/patchwork-providers",
14
+ const self = fileURLToPath(import.meta.url);
15
+
16
+ /**
17
+ * Resolve one of this package's own dependencies from its node_modules
18
+ * rather than the site's, so a vite plugin bundling it never needs the site
19
+ * to install it or agree on a version. Exported so `@inkandswitch/patchwork`'s
20
+ * vite plugin (which lives in a different package) can reuse this for the
21
+ * externals bootloader actually owns, while resolving itself separately.
22
+ *
23
+ * This goes through rollup's resolver rather than import.meta.resolve or
24
+ * require.resolve because those apply node's conditions: subduction (and
25
+ * others) would hand us `dist/esm/node.js`, which imports node:path and blows
26
+ * up at bundle time. rollup applies the browser conditions vite configured.
27
+ */
28
+ export async function resolveExternal(
29
+ this: import("rollup").PluginContext,
30
+ name: string
31
+ ): Promise<string> {
32
+ const resolved = await this.resolve(name, self, { skipSelf: true });
33
+ if (!resolved) {
34
+ throw new Error(
35
+ `@inkandswitch/patchwork-bootloader: couldn't resolve the external ` +
36
+ `"${name}". it should be one of the bootloader's own dependencies.`
37
+ );
38
+ }
39
+ return resolved.id;
40
+ }
41
+
42
+ /** Emits automerge/keyhive/subduction's wasm binaries as build assets, so the service worker can fetch them. */
43
+ export function emitWasmAssets(this: import("rollup").PluginContext): void {
44
+ const automergeWasmPath = require.resolve(
45
+ "@automerge/automerge/automerge.wasm"
46
+ );
47
+ this.emitFile({
48
+ type: "asset",
49
+ fileName: "automerge.wasm",
50
+ source: readFileSync(automergeWasmPath),
51
+ });
27
52
 
28
- // sad
29
- "@codemirror/state",
30
- "@codemirror/view",
31
- "@codemirror/language",
32
- "@codemirror/commands",
53
+ const keyhiveWasmPath = require.resolve(
54
+ "@keyhive/keyhive/keyhive_wasm.wasm"
55
+ );
56
+ this.emitFile({
57
+ type: "asset",
58
+ fileName: "keyhive_wasm.wasm",
59
+ source: readFileSync(keyhiveWasmPath),
60
+ });
33
61
 
34
- // rip
35
- "solid-js",
36
- "solid-js/html",
37
- "solid-js/web",
38
- "solid-js/h",
39
- "solid-js/store",
40
- "solid-js/jsx-runtime",
41
- ];
42
- export default externals;
62
+ const subdWasmPath = require.resolve("@automerge/automerge-subduction/wasm");
63
+ this.emitFile({
64
+ type: "asset",
65
+ fileName: "subduction.wasm",
66
+ source: readFileSync(subdWasmPath),
67
+ });
68
+ }