@inkandswitch/patchwork 0.3.3 → 0.4.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,25 @@
1
1
  # @inkandswitch/patchwork
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 776b9bb: Boot no longer waits on datatypes it doesn't own. `resolveAccountHandle` writes
8
+ the account doc directly instead of blocking on `loadWhenReady("account")`, and
9
+ `createDefaultAccount` builds the root folder, module-settings and anonymous
10
+ contact subdocs itself rather than waiting for the `folder`,
11
+ `patchwork:module-settings` and `contact` datatypes. A package bundle that never
12
+ registers those no longer hangs setup until its timeout.
13
+
14
+ `AccountDoc.frameToolId` is now optional. `createDefaultAccount` still writes
15
+ `"threepane"`, and the router falls back to the first registered `frame-tool`
16
+ when an account has none.
17
+
18
+ ### Patch Changes
19
+
20
+ - Updated dependencies [776b9bb]
21
+ - @inkandswitch/patchwork-plugins@1.2.0
22
+
3
23
  ## 0.3.3
4
24
 
5
25
  ### Patch Changes
@@ -1,2 +1,2 @@
1
- import { type AccountCreator, type AccountDoc } from "@inkandswitch/patchwork-plugins";
1
+ import type { AccountCreator, AccountDoc } from "@inkandswitch/patchwork-plugins";
2
2
  export declare const createDefaultAccount: AccountCreator<AccountDoc>;
@@ -1,18 +1,28 @@
1
- import { createDocOfDatatype2, getRegistry, } from "@inkandswitch/patchwork-plugins";
1
+ async function createSubdoc(repo, type, init) {
2
+ const handle = await repo.create2();
3
+ handle.change((doc) => {
4
+ doc["@patchwork"] = { type };
5
+ init(doc);
6
+ });
7
+ return handle;
8
+ }
2
9
  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
- }));
10
+ const [rootFolder, moduleSettings, contact] = await Promise.all([
11
+ createSubdoc(repo, "folder", (doc) => {
12
+ doc.title = "New Folder";
13
+ doc.docs = [];
14
+ }),
15
+ createSubdoc(repo, "patchwork:module-settings", (doc) => {
16
+ doc.modules = [];
17
+ }),
18
+ createSubdoc(repo, "contact", (doc) => {
19
+ doc.type = "anonymous";
20
+ }),
21
+ ]);
14
22
  accountHandle.change((doc) => {
15
- for (const [field, url] of subdocs)
16
- doc[field] = url;
23
+ doc.frameToolId = "threepane";
24
+ doc.rootFolderUrl = rootFolder.url;
25
+ doc.moduleSettingsUrl = moduleSettings.url;
26
+ doc.contactUrl = contact.url;
17
27
  });
18
28
  };
package/dist/router.js CHANGED
@@ -42,6 +42,11 @@ export function docParamToUrl(docParam) {
42
42
  return undefined;
43
43
  return stringifyAutomergeUrl({ documentId: documentId });
44
44
  }
