nervur 0.23.0 → 0.24.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/CONTRIBUTING.md +13 -0
- package/LICENSE +55 -202
- package/NOTICE +3 -8
- package/README.md +14 -156
- package/RELEASING.md +15 -0
- package/SECURITY.md +9 -0
- package/bin/nervur.js +6 -0
- package/package.json +26 -81
- package/AUTHORING.md +0 -935
- package/COMMAND.md +0 -179
- package/FACES.md +0 -280
- package/FACULTIES.md +0 -578
- package/GROUNDS.md +0 -315
- package/KIT-SPEC.md +0 -304
- package/WORLD.md +0 -195
- package/dist/app/app-ground.d.ts +0 -18
- package/dist/app/app-ground.js +0 -23
- package/dist/app/index.d.ts +0 -2
- package/dist/app/index.js +0 -5
- package/dist/app/native.d.ts +0 -11
- package/dist/app/native.js +0 -13
- package/dist/being/being.d.ts +0 -306
- package/dist/being/being.js +0 -20
- package/dist/being/covers.d.ts +0 -9
- package/dist/being/covers.js +0 -21
- package/dist/being/index.d.ts +0 -4
- package/dist/being/index.js +0 -6
- package/dist/being/need.d.ts +0 -49
- package/dist/being/need.js +0 -33
- package/dist/being/schema.d.ts +0 -100
- package/dist/being/schema.js +0 -132
- package/dist/being/table.d.ts +0 -48
- package/dist/being/table.js +0 -344
- package/dist/bench/bench-ground.d.ts +0 -73
- package/dist/bench/bench-ground.js +0 -153
- package/dist/bench/bench.d.ts +0 -101
- package/dist/bench/bench.js +0 -368
- package/dist/bench/fake-clock.d.ts +0 -17
- package/dist/bench/fake-clock.js +0 -34
- package/dist/bench/fake-memory.d.ts +0 -16
- package/dist/bench/fake-memory.js +0 -46
- package/dist/bench/fake-network.d.ts +0 -66
- package/dist/bench/fake-network.js +0 -222
- package/dist/bench/fake-unlock.d.ts +0 -6
- package/dist/bench/fake-unlock.js +0 -10
- package/dist/bench/index.d.ts +0 -3
- package/dist/bench/index.js +0 -5
- package/dist/bench/seeded.d.ts +0 -11
- package/dist/bench/seeded.js +0 -37
- package/dist/bench/settle.d.ts +0 -2
- package/dist/bench/settle.js +0 -49
- package/dist/bench/stewards.d.ts +0 -169
- package/dist/bench/stewards.js +0 -128
- package/dist/bodies/class-list.d.ts +0 -14
- package/dist/bodies/class-list.js +0 -33
- package/dist/bodies/joined-carry.d.ts +0 -29
- package/dist/bodies/joined-carry.js +0 -48
- package/dist/bodies/kept.d.ts +0 -44
- package/dist/bodies/kept.js +0 -91
- package/dist/bodies/noble-crypto.d.ts +0 -22
- package/dist/bodies/noble-crypto.js +0 -88
- package/dist/bodies/seed-keys.d.ts +0 -10
- package/dist/bodies/seed-keys.js +0 -42
- package/dist/bodies/strict-tools.d.ts +0 -10
- package/dist/bodies/strict-tools.js +0 -306
- package/dist/bodies/vouch.d.ts +0 -20
- package/dist/bodies/vouch.js +0 -71
- package/dist/bodies/web-carry.d.ts +0 -72
- package/dist/bodies/web-carry.js +0 -245
- package/dist/bodies/web-clock.d.ts +0 -12
- package/dist/bodies/web-clock.js +0 -33
- package/dist/browser/browser-ground.d.ts +0 -76
- package/dist/browser/browser-ground.js +0 -294
- package/dist/browser/index.d.ts +0 -4
- package/dist/browser/index.js +0 -7
- package/dist/browser/indexeddb-memory.d.ts +0 -17
- package/dist/browser/indexeddb-memory.js +0 -97
- package/dist/browser/locked-unlock.d.ts +0 -24
- package/dist/browser/locked-unlock.js +0 -85
- package/dist/browser/origin-classes.d.ts +0 -7
- package/dist/browser/origin-classes.js +0 -31
- package/dist/edge/durable-clock.d.ts +0 -19
- package/dist/edge/durable-clock.js +0 -61
- package/dist/edge/durable-memory.d.ts +0 -5
- package/dist/edge/durable-memory.js +0 -11
- package/dist/edge/durable.d.ts +0 -18
- package/dist/edge/durable.js +0 -24
- package/dist/edge/edge-ground.d.ts +0 -49
- package/dist/edge/edge-ground.js +0 -223
- package/dist/edge/index.d.ts +0 -7
- package/dist/edge/index.js +0 -9
- package/dist/edge/native-crypto.d.ts +0 -8
- package/dist/edge/native-crypto.js +0 -102
- package/dist/edge/secret-unlock.d.ts +0 -7
- package/dist/edge/secret-unlock.js +0 -13
- package/dist/edge/socket-carry.d.ts +0 -39
- package/dist/edge/socket-carry.js +0 -111
- package/dist/foundation.d.ts +0 -162
- package/dist/foundation.js +0 -4
- package/dist/ground/dock.d.ts +0 -1460
- package/dist/ground/dock.js +0 -1159
- package/dist/ground/ground.d.ts +0 -239
- package/dist/ground/ground.js +0 -787
- package/dist/ground/views.d.ts +0 -76
- package/dist/ground/views.js +0 -208
- package/dist/house/crossing.d.ts +0 -50
- package/dist/house/crossing.js +0 -153
- package/dist/house/house.d.ts +0 -88
- package/dist/house/house.js +0 -2069
- package/dist/house/rows-shape.d.ts +0 -110
- package/dist/house/rows-shape.js +0 -12
- package/dist/house/rows.d.ts +0 -27
- package/dist/house/rows.js +0 -185
- package/dist/index.d.ts +0 -33
- package/dist/index.js +0 -29
- package/dist/node/bridge.d.ts +0 -20
- package/dist/node/bridge.js +0 -284
- package/dist/node/cli.d.ts +0 -2
- package/dist/node/cli.js +0 -225
- package/dist/node/file-memory.d.ts +0 -13
- package/dist/node/file-memory.js +0 -86
- package/dist/node/folder-classes.d.ts +0 -5
- package/dist/node/folder-classes.js +0 -40
- package/dist/node/gone.d.ts +0 -2
- package/dist/node/gone.js +0 -7
- package/dist/node/hand.d.ts +0 -39
- package/dist/node/hand.js +0 -107
- package/dist/node/http.d.ts +0 -11
- package/dist/node/http.js +0 -90
- package/dist/node/index.d.ts +0 -11
- package/dist/node/index.js +0 -13
- package/dist/node/ledger-memory.d.ts +0 -17
- package/dist/node/ledger-memory.js +0 -152
- package/dist/node/lock.d.ts +0 -10
- package/dist/node/lock.js +0 -78
- package/dist/node/node-ground.d.ts +0 -26
- package/dist/node/node-ground.js +0 -228
- package/dist/node/notify.d.ts +0 -1
- package/dist/node/notify.js +0 -18
- package/dist/node/shell.d.ts +0 -11
- package/dist/node/shell.js +0 -35
- package/dist/node/sync-folder.d.ts +0 -6
- package/dist/node/sync-folder.js +0 -18
- package/dist/node/tcp-carry.d.ts +0 -42
- package/dist/node/tcp-carry.js +0 -193
- package/dist/node/unlock.d.ts +0 -17
- package/dist/node/unlock.js +0 -86
- package/dist/node/websocket.d.ts +0 -12
- package/dist/node/websocket.js +0 -134
- package/dist/quo/frame.d.ts +0 -33
- package/dist/quo/frame.js +0 -92
- package/dist/quo/index.d.ts +0 -1
- package/dist/quo/index.js +0 -5
- package/dist/quo/room.d.ts +0 -154
- package/dist/quo/room.js +0 -362
- package/dist/serve/index.d.ts +0 -45
- package/dist/serve/index.js +0 -71
package/dist/ground/views.d.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import type { Carry, Clock, Crypto, Memory, PlaceRead, Sent, Tools } from '../foundation.ts';
|
|
2
|
-
export declare class HouseClock implements Clock {
|
|
3
|
-
#private;
|
|
4
|
-
constructor(clock: Clock, house: string);
|
|
5
|
-
now(): number;
|
|
6
|
-
wait({ id, ms }: {
|
|
7
|
-
id: string;
|
|
8
|
-
ms: number;
|
|
9
|
-
}): Promise<boolean>;
|
|
10
|
-
cancel({ id }: {
|
|
11
|
-
id: string;
|
|
12
|
-
}): void;
|
|
13
|
-
close(): void;
|
|
14
|
-
}
|
|
15
|
-
export declare class HouseCarry implements Carry {
|
|
16
|
-
#private;
|
|
17
|
-
constructor(carry: Carry);
|
|
18
|
-
send(options: {
|
|
19
|
-
ward: string;
|
|
20
|
-
at: readonly string[];
|
|
21
|
-
box: Uint8Array;
|
|
22
|
-
wait?: number;
|
|
23
|
-
}): Promise<Sent>;
|
|
24
|
-
at(options?: {
|
|
25
|
-
toward?: string;
|
|
26
|
-
}): readonly string[];
|
|
27
|
-
vouched(options: {
|
|
28
|
-
ward: string;
|
|
29
|
-
at: readonly string[];
|
|
30
|
-
}): Promise<readonly string[]>;
|
|
31
|
-
close(): void;
|
|
32
|
-
}
|
|
33
|
-
export declare class LadderCarry implements Carry {
|
|
34
|
-
#private;
|
|
35
|
-
constructor(carry: () => Carry | string);
|
|
36
|
-
send(options: {
|
|
37
|
-
ward: string;
|
|
38
|
-
at: readonly string[];
|
|
39
|
-
box: Uint8Array;
|
|
40
|
-
wait?: number;
|
|
41
|
-
}): Promise<Sent>;
|
|
42
|
-
at(options?: {
|
|
43
|
-
toward?: string;
|
|
44
|
-
}): readonly string[];
|
|
45
|
-
vouched(options: {
|
|
46
|
-
ward: string;
|
|
47
|
-
at: readonly string[];
|
|
48
|
-
}): Promise<readonly string[]>;
|
|
49
|
-
}
|
|
50
|
-
type Writes = Readonly<Record<string, Readonly<Record<string, Uint8Array | null>>>>;
|
|
51
|
-
type Expect = Readonly<Record<string, string | null>>;
|
|
52
|
-
export declare class ViewMemory implements Memory {
|
|
53
|
-
#private;
|
|
54
|
-
constructor(memory: Memory, prefix: string);
|
|
55
|
-
read({ place }: {
|
|
56
|
-
place: string;
|
|
57
|
-
}): Promise<PlaceRead>;
|
|
58
|
-
list(): Promise<readonly string[]>;
|
|
59
|
-
write({ writes, expect }: {
|
|
60
|
-
writes: Writes;
|
|
61
|
-
expect: Expect;
|
|
62
|
-
}): Promise<Readonly<Record<string, string | null>> | null>;
|
|
63
|
-
}
|
|
64
|
-
export declare class SealedMemory implements Memory {
|
|
65
|
-
#private;
|
|
66
|
-
constructor(memory: Memory, key: Uint8Array, crypto: Crypto, tools: Tools);
|
|
67
|
-
read({ place }: {
|
|
68
|
-
place: string;
|
|
69
|
-
}): Promise<PlaceRead>;
|
|
70
|
-
list(): Promise<readonly string[]>;
|
|
71
|
-
write({ writes, expect }: {
|
|
72
|
-
writes: Writes;
|
|
73
|
-
expect: Expect;
|
|
74
|
-
}): Promise<Readonly<Record<string, string | null>> | null>;
|
|
75
|
-
}
|
|
76
|
-
export {};
|
package/dist/ground/views.js
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
// The ground's clock as one house sees it: its waits named apart from every
|
|
2
|
-
// other house's. When the ground closes it, every wait runs out, and each
|
|
3
|
-
// wait asked after runs out once, so every ask in flight on the house ends
|
|
4
|
-
// and none waits again.
|
|
5
|
-
export class HouseClock {
|
|
6
|
-
#clock;
|
|
7
|
-
#prefix;
|
|
8
|
-
#waits = new Map();
|
|
9
|
-
/** The waits that ran out after the close, each once. */
|
|
10
|
-
#spent = new Set();
|
|
11
|
-
#turn = 0;
|
|
12
|
-
#closed = false;
|
|
13
|
-
constructor(clock, house) {
|
|
14
|
-
this.#clock = clock;
|
|
15
|
-
this.#prefix = `${house}\n`;
|
|
16
|
-
}
|
|
17
|
-
now() {
|
|
18
|
-
return this.#clock.now();
|
|
19
|
-
}
|
|
20
|
-
wait({ id, ms }) {
|
|
21
|
-
if (this.#closed) {
|
|
22
|
-
if (this.#spent.has(id))
|
|
23
|
-
return Promise.resolve(false);
|
|
24
|
-
this.#spent.add(id);
|
|
25
|
-
return Promise.resolve(true);
|
|
26
|
-
}
|
|
27
|
-
const turn = ++this.#turn;
|
|
28
|
-
return new Promise((run) => {
|
|
29
|
-
this.#waits.get(id)?.run(false);
|
|
30
|
-
this.#waits.set(id, { turn, run });
|
|
31
|
-
void this.#clock.wait({ id: this.#prefix + id, ms }).then((fired) => {
|
|
32
|
-
if (this.#waits.get(id)?.turn === turn)
|
|
33
|
-
this.#waits.delete(id);
|
|
34
|
-
run(fired);
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
cancel({ id }) {
|
|
39
|
-
this.#clock.cancel({ id: this.#prefix + id });
|
|
40
|
-
}
|
|
41
|
-
close() {
|
|
42
|
-
this.#closed = true;
|
|
43
|
-
for (const [id, { run }] of this.#waits) {
|
|
44
|
-
this.#spent.add(id);
|
|
45
|
-
run(true);
|
|
46
|
-
this.#clock.cancel({ id: this.#prefix + id });
|
|
47
|
-
}
|
|
48
|
-
this.#waits.clear();
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
// The ground's carry as one house sees it: silent once the ground closes it.
|
|
52
|
-
export class HouseCarry {
|
|
53
|
-
#carry;
|
|
54
|
-
#closed = false;
|
|
55
|
-
constructor(carry) {
|
|
56
|
-
this.#carry = carry;
|
|
57
|
-
}
|
|
58
|
-
send(options) {
|
|
59
|
-
return this.#closed ? Promise.resolve({ reply: null, heard: false }) : this.#carry.send(options);
|
|
60
|
-
}
|
|
61
|
-
at(options = {}) {
|
|
62
|
-
return this.#carry.at(options);
|
|
63
|
-
}
|
|
64
|
-
vouched(options) {
|
|
65
|
-
return this.#closed ? Promise.resolve([]) : this.#carry.vouched(options);
|
|
66
|
-
}
|
|
67
|
-
close() {
|
|
68
|
-
this.#closed = true;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
// The carry the dock holds from before the ladder stands: each send goes by
|
|
72
|
-
// the carries standing when it is made, and where none stands it is unheard.
|
|
73
|
-
export class LadderCarry {
|
|
74
|
-
#carry;
|
|
75
|
-
constructor(carry) {
|
|
76
|
-
this.#carry = carry;
|
|
77
|
-
}
|
|
78
|
-
send(options) {
|
|
79
|
-
const carry = this.#carry();
|
|
80
|
-
return typeof carry === 'string' ? Promise.resolve({ reply: null, heard: false }) : carry.send(options);
|
|
81
|
-
}
|
|
82
|
-
at(options = {}) {
|
|
83
|
-
const carry = this.#carry();
|
|
84
|
-
return typeof carry === 'string' ? [] : carry.at(options);
|
|
85
|
-
}
|
|
86
|
-
vouched(options) {
|
|
87
|
-
const carry = this.#carry();
|
|
88
|
-
return typeof carry === 'string' ? Promise.resolve([]) : carry.vouched(options);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
// The places of one memory under a prefix, named without it: a view lists
|
|
92
|
-
// its own places alone, so one memory holds a ground's every house and
|
|
93
|
-
// faculty, and each reads as a memory of its own.
|
|
94
|
-
export class ViewMemory {
|
|
95
|
-
#memory;
|
|
96
|
-
#prefix;
|
|
97
|
-
constructor(memory, prefix) {
|
|
98
|
-
if (prefix === '')
|
|
99
|
-
throw new TypeError('a view names a prefix');
|
|
100
|
-
this.#memory = memory;
|
|
101
|
-
this.#prefix = prefix;
|
|
102
|
-
}
|
|
103
|
-
read({ place }) {
|
|
104
|
-
return this.#memory.read({ place: this.#prefix + place });
|
|
105
|
-
}
|
|
106
|
-
async list() {
|
|
107
|
-
return (await this.#memory.list()).filter((place) => place.startsWith(this.#prefix)).map((place) => place.slice(this.#prefix.length));
|
|
108
|
-
}
|
|
109
|
-
async write({ writes, expect }) {
|
|
110
|
-
const inner = (named) => Object.fromEntries(Object.entries(named).map(([place, value]) => [this.#prefix + place, value]));
|
|
111
|
-
const landed = await this.#memory.write({ writes: inner(writes), expect: inner(expect) });
|
|
112
|
-
if (landed === null)
|
|
113
|
-
return null;
|
|
114
|
-
return Object.fromEntries(Object.keys(writes).map((place) => [place, landed[this.#prefix + place] ?? null]));
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
const NONCE = 12;
|
|
118
|
-
// A memory whose every entry is sealed under one key. A place and an entry
|
|
119
|
-
// are kept under digests that say nothing, and each sealed entry carries
|
|
120
|
-
// its place's name and its own, so the view reads back what was written.
|
|
121
|
-
// Versions pass through, so `expect` guards one writer as it does below.
|
|
122
|
-
export class SealedMemory {
|
|
123
|
-
#memory;
|
|
124
|
-
#key;
|
|
125
|
-
#crypto;
|
|
126
|
-
#tools;
|
|
127
|
-
constructor(memory, key, crypto, tools) {
|
|
128
|
-
if (key.length !== 32)
|
|
129
|
-
throw new TypeError('a sealed memory takes a key of thirty-two bytes');
|
|
130
|
-
this.#memory = memory;
|
|
131
|
-
this.#key = key;
|
|
132
|
-
this.#crypto = crypto;
|
|
133
|
-
this.#tools = tools;
|
|
134
|
-
}
|
|
135
|
-
async #digest(text) {
|
|
136
|
-
return this.#tools.hex((await this.#crypto.sha256(new Uint8Array([...this.#key, ...this.#tools.utf8(text)]))).subarray(0, 16));
|
|
137
|
-
}
|
|
138
|
-
#place(place) {
|
|
139
|
-
return this.#digest(`place\n${place}`);
|
|
140
|
-
}
|
|
141
|
-
#entry(place, entry) {
|
|
142
|
-
return this.#digest(`entry\n${place}\n${entry}`);
|
|
143
|
-
}
|
|
144
|
-
// One entry opened: its place, its name and its bytes, or `null` where it does not open under this key.
|
|
145
|
-
async #open(stored, name, sealed) {
|
|
146
|
-
const opened = await this.#crypto.open(this.#key, sealed.subarray(0, NONCE), sealed.subarray(NONCE), this.#tools.utf8(`${stored}\n${name}`));
|
|
147
|
-
if (opened === null || opened.length < 4)
|
|
148
|
-
return null;
|
|
149
|
-
const length = new DataView(opened.buffer, opened.byteOffset, opened.byteLength).getUint32(0);
|
|
150
|
-
const header = this.#tools.text(opened.subarray(4, 4 + length));
|
|
151
|
-
const parsed = header === null ? null : this.#tools.parse(header);
|
|
152
|
-
const names = parsed?.value;
|
|
153
|
-
if (!Array.isArray(names) || names.length !== 2 || typeof names[0] !== 'string' || typeof names[1] !== 'string')
|
|
154
|
-
return null;
|
|
155
|
-
return { place: names[0], entry: names[1], bytes: opened.slice(4 + length) };
|
|
156
|
-
}
|
|
157
|
-
async read({ place }) {
|
|
158
|
-
const stored = await this.#place(place);
|
|
159
|
-
const { entries, version } = await this.#memory.read({ place: stored });
|
|
160
|
-
const read = {};
|
|
161
|
-
for (const [name, sealed] of Object.entries(entries)) {
|
|
162
|
-
const opened = await this.#open(stored, name, sealed);
|
|
163
|
-
if (opened === null || opened.place !== place)
|
|
164
|
-
throw new Error('an entry does not open under this key');
|
|
165
|
-
read[opened.entry] = opened.bytes;
|
|
166
|
-
}
|
|
167
|
-
return { entries: read, version };
|
|
168
|
-
}
|
|
169
|
-
async list() {
|
|
170
|
-
const places = [];
|
|
171
|
-
for (const stored of await this.#memory.list()) {
|
|
172
|
-
const { entries } = await this.#memory.read({ place: stored });
|
|
173
|
-
const [first] = Object.entries(entries);
|
|
174
|
-
const opened = first === undefined ? null : await this.#open(stored, first[0], first[1]);
|
|
175
|
-
if (opened !== null)
|
|
176
|
-
places.push(opened.place);
|
|
177
|
-
}
|
|
178
|
-
return places;
|
|
179
|
-
}
|
|
180
|
-
async write({ writes, expect }) {
|
|
181
|
-
const sealed = {};
|
|
182
|
-
const stored = new Map();
|
|
183
|
-
for (const place of new Set([...Object.keys(writes), ...Object.keys(expect)]))
|
|
184
|
-
stored.set(place, await this.#place(place));
|
|
185
|
-
for (const [place, entries] of Object.entries(writes)) {
|
|
186
|
-
const at = stored.get(place);
|
|
187
|
-
sealed[at] = {};
|
|
188
|
-
for (const [entry, bytes] of Object.entries(entries)) {
|
|
189
|
-
const name = await this.#entry(place, entry);
|
|
190
|
-
if (bytes === null) {
|
|
191
|
-
sealed[at][name] = null;
|
|
192
|
-
continue;
|
|
193
|
-
}
|
|
194
|
-
const header = this.#tools.utf8(this.#tools.canonical([place, entry]));
|
|
195
|
-
const plain = new Uint8Array(4 + header.length + bytes.length);
|
|
196
|
-
new DataView(plain.buffer).setUint32(0, header.length);
|
|
197
|
-
plain.set(header, 4);
|
|
198
|
-
plain.set(bytes, 4 + header.length);
|
|
199
|
-
const nonce = this.#crypto.random(NONCE);
|
|
200
|
-
sealed[at][name] = new Uint8Array([...nonce, ...(await this.#crypto.seal(this.#key, nonce, plain, this.#tools.utf8(`${at}\n${name}`)))]);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
const landed = await this.#memory.write({ writes: sealed, expect: Object.fromEntries(Object.entries(expect).map(([place, version]) => [stored.get(place), version])) });
|
|
204
|
-
if (landed === null)
|
|
205
|
-
return null;
|
|
206
|
-
return Object.fromEntries(Object.keys(writes).map((place) => [place, landed[stored.get(place)] ?? null]));
|
|
207
|
-
}
|
|
208
|
-
}
|
package/dist/house/crossing.d.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import type { Tools } from '../foundation.ts';
|
|
2
|
-
type Node = Readonly<Record<string, unknown>>;
|
|
3
|
-
/** Where a handle points, and who may pass it on. */
|
|
4
|
-
export interface Pointed {
|
|
5
|
-
readonly being: string;
|
|
6
|
-
readonly occupant: string;
|
|
7
|
-
readonly holder: string;
|
|
8
|
-
/** How long each invitation minted from it may wait unspent, in milliseconds. */
|
|
9
|
-
readonly expires?: number;
|
|
10
|
-
}
|
|
11
|
-
/** A reference to an occupant: one of her own, or one her steward minted on another being. It is no value. */
|
|
12
|
-
export declare class HandleRef {
|
|
13
|
-
readonly id: string;
|
|
14
|
-
constructor(occupant: string);
|
|
15
|
-
}
|
|
16
|
-
/** An invitation carried unopened. It is no value. */
|
|
17
|
-
export declare class Carried {
|
|
18
|
-
readonly invitation = true;
|
|
19
|
-
constructor();
|
|
20
|
-
toJSON(): never;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* One house's marks on the objects it hands its beings: where each handle
|
|
24
|
-
* points, and the bytes of each invitation carried. An object another
|
|
25
|
-
* house marked is no handle and no invitation here.
|
|
26
|
-
*/
|
|
27
|
-
export declare class Marks {
|
|
28
|
-
#private;
|
|
29
|
-
handle(being: string, occupant: string, holder?: string, expires?: number): HandleRef;
|
|
30
|
-
carried(hex: string): Carried;
|
|
31
|
-
/** Where a handle points, where it is one of this house's. */
|
|
32
|
-
handleOf(value: unknown): Pointed | undefined;
|
|
33
|
-
/** An invitation's bytes, where it is one this house carries. */
|
|
34
|
-
hexOf(value: unknown): string | undefined;
|
|
35
|
-
}
|
|
36
|
-
/** A failure of a crossing, with the message the caller reads. */
|
|
37
|
-
export declare class Crossing extends Error {
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Her value made wire JSON. `mint` turns a handle she holds into the hex its
|
|
41
|
-
* receiver can call. `owner` is her id: a handle she does not hold is refused.
|
|
42
|
-
* A handle under `s.invitation` leaves as an invitation, as one carried does.
|
|
43
|
-
* An invitation carried under `s.handle` leaves as itself, for its receiver
|
|
44
|
-
* to take. `redeem` turns a carried invitation this house minted into what
|
|
45
|
-
* its reader calls, where the reader is a faculty: a token for its occupant.
|
|
46
|
-
*/
|
|
47
|
-
export declare const outward: (tools: Tools, marks: Marks, schema: Node | undefined, value: unknown, owner: string, mint: (handle: Pointed) => Promise<string>, redeem?: (hex: string) => Promise<string | undefined>) => Promise<unknown>;
|
|
48
|
-
/** Wire JSON made her value. `accept` turns an invitation's hex into a standing id. */
|
|
49
|
-
export declare const inward: (tools: Tools, marks: Marks, schema: Node | undefined, value: unknown, accept: (hex: string) => Promise<string>) => Promise<unknown>;
|
|
50
|
-
export {};
|
package/dist/house/crossing.js
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// What crosses between a being and the wire. A handle, an invitation
|
|
3
|
-
// carried unopened and bytes are objects in her hands and hex on the wire.
|
|
4
|
-
// The schema says where each stands.
|
|
5
|
-
import { HANDLE_MEDIA, INVITATION_MEDIA } from '../being/schema.js';
|
|
6
|
-
/** A reference to an occupant: one of her own, or one her steward minted on another being. It is no value. */
|
|
7
|
-
export class HandleRef {
|
|
8
|
-
id;
|
|
9
|
-
constructor(occupant) {
|
|
10
|
-
this.id = occupant;
|
|
11
|
-
Object.freeze(this);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
/** An invitation carried unopened. It is no value. */
|
|
15
|
-
export class Carried {
|
|
16
|
-
invitation = true;
|
|
17
|
-
constructor() {
|
|
18
|
-
Object.freeze(this);
|
|
19
|
-
}
|
|
20
|
-
toJSON() {
|
|
21
|
-
throw new Crossing('an invitation carried unopened is no value');
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* One house's marks on the objects it hands its beings: where each handle
|
|
26
|
-
* points, and the bytes of each invitation carried. An object another
|
|
27
|
-
* house marked is no handle and no invitation here.
|
|
28
|
-
*/
|
|
29
|
-
export class Marks {
|
|
30
|
-
#minted = new WeakMap();
|
|
31
|
-
#carried = new WeakMap();
|
|
32
|
-
handle(being, occupant, holder = being, expires) {
|
|
33
|
-
const handle = new HandleRef(occupant);
|
|
34
|
-
this.#minted.set(handle, { being, occupant, holder, ...(expires === undefined ? {} : { expires }) });
|
|
35
|
-
return handle;
|
|
36
|
-
}
|
|
37
|
-
carried(hex) {
|
|
38
|
-
const invitation = new Carried();
|
|
39
|
-
this.#carried.set(invitation, hex);
|
|
40
|
-
return invitation;
|
|
41
|
-
}
|
|
42
|
-
/** Where a handle points, where it is one of this house's. */
|
|
43
|
-
handleOf(value) {
|
|
44
|
-
return typeof value === 'object' && value !== null ? this.#minted.get(value) : undefined;
|
|
45
|
-
}
|
|
46
|
-
/** An invitation's bytes, where it is one this house carries. */
|
|
47
|
-
hexOf(value) {
|
|
48
|
-
return typeof value === 'object' && value !== null ? this.#carried.get(value) : undefined;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
/** A failure of a crossing, with the message the caller reads. */
|
|
52
|
-
export class Crossing extends Error {
|
|
53
|
-
}
|
|
54
|
-
const branchFits = (tools, branch, value) => tools.check(branch, value) === null;
|
|
55
|
-
/**
|
|
56
|
-
* Her value made wire JSON. `mint` turns a handle she holds into the hex its
|
|
57
|
-
* receiver can call. `owner` is her id: a handle she does not hold is refused.
|
|
58
|
-
* A handle under `s.invitation` leaves as an invitation, as one carried does.
|
|
59
|
-
* An invitation carried under `s.handle` leaves as itself, for its receiver
|
|
60
|
-
* to take. `redeem` turns a carried invitation this house minted into what
|
|
61
|
-
* its reader calls, where the reader is a faculty: a token for its occupant.
|
|
62
|
-
*/
|
|
63
|
-
export const outward = async (tools, marks, schema, value, owner, mint, redeem = () => Promise.resolve(undefined)) => {
|
|
64
|
-
const held = (at) => {
|
|
65
|
-
const handle = marks.handleOf(at);
|
|
66
|
-
return handle !== undefined && handle.holder === owner ? handle : undefined;
|
|
67
|
-
};
|
|
68
|
-
const walk = async (node, at) => {
|
|
69
|
-
if (node === undefined)
|
|
70
|
-
return at;
|
|
71
|
-
if (node.contentMediaType === HANDLE_MEDIA) {
|
|
72
|
-
const handle = held(at);
|
|
73
|
-
if (handle !== undefined)
|
|
74
|
-
return mint(handle);
|
|
75
|
-
// An invitation carried unopened is handed on, and its receiver takes it.
|
|
76
|
-
const hex = marks.hexOf(at);
|
|
77
|
-
if (hex === undefined)
|
|
78
|
-
throw new Crossing('a handle is owed where a value stands');
|
|
79
|
-
return (await redeem(hex)) ?? hex;
|
|
80
|
-
}
|
|
81
|
-
if (node.contentMediaType === INVITATION_MEDIA) {
|
|
82
|
-
const handle = held(at);
|
|
83
|
-
if (handle !== undefined)
|
|
84
|
-
return mint(handle);
|
|
85
|
-
const hex = marks.hexOf(at);
|
|
86
|
-
if (hex === undefined)
|
|
87
|
-
throw new Crossing('an invitation is owed where a value stands');
|
|
88
|
-
return (await redeem(hex)) ?? hex;
|
|
89
|
-
}
|
|
90
|
-
if (node.contentEncoding === 'base16' && at instanceof Uint8Array)
|
|
91
|
-
return tools.hex(at);
|
|
92
|
-
if (Array.isArray(node.anyOf)) {
|
|
93
|
-
for (const branch of node.anyOf) {
|
|
94
|
-
try {
|
|
95
|
-
const out = await walk(branch, at);
|
|
96
|
-
if (branchFits(tools, branch, out))
|
|
97
|
-
return out;
|
|
98
|
-
}
|
|
99
|
-
catch (error) {
|
|
100
|
-
if (!(error instanceof Crossing))
|
|
101
|
-
throw error;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return at;
|
|
105
|
-
}
|
|
106
|
-
if (Array.isArray(at) && node.items !== undefined)
|
|
107
|
-
return Promise.all(at.map((item) => walk(node.items, item)));
|
|
108
|
-
if (typeof at === 'object' && at !== null && !Array.isArray(at) && !(at instanceof Uint8Array) && node.properties !== undefined) {
|
|
109
|
-
const properties = node.properties;
|
|
110
|
-
const out = {};
|
|
111
|
-
for (const [key, field] of Object.entries(at)) {
|
|
112
|
-
if (field === undefined)
|
|
113
|
-
continue;
|
|
114
|
-
out[key] = await walk(Object.hasOwn(properties, key) ? properties[key] : undefined, field);
|
|
115
|
-
}
|
|
116
|
-
return out;
|
|
117
|
-
}
|
|
118
|
-
return at;
|
|
119
|
-
};
|
|
120
|
-
const out = await walk(schema, value);
|
|
121
|
-
const why = schema === undefined ? null : tools.check(schema, out);
|
|
122
|
-
if (why !== null)
|
|
123
|
-
throw new Crossing(why);
|
|
124
|
-
return out;
|
|
125
|
-
};
|
|
126
|
-
/** Wire JSON made her value. `accept` turns an invitation's hex into a standing id. */
|
|
127
|
-
export const inward = async (tools, marks, schema, value, accept) => {
|
|
128
|
-
const walk = async (node, at) => {
|
|
129
|
-
if (node === undefined)
|
|
130
|
-
return at;
|
|
131
|
-
if (node.contentMediaType === HANDLE_MEDIA)
|
|
132
|
-
return accept(at);
|
|
133
|
-
if (node.contentMediaType === INVITATION_MEDIA)
|
|
134
|
-
return marks.carried(at);
|
|
135
|
-
if (node.contentEncoding === 'base16')
|
|
136
|
-
return tools.bytes(at);
|
|
137
|
-
if (Array.isArray(node.anyOf)) {
|
|
138
|
-
const branch = node.anyOf.find((option) => branchFits(tools, option, at));
|
|
139
|
-
return walk(branch, at);
|
|
140
|
-
}
|
|
141
|
-
if (Array.isArray(at) && node.items !== undefined)
|
|
142
|
-
return Promise.all(at.map((item) => walk(node.items, item)));
|
|
143
|
-
if (typeof at === 'object' && at !== null && !Array.isArray(at) && node.properties !== undefined) {
|
|
144
|
-
const properties = node.properties;
|
|
145
|
-
const out = {};
|
|
146
|
-
for (const [key, field] of Object.entries(at))
|
|
147
|
-
out[key] = await walk(Object.hasOwn(properties, key) ? properties[key] : undefined, field);
|
|
148
|
-
return out;
|
|
149
|
-
}
|
|
150
|
-
return at;
|
|
151
|
-
};
|
|
152
|
-
return walk(schema, value);
|
|
153
|
-
};
|
package/dist/house/house.d.ts
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import type { Json } from '../being/being.ts';
|
|
2
|
-
import type { Carry, Classes, Clock, Crypto, Keys, Memory, Tools } from '../foundation.ts';
|
|
3
|
-
import { type Answer } from './rows-shape.ts';
|
|
4
|
-
export type { Answer } from './rows-shape.ts';
|
|
5
|
-
/** The seven references a house calls. */
|
|
6
|
-
export interface Foundation {
|
|
7
|
-
readonly keys: Keys;
|
|
8
|
-
readonly memory: Memory;
|
|
9
|
-
readonly classes: Classes;
|
|
10
|
-
readonly carry: Carry;
|
|
11
|
-
readonly clock: Clock;
|
|
12
|
-
readonly crypto: Crypto;
|
|
13
|
-
readonly tools: Tools;
|
|
14
|
-
}
|
|
15
|
-
/** A faculty the ground offers to beings. */
|
|
16
|
-
export interface Offer {
|
|
17
|
-
readonly blueprint: unknown;
|
|
18
|
-
readonly object: object;
|
|
19
|
-
readonly kinds?: readonly string[];
|
|
20
|
-
/** How long the faculty remembers a call id, in milliseconds. */
|
|
21
|
-
readonly window?: number;
|
|
22
|
-
/** Told once the house opens, with the house's context, so its tokens answer before any being calls it. */
|
|
23
|
-
opened?(context: OpenedContext): void | Promise<void>;
|
|
24
|
-
}
|
|
25
|
-
/** What a faculty is handed when a house that offers it opens: the house's ward, and its tokens called as a method's context calls them. */
|
|
26
|
-
export interface OpenedContext {
|
|
27
|
-
readonly ward: string;
|
|
28
|
-
readonly call: FacultyContext['call'];
|
|
29
|
-
readonly describe: FacultyContext['describe'];
|
|
30
|
-
}
|
|
31
|
-
/** What a faculty's method receives beside its args. */
|
|
32
|
-
export interface FacultyContext {
|
|
33
|
-
readonly id: string;
|
|
34
|
-
/**
|
|
35
|
-
* A token it was handed, asked. A handle's token asks its one ask. An
|
|
36
|
-
* occupant's token asks the `method` named, as that occupant, and
|
|
37
|
-
* `after` makes a `readOnly` ask a watch. `home` carries the answer's
|
|
38
|
-
* handles home: they leave as invitation bytes, which a house takes,
|
|
39
|
-
* in place of tokens.
|
|
40
|
-
*/
|
|
41
|
-
call(options: {
|
|
42
|
-
token: string;
|
|
43
|
-
method?: string;
|
|
44
|
-
args?: Json;
|
|
45
|
-
id: string;
|
|
46
|
-
after?: Answer;
|
|
47
|
-
home?: boolean;
|
|
48
|
-
}): Promise<Answer>;
|
|
49
|
-
/** What the occupant behind a token may ask now, as her describe shows it. */
|
|
50
|
-
describe(options: {
|
|
51
|
-
token: string;
|
|
52
|
-
}): Promise<{
|
|
53
|
-
describe: Json;
|
|
54
|
-
} | {
|
|
55
|
-
error: {
|
|
56
|
-
message: string;
|
|
57
|
-
};
|
|
58
|
-
}>;
|
|
59
|
-
}
|
|
60
|
-
/** What `House.open` gives. */
|
|
61
|
-
export interface Opened {
|
|
62
|
-
readonly ward: string;
|
|
63
|
-
door(box: Uint8Array): Promise<Uint8Array | null>;
|
|
64
|
-
/**
|
|
65
|
-
* The hand: a being asked by `id` as `root`, the steward where no id is
|
|
66
|
-
* named. `after` is the answer the caller holds, which makes a `readOnly`
|
|
67
|
-
* ask a watch. `cells` reads her cells and asks nothing, which no other
|
|
68
|
-
* way into the house can. `call` is the ask's call id: asked again, it
|
|
69
|
-
* answers what the first answered and runs nothing twice.
|
|
70
|
-
*/
|
|
71
|
-
ask(request: {
|
|
72
|
-
id?: string;
|
|
73
|
-
method?: string;
|
|
74
|
-
args?: Json;
|
|
75
|
-
after?: Answer;
|
|
76
|
-
cells?: true;
|
|
77
|
-
call?: string;
|
|
78
|
-
}): Promise<Answer | {
|
|
79
|
-
readonly describe: Json;
|
|
80
|
-
}>;
|
|
81
|
-
}
|
|
82
|
-
/** What a ground may set on a house beside its foundation and offers. */
|
|
83
|
-
export interface Options {
|
|
84
|
-
/** The longest any ask here may take, in milliseconds. Each entry's own wait stands under it. */
|
|
85
|
-
readonly wait?: number;
|
|
86
|
-
}
|
|
87
|
-
/** A house opened on its foundation and its offers: its ward, its door and its hand, and nothing more. */
|
|
88
|
-
export declare const openHouse: (foundation: Foundation, offers: readonly Offer[], options?: Options) => Promise<Opened>;
|