@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.
- package/README.md +6 -1
- package/dist/network/mesh.d.ts.map +1 -1
- package/dist/network/mesh.js +8 -0
- package/dist/network/mesh.js.map +1 -1
- package/dist/network/network-manager.d.ts +2 -0
- package/dist/network/network-manager.d.ts.map +1 -1
- package/dist/network/network-manager.js +4 -0
- package/dist/network/network-manager.js.map +1 -1
- package/dist/network/peer-auth.d.ts +5 -0
- package/dist/network/peer-auth.d.ts.map +1 -1
- package/dist/network/peer-auth.js +7 -3
- package/dist/network/peer-auth.js.map +1 -1
- package/dist/node/actions.d.ts.map +1 -1
- package/dist/node/actions.js +10 -2
- package/dist/node/actions.js.map +1 -1
- package/dist/node/space-runtime.d.ts.map +1 -1
- package/dist/node/space-runtime.js +52 -0
- package/dist/node/space-runtime.js.map +1 -1
- package/dist/schemas/apps.d.ts +12 -0
- package/dist/schemas/apps.d.ts.map +1 -1
- package/dist/schemas/apps.js +33 -0
- package/dist/schemas/apps.js.map +1 -1
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +1 -1
- package/dist/schemas/index.js.map +1 -1
- package/docs/README.md +49 -0
- package/docs/agents.md +59 -0
- package/docs/building-an-app.md +162 -0
- package/docs/collections.md +151 -0
- package/docs/records-and-queries.md +125 -0
- package/docs/screens-and-apps.md +129 -0
- package/package.json +2 -1
|
@@ -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
|
+
"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",
|