45
+ function registeredFrameToolId() {
46
+ return getRegistry("patchwork:tool")
47
+ .filter((tool) => !!tool.tags?.includes("frame-tool") && !tool.unlisted)
48
+ .at(0)?.id;
49
+ }
45
50
  export function createRouter({ rootElement, repo, accountDocHandle, siteName, }) {
46
51
  const route = async () => {
47
52
  // The first call seeds the root view's tool/doc so it can mount; later
@@ -49,7 +54,12 @@ export function createRouter({ rootElement, repo, accountDocHandle, siteName, })
49
54
  if (!rootElement.hasAttribute("tool-id")) {
50
55
  const params = new URLSearchParams(location.hash.slice(1));
51
56
  const frame = params.get("frame");
52
- rootElement.setAttribute("tool-id", frame ?? accountDocHandle.doc().frameToolId);
57
+ const toolId = frame ?? accountDocHandle.doc().frameToolId ?? registeredFrameToolId();
58
+ if (!toolId) {
59
+ console.error("patchwork: no frame tool registered, nothing to mount");
60
+ return;
61
+ }
62
+ rootElement.setAttribute("tool-id", toolId);
53
63
  rootElement.setAttribute("doc-url", (frame && docParamToUrl(params.get("doc"))) || accountDocHandle.url);
54
64
  return;
55
65
  }
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.3.3",
8
+ "version": "0.4.0",
9
9
  "author": "Ink & Switch",
10
10
  "type": "module",
11
11
  "license": "MIT",
@@ -42,11 +42,11 @@
42
42
  "debug": "^4.4.3",
43
43
  "sharp": "^0.35.3",
44
44
  "vite-plugin-wasm": "^3.6.0",
45
- "@inkandswitch/patchwork-bootloader": "^0.5.4",
45
+ "@inkandswitch/patchwork-plugins": "^1.2.0",
46
+ "@inkandswitch/patchwork-providers": "^0.5.0",
46
47
  "@inkandswitch/patchwork-elements": "^6.0.0",
47
48
  "@inkandswitch/patchwork-filesystem": "^0.2.5",
48
- "@inkandswitch/patchwork-plugins": "^1.1.0",
49
- "@inkandswitch/patchwork-providers": "^0.5.0"
49
+ "@inkandswitch/patchwork-bootloader": "^0.5.4"
50
50
  },
51
51
  "devDependencies": {
52
52
  "esbuild": "^0.23.1",
@@ -1,31 +1,48 @@
1
- import {
2
- type AccountCreator,
3
- type AccountDoc,
4
- type DatatypeDescription,
5
- createDocOfDatatype2,
6
- getRegistry,
1
+ import type { Repo } from "@automerge/automerge-repo/slim";
2
+ import type {
3
+ AccountCreator,
4
+ AccountDoc,
7
5
  } from "@inkandswitch/patchwork-plugins";
6
+ import type { HasPatchworkMetadata } from "@inkandswitch/patchwork-filesystem";
7
+
8
+ async function createSubdoc<D>(
9
+ repo: Repo,
10
+ type: string,
11
+ init: (doc: D) => void
12
+ ) {
13
+ const handle = await repo.create2<D & HasPatchworkMetadata>();
14
+ handle.change((doc: D & HasPatchworkMetadata) => {
15
+ doc["@patchwork"] = { type };
16
+ init(doc);
17
+ });
18
+ return handle;
19
+ }
8
20
 
9
21
  export const createDefaultAccount: AccountCreator<AccountDoc> = async (
10
22
  accountHandle,
11
23
  repo
12
24
  ) => {
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
- );
25
+ const [rootFolder, moduleSettings, contact] = await Promise.all([
26
+ createSubdoc<{ title: string; docs: unknown[] }>(repo, "folder", (doc) => {
27
+ doc.title = "New Folder";
28
+ doc.docs = [];
29
+ }),
30
+ createSubdoc<{ modules: string[] }>(
31
+ repo,
32
+ "patchwork:module-settings",
33
+ (doc) => {
34
+ doc.modules = [];
35
+ }
36
+ ),
37
+ createSubdoc<{ type: string }>(repo, "contact", (doc) => {
38
+ doc.type = "anonymous";
39
+ }),
40
+ ]);
27
41
 
28
42
  accountHandle.change((doc) => {
29
- for (const [field, url] of subdocs) doc[field] = url;
43
+ doc.frameToolId = "threepane";
44
+ doc.rootFolderUrl = rootFolder.url;
45
+ doc.moduleSettingsUrl = moduleSettings.url;
46
+ doc.contactUrl = contact.url;
30
47
  });
31
48
  };
package/src/router.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  type AccountDoc,
13
13
  type DatatypeDescription,
14
14
  type DatatypeImplementation,
15
+ type ToolDescription,
15
16
  getRegistry,
16
17
  } from "@inkandswitch/patchwork-plugins";
17
18
 
@@ -71,6 +72,12 @@ export interface Router {
71
72
  route(): Promise<void>;
72
73
  }
73
74
 
75
+ function registeredFrameToolId(): string | undefined {
76
+ return getRegistry<ToolDescription>("patchwork:tool")
77
+ .filter((tool) => !!tool.tags?.includes("frame-tool") && !tool.unlisted)
78
+ .at(0)?.id;
79
+ }
80
+
74
81
  export function createRouter({
75
82
  rootElement,
76
83
  repo,
@@ -83,10 +90,13 @@ export function createRouter({
83
90
  if (!rootElement.hasAttribute("tool-id")) {
84
91
  const params = new URLSearchParams(location.hash.slice(1));
85
92
  const frame = params.get("frame");
86
- rootElement.setAttribute(
87
- "tool-id",
88
- frame ?? accountDocHandle.doc().frameToolId
89
- );
93
+ const toolId =
94
+ frame ?? accountDocHandle.doc().frameToolId ?? registeredFrameToolId();
95
+ if (!toolId) {
96
+ console.error("patchwork: no frame tool registered, nothing to mount");
97
+ return;
98
+ }
99
+ rootElement.setAttribute("tool-id", toolId);
90
100
  rootElement.setAttribute(
91
101
  "doc-url",
92
102
  (frame && docParamToUrl(params.get("doc"))) || accountDocHandle.url