@inkandswitch/patchwork 0.7.3 → 0.7.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/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # @inkandswitch/patchwork
2
2
 
3
+ ## 0.7.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 7339066: The dev importmap now names each builtin's pre-bundled dep URL
8
+ (`/node_modules/.vite/deps/…?v=…`) instead of `/@id/<dep>`. Both URLs resolve to
9
+ the same file, but a module fetched under two URLs is evaluated twice — the site
10
+ imported solid through the pre-bundled URL and tool code imported it through the
11
+ importmap, so tools ran against a second solid with its own owner stack and
12
+ logged "computations created outside a `createRoot`" for every effect they
13
+ created. Builtins that aren't pre-bundled still fall back to `/@id/<dep>`.
14
+ - ebca53b: Move the automerge-repo subduction fork to 2.6.0-subduction.48, `@automerge/automerge-repo-keyhive` to 0.5.0-alpha.7, and `@keyhive/keyhive` to 0.1.0-alpha.8. These three are bumped together because the keyhive package pins its automerge-repo version exactly.
15
+
16
+ keyhive 0.5 renames the two hive flavours. The network-adapter hive is now `LegacyAutomergeRepoKeyhive`, built by `initializeLegacyAutomergeRepoKeyhive`; the subduction hive keeps the name `AutomergeRepoKeyhive` and is built by `initializeAutomergeRepoKeyhive`. Both extend `AutomergeRepoKeyhiveBase`, which is what Patchwork's `hive` fields are typed as, so a tool that only reads membership works against either.
17
+
18
+ `createKeyhiveNetworkAdapter` takes an options object instead of positional arguments, and `onlyShareWithHardcodedServerPeerId` is now `onlyShareWithSyncServer`.
19
+
20
+ - Updated dependencies [ebca53b]
21
+ - Updated dependencies [882eacd]
22
+ - @inkandswitch/patchwork-bootloader@0.6.3
23
+ - @inkandswitch/patchwork-elements@6.0.2
24
+ - @inkandswitch/patchwork-filesystem@0.2.8
25
+ - @inkandswitch/patchwork-plugins@1.2.3
26
+ - @inkandswitch/patchwork-providers@0.5.2
27
+
3
28
  ## 0.7.3
4
29
 
5
30
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -18,7 +18,7 @@
18
18
  * and the automerge-worker handoff and nothing else.
19
19
  */
20
20
  import { Repo } from "@automerge/vanillajs/slim";
21
- import type { AutomergeRepoKeyhive } from "@automerge/automerge-repo-keyhive";
21
+ import type { AutomergeRepoKeyhiveBase as AutomergeRepoKeyhive } from "@automerge/automerge-repo-keyhive";
22
22
  import type { Patchwork, PatchworkOptions } from "./types.js";
23
23
  declare global {
24
24
  interface Window {
package/dist/index.js CHANGED
@@ -94,7 +94,11 @@ async function doSetup(options) {
94
94
  // Mirror the boot wiring: a keyhive repo talks to the worker through a
95
95
  // keyhive adapter wrapped around the message channel.
96
96
  const registered = bootHive
97
- ? bootHive.createKeyhiveNetworkAdapter(fresh, false, false, 2000)
97
+ ? bootHive.createKeyhiveNetworkAdapter(fresh, {
98
+ onlyShareWithSyncServer: false,
99
+ periodicallyRequestSync: false,
100
+ syncRequestInterval: 2000,
101
+ })
98
102
  : fresh;
99
103
  repo.networkSubsystem.addNetworkAdapter(registered);
100
104
  removeAdapterFor(repo, workerAdapter, registered);
package/dist/repo.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { MessageChannelNetworkAdapter, Repo } from "@automerge/vanillajs/slim";
2
- import { type AutomergeRepoKeyhive } from "@automerge/automerge-repo-keyhive";
2
+ import { type AutomergeRepoKeyhiveBase } from "@automerge/automerge-repo-keyhive";
3
3
  import setupServiceWorker from "@inkandswitch/patchwork-bootloader";
4
4
  import type { SignerIdentity } from "./types.js";
5
5
  export declare function initWasm(): Promise<void>;
6
6
  export declare function createRepo(workerAdapter: MessageChannelNetworkAdapter): Promise<{
7
7
  repo: Repo;
8
- hive?: AutomergeRepoKeyhive;
8
+ hive?: AutomergeRepoKeyhiveBase;
9
9
  signerIdentity?: SignerIdentity;
10
10
  }>;
11
11
  /**
package/dist/repo.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { initializeWasm, Repo, } from "@automerge/vanillajs/slim";
2
2
  import { IndexedDBWorkerStorageAdapter } from "@automerge/automerge-repo-storage-indexeddb/IndexedDBWorkerStorageAdapter";
3
- import { initKeyhiveWasm, initializeAutomergeRepoKeyhiveWithRepo, } from "@automerge/automerge-repo-keyhive";
3
+ import { initKeyhiveWasm, initializeLegacyAutomergeRepoKeyhive, } from "@automerge/automerge-repo-keyhive";
4
4
  // eslint-disable-next-line
5
5
  // @ts-ignore — initSync is a wasm-bindgen runtime helper not in the .d.ts
6
6
  import { initSync as initSubductionSync } from "@automerge/automerge-subduction/slim";
@@ -32,14 +32,14 @@ export async function createRepo(workerAdapter) {
32
32
  if (syncServer.keyhive) {
33
33
  log("setting up keyhive");
34
34
  initKeyhiveWasm();
35
- const { hive, repo } = await initializeAutomergeRepoKeyhiveWithRepo({
35
+ const { hive, repo } = await initializeLegacyAutomergeRepoKeyhive({
36
36
  createRepo: (repoConfig) => new Repo(repoConfig),
37
37
  storage: new IndexedDBWorkerStorageAdapter(keyhiveStorageName),
38
38
  peerIdSuffix: storagePrefix + Math.random().toString(36).slice(2),
39
39
  networkAdapter: workerAdapter,
40
40
  automaticArchiveIngestion: true,
41
41
  cachingMode: "periodic",
42
- onlyShareWithHardcodedServerPeerId: false,
42
+ onlyShareWithSyncServer: false,
43
43
  // ARK selects the relay via `syncServer`, defaulting to "subduction".
44
44
  syncServer: syncServer.keyhive,
45
45
  repo: {
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { AutomergeUrl, DocHandle, Repo } from "@automerge/vanillajs/slim";
2
- import type { AutomergeRepoKeyhive } from "@automerge/automerge-repo-keyhive";
2
+ import type { AutomergeRepoKeyhiveBase as AutomergeRepoKeyhive } from "@automerge/automerge-repo-keyhive";
3
3
  import type { ModuleWatcher, HasPatchworkMetadata } from "@inkandswitch/patchwork-filesystem";
4
4
  import type { AccountCreator, AccountDoc } from "@inkandswitch/patchwork-plugins";
5
5
  import type { ServiceWorkerRepoChannelListener, SyncStateDocMessage } from "@inkandswitch/patchwork-bootloader/types";
@@ -1,4 +1,5 @@
1
1
  import { fileURLToPath } from "node:url";
2
+ import { relative } from "node:path";
2
3
  /**
3
4
  * bootloader owns resolving/emitting its own dependencies (it's the one that
4
5
  * actually has automerge/keyhive/codemirror/solid/the other patchwork-*
@@ -87,11 +88,22 @@ export function importmap(options) {
87
88
  },
88
89
  transformIndexHtml: {
89
90
  order: "pre",
90
- handler(html, context) {
91
+ async handler(html, context) {
91
92
  const activeImportmap = structuredClone(importmap);
92
93
  if (context.server) {
94
+ // The importmap has to name the same URL the site's own imports get
95
+ // rewritten to, which is the pre-bundled dep. `/@id/<dep>` resolves
96
+ // to the same file but is a second URL, and a module fetched under
97
+ // two URLs is evaluated twice — two solids, two automerges.
98
+ const optimizer = context.server.environments.client.depsOptimizer;
99
+ await optimizer?.init();
100
+ const root = context.server.config.root;
93
101
  for (const id of Object.keys(builtins)) {
94
- activeImportmap.imports[id] = `/@id/${devDependencyId(id)}`;
102
+ const dependency = devDependencyId(id);
103
+ const optimized = optimizer?.metadata.optimized[dependency];
104
+ activeImportmap.imports[id] = optimized
105
+ ? `/${relative(root, optimized.file)}?v=${optimized.browserHash}`
106
+ : `/@id/${dependency}`;
95
107
  }
96
108
  }
97
109
  return {
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "url": "git+https://github.com/inkandswitch/patchwork-system.git",
6
6
  "directory": "core/patchwork"
7
7
  },
8
- "version": "0.7.3",
8
+ "version": "0.7.4",
9
9
  "author": "Ink & Switch",
10
10
  "type": "module",
11
11
  "license": "MIT",
@@ -73,21 +73,21 @@
73
73
  },
74
74
  "dependencies": {
75
75
  "@automerge/automerge": "3.3.2",
76
- "@automerge/automerge-repo": "2.6.0-subduction.47",
77
- "@automerge/automerge-repo-keyhive": "0.3.0-alpha.sub.8b",
78
- "@automerge/automerge-repo-storage-indexeddb": "2.6.0-subduction.47",
76
+ "@automerge/automerge-repo": "2.6.0-subduction.48",
77
+ "@automerge/automerge-repo-keyhive": "0.5.0-alpha.7",
78
+ "@automerge/automerge-repo-storage-indexeddb": "2.6.0-subduction.48",
79
79
  "@automerge/automerge-subduction": "0.16.1",
80
- "@automerge/vanillajs": "2.6.0-subduction.47",
80
+ "@automerge/vanillajs": "2.6.0-subduction.48",
81
81
  "@types/debug": "^4.1.13",
82
82
  "debug": "^4.4.3",
83
83
  "esbuild": "^0.23.1",
84
84
  "sharp": "^0.35.3",
85
85
  "vite-plugin-wasm": "^3.6.0",
86
- "@inkandswitch/patchwork-bootloader": "^0.6.2",
87
- "@inkandswitch/patchwork-elements": "^6.0.1",
88
- "@inkandswitch/patchwork-filesystem": "^0.2.6",
89
- "@inkandswitch/patchwork-plugins": "^1.2.1",
90
- "@inkandswitch/patchwork-providers": "^0.5.0"
86
+ "@inkandswitch/patchwork-bootloader": "^0.6.3",
87
+ "@inkandswitch/patchwork-elements": "^6.0.2",
88
+ "@inkandswitch/patchwork-filesystem": "^0.2.8",
89
+ "@inkandswitch/patchwork-plugins": "^1.2.3",
90
+ "@inkandswitch/patchwork-providers": "^0.5.2"
91
91
  },
92
92
  "devDependencies": {
93
93
  "rollup": "^4.61.1",
package/src/index.ts CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  } from "@automerge/vanillajs/slim";
26
26
  import * as Automerge from "@automerge/automerge/slim";
27
27
  import * as AutomergeRepo from "@automerge/automerge-repo/slim";
28
- import type { AutomergeRepoKeyhive } from "@automerge/automerge-repo-keyhive";
28
+ import type { AutomergeRepoKeyhiveBase as AutomergeRepoKeyhive } from "@automerge/automerge-repo-keyhive";
29
29
 
30
30
  import { ModuleWatcher } from "@inkandswitch/patchwork-filesystem";
31
31
  import { importAutomergePackageViaWorker } from "@inkandswitch/patchwork-bootloader/module-loader";
@@ -97,9 +97,7 @@ export function setup(options: PatchworkOptions = {}): Promise<Patchwork> {
97
97
  timer = setTimeout(
98
98
  () =>
99
99
  reject(
100
- new Error(
101
- `patchwork.setup: boot did not finish within ${timeout}ms`
102
- )
100
+ new Error(`patchwork.setup: boot did not finish within ${timeout}ms`)
103
101
  ),
104
102
  timeout
105
103
  );
@@ -161,7 +159,11 @@ async function doSetup(options: PatchworkOptions): Promise<Patchwork> {
161
159
  // Mirror the boot wiring: a keyhive repo talks to the worker through a
162
160
  // keyhive adapter wrapped around the message channel.
163
161
  const registered = bootHive
164
- ? bootHive.createKeyhiveNetworkAdapter(fresh, false, false, 2000)
162
+ ? bootHive.createKeyhiveNetworkAdapter(fresh, {
163
+ onlyShareWithSyncServer: false,
164
+ periodicallyRequestSync: false,
165
+ syncRequestInterval: 2000,
166
+ })
165
167
  : fresh;
166
168
  repo.networkSubsystem.addNetworkAdapter(registered as any);
167
169
  removeAdapterFor(repo, workerAdapter, registered);
@@ -264,9 +266,8 @@ async function doSetup(options: PatchworkOptions): Promise<Patchwork> {
264
266
  },
265
267
 
266
268
  async create<D>(type: string, init?: (doc: D) => void) {
267
- const datatype = await getRegistry<DatatypeDescription>(
268
- "patchwork:datatype"
269
- ).load(type);
269
+ const datatype =
270
+ await getRegistry<DatatypeDescription>("patchwork:datatype").load(type);
270
271
  if (!datatype) {
271
272
  throw new Error(
272
273
  `patchwork.create: no datatype registered for "${type}"`
package/src/repo.ts CHANGED
@@ -8,8 +8,8 @@ import { IndexedDBWorkerStorageAdapter } from "@automerge/automerge-repo-storage
8
8
  import * as AutomergeRepo from "@automerge/automerge-repo/slim";
9
9
  import {
10
10
  initKeyhiveWasm,
11
- initializeAutomergeRepoKeyhiveWithRepo,
12
- type AutomergeRepoKeyhive,
11
+ initializeLegacyAutomergeRepoKeyhive,
12
+ type AutomergeRepoKeyhiveBase,
13
13
  type SyncServerSelection,
14
14
  } from "@automerge/automerge-repo-keyhive";
15
15
  // eslint-disable-next-line
@@ -57,20 +57,20 @@ export async function createRepo(
57
57
  workerAdapter: MessageChannelNetworkAdapter
58
58
  ): Promise<{
59
59
  repo: Repo;
60
- hive?: AutomergeRepoKeyhive;
60
+ hive?: AutomergeRepoKeyhiveBase;
61
61
  signerIdentity?: SignerIdentity;
62
62
  }> {
63
63
  if (syncServer.keyhive) {
64
64
  log("setting up keyhive");
65
65
  initKeyhiveWasm();
66
- const { hive, repo } = await initializeAutomergeRepoKeyhiveWithRepo({
66
+ const { hive, repo } = await initializeLegacyAutomergeRepoKeyhive({
67
67
  createRepo: (repoConfig) => new Repo(repoConfig),
68
68
  storage: new IndexedDBWorkerStorageAdapter(keyhiveStorageName),
69
69
  peerIdSuffix: storagePrefix + Math.random().toString(36).slice(2),
70
70
  networkAdapter: workerAdapter,
71
71
  automaticArchiveIngestion: true,
72
72
  cachingMode: "periodic",
73
- onlyShareWithHardcodedServerPeerId: false,
73
+ onlyShareWithSyncServer: false,
74
74
  // ARK selects the relay via `syncServer`, defaulting to "subduction".
75
75
  syncServer: syncServer.keyhive,
76
76
  repo: {
package/src/types.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { AutomergeUrl, DocHandle, Repo } from "@automerge/vanillajs/slim";
2
- import type { AutomergeRepoKeyhive } from "@automerge/automerge-repo-keyhive";
2
+ import type { AutomergeRepoKeyhiveBase as AutomergeRepoKeyhive } from "@automerge/automerge-repo-keyhive";
3
3
  import type {
4
4
  ModuleWatcher,
5
5
  HasPatchworkMetadata,
@@ -4,6 +4,7 @@ import type {
4
4
  PatchworkVitePluginOptions,
5
5
  } from "./patchwork-plugin.js";
6
6
  import { fileURLToPath } from "node:url";
7
+ import { relative } from "node:path";
7
8
 
8
9
  /**
9
10
  * bootloader owns resolving/emitting its own dependencies (it's the one that
@@ -115,11 +116,22 @@ export function importmap(options?: PatchworkVitePluginOptions): Plugin {
115
116
  },
116
117
  transformIndexHtml: {
117
118
  order: "pre",
118
- handler(html, context) {
119
+ async handler(html, context) {
119
120
  const activeImportmap = structuredClone(importmap);
120
121
  if (context.server) {
122
+ // The importmap has to name the same URL the site's own imports get
123
+ // rewritten to, which is the pre-bundled dep. `/@id/<dep>` resolves
124
+ // to the same file but is a second URL, and a module fetched under
125
+ // two URLs is evaluated twice — two solids, two automerges.
126
+ const optimizer = context.server.environments.client.depsOptimizer;
127
+ await optimizer?.init();
128
+ const root = context.server.config.root;
121
129
  for (const id of Object.keys(builtins)) {
122
- activeImportmap.imports[id] = `/@id/${devDependencyId(id)}`;
130
+ const dependency = devDependencyId(id);
131
+ const optimized = optimizer?.metadata.optimized[dependency];
132
+ activeImportmap.imports[id] = optimized
133
+ ? `/${relative(root, optimized.file)}?v=${optimized.browserHash}`
134
+ : `/@id/${dependency}`;
123
135
  }
124
136
  }
125
137
  return {