nervur 0.22.0 → 0.22.2-3
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/AUTHORING.md +741 -0
- package/KIT-SPEC.md +286 -0
- package/LICENSE +1 -1
- package/NOTICE +6 -2
- package/README.md +97 -424
- package/dist/app/app-ground.d.ts +18 -0
- package/dist/app/app-ground.js +25 -0
- package/dist/app/index.d.ts +2 -0
- package/dist/app/index.js +5 -0
- package/dist/app/native.d.ts +46 -0
- package/dist/app/native.js +101 -0
- package/dist/being/being.d.ts +229 -0
- package/dist/being/being.js +20 -0
- package/dist/being/covers.d.ts +9 -0
- package/dist/being/covers.js +21 -0
- package/dist/being/index.d.ts +3 -0
- package/dist/being/index.js +5 -0
- package/dist/being/need.d.ts +49 -0
- package/dist/being/need.js +33 -0
- package/dist/being/schema.d.ts +100 -0
- package/dist/being/schema.js +132 -0
- package/dist/being/table.d.ts +42 -0
- package/dist/being/table.js +288 -0
- package/dist/bench/bench-ground.d.ts +55 -0
- package/dist/bench/bench-ground.js +101 -0
- package/dist/bench/bench.d.ts +87 -0
- package/dist/bench/bench.js +260 -0
- package/dist/bench/fake-carry.d.ts +32 -0
- package/dist/bench/fake-carry.js +56 -0
- package/dist/bench/fake-clock.d.ts +17 -0
- package/dist/bench/fake-clock.js +34 -0
- package/dist/bench/fake-custody.d.ts +9 -0
- package/dist/bench/fake-custody.js +10 -0
- package/dist/bench/fake-faculty.d.ts +25 -0
- package/dist/bench/fake-faculty.js +48 -0
- package/dist/bench/fake-keys.d.ts +5 -0
- package/dist/bench/fake-keys.js +9 -0
- package/dist/bench/fake-memory.d.ts +14 -0
- package/dist/bench/fake-memory.js +46 -0
- package/dist/bench/fake-network.d.ts +57 -0
- package/dist/bench/fake-network.js +169 -0
- package/dist/bench/index.d.ts +11 -0
- package/dist/bench/index.js +13 -0
- package/dist/bench/seeded.d.ts +11 -0
- package/dist/bench/seeded.js +37 -0
- package/dist/bench/settle.d.ts +2 -0
- package/dist/bench/settle.js +49 -0
- package/dist/bench/stewards.d.ts +17 -0
- package/dist/bench/stewards.js +20 -0
- package/dist/bodies/class-list.d.ts +14 -0
- package/dist/bodies/class-list.js +33 -0
- package/dist/bodies/joined-carry.d.ts +23 -0
- package/dist/bodies/joined-carry.js +42 -0
- package/dist/bodies/noble-crypto.d.ts +22 -0
- package/dist/bodies/noble-crypto.js +88 -0
- package/dist/bodies/seed-keys.d.ts +10 -0
- package/dist/bodies/seed-keys.js +42 -0
- package/dist/bodies/strict-tools.d.ts +10 -0
- package/dist/bodies/strict-tools.js +306 -0
- package/dist/bodies/web-carry.d.ts +65 -0
- package/dist/bodies/web-carry.js +224 -0
- package/dist/bodies/web-clock.d.ts +12 -0
- package/dist/bodies/web-clock.js +33 -0
- package/dist/browser/browser-ground.d.ts +69 -0
- package/dist/browser/browser-ground.js +219 -0
- package/dist/browser/index.d.ts +4 -0
- package/dist/browser/index.js +7 -0
- package/dist/browser/indexeddb-memory.d.ts +17 -0
- package/dist/browser/indexeddb-memory.js +97 -0
- package/dist/browser/locked-custody.d.ts +25 -0
- package/dist/browser/locked-custody.js +89 -0
- package/dist/browser/origin-classes.d.ts +7 -0
- package/dist/browser/origin-classes.js +31 -0
- package/dist/foundation.d.ts +150 -0
- package/dist/foundation.js +4 -0
- package/dist/ground/ground.d.ts +177 -0
- package/dist/ground/ground.js +363 -0
- package/dist/house/crossing.d.ts +37 -0
- package/dist/house/crossing.js +131 -0
- package/dist/house/house.d.ts +80 -0
- package/dist/house/house.js +1753 -0
- package/dist/house/rows-shape.d.ts +103 -0
- package/dist/house/rows-shape.js +12 -0
- package/dist/house/rows.d.ts +27 -0
- package/dist/house/rows.js +168 -0
- package/dist/index.d.ts +29 -1
- package/dist/index.js +25 -14
- package/dist/node/bridge.d.ts +17 -0
- package/dist/node/bridge.js +188 -0
- package/dist/node/cli.js +170 -0
- package/dist/node/custody.d.ts +20 -0
- package/dist/node/custody.js +34 -0
- package/dist/node/file-keys.d.ts +7 -0
- package/dist/node/file-keys.js +30 -0
- package/dist/node/file-memory.d.ts +13 -0
- package/dist/node/file-memory.js +91 -0
- package/dist/node/folder-classes.d.ts +5 -0
- package/dist/node/folder-classes.js +40 -0
- package/dist/node/gone.d.ts +2 -0
- package/dist/node/gone.js +7 -0
- package/dist/node/hand.d.ts +29 -0
- package/dist/node/hand.js +85 -0
- package/dist/node/held-keys.d.ts +14 -0
- package/dist/node/held-keys.js +36 -0
- package/dist/node/http.d.ts +11 -0
- package/dist/node/http.js +90 -0
- package/dist/node/index.d.ts +13 -0
- package/dist/node/index.js +15 -0
- package/dist/node/keychain-keys.d.ts +10 -0
- package/dist/node/keychain-keys.js +51 -0
- package/dist/node/ledger-memory.d.ts +17 -0
- package/dist/node/ledger-memory.js +151 -0
- package/dist/node/lock.d.ts +10 -0
- package/dist/node/lock.js +78 -0
- package/dist/node/node-ground.d.ts +33 -0
- package/dist/node/node-ground.js +147 -0
- package/dist/node/notify.d.ts +1 -0
- package/dist/node/notify.js +18 -0
- package/dist/node/tcp-carry.d.ts +39 -0
- package/dist/node/tcp-carry.js +216 -0
- package/dist/node/websocket.d.ts +6 -0
- package/dist/node/websocket.js +118 -0
- package/dist/quo/frame.d.ts +20 -0
- package/dist/quo/frame.js +48 -0
- package/dist/quo/room.d.ts +154 -0
- package/dist/quo/room.js +362 -0
- package/dist/serve/index.d.ts +27 -0
- package/dist/serve/index.js +55 -0
- package/package.json +49 -47
- package/dist/browser.d.ts +0 -1
- package/dist/browser.js +0 -8
- package/dist/cli.js +0 -16
- package/dist/core/being/being.d.ts +0 -17
- package/dist/core/being/being.js +0 -72
- package/dist/core/being/digest.d.ts +0 -3
- package/dist/core/being/digest.js +0 -17
- package/dist/core/being/faculty.d.ts +0 -10
- package/dist/core/being/faculty.js +0 -77
- package/dist/core/being/index.d.ts +0 -6
- package/dist/core/being/index.js +0 -8
- package/dist/core/being/kind.d.ts +0 -6
- package/dist/core/being/kind.js +0 -34
- package/dist/core/being/types.d.ts +0 -61
- package/dist/core/being/types.js +0 -4
- package/dist/core/being/words.d.ts +0 -13
- package/dist/core/being/words.js +0 -14
- package/dist/core/browser/index.d.ts +0 -37
- package/dist/core/browser/index.js +0 -196
- package/dist/core/browser/worker.d.ts +0 -11
- package/dist/core/browser/worker.js +0 -37
- package/dist/core/cli/command.d.ts +0 -13
- package/dist/core/cli/command.js +0 -330
- package/dist/core/cli/edge.d.ts +0 -7
- package/dist/core/cli/edge.js +0 -79
- package/dist/core/cli/harbor.d.ts +0 -25
- package/dist/core/cli/harbor.js +0 -115
- package/dist/core/contract/index.d.ts +0 -42
- package/dist/core/contract/index.js +0 -34
- package/dist/core/contract/link.d.ts +0 -4
- package/dist/core/contract/link.js +0 -45
- package/dist/core/crypto/aes.d.ts +0 -3
- package/dist/core/crypto/aes.js +0 -24
- package/dist/core/crypto/bytes.d.ts +0 -6
- package/dist/core/crypto/bytes.js +0 -33
- package/dist/core/crypto/ed25519.d.ts +0 -3
- package/dist/core/crypto/ed25519.js +0 -93
- package/dist/core/crypto/hash.d.ts +0 -2
- package/dist/core/crypto/hash.js +0 -11
- package/dist/core/crypto/index.d.ts +0 -7
- package/dist/core/crypto/index.js +0 -10
- package/dist/core/crypto/json.d.ts +0 -8
- package/dist/core/crypto/json.js +0 -250
- package/dist/core/crypto/mlkem.d.ts +0 -12
- package/dist/core/crypto/mlkem.js +0 -36
- package/dist/core/crypto/subtle.d.ts +0 -3
- package/dist/core/crypto/subtle.js +0 -11
- package/dist/core/crypto/x25519.d.ts +0 -2
- package/dist/core/crypto/x25519.js +0 -24
- package/dist/core/edge/index.d.ts +0 -164
- package/dist/core/edge/index.js +0 -739
- package/dist/core/edge/kit.d.ts +0 -2
- package/dist/core/edge/kit.js +0 -2
- package/dist/core/folder/index.d.ts +0 -18
- package/dist/core/folder/index.js +0 -130
- package/dist/core/git/http.d.ts +0 -6
- package/dist/core/git/http.js +0 -102
- package/dist/core/git/index.d.ts +0 -5
- package/dist/core/git/index.js +0 -10
- package/dist/core/git/object.d.ts +0 -40
- package/dist/core/git/object.js +0 -103
- package/dist/core/git/pack.d.ts +0 -9
- package/dist/core/git/pack.js +0 -171
- package/dist/core/git/store.d.ts +0 -23
- package/dist/core/git/store.js +0 -120
- package/dist/core/git/zlib.d.ts +0 -6
- package/dist/core/git/zlib.js +0 -210
- package/dist/core/harbor/carrying.d.ts +0 -51
- package/dist/core/harbor/carrying.js +0 -69
- package/dist/core/harbor/catalogue.d.ts +0 -33
- package/dist/core/harbor/catalogue.js +0 -365
- package/dist/core/harbor/dna.d.ts +0 -13
- package/dist/core/harbor/dna.js +0 -120
- package/dist/core/harbor/dock.d.ts +0 -62
- package/dist/core/harbor/dock.js +0 -381
- package/dist/core/harbor/harbor.d.ts +0 -16
- package/dist/core/harbor/harbor.js +0 -438
- package/dist/core/harbor/index.d.ts +0 -11
- package/dist/core/harbor/index.js +0 -14
- package/dist/core/harbor/memory.d.ts +0 -10
- package/dist/core/harbor/memory.js +0 -25
- package/dist/core/harbor/package.d.ts +0 -20
- package/dist/core/harbor/package.js +0 -172
- package/dist/core/harbor/probe.d.ts +0 -22
- package/dist/core/harbor/probe.js +0 -15
- package/dist/core/harbor/registry.d.ts +0 -15
- package/dist/core/harbor/registry.js +0 -110
- package/dist/core/harbor/root-line.d.ts +0 -7
- package/dist/core/harbor/root-line.js +0 -9
- package/dist/core/harbor/terrain.d.ts +0 -25
- package/dist/core/harbor/terrain.js +0 -28
- package/dist/core/http/index.d.ts +0 -2
- package/dist/core/http/index.js +0 -154
- package/dist/core/http/websocket.d.ts +0 -29
- package/dist/core/http/websocket.js +0 -133
- package/dist/core/line/answer.d.ts +0 -8
- package/dist/core/line/answer.js +0 -60
- package/dist/core/line/frame.d.ts +0 -29
- package/dist/core/line/frame.js +0 -77
- package/dist/core/line/ground.d.ts +0 -3
- package/dist/core/line/ground.js +0 -7
- package/dist/core/line/index.d.ts +0 -4
- package/dist/core/line/index.js +0 -8
- package/dist/core/line/web.d.ts +0 -12
- package/dist/core/line/web.js +0 -117
- package/dist/core/node/index.d.ts +0 -23
- package/dist/core/node/index.js +0 -124
- package/dist/core/pointer/bodies.d.ts +0 -31
- package/dist/core/pointer/bodies.js +0 -118
- package/dist/core/pointer/index.d.ts +0 -2
- package/dist/core/pointer/index.js +0 -4
- package/dist/core/pointer/world.d.ts +0 -45
- package/dist/core/pointer/world.js +0 -106
- package/dist/core/proof/contracts.d.ts +0 -19
- package/dist/core/proof/contracts.js +0 -116
- package/dist/core/proof/expect.d.ts +0 -6
- package/dist/core/proof/expect.js +0 -18
- package/dist/core/proof/index.d.ts +0 -3
- package/dist/core/proof/index.js +0 -14
- package/dist/core/proof/law.d.ts +0 -25
- package/dist/core/proof/law.js +0 -715
- package/dist/core/quo/address.d.ts +0 -19
- package/dist/core/quo/address.js +0 -84
- package/dist/core/quo/door.d.ts +0 -34
- package/dist/core/quo/door.js +0 -174
- package/dist/core/quo/index.d.ts +0 -9
- package/dist/core/quo/index.js +0 -12
- package/dist/core/quo/invitation.d.ts +0 -8
- package/dist/core/quo/invitation.js +0 -19
- package/dist/core/quo/keys.d.ts +0 -40
- package/dist/core/quo/keys.js +0 -79
- package/dist/core/quo/payload.d.ts +0 -15
- package/dist/core/quo/payload.js +0 -55
- package/dist/core/quo/relations.d.ts +0 -40
- package/dist/core/quo/relations.js +0 -33
- package/dist/core/quo/reply.d.ts +0 -13
- package/dist/core/quo/reply.js +0 -35
- package/dist/core/quo/seal.d.ts +0 -42
- package/dist/core/quo/seal.js +0 -78
- package/dist/core/quo/standing.d.ts +0 -39
- package/dist/core/quo/standing.js +0 -90
- package/dist/core/tcp/index.d.ts +0 -27
- package/dist/core/tcp/index.js +0 -209
- package/dist/core/ward/allowance.d.ts +0 -14
- package/dist/core/ward/allowance.js +0 -32
- package/dist/core/ward/cells.d.ts +0 -7
- package/dist/core/ward/cells.js +0 -74
- package/dist/core/ward/house.d.ts +0 -67
- package/dist/core/ward/house.js +0 -473
- package/dist/core/ward/index.d.ts +0 -5
- package/dist/core/ward/index.js +0 -7
- package/dist/core/ward/partition.d.ts +0 -50
- package/dist/core/ward/partition.js +0 -66
- package/dist/core/ward/stance.d.ts +0 -29
- package/dist/core/ward/stance.js +0 -186
- package/dist/core/ward/ward.d.ts +0 -44
- package/dist/core/ward/ward.js +0 -140
- package/dist/core.d.ts +0 -10
- package/dist/core.js +0 -19
- package/dist/defaults/dock/index.d.ts +0 -4
- package/dist/defaults/dock/index.js +0 -11
- package/dist/defaults/index.d.ts +0 -5
- package/dist/defaults/index.js +0 -10
- package/dist/defaults/memory/index.d.ts +0 -12
- package/dist/defaults/memory/index.js +0 -39
- package/dist/defaults/tcp/index.d.ts +0 -16
- package/dist/defaults/tcp/index.js +0 -82
- package/dist/defaults/ward/index.d.ts +0 -4
- package/dist/defaults/ward/index.js +0 -11
- package/dist/defaults/web/index.d.ts +0 -15
- package/dist/defaults/web/index.js +0 -90
- package/dist/edge.d.ts +0 -1
- package/dist/edge.js +0 -9
- package/dist/kit.d.ts +0 -4
- package/dist/kit.js +0 -12
- package/dist/node.d.ts +0 -1
- package/dist/node.js +0 -8
- package/src/browser.ts +0 -10
- package/src/cli.ts +0 -15
- package/src/core/being/being.ts +0 -84
- package/src/core/being/digest.ts +0 -18
- package/src/core/being/faculty.ts +0 -76
- package/src/core/being/index.ts +0 -8
- package/src/core/being/kind.ts +0 -37
- package/src/core/being/types.ts +0 -74
- package/src/core/being/words.ts +0 -31
- package/src/core/browser/index.ts +0 -219
- package/src/core/browser/worker.ts +0 -63
- package/src/core/cli/command.ts +0 -311
- package/src/core/cli/edge.ts +0 -86
- package/src/core/cli/harbor.ts +0 -120
- package/src/core/contract/index.ts +0 -82
- package/src/core/contract/link.ts +0 -58
- package/src/core/crypto/aes.ts +0 -26
- package/src/core/crypto/bytes.ts +0 -37
- package/src/core/crypto/ed25519.ts +0 -92
- package/src/core/crypto/hash.ts +0 -14
- package/src/core/crypto/index.ts +0 -10
- package/src/core/crypto/json.ts +0 -241
- package/src/core/crypto/mlkem.ts +0 -38
- package/src/core/crypto/subtle.ts +0 -13
- package/src/core/crypto/x25519.ts +0 -23
- package/src/core/edge/index.ts +0 -865
- package/src/core/folder/index.ts +0 -137
- package/src/core/git/http.ts +0 -103
- package/src/core/git/index.ts +0 -10
- package/src/core/git/object.ts +0 -116
- package/src/core/git/pack.ts +0 -147
- package/src/core/git/store.ts +0 -122
- package/src/core/git/zlib.ts +0 -197
- package/src/core/harbor/carrying.ts +0 -124
- package/src/core/harbor/catalogue.ts +0 -386
- package/src/core/harbor/dna.ts +0 -116
- package/src/core/harbor/dock.ts +0 -420
- package/src/core/harbor/harbor.ts +0 -433
- package/src/core/harbor/index.ts +0 -14
- package/src/core/harbor/memory.ts +0 -31
- package/src/core/harbor/package.ts +0 -195
- package/src/core/harbor/probe.ts +0 -39
- package/src/core/harbor/registry.ts +0 -107
- package/src/core/harbor/root-line.ts +0 -19
- package/src/core/harbor/terrain.ts +0 -54
- package/src/core/http/index.ts +0 -147
- package/src/core/http/websocket.ts +0 -124
- package/src/core/line/answer.ts +0 -60
- package/src/core/line/frame.ts +0 -83
- package/src/core/line/ground.ts +0 -18
- package/src/core/line/index.ts +0 -8
- package/src/core/line/web.ts +0 -123
- package/src/core/node/index.ts +0 -139
- package/src/core/pointer/bodies.ts +0 -122
- package/src/core/pointer/index.ts +0 -4
- package/src/core/pointer/world.ts +0 -134
- package/src/core/proof/contracts.ts +0 -134
- package/src/core/proof/expect.ts +0 -25
- package/src/core/proof/index.ts +0 -14
- package/src/core/proof/law.ts +0 -742
- package/src/core/quo/address.ts +0 -87
- package/src/core/quo/door.ts +0 -180
- package/src/core/quo/index.ts +0 -12
- package/src/core/quo/invitation.ts +0 -19
- package/src/core/quo/keys.ts +0 -91
- package/src/core/quo/payload.ts +0 -61
- package/src/core/quo/relations.ts +0 -62
- package/src/core/quo/reply.ts +0 -38
- package/src/core/quo/seal.ts +0 -101
- package/src/core/quo/standing.ts +0 -111
- package/src/core/stand/main.ts +0 -20
- package/src/core/stand/stand.ts +0 -259
- package/src/core/tcp/index.ts +0 -227
- package/src/core/ward/allowance.ts +0 -47
- package/src/core/ward/cells.ts +0 -77
- package/src/core/ward/house.ts +0 -524
- package/src/core/ward/index.ts +0 -7
- package/src/core/ward/partition.ts +0 -117
- package/src/core/ward/stance.ts +0 -207
- package/src/core/ward/ward.ts +0 -166
- package/src/core.ts +0 -55
- package/src/defaults/dock/index.ts +0 -12
- package/src/defaults/index.ts +0 -10
- package/src/defaults/memory/index.ts +0 -50
- package/src/defaults/tcp/index.ts +0 -89
- package/src/defaults/ward/index.ts +0 -12
- package/src/defaults/web/index.ts +0 -97
- package/src/edge.ts +0 -11
- package/src/index.ts +0 -18
- package/src/kit.ts +0 -15
- package/src/node.ts +0 -10
- /package/dist/{cli.d.ts → node/cli.d.ts} +0 -0
package/src/core/ward/cells.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// A being's cells, guarded. Her cells are kept by whatever memory her
|
|
3
|
-
// terrain gives, and a memory that writes JSON would hand back something
|
|
4
|
-
// other than what she wrote if she wrote anything JSON cannot hold. So a
|
|
5
|
-
// write that is not a value throws where she wrote it, in her own frame,
|
|
6
|
-
// and her answer becomes silence like any throw.
|
|
7
|
-
//
|
|
8
|
-
// What passes is stored as a fresh copy of its JSON text, so a reference
|
|
9
|
-
// she kept to what she wrote is not a way around the guard. Every key lands
|
|
10
|
-
// as an own key, `__proto__` included. A list grows at its end: a slot or a
|
|
11
|
-
// length past it would leave a hole.
|
|
12
|
-
import { writeValue, type Json } from '../crypto/index.ts';
|
|
13
|
-
import type { JsonObject } from '../being/index.ts';
|
|
14
|
-
|
|
15
|
-
export const DEPTH = 64;
|
|
16
|
-
|
|
17
|
-
const refuse = (why: string): never => {
|
|
18
|
-
throw new TypeError(`cells hold values: ${why}`);
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const copy = (value: unknown, room: number, where: string): Json => {
|
|
22
|
-
const text = writeValue(value, room);
|
|
23
|
-
return text === undefined ? refuse(`${where} is not a value JSON keeps, within ${room} levels`) : (JSON.parse(text) as Json);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export class Cells {
|
|
27
|
-
readonly #guards = new WeakMap<object, object>();
|
|
28
|
-
readonly #wrote: () => void;
|
|
29
|
-
|
|
30
|
-
constructor(wrote: () => void) {
|
|
31
|
-
this.#wrote = wrote;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// The guarded view of a being's cells.
|
|
35
|
-
guard(cells: JsonObject): JsonObject {
|
|
36
|
-
return this.#guard(cells, 'cells', 1);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
#guard<T extends object>(target: T, path: string, level: number): T {
|
|
40
|
-
const had = this.#guards.get(target);
|
|
41
|
-
if (had) return had as T;
|
|
42
|
-
const room = DEPTH - level;
|
|
43
|
-
const place = (t: T, k: string | symbol, value: unknown): boolean => {
|
|
44
|
-
if (typeof k !== 'string') return refuse(`${path} takes no symbol key`);
|
|
45
|
-
const where = `${path}.${k}`;
|
|
46
|
-
if (Array.isArray(t)) {
|
|
47
|
-
if (k === 'length') {
|
|
48
|
-
if (typeof value !== 'number' || value > t.length) refuse(`${where} past its end would leave a hole`);
|
|
49
|
-
t.length = value as number;
|
|
50
|
-
this.#wrote();
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
if (!/^(0|[1-9]\d*)$/.test(k)) refuse(`${where} is not a slot of a list`);
|
|
54
|
-
if (Number(k) > t.length) refuse(`${where} would leave a hole`);
|
|
55
|
-
}
|
|
56
|
-
const ok = Reflect.defineProperty(t, k, { value: copy(value, room, where), enumerable: true, writable: true, configurable: true });
|
|
57
|
-
this.#wrote();
|
|
58
|
-
return ok;
|
|
59
|
-
};
|
|
60
|
-
const proxy = new Proxy(target, {
|
|
61
|
-
get: (t, k, r) => {
|
|
62
|
-
const v: unknown = Reflect.get(t, k, r);
|
|
63
|
-
return typeof k === 'string' && Object.hasOwn(t, k) && typeof v === 'object' && v !== null ? this.#guard(v, `${path}.${k}`, level + 1) : v;
|
|
64
|
-
},
|
|
65
|
-
set: (t, k, v) => place(t, k, v),
|
|
66
|
-
defineProperty: (t, k, d) => ('value' in d ? place(t, k, d.value) : refuse(`${path}.${String(k)} is an accessor`)),
|
|
67
|
-
deleteProperty: (t, k) => {
|
|
68
|
-
const ok = Reflect.deleteProperty(t, k);
|
|
69
|
-
this.#wrote();
|
|
70
|
-
return ok;
|
|
71
|
-
},
|
|
72
|
-
setPrototypeOf: () => refuse(`${path} keeps its prototype`),
|
|
73
|
-
});
|
|
74
|
-
this.#guards.set(target, proxy);
|
|
75
|
-
return proxy;
|
|
76
|
-
}
|
|
77
|
-
}
|
package/src/core/ward/house.ts
DELETED
|
@@ -1,524 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// The house: the plumbing behind Quo's door. It keeps Quo's ward, its seed
|
|
3
|
-
// and keys, one door, one partition and its head, and the beings behind the
|
|
4
|
-
// door. It unpacks from its seed, its memory and the classes it resolves
|
|
5
|
-
// kinds through, and stands what is behind its door for `quo/`. It brings
|
|
6
|
-
// no being to life on its own: whoever unpacks it stands its ward. In the
|
|
7
|
-
// box ward the dock stands each faculty, and it stands from then on. In
|
|
8
|
-
// every other ward a being is born from her row when an ask reaches her,
|
|
9
|
-
// once for every ask in flight on her, and is dropped when the last one
|
|
10
|
-
// ends: her cells, occupants and standings are her ward's rows, kept by
|
|
11
|
-
// the ward's memory, so nothing of her lives between asks. No author sees
|
|
12
|
-
// or extends it.
|
|
13
|
-
import { readValue, writeValue } from '../crypto/index.ts';
|
|
14
|
-
import { Door, readInvitation, WardKey, type Behind, type Choice, type Invitation, type Payload } from '../quo/index.ts';
|
|
15
|
-
import type { Carrier, Clock, Entropy, Rows } from '../contract/index.ts';
|
|
16
|
-
import { digest, Faculty, isSilence, isWord, OWNER, ownKind, silence, WARD, word, type Answer, type Asker, type BeingClass, type BeingLike, type JsonObject, type Reply } from '../being/index.ts';
|
|
17
|
-
import { Partition, PartitionRelations, type BeingRow } from './partition.ts';
|
|
18
|
-
import { DEPTH, HouseStance, type Inside } from './stance.ts';
|
|
19
|
-
import { Ward, type Steward, type WardStance } from './ward.ts';
|
|
20
|
-
|
|
21
|
-
// Where a house finds a class by the kind a row keeps, through the registry
|
|
22
|
-
// the row names, or the house's own where it names none.
|
|
23
|
-
export interface Classes {
|
|
24
|
-
classOf(kind: string, registry?: string): BeingClass | undefined;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export type HouseParts = {
|
|
28
|
-
readonly seed: Uint8Array | string;
|
|
29
|
-
readonly memory: Rows;
|
|
30
|
-
readonly classes: Classes;
|
|
31
|
-
readonly entropy: Entropy;
|
|
32
|
-
readonly clock: Clock;
|
|
33
|
-
readonly carrier: Carrier;
|
|
34
|
-
// Which classes may be this house's ward, and the kind she takes at
|
|
35
|
-
// genesis.
|
|
36
|
-
readonly ward: WardClass;
|
|
37
|
-
// What every stance of this house carries, for the classes born of it:
|
|
38
|
-
// the box ward's carries its harbor as `ground`.
|
|
39
|
-
readonly carries?: Readonly<Record<string, unknown>>;
|
|
40
|
-
// An invitation on the dock, taken by the ward under `dock` when
|
|
41
|
-
// she holds no such standing yet.
|
|
42
|
-
readonly dock?: Invitation;
|
|
43
|
-
// Where the ward is reached, and where a ward it takes an invitation of
|
|
44
|
-
// is reached. A ward alone is reached nowhere and learns nothing.
|
|
45
|
-
readonly routes?: Routes;
|
|
46
|
-
// Whether its beings stand once stood, as the box ward's faculties do.
|
|
47
|
-
// Where not, each is born for the asks that reach her.
|
|
48
|
-
readonly stands?: boolean;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export interface Routes {
|
|
52
|
-
reach(): readonly string[];
|
|
53
|
-
learn(ward: string, at: readonly string[]): Promise<void>;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// The ward's class, as the WARD row's kind names it through the classes:
|
|
57
|
-
// the kind an empty row takes at genesis, the contract a class must fulfil
|
|
58
|
-
// here, and the class that stands while the row's kind does not resolve.
|
|
59
|
-
// With no fallback, a ward whose kind does not resolve does not unpack.
|
|
60
|
-
export type WardClass = {
|
|
61
|
-
readonly genesis: string;
|
|
62
|
-
readonly contract: string;
|
|
63
|
-
fits(C: BeingClass): boolean;
|
|
64
|
-
readonly fallback?: BeingClass;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// The standing every hosted ward holds on the dock.
|
|
68
|
-
export const DOCK = 'dock';
|
|
69
|
-
|
|
70
|
-
// A ward that lends to her own ward's beings, as the dock does.
|
|
71
|
-
export interface Lender {
|
|
72
|
-
offer(contract: string): Promise<Invitation | null>;
|
|
73
|
-
withdraw(contract: string, heir: string): Promise<void>;
|
|
74
|
-
}
|
|
75
|
-
const lends = (being: unknown): being is Lender => typeof (being as Partial<Lender>).offer === 'function';
|
|
76
|
-
|
|
77
|
-
type Birth = 'booted' | 'key taken' | 'no such class' | 'threw at birth';
|
|
78
|
-
type Resident = { being: BeingLike; row: BeingRow; stance: HouseStance };
|
|
79
|
-
// A being born for the asks in flight on her, and how many there are.
|
|
80
|
-
type Visit = Resident & { asks: number };
|
|
81
|
-
|
|
82
|
-
class RootStance extends HouseStance implements WardStance {
|
|
83
|
-
readonly steward: Steward;
|
|
84
|
-
constructor(inside: Inside, row: BeingRow, steward: Steward, carries: Readonly<Record<string, unknown>>) {
|
|
85
|
-
super(inside, WARD, row, carries);
|
|
86
|
-
this.steward = steward;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export class House implements Behind, Inside {
|
|
91
|
-
readonly key: WardKey;
|
|
92
|
-
readonly partition: Partition;
|
|
93
|
-
readonly door: Door;
|
|
94
|
-
readonly clock: Clock;
|
|
95
|
-
readonly #parts: HouseParts;
|
|
96
|
-
readonly #residents = new Map<string, Resident>();
|
|
97
|
-
readonly #visits = new Map<string, Visit>();
|
|
98
|
-
readonly #birthing = new Set<string>();
|
|
99
|
-
#fault: string | null = null;
|
|
100
|
-
|
|
101
|
-
private constructor(parts: HouseParts, key: WardKey) {
|
|
102
|
-
this.#parts = parts;
|
|
103
|
-
this.key = key;
|
|
104
|
-
this.clock = parts.clock;
|
|
105
|
-
this.partition = new Partition(parts.memory);
|
|
106
|
-
this.door = new Door(key, new PartitionRelations(this.partition), this, parts.entropy.drawer);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// The house of a seed and its memory, its ward's row written with the
|
|
110
|
-
// genesis kind where the row is new. No being stands yet.
|
|
111
|
-
static async unpack(parts: HouseParts): Promise<House> {
|
|
112
|
-
const ward = new House(parts, await WardKey.from(parts.seed));
|
|
113
|
-
if (!ward.partition.being(WARD)) {
|
|
114
|
-
ward.partition.beings[WARD] = { class: ward.#class.genesis, cells: {}, occupants: {}, standings: {} };
|
|
115
|
-
ward.partition.told(WARD);
|
|
116
|
-
ward.partition.toldHead();
|
|
117
|
-
}
|
|
118
|
-
return ward;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// The ward, of the class her row's kind resolves. A ward class that does
|
|
122
|
-
// not resolve or fits no ward here stands the fallback, with why, or the
|
|
123
|
-
// ward does not stand and this throws. The ward stands once.
|
|
124
|
-
async standWard(): Promise<void> {
|
|
125
|
-
if (this.#residents.has(WARD)) return;
|
|
126
|
-
const own = this.partition.being(WARD)!;
|
|
127
|
-
const stance = new RootStance(this, own, this.#steward, this.#parts.carries ?? {});
|
|
128
|
-
const found = this.#wardOf(own.class, own.registry);
|
|
129
|
-
let being: BeingLike | undefined;
|
|
130
|
-
if (typeof found === 'string') this.#fault = found;
|
|
131
|
-
else {
|
|
132
|
-
try {
|
|
133
|
-
being = new found(stance);
|
|
134
|
-
} catch (e) {
|
|
135
|
-
this.#fault = `${own.class} threw at birth: ${e instanceof Error ? e.message : String(e)}`;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
if (!being) {
|
|
139
|
-
const { fallback } = this.#class;
|
|
140
|
-
if (!fallback) throw new Error(this.#fault!);
|
|
141
|
-
being = new fallback(stance);
|
|
142
|
-
}
|
|
143
|
-
this.#residents.set(WARD, { being, row: own, stance });
|
|
144
|
-
// The standing on the dock is kept at once: its heir is spent, so a
|
|
145
|
-
// restart before the ward's first keep would find no way back.
|
|
146
|
-
const { dock } = this.#parts;
|
|
147
|
-
if (dock && !Object.hasOwn(own.standings, DOCK) && (await stance.standings.take(DOCK, dock)) !== null && !(await this.partition.kept())) {
|
|
148
|
-
throw new Error('the standing on the dock was not kept');
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// One being of a house whose beings stand, from her row, where she does
|
|
153
|
-
// not stand yet: a class nothing resolves, or one that throws, leaves her
|
|
154
|
-
// absent and her row as it stands. In any other house no being stands.
|
|
155
|
-
stand(key: string): 'booted' | 'stands' | 'no such being' | 'no such class' | 'threw at birth' {
|
|
156
|
-
if (this.#residents.has(key)) return 'stands';
|
|
157
|
-
const row = key === WARD || !this.#parts.stands ? undefined : this.partition.being(key);
|
|
158
|
-
if (!row) return 'no such being';
|
|
159
|
-
const C = this.#classOf(row);
|
|
160
|
-
if (!C) return 'no such class';
|
|
161
|
-
return this.#bear(key, row, C) ? 'booted' : 'threw at birth';
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// A being of a kind the core ships, written and stood where her key holds
|
|
165
|
-
// none: how the harbor stands the catalogue on empty memory, before any
|
|
166
|
-
// ward being stands to boot her.
|
|
167
|
-
make(key: string, className: string): Promise<Birth> {
|
|
168
|
-
return this.#make(key, className);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
#classOf(row: BeingRow): BeingClass | undefined {
|
|
172
|
-
return this.#parts.classes.classOf(row.class, row.registry);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
get pk(): string {
|
|
176
|
-
return this.key.pk;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
get draw() {
|
|
180
|
-
return this.#parts.entropy.drawer;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
get ward(): Ward {
|
|
184
|
-
return this.#residents.get(WARD)!.being as Ward;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Why the ward stands the fallback and not her row's class, or null.
|
|
188
|
-
get fault(): string | null {
|
|
189
|
-
return this.#fault;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
get #class(): WardClass {
|
|
193
|
-
return this.#parts.ward;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// The class of a ward kind, or why none may be this house's ward.
|
|
197
|
-
#wardOf(kind: string, registry: string | undefined): BeingClass | string {
|
|
198
|
-
const C = this.#parts.classes.classOf(kind, registry);
|
|
199
|
-
if (!C) return `no class of kind ${kind} runs`;
|
|
200
|
-
return this.#class.fits(C) ? C : `${kind} is no ${this.#class.contract}`;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// The ward born again of her row's class where it resolves now and is
|
|
204
|
-
// not the class she stands as, on the stance she holds.
|
|
205
|
-
#wardAnew(): void {
|
|
206
|
-
const resident = this.#residents.get(WARD);
|
|
207
|
-
if (!resident) return;
|
|
208
|
-
const found = this.#wardOf(resident.row.class, resident.row.registry);
|
|
209
|
-
if (typeof found === 'string') {
|
|
210
|
-
if (ownKind(resident.being.constructor) !== resident.row.class) this.#fault = found;
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
if (resident.being.constructor === found) return;
|
|
214
|
-
try {
|
|
215
|
-
resident.being = new found(resident.stance);
|
|
216
|
-
this.#fault = null;
|
|
217
|
-
} catch (e) {
|
|
218
|
-
this.#fault = `${resident.row.class} threw at birth: ${e instanceof Error ? e.message : String(e)}`;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// The being standing under a key, for the harbor's own faculties.
|
|
223
|
-
being(key: string): BeingLike | undefined {
|
|
224
|
-
return this.#residents.get(key)?.being;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// Every standing being whose kind now resolves to another class, born
|
|
228
|
-
// again of it on the stance she holds, so her relations and their lanes
|
|
229
|
-
// stay hers. A new class that throws at birth leaves her as she was. The
|
|
230
|
-
// ward is one of them. A being born for an ask needs none of this: the
|
|
231
|
-
// next ask that reaches her is born of the class that runs then.
|
|
232
|
-
renew(): void {
|
|
233
|
-
this.#wardAnew();
|
|
234
|
-
for (const [key, resident] of this.#residents) {
|
|
235
|
-
if (key === WARD) continue;
|
|
236
|
-
const C = this.#classOf(resident.row);
|
|
237
|
-
if (!C || resident.being.constructor === C) continue;
|
|
238
|
-
try {
|
|
239
|
-
resident.being = new C(resident.stance);
|
|
240
|
-
} catch {
|
|
241
|
-
continue;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// The unsealed ask: the ward, asked by whoever holds this house.
|
|
247
|
-
// It reaches every being of the house through the ward, so every
|
|
248
|
-
// row is put back where the memory refuses.
|
|
249
|
-
async root(method?: string, args: JsonObject = {}): Promise<Answer> {
|
|
250
|
-
return this.#kept(Object.keys(this.partition.beings), () => this.#answer(WARD, { id: OWNER }, method, args));
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// An answer, kept. Where the memory refuses, what the beings wrote is put
|
|
254
|
-
// back and the answer is silence. What their relations stand on is not
|
|
255
|
-
// put back: a relation's keys move only as far as its standing follows.
|
|
256
|
-
async #kept(keys: readonly string[], work: () => Promise<Answer>): Promise<Answer> {
|
|
257
|
-
const before = keys.flatMap((key): [string, JsonObject, string][] => {
|
|
258
|
-
const row = this.partition.being(key);
|
|
259
|
-
return row ? [[key, row.cells, JSON.stringify(row.cells)]] : [];
|
|
260
|
-
});
|
|
261
|
-
const out = await work();
|
|
262
|
-
if (await this.partition.kept()) return out;
|
|
263
|
-
for (const [key, cells, was] of before) {
|
|
264
|
-
if (JSON.stringify(cells) === was) continue;
|
|
265
|
-
for (const k of Object.keys(cells)) delete cells[k];
|
|
266
|
-
for (const [k, v] of Object.entries(JSON.parse(was) as JsonObject)) Object.defineProperty(cells, k, { value: v, enumerable: true, writable: true, configurable: true });
|
|
267
|
-
this.partition.told(key);
|
|
268
|
-
}
|
|
269
|
-
return silence;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Behind: the zero head reaches the public being, an heir the being that
|
|
273
|
-
// invited it.
|
|
274
|
-
get zero(): boolean {
|
|
275
|
-
const key = this.partition.head.public;
|
|
276
|
-
return key !== null && this.#reachable(key);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Whether an ask reaches the being under a key: she stands, or she is
|
|
280
|
-
// born for it, her class resolving.
|
|
281
|
-
#reachable(key: string): boolean {
|
|
282
|
-
if (this.#residents.has(key)) return true;
|
|
283
|
-
const row = key === WARD || this.#parts.stands ? undefined : this.partition.being(key);
|
|
284
|
-
return row !== undefined && this.#classOf(row) !== undefined;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
async answer(heir: string | null, p: Payload): Promise<Choice> {
|
|
288
|
-
const bound = heir === null ? undefined : this.partition.head.bind[heir];
|
|
289
|
-
const key = heir === null ? this.partition.head.public : bound?.being;
|
|
290
|
-
const asker: Asker = bound ? { id: bound.id } : {};
|
|
291
|
-
const args = p.args === undefined ? {} : readValue(p.args, DEPTH + 1);
|
|
292
|
-
if (key === null || key === undefined || typeof args !== 'object' || args === null || Array.isArray(args)) return { silence: true };
|
|
293
|
-
let seen: string | null = null;
|
|
294
|
-
const out = await this.#kept([key], () =>
|
|
295
|
-
this.#with(key, silence, async (being) => {
|
|
296
|
-
const reply = await this.#reply(being, asker, p.method, args);
|
|
297
|
-
if (p.method !== undefined && !isSilence(reply) && !isWord(reply) && being.describe) seen = await digest(being.describe(asker));
|
|
298
|
-
return reply;
|
|
299
|
-
}),
|
|
300
|
-
);
|
|
301
|
-
const object = isSilence(out) || isWord(out) ? undefined : writeValue(out, DEPTH);
|
|
302
|
-
return object === undefined ? { silence: true } : { object, seen };
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// Every path that reaches a being's answer. A throw, a word out of her,
|
|
306
|
-
// or nothing at all is silence.
|
|
307
|
-
#answer(key: string, asker: Asker, method: string | undefined, args: JsonObject): Promise<Answer> {
|
|
308
|
-
return this.#with(key, silence, (being) => this.#reply(being, asker, method, args));
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
async #reply(being: BeingLike, asker: Asker, method: string | undefined, args: JsonObject): Promise<Answer> {
|
|
312
|
-
let out: Reply;
|
|
313
|
-
try {
|
|
314
|
-
out = await being.answer(asker, method, args);
|
|
315
|
-
} catch {
|
|
316
|
-
return silence;
|
|
317
|
-
}
|
|
318
|
-
return out === undefined || isWord(out) ? silence : out;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// The being under a key for the length of `work`: the one that stands,
|
|
322
|
-
// or, in a house whose beings do not stand, one born from her row for
|
|
323
|
-
// it, the same one for every ask in flight on her, so her relations keep
|
|
324
|
-
// one lane each, dropped when the last ends. A being nothing resolves, or
|
|
325
|
-
// one that throws at birth, is none.
|
|
326
|
-
async #with<T>(key: string, none: T, work: (being: BeingLike) => Promise<T>): Promise<T> {
|
|
327
|
-
const standing = this.#residents.get(key);
|
|
328
|
-
if (standing) return work(standing.being);
|
|
329
|
-
const visit = this.#visit(key);
|
|
330
|
-
if (!visit) return none;
|
|
331
|
-
try {
|
|
332
|
-
return await work(visit.being);
|
|
333
|
-
} finally {
|
|
334
|
-
visit.asks -= 1;
|
|
335
|
-
if (visit.asks === 0 && this.#visits.get(key) === visit) this.#visits.delete(key);
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
#visit(key: string): Visit | undefined {
|
|
340
|
-
const held = this.#visits.get(key);
|
|
341
|
-
if (held) {
|
|
342
|
-
held.asks += 1;
|
|
343
|
-
return held;
|
|
344
|
-
}
|
|
345
|
-
const row = key === WARD || this.#parts.stands ? undefined : this.partition.being(key);
|
|
346
|
-
const C = row && this.#classOf(row);
|
|
347
|
-
if (!row || !C) return undefined;
|
|
348
|
-
const stance = new HouseStance(this, key, row, this.#parts.carries ?? {});
|
|
349
|
-
try {
|
|
350
|
-
const visit = { being: new C(stance), row, stance, asks: 1 };
|
|
351
|
-
this.#visits.set(key, visit);
|
|
352
|
-
return visit;
|
|
353
|
-
} catch {
|
|
354
|
-
return undefined;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// The stance a being of this house acts on: hers where she stands or is
|
|
359
|
-
// in flight, else one made on her row for what her ward does with it.
|
|
360
|
-
#stanceOf(key: string): HouseStance | undefined {
|
|
361
|
-
const held = this.#residents.get(key) ?? this.#visits.get(key);
|
|
362
|
-
if (held) return held.stance;
|
|
363
|
-
const row = key === WARD ? undefined : this.partition.being(key);
|
|
364
|
-
return row ? new HouseStance(this, key, row, this.#parts.carries ?? {}) : undefined;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// Inside: what every stance of this ward stands on.
|
|
368
|
-
|
|
369
|
-
// One path through a door for every ask, this ward's own included.
|
|
370
|
-
async send(pk: string, bytes: Uint8Array): Promise<Uint8Array | null> {
|
|
371
|
-
if (pk === this.pk) return (await this.door.arrive(bytes)).bytes;
|
|
372
|
-
return this.#parts.carrier.carry(pk, bytes);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// A lend: the ward lends herself, as the dock does, or asks the dock
|
|
376
|
-
// through her standing.
|
|
377
|
-
async offer(contract: string): Promise<Invitation | null> {
|
|
378
|
-
const own = this.#residents.get(WARD)!;
|
|
379
|
-
if (lends(own.being)) return own.being.offer(contract);
|
|
380
|
-
const out = await own.stance.standings.get(DOCK)?.ask('lend', { contract });
|
|
381
|
-
return readInvitation((out as { invitation?: unknown } | undefined)?.invitation);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
async retract(contract: string, heir: string): Promise<void> {
|
|
385
|
-
const own = this.#residents.get(WARD)!;
|
|
386
|
-
if (lends(own.being)) return own.being.withdraw(contract, heir);
|
|
387
|
-
await own.stance.standings.get(DOCK)?.ask('retract', { contract, heir });
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
reach(): readonly string[] {
|
|
391
|
-
return this.#parts.routes?.reach() ?? [];
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
learn(ward: string, at: readonly string[]): Promise<void> {
|
|
395
|
-
return this.#parts.routes?.learn(ward, at) ?? Promise.resolve();
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// A stance speaks for a being while her row is the one her ward keeps.
|
|
399
|
-
live(key: string, row: BeingRow): boolean {
|
|
400
|
-
return this.partition.being(key) === row;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// A being boots another of this ward. With an id, the new being invites
|
|
404
|
-
// her maker under the maker's key, and the maker takes it under id; a
|
|
405
|
-
// relation that could not be made unmakes the new being.
|
|
406
|
-
async boot(maker: string, className: string, key: string, id?: string): Promise<string | null> {
|
|
407
|
-
if ((await this.#make(key, className)) !== 'booted') return null;
|
|
408
|
-
if (id === undefined) return key;
|
|
409
|
-
const invitation = await this.#stanceOf(key)!.occupants.invite(maker);
|
|
410
|
-
const taken = invitation ? await this.#stanceOf(maker)?.standings.take(id, invitation) : null;
|
|
411
|
-
if (taken) return key;
|
|
412
|
-
this.#unboot(key);
|
|
413
|
-
return null;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// A new row and her first birth, which writes her cells' defaults: she
|
|
417
|
-
// stands from then on in a house whose beings stand, and is dropped at
|
|
418
|
-
// once in any other, to be born again for the asks that reach her.
|
|
419
|
-
async #make(key: string, className: string, registry?: string): Promise<Birth> {
|
|
420
|
-
if (key === '' || key === WARD || this.partition.being(key) || this.#birthing.has(key)) return 'key taken';
|
|
421
|
-
// A house whose beings stand, the box, holds faculties alone, and every
|
|
422
|
-
// other house holds beings that are no faculty. A ward is no being of
|
|
423
|
-
// any house.
|
|
424
|
-
const C = this.#parts.classes.classOf(className, registry);
|
|
425
|
-
if (!C || Ward.fulfils(C) || Faculty.fulfils(C) !== (this.#parts.stands === true)) return 'no such class';
|
|
426
|
-
this.#birthing.add(key);
|
|
427
|
-
try {
|
|
428
|
-
const row: BeingRow = { class: className, ...(registry === undefined ? {} : { registry }), cells: {}, occupants: {}, standings: {} };
|
|
429
|
-
this.partition.beings[key] = row;
|
|
430
|
-
if (!(this.#parts.stands ? this.#bear(key, row, C) : this.#born(key, row, C) !== undefined)) {
|
|
431
|
-
delete this.partition.beings[key];
|
|
432
|
-
return 'threw at birth';
|
|
433
|
-
}
|
|
434
|
-
this.partition.told(key);
|
|
435
|
-
return 'booted';
|
|
436
|
-
} finally {
|
|
437
|
-
this.#birthing.delete(key);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
#born(key: string, row: BeingRow, C: BeingClass): BeingLike | undefined {
|
|
442
|
-
try {
|
|
443
|
-
return new C(new HouseStance(this, key, row, this.#parts.carries ?? {}));
|
|
444
|
-
} catch {
|
|
445
|
-
return undefined;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
#bear(key: string, row: BeingRow, C: BeingClass): boolean {
|
|
450
|
-
const stance = new HouseStance(this, key, row, this.#parts.carries ?? {});
|
|
451
|
-
try {
|
|
452
|
-
this.#residents.set(key, { being: new C(stance), row, stance });
|
|
453
|
-
return true;
|
|
454
|
-
} catch {
|
|
455
|
-
this.#residents.delete(key);
|
|
456
|
-
return false;
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
#unboot(key: string): boolean {
|
|
461
|
-
const row = key === WARD ? undefined : this.partition.being(key);
|
|
462
|
-
if (!row) return false;
|
|
463
|
-
for (const { heir } of Object.values(row.occupants)) {
|
|
464
|
-
this.door.remove(heir);
|
|
465
|
-
delete this.partition.head.bind[heir];
|
|
466
|
-
}
|
|
467
|
-
if (this.partition.head.public === key) this.partition.head.public = null;
|
|
468
|
-
delete this.partition.beings[key];
|
|
469
|
-
this.#residents.delete(key);
|
|
470
|
-
this.partition.toldHead();
|
|
471
|
-
this.partition.told(key);
|
|
472
|
-
return true;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
// What the ward asks of her house.
|
|
476
|
-
readonly #steward: Steward = {
|
|
477
|
-
pk: () => this.pk,
|
|
478
|
-
classOf: (name, registry) => this.#parts.classes.classOf(name, registry),
|
|
479
|
-
beings: () => {
|
|
480
|
-
const out: ReturnType<Steward['beings']> = {};
|
|
481
|
-
// A being is absent where no ask would reach her: in a house whose
|
|
482
|
-
// beings stand, one that does not stand; in any other, one whose
|
|
483
|
-
// class does not resolve.
|
|
484
|
-
for (const [key, row] of Object.entries(this.partition.beings)) {
|
|
485
|
-
if (key !== WARD) out[key] = { class: row.class, ...(row.registry === undefined ? {} : { registry: row.registry }), public: this.partition.head.public === key, absent: !this.#reachable(key) };
|
|
486
|
-
}
|
|
487
|
-
return out;
|
|
488
|
-
},
|
|
489
|
-
boot: (key, className, registry) => this.#make(key, className, registry),
|
|
490
|
-
stand: (key) => this.stand(key),
|
|
491
|
-
unboot: (key) => this.#unboot(key),
|
|
492
|
-
publish: (key) => {
|
|
493
|
-
if (key !== null && (key === WARD || !this.partition.being(key))) return false;
|
|
494
|
-
this.partition.head.public = key;
|
|
495
|
-
this.partition.toldHead();
|
|
496
|
-
return true;
|
|
497
|
-
},
|
|
498
|
-
invite: (being, id, notes): Promise<Invitation | null> => {
|
|
499
|
-
const stance = being === WARD || !this.#reachable(being) ? undefined : this.#stanceOf(being);
|
|
500
|
-
return stance ? stance.occupants.invite(id, notes) : Promise.resolve(null);
|
|
501
|
-
},
|
|
502
|
-
ask: (being, method, args) => {
|
|
503
|
-
const key = being ?? this.partition.head.public;
|
|
504
|
-
if (key === null || key === WARD) return Promise.resolve(word('unreached'));
|
|
505
|
-
return this.#answer(key, being === null ? {} : { id: OWNER }, method, args);
|
|
506
|
-
},
|
|
507
|
-
become: (kind, registry) => {
|
|
508
|
-
const found = this.#wardOf(kind, registry);
|
|
509
|
-
if (typeof found === 'string') return found;
|
|
510
|
-
const resident = this.#residents.get(WARD)!;
|
|
511
|
-
try {
|
|
512
|
-
resident.being = new found(resident.stance);
|
|
513
|
-
} catch {
|
|
514
|
-
return `${kind} threw at birth`;
|
|
515
|
-
}
|
|
516
|
-
resident.row.class = kind;
|
|
517
|
-
if (registry === undefined) delete resident.row.registry;
|
|
518
|
-
else resident.row.registry = registry;
|
|
519
|
-
this.partition.told(WARD);
|
|
520
|
-
this.#fault = null;
|
|
521
|
-
return null;
|
|
522
|
-
},
|
|
523
|
-
};
|
|
524
|
-
}
|
package/src/core/ward/index.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// The ward and its house: the partition, the stances, the ward, and the house.
|
|
3
|
-
export { allow, CEILING, DEFAULT } from './allowance.ts';
|
|
4
|
-
export { HEAD_ROW, Partition, type BeingRow, type Head, type StandingRow } from './partition.ts';
|
|
5
|
-
export { DEPTH } from './stance.ts';
|
|
6
|
-
export { DOCK, House, type Classes, type HouseParts, type Lender, type Routes, type WardClass } from './house.ts';
|
|
7
|
-
export { HELD, ownerAsk, pilots, rootAsk, Ward, type Steward, type WardStance } from './ward.ts';
|