@weaveprotocol/core 0.2.3 → 0.2.5

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.
@@ -0,0 +1,129 @@
1
+ # Screens and apps
2
+
3
+ A space can grow its own tools without anyone deploying anything. An **app**
4
+ is a record that proposes some collections. A **screen** is a small UI that
5
+ travels on a collection definition.
6
+
7
+ ## Apps: proposing collections
8
+
9
+ ```typescript
10
+ import { proposeApp, reviewApp, addApp } from '@weaveprotocol/core/schemas';
11
+
12
+ const proposal = await proposeApp(node, space.id, {
13
+ title: 'Chores',
14
+ description: 'Who does what around the house this week.',
15
+ needs: [
16
+ {
17
+ name: 'app.chores.task',
18
+ title: 'Chore',
19
+ schema: {
20
+ type: 'object',
21
+ properties: { title: { type: 'string', minLength: 1, maxLength: 200 }, done: { type: 'boolean' } },
22
+ required: ['title'],
23
+ },
24
+ rules: { delete: 'creator' },
25
+ },
26
+ ],
27
+ });
28
+
29
+ // Someone allowed to define collections reads what it would do, then adds it
30
+ const review = reviewApp(proposal.body!, await node.collections.list(space.id));
31
+ await addApp(node, space.id, proposal.key);
32
+ ```
33
+
34
+ - A proposal is one `std.app` record. Nothing is defined yet, so it can't
35
+ break anything.
36
+ - `reviewApp` says, per collection, whether it is new, a change, or the same,
37
+ with a summary in sentences worked out from its rules. Show that to the
38
+ person before they add it.
39
+ - `addApp` defines each collection, signed by whoever adds it. They need the
40
+ `define` permission in the space.
41
+ - An agent can propose but never add: every peer ignores definitions signed
42
+ under an agent's note.
43
+ - At most 10 collections per app.
44
+ - To change an app, propose a new one with `updates: <its key>`. Until the
45
+ update is added, the old one stays in use; after, `supersededApps` names the
46
+ old one, and `addApp` refuses it, since adding it would undo the update.
47
+
48
+ ## Screens: a UI on a collection
49
+
50
+ A definition may carry `screen`: one HTML document, scripts and styles inline,
51
+ at most 48 KB. Apps that show the space can run it instead of plain lists.
52
+
53
+ It runs sealed: no network, no storage, no popups, no forms that submit, no
54
+ libraries or fonts from URLs. It reaches records only through `window.weave`,
55
+ as the person looking, so every rule still holds and a screen can do nothing
56
+ its viewer couldn't.
57
+
58
+ ```html
59
+ <ul id="list"></ul>
60
+ <form id="add"><input name="title" required><button>Add</button></form>
61
+ <script>
62
+ const list = document.getElementById('list');
63
+ async function draw() {
64
+ const chores = await weave.list({ collection: 'app.chores.task' });
65
+ list.replaceChildren(...chores.map((chore) => {
66
+ const item = document.createElement('li');
67
+ item.textContent = chore.body.title + (chore.body.done ? ' ✓' : '');
68
+ item.onclick = () => weave.update(chore.key, { ...chore.body, done: !chore.body.done });
69
+ return item;
70
+ }));
71
+ }
72
+ document.getElementById('add').onsubmit = async (event) => {
73
+ event.preventDefault();
74
+ await weave.put('app.chores.task', { title: event.target.title.value });
75
+ event.target.reset();
76
+ };
77
+ weave.onChange(draw);
78
+ draw();
79
+ </script>
80
+ ```
81
+
82
+ `window.weave`:
83
+
84
+ | | |
85
+ |---|---|
86
+ | `weave.me` | `{ did, name }`: who is looking |
87
+ | `weave.collections` | The collection names this screen may use (its app's) |
88
+ | `await weave.list({ collection, where })` | Records, oldest first. `where: { "link:<rel>": key }` or `{ field: value }` |
89
+ | `await weave.get(key)` | One record, or null |
90
+ | `await weave.put(collection, body, { links, key })` | Writes a record as the person looking |
91
+ | `await weave.update(key, body, { links })` | The next version |
92
+ | `await weave.remove(key)` | Deletes |
93
+ | `await weave.people()` | `[{ did, name }]` of the space |
94
+ | `weave.onChange(callback)` | Called when records change, here or on another device. Returns a stop function |
95
+
96
+ Each record is `{ key, collection, body, links, createdBy, createdAt, updatedAt, mine, viaAgent }`.
97
+
98
+ - Keep all state in records and redraw on `onChange`. Other people's changes
99
+ arrive that way.
100
+ - Two people can write at once. Let the collection's rules settle clashes
101
+ (`onePer`, creator-only edits), not the screen.
102
+ - A refused write rejects with the reason. An error the screen doesn't catch
103
+ is shown to the person.
104
+ - The full guide an agent is given is exported as `SCREEN_GUIDE` from
105
+ `@weaveprotocol/core/schemas`.
106
+
107
+ ## Hosting screens in your app
108
+
109
+ To show screens, run them in an `<iframe sandbox="allow-scripts">` whose page
110
+ removes network access (a strict Content-Security-Policy), and hand it a
111
+ message port to a bridge:
112
+
113
+ ```typescript
114
+ import { createScreenBridge, screenDocument } from '@weaveprotocol/core/schemas';
115
+
116
+ const channel = new MessageChannel();
117
+ const bridge = createScreenBridge({ node, spaceId, collections, port: channel.port1 });
118
+ frame.contentWindow.postMessage(
119
+ { weave: 'load', document: screenDocument(screen), me: { did: node.did, name }, collections },
120
+ '*',
121
+ [channel.port2],
122
+ );
123
+ // bridge.close() when the frame goes away
124
+ ```
125
+
126
+ The page inside the frame writes the document it is given, with `window.__weave`
127
+ set to `{ port, me, collections }` first. The Weave example app's frame page,
128
+ `apps/example/public/screen.html`, and `apps/example/src/components/apps/ScreenFrame.tsx`,
129
+ in the repository, show the whole thing.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weaveprotocol/core",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "type": "module",
5
5
  "description": "Self-sovereign P2P protocol for the browser — identity, schemas, storage, networking, and gossip sync",
6
6
  "repository": {
@@ -10,6 +10,7 @@
10
10
  },
11
11
  "files": [
12
12
  "dist",
13
+ "docs",
13
14
  "README.md"
14
15
  ],
15
16
  "main": "dist/index.js",