@inkandswitch/patchwork 0.1.0 → 0.3.0

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,55 @@
1
1
  # @inkandswitch/patchwork
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 9e6e0e0: Add a `createAccount` setup option, create required account subdocuments before exposing a fresh account, and stop exposing the account handle as `window.accountDocHandle`.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [9e6e0e0]
12
+ - @inkandswitch/patchwork-plugins@1.1.0
13
+ - @inkandswitch/patchwork-elements@5.0.0
14
+ - @inkandswitch/patchwork-bootloader@0.5.3
15
+
16
+ ## 0.2.1
17
+
18
+ ### Patch Changes
19
+
20
+ - 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.
21
+ - Updated dependencies [f00dcb8]
22
+ - @inkandswitch/patchwork-bootloader@0.5.2
23
+ - @inkandswitch/patchwork-filesystem@0.2.5
24
+ - @inkandswitch/patchwork-elements@4.0.4
25
+ - @inkandswitch/patchwork-plugins@1.0.3
26
+
27
+ ## 0.2.0
28
+
29
+ ### Minor Changes
30
+
31
+ - 2fffabe: `setup()` now uses `packageListURL` as given instead of letting `localStorage.systemPackageListURL` silently replace it. A site that wants a dev override resolves it itself and passes the result in:
32
+
33
+ ```ts
34
+ const packageListURL =
35
+ new URLSearchParams(location.search).get("system-package-list") ||
36
+ localStorage.getItem("systemPackageListURL") ||
37
+ DEFAULT_PACKAGE_LIST;
38
+ ```
39
+
40
+ This keeps the precedence in one place — the site — so a site can add its own override sources without fighting the library for priority.
41
+
42
+ ### Patch Changes
43
+
44
+ - 6be3922: Wait for configured modules to load before routing the root view so registered frame tools are available for the initial route.
45
+ - 77bd37c: Expose the account document handle as `window.accountDocHandle` alongside `window.patchwork.account`.
46
+ - 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.
47
+ - Updated dependencies [5f70c14]
48
+ - @inkandswitch/patchwork-bootloader@0.5.1
49
+ - @inkandswitch/patchwork-filesystem@0.2.4
50
+ - @inkandswitch/patchwork-elements@4.0.3
51
+ - @inkandswitch/patchwork-plugins@1.0.2
52
+
3
53
  ## 0.1.0
4
54
 
5
55
  ### Minor Changes
package/dist/client.d.ts CHANGED
@@ -18,7 +18,7 @@ declare global {
18
18
  /**
19
19
  * Comma-separated list of default tool-manifest sources the shell boots
20
20
  * with. Each entry is an `automerge:` URL or a static `modules.json`
21
- * URL. Overridable at runtime via `localStorage.systemPackageListURL`.
21
+ * URL.
22
22
  */
23
23
  readonly PATCHWORK_SYSTEM_PACKAGE_LIST_URL?: string;
24
24
  /**
@@ -0,0 +1,2 @@
1
+ import { type AccountCreator, type AccountDoc } from "@inkandswitch/patchwork-plugins";
2
+ export declare const createDefaultAccount: AccountCreator<AccountDoc>;
@@ -0,0 +1,18 @@
1
+ import { createDocOfDatatype2, getRegistry, } from "@inkandswitch/patchwork-plugins";
2
+ export const createDefaultAccount = async (accountHandle, repo) => {
3
+ const fields = [
4
+ ["rootFolderUrl", "folder"],
5
+ ["moduleSettingsUrl", "patchwork:module-settings"],
6
+ ["contactUrl", "contact"],
7
+ ];
8
+ const registry = getRegistry("patchwork:datatype");
9
+ const subdocs = await Promise.all(fields.map(async ([field, datatypeId]) => {
10
+ const datatype = await registry.loadWhenReady(datatypeId);
11
+ const handle = await createDocOfDatatype2(datatype, repo);
12
+ return [field, handle.url];
13
+ }));
14
+ accountHandle.change((doc) => {
15
+ for (const [field, url] of subdocs)
16
+ doc[field] = url;
17
+ });
18
+ };
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@
17
17
  * `@inkandswitch/patchwork-bootloader` directly, which does SW registration
18
18
  * and the automerge-worker handoff and nothing else.
19
19
  */
20
- import { MessageChannelNetworkAdapter, isValidAutomergeUrl, } from "@automerge/vanillajs/slim";
20
+ import { MessageChannelNetworkAdapter, } from "@automerge/vanillajs/slim";
21
21
  import * as Automerge from "@automerge/automerge/slim";
22
22
  import * as AutomergeRepo from "@automerge/automerge-repo/slim";
23
23
  import { ModuleWatcher } from "@inkandswitch/patchwork-filesystem";
@@ -30,6 +30,7 @@ import setupServiceWorker, { lifecycleLog, } from "@inkandswitch/patchwork-bootl
30
30
  import debug from "debug";
31
31
  import { createRepo, firstRepoPort, initWasm, removeAdapterFor, } from "./repo.js";
32
32
  import { createRouter } from "./router.js";
33
+ import { createDefaultAccount } from "./createAccount.js";
33
34
  const log = debug("patchwork:setup");
34
35
  // ── Setup ────────────────────────────────────────────────────────────────
35
36
  let setupCalled = false;
@@ -139,11 +140,16 @@ async function doSetup(options) {
139
140
  const accountDocHandle = (await resolveAccountHandle(repo, {
140
141
  storageKey: options.accountKey ?? "patchworkAccountURL",
141
142
  hive,
143
+ createAccount: options.createAccount ?? createDefaultAccount,
142
144
  }));
143
145
  wireModuleSettings(accountDocHandle, moduleWatcher);
146
+ const toolsLoaded = moduleWatcher.doneLoading.then(() => log("doneLoading, tools registered:", getRegistry("patchwork:tool")
147
+ .all()
148
+ .map((t) => t.id)), (err) => console.error("doneLoading rejected:", err));
144
149
  let router;
145
150
  if (routing !== false) {
146
151
  rootElement.style.visibility = "hidden";
152
+ await toolsLoaded;
147
153
  router = createRouter({
148
154
  rootElement,
149
155
  repo,
@@ -151,9 +157,6 @@ async function doSetup(options) {
151
157
  siteName,
152
158
  });
153
159
  }
154
- const toolsLoaded = moduleWatcher.doneLoading.then(() => log("doneLoading, tools registered:", getRegistry("patchwork:tool")
155
- .all()
156
- .map((t) => t.id)), (err) => console.error("doneLoading rejected:", err));
157
160
  installReveal(rootElement, router, toolsLoaded);
158
161
  return {
159
162
  repo,
@@ -215,25 +218,13 @@ function installReveal(rootElement, router, toolsLoaded) {
215
218
  setTimeout(reveal, 12_000);
216
219
  }
217
220
  // ── Module sources ───────────────────────────────────────────────────────
218
- function isValidModuleSource(source) {
219
- return isValidAutomergeUrl(source) || /^(https?:\/\/|\.?\/)/.test(source);
220
- }
221
221
  /**
222
- * The site's default module-list sources, honouring the
223
- * `localStorage.systemPackageListURL` dev override, which replaces the entire
224
- * built-in bundle.
222
+ * The site's module-list sources. The site owns any dev overrides and passes
223
+ * the result in as `packageListURL`.
225
224
  */
226
225
  function resolveDefaultModules(options) {
227
226
  const configured = options.packageListURL ?? [];
228
227
  const builtin = (Array.isArray(configured) ? configured : [configured]).filter(Boolean);
229
- const override = globalThis.localStorage?.getItem("systemPackageListURL");
230
- if (override && isValidModuleSource(override)) {
231
- console.info(`using systemPackageListURL from localStorage: ${override}`);
232
- return [override];
233
- }
234
- if (override) {
235
- console.warn(`ignoring invalid systemPackageListURL in localStorage: ${override}`);
236
- }
237
228
  if (builtin.length === 0) {
238
229
  throw new Error("patchwork.setup: no default module sources configured (set `packageListURL`)");
239
230
  }
@@ -256,8 +247,7 @@ function onModuleLoaded(name, mod) {
256
247
  registerPlugins(mod.plugins, name);
257
248
  }
258
249
  /**
259
- * The frame lazy-creates `moduleSettingsUrl` on first mount, so watch for it to
260
- * appear and feed it to the ModuleWatcher.
250
+ * Feed the account's module settings document to the ModuleWatcher.
261
251
  */
262
252
  function wireModuleSettings(accountDocHandle, moduleWatcher) {
263
253
  const wire = () => {
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { AutomergeUrl, DocHandle, Repo } from "@automerge/vanillajs/slim";
2
2
  import type { AutomergeRepoKeyhive } from "@automerge/automerge-repo-keyhive";
3
3
  import type { ModuleWatcher, HasPatchworkMetadata } from "@inkandswitch/patchwork-filesystem";
4
- import type { AccountDoc } from "@inkandswitch/patchwork-plugins";
4
+ import type { AccountCreator, AccountDoc } from "@inkandswitch/patchwork-plugins";
5
5
  import type { ServiceWorkerRepoChannelListener, SyncStateDocMessage } from "@inkandswitch/patchwork-bootloader/types";
6
6
  import type * as pluginsNS from "@inkandswitch/patchwork-plugins";
7
7
  export type PluginsApi = typeof pluginsNS;
@@ -36,8 +36,6 @@ export interface PatchworkOptions {
36
36
  * The module URLs *inside* either kind of source may themselves be Automerge
37
37
  * folder docs or plain HTTP(S) bundles, so deployment targets can be freely
38
38
  * mixed.
39
- *
40
- * Overridable at runtime with `localStorage.systemPackageListURL`.
41
39
  */
42
40
  packageListURL?: string | string[];
43
41
  /**
@@ -47,6 +45,7 @@ export interface PatchworkOptions {
47
45
  * other's accounts.
48
46
  */
49
47
  accountKey?: string;
48
+ createAccount?: AccountCreator;
50
49
  /**
51
50
  * Brand word for this site: appended to the document title as
52
51
  * `"<doc> | <name>"` when a document is open (the separator is provided
package/package.json CHANGED
@@ -1,6 +1,11 @@
1
1
  {
2
2
  "name": "@inkandswitch/patchwork",
3
- "version": "0.1.0",
3
+ "repository": {
4
+ "type": "git",
5
+ "url": "git+https://github.com/inkandswitch/patchwork-system.git",
6
+ "directory": "core/patchwork"
7
+ },
8
+ "version": "0.3.0",
4
9
  "author": "Ink & Switch",
5
10
  "type": "module",
6
11
  "license": "MIT",
@@ -37,10 +42,10 @@
37
42
  "debug": "^4.4.3",
38
43
  "sharp": "^0.35.3",
39
44
  "vite-plugin-wasm": "^3.6.0",
40
- "@inkandswitch/patchwork-bootloader": "^0.5.0",
41
- "@inkandswitch/patchwork-elements": "^4.0.2",
42
- "@inkandswitch/patchwork-filesystem": "^0.2.3",
43
- "@inkandswitch/patchwork-plugins": "^1.0.1",
45
+ "@inkandswitch/patchwork-bootloader": "^0.5.3",
46
+ "@inkandswitch/patchwork-elements": "^5.0.0",
47
+ "@inkandswitch/patchwork-plugins": "^1.1.0",
48
+ "@inkandswitch/patchwork-filesystem": "^0.2.5",
44
49
  "@inkandswitch/patchwork-providers": "^0.4.2"
45
50
  },
46
51
  "devDependencies": {
package/src/client.d.ts CHANGED
@@ -18,7 +18,7 @@ declare global {
18
18
  /**
19
19
  * Comma-separated list of default tool-manifest sources the shell boots
20
20
  * with. Each entry is an `automerge:` URL or a static `modules.json`
21
- * URL. Overridable at runtime via `localStorage.systemPackageListURL`.
21
+ * URL.
22
22
  */
23
23
  readonly PATCHWORK_SYSTEM_PACKAGE_LIST_URL?: string;
24
24
  /**
@@ -0,0 +1,31 @@
1
+ import {
2
+ type AccountCreator,
3
+ type AccountDoc,
4
+ type DatatypeDescription,
5
+ createDocOfDatatype2,
6
+ getRegistry,
7
+ } from "@inkandswitch/patchwork-plugins";
8
+
9
+ export const createDefaultAccount: AccountCreator<AccountDoc> = async (
10
+ accountHandle,
11
+ repo
12
+ ) => {
13
+ const fields = [
14
+ ["rootFolderUrl", "folder"],
15
+ ["moduleSettingsUrl", "patchwork:module-settings"],
16
+ ["contactUrl", "contact"],
17
+ ] as const;
18
+ const registry = getRegistry<DatatypeDescription>("patchwork:datatype");
19
+
20
+ const subdocs = await Promise.all(
21
+ fields.map(async ([field, datatypeId]) => {
22
+ const datatype = await registry.loadWhenReady(datatypeId);
23
+ const handle = await createDocOfDatatype2(datatype, repo);
24
+ return [field, handle.url] as const;
25
+ })
26
+ );
27
+
28
+ accountHandle.change((doc) => {
29
+ for (const [field, url] of subdocs) doc[field] = url;
30
+ });
31
+ };
package/src/index.ts CHANGED
@@ -22,7 +22,6 @@ import {
22
22
  type DocHandle,
23
23
  MessageChannelNetworkAdapter,
24
24
  Repo,
25
- isValidAutomergeUrl,
26
25
  } from "@automerge/vanillajs/slim";
27
26
  import * as Automerge from "@automerge/automerge/slim";
28
27
  import * as AutomergeRepo from "@automerge/automerge-repo/slim";
@@ -61,6 +60,7 @@ import {
61
60
  removeAdapterFor,
62
61
  } from "./repo.js";
63
62
  import { createRouter, type Router } from "./router.js";
63
+ import { createDefaultAccount } from "./createAccount.js";
64
64
 
65
65
  const log = debug("patchwork:setup");
66
66
 
@@ -222,21 +222,11 @@ async function doSetup(options: PatchworkOptions): Promise<Patchwork> {
222
222
  const accountDocHandle = (await resolveAccountHandle(repo, {
223
223
  storageKey: options.accountKey ?? "patchworkAccountURL",
224
224
  hive,
225
+ createAccount: options.createAccount ?? createDefaultAccount,
225
226
  })) as DocHandle<AccountDoc>;
226
227
 
227
228
  wireModuleSettings(accountDocHandle, moduleWatcher);
228
229
 
229
- let router: Router | undefined;
230
- if (routing !== false) {
231
- rootElement.style.visibility = "hidden";
232
- router = createRouter({
233
- rootElement,
234
- repo,
235
- accountDocHandle,
236
- siteName,
237
- });
238
- }
239
-
240
230
  const toolsLoaded = moduleWatcher.doneLoading.then(
241
231
  () =>
242
232
  log(
@@ -248,6 +238,18 @@ async function doSetup(options: PatchworkOptions): Promise<Patchwork> {
248
238
  (err: unknown) => console.error("doneLoading rejected:", err)
249
239
  );
250
240
 
241
+ let router: Router | undefined;
242
+ if (routing !== false) {
243
+ rootElement.style.visibility = "hidden";
244
+ await toolsLoaded;
245
+ router = createRouter({
246
+ rootElement,
247
+ repo,
248
+ accountDocHandle,
249
+ siteName,
250
+ });
251
+ }
252
+
251
253
  installReveal(rootElement, router, toolsLoaded);
252
254
 
253
255
  return {
@@ -330,14 +332,9 @@ function installReveal(
330
332
 
331
333
  // ── Module sources ───────────────────────────────────────────────────────
332
334
 
333
- function isValidModuleSource(source: string): boolean {
334
- return isValidAutomergeUrl(source) || /^(https?:\/\/|\.?\/)/.test(source);
335
- }
336
-
337
335
  /**
338
- * The site's default module-list sources, honouring the
339
- * `localStorage.systemPackageListURL` dev override, which replaces the entire
340
- * built-in bundle.
336
+ * The site's module-list sources. The site owns any dev overrides and passes
337
+ * the result in as `packageListURL`.
341
338
  */
342
339
  function resolveDefaultModules(options: PatchworkOptions): string[] {
343
340
  const configured = options.packageListURL ?? [];
@@ -345,18 +342,6 @@ function resolveDefaultModules(options: PatchworkOptions): string[] {
345
342
  Array.isArray(configured) ? configured : [configured]
346
343
  ).filter(Boolean);
347
344
 
348
- const override = globalThis.localStorage?.getItem("systemPackageListURL");
349
-
350
- if (override && isValidModuleSource(override)) {
351
- console.info(`using systemPackageListURL from localStorage: ${override}`);
352
- return [override];
353
- }
354
- if (override) {
355
- console.warn(
356
- `ignoring invalid systemPackageListURL in localStorage: ${override}`
357
- );
358
- }
359
-
360
345
  if (builtin.length === 0) {
361
346
  throw new Error(
362
347
  "patchwork.setup: no default module sources configured (set `packageListURL`)"
@@ -389,8 +374,7 @@ function onModuleLoaded(name: string, mod: any): void {
389
374
  }
390
375
 
391
376
  /**
392
- * The frame lazy-creates `moduleSettingsUrl` on first mount, so watch for it to
393
- * appear and feed it to the ModuleWatcher.
377
+ * Feed the account's module settings document to the ModuleWatcher.
394
378
  */
395
379
  function wireModuleSettings(
396
380
  accountDocHandle: DocHandle<AccountDoc>,
package/src/types.ts CHANGED
@@ -1,14 +1,13 @@
1
- import type {
2
- AutomergeUrl,
3
- DocHandle,
4
- Repo,
5
- } from "@automerge/vanillajs/slim";
1
+ import type { AutomergeUrl, DocHandle, Repo } from "@automerge/vanillajs/slim";
6
2
  import type { AutomergeRepoKeyhive } from "@automerge/automerge-repo-keyhive";
7
3
  import type {
8
4
  ModuleWatcher,
9
5
  HasPatchworkMetadata,
10
6
  } from "@inkandswitch/patchwork-filesystem";
11
- import type { AccountDoc } from "@inkandswitch/patchwork-plugins";
7
+ import type {
8
+ AccountCreator,
9
+ AccountDoc,
10
+ } from "@inkandswitch/patchwork-plugins";
12
11
  import type {
13
12
  ServiceWorkerRepoChannelListener,
14
13
  SyncStateDocMessage,
@@ -53,8 +52,6 @@ export interface PatchworkOptions {
53
52
  * The module URLs *inside* either kind of source may themselves be Automerge
54
53
  * folder docs or plain HTTP(S) bundles, so deployment targets can be freely
55
54
  * mixed.
56
- *
57
- * Overridable at runtime with `localStorage.systemPackageListURL`.
58
55
  */
59
56
  packageListURL?: string | string[];
60
57
 
@@ -65,6 +62,7 @@ export interface PatchworkOptions {
65
62
  * other's accounts.
66
63
  */
67
64
  accountKey?: string;
65
+ createAccount?: AccountCreator;
68
66
 
69
67
  /**
70
68
  * Brand word for this site: appended to the document title as