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
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// The package: a harbor's memory, sealed under the harbor's seed. The
|
|
3
|
-
// terrain keeps its bytes and reads neither a ward's name, nor a being's
|
|
4
|
-
// key, nor anything a row holds.
|
|
5
|
-
//
|
|
6
|
-
// key HKDF-SHA-256 of the seed under `nervur-package`
|
|
7
|
-
// place 16 bytes under ["place", ward], as hex
|
|
8
|
-
// entry 16 bytes under ["entry", ward, row], as hex
|
|
9
|
-
// seal 32 bytes under ["seal", ward]
|
|
10
|
-
// entry bytes nonce (12) || AES-256-GCM( JSON { row, value } ),
|
|
11
|
-
// the entry's name as additional data
|
|
12
|
-
//
|
|
13
|
-
// A row is the head, under the empty name, or one being, under her key. An
|
|
14
|
-
// entry that does not open refuses the whole ward, so nothing unpacks from
|
|
15
|
-
// bytes the package did not seal.
|
|
16
|
-
import { concat, decrypt, encrypt, hex, hkdf, isHex, unhex, utf8 } from '../crypto/index.js';
|
|
17
|
-
import { HEAD_ROW } from '../ward/index.js';
|
|
18
|
-
// Every place of one memory, written into another, and the places
|
|
19
|
-
// carried. The bytes are the package's own, sealed under a seed neither
|
|
20
|
-
// memory holds, so a harbor opened on the second memory under that seed
|
|
21
|
-
// stands what the first one stood. A place the second memory already
|
|
22
|
-
// holds is written over.
|
|
23
|
-
export const copyPackage = async (from, to) => {
|
|
24
|
-
const places = await from.places();
|
|
25
|
-
for (const place of places)
|
|
26
|
-
await to.write(place, await from.read(place));
|
|
27
|
-
return places;
|
|
28
|
-
};
|
|
29
|
-
// A carried harbor as JSON reads, or null for anything else.
|
|
30
|
-
export const readCarried = (value) => {
|
|
31
|
-
if (typeof value !== 'object' || value === null)
|
|
32
|
-
return null;
|
|
33
|
-
const { seed, places } = value;
|
|
34
|
-
if (seed !== undefined && !isHex(seed, 32))
|
|
35
|
-
return null;
|
|
36
|
-
if (typeof places !== 'object' || places === null || Array.isArray(places))
|
|
37
|
-
return null;
|
|
38
|
-
for (const entries of Object.values(places)) {
|
|
39
|
-
if (typeof entries !== 'object' || entries === null || Array.isArray(entries))
|
|
40
|
-
return null;
|
|
41
|
-
for (const bytes of Object.values(entries))
|
|
42
|
-
if (!isHex(bytes))
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
return { ...(seed === undefined ? {} : { seed }), places: places };
|
|
46
|
-
};
|
|
47
|
-
// Every place of a memory, as a carried harbor holds it.
|
|
48
|
-
export const carryPlaces = async (memory) => {
|
|
49
|
-
const places = {};
|
|
50
|
-
for (const place of await memory.places()) {
|
|
51
|
-
places[place] = Object.fromEntries([...(await memory.read(place))].map(([name, bytes]) => [name, hex(bytes)]));
|
|
52
|
-
}
|
|
53
|
-
return places;
|
|
54
|
-
};
|
|
55
|
-
// A carried harbor's places, written into a memory, and their names.
|
|
56
|
-
export const landPlaces = async (memory, carried) => {
|
|
57
|
-
for (const [place, entries] of Object.entries(carried.places)) {
|
|
58
|
-
await memory.write(place, new Map(Object.entries(entries).map(([name, bytes]) => [name, unhex(bytes)])));
|
|
59
|
-
}
|
|
60
|
-
return Object.keys(carried.places);
|
|
61
|
-
};
|
|
62
|
-
const NONCE = 12;
|
|
63
|
-
const LABEL = utf8('nervur-package');
|
|
64
|
-
class PackageRows {
|
|
65
|
-
rows;
|
|
66
|
-
#ward;
|
|
67
|
-
#told = new Set();
|
|
68
|
-
#line = Promise.resolve(true);
|
|
69
|
-
constructor(ward, rows) {
|
|
70
|
-
this.#ward = ward;
|
|
71
|
-
this.rows = rows;
|
|
72
|
-
}
|
|
73
|
-
told(row) {
|
|
74
|
-
this.#told.add(row);
|
|
75
|
-
}
|
|
76
|
-
// Every row told since the last keep, sealed and written as one keep, one
|
|
77
|
-
// keep at a time. Where nothing was told, nothing is written, so an ask
|
|
78
|
-
// that only reads keeps even where the keeper refuses every write.
|
|
79
|
-
kept() {
|
|
80
|
-
const rows = [...this.#told];
|
|
81
|
-
this.#told.clear();
|
|
82
|
-
this.#line = this.#line.then(() => this.#write(rows)).catch(() => false);
|
|
83
|
-
return this.#line;
|
|
84
|
-
}
|
|
85
|
-
async #write(told) {
|
|
86
|
-
if (told.length === 0)
|
|
87
|
-
return true;
|
|
88
|
-
const beings = (this.rows.beings ?? {});
|
|
89
|
-
const entries = new Map();
|
|
90
|
-
for (const row of told) {
|
|
91
|
-
const value = row === HEAD_ROW ? (this.rows.ward ?? null) : Object.hasOwn(beings, row) ? beings[row] : undefined;
|
|
92
|
-
entries.set(await this.#ward.entry(row), value === undefined ? null : await this.#ward.seal(row, value));
|
|
93
|
-
}
|
|
94
|
-
await this.#ward.write(entries);
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
class WardPlace {
|
|
99
|
-
#pack;
|
|
100
|
-
#name;
|
|
101
|
-
#seal;
|
|
102
|
-
#keeper;
|
|
103
|
-
place;
|
|
104
|
-
constructor(pack, name, seal, place, keeper) {
|
|
105
|
-
this.#pack = pack;
|
|
106
|
-
this.#name = name;
|
|
107
|
-
this.#seal = seal;
|
|
108
|
-
this.place = place;
|
|
109
|
-
this.#keeper = keeper;
|
|
110
|
-
}
|
|
111
|
-
read() {
|
|
112
|
-
return this.#keeper.read(this.place);
|
|
113
|
-
}
|
|
114
|
-
entry(row) {
|
|
115
|
-
return this.#pack.derive(['entry', this.#name, row], 16).then(hex);
|
|
116
|
-
}
|
|
117
|
-
async seal(row, value) {
|
|
118
|
-
const nonce = this.#pack.entropy.draw(NONCE);
|
|
119
|
-
const text = utf8(JSON.stringify({ row, value }));
|
|
120
|
-
return concat(nonce, await encrypt(this.#seal, nonce, utf8(await this.entry(row)), text));
|
|
121
|
-
}
|
|
122
|
-
// The name is the additional data, so an entry moved under another name
|
|
123
|
-
// does not open either.
|
|
124
|
-
async open(name, bytes) {
|
|
125
|
-
const text = bytes.length > NONCE ? await decrypt(this.#seal, bytes.subarray(0, NONCE), utf8(name), bytes.subarray(NONCE)) : null;
|
|
126
|
-
if (text === null)
|
|
127
|
-
throw new Error('an entry the package did not seal');
|
|
128
|
-
return JSON.parse(new TextDecoder().decode(text));
|
|
129
|
-
}
|
|
130
|
-
write(entries) {
|
|
131
|
-
return this.#keeper.write(this.place, entries);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
export class Package {
|
|
135
|
-
memory;
|
|
136
|
-
entropy;
|
|
137
|
-
#key;
|
|
138
|
-
constructor(memory, entropy, key) {
|
|
139
|
-
this.memory = memory;
|
|
140
|
-
this.entropy = entropy;
|
|
141
|
-
this.#key = key;
|
|
142
|
-
}
|
|
143
|
-
static async open(memory, entropy, seed) {
|
|
144
|
-
return new Package(memory, entropy, await hkdf(seed, LABEL, 32));
|
|
145
|
-
}
|
|
146
|
-
derive(info, length) {
|
|
147
|
-
return hkdf(this.#key, utf8(JSON.stringify(info)), length);
|
|
148
|
-
}
|
|
149
|
-
// The place a ward's rows live in.
|
|
150
|
-
place(name) {
|
|
151
|
-
return this.derive(['place', name], 16).then(hex);
|
|
152
|
-
}
|
|
153
|
-
// One ward's rows, as its keeper kept them: the root memory unless a
|
|
154
|
-
// memory faculty is named.
|
|
155
|
-
async rows(name, keeper = this.memory) {
|
|
156
|
-
const ward = new WardPlace(this, name, await this.derive(['seal', name], 32), await this.place(name), keeper);
|
|
157
|
-
const rows = {};
|
|
158
|
-
const beings = {};
|
|
159
|
-
let any = false;
|
|
160
|
-
for (const [entry, bytes] of await ward.read()) {
|
|
161
|
-
const { row, value } = await ward.open(entry, bytes);
|
|
162
|
-
any = true;
|
|
163
|
-
if (row === HEAD_ROW)
|
|
164
|
-
rows.ward = value;
|
|
165
|
-
else
|
|
166
|
-
beings[row] = value;
|
|
167
|
-
}
|
|
168
|
-
if (any)
|
|
169
|
-
rows.beings = beings;
|
|
170
|
-
return new PackageRows(ward, rows);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { Bundled } from '../contract/index.ts';
|
|
2
|
-
import type { Defaults, Terrain } from './terrain.ts';
|
|
3
|
-
export type Probing = {
|
|
4
|
-
readonly where?: string;
|
|
5
|
-
readonly given?: unknown;
|
|
6
|
-
readonly bundle?: readonly Bundled[];
|
|
7
|
-
};
|
|
8
|
-
export type GroundProbe = {
|
|
9
|
-
readonly name: string;
|
|
10
|
-
fits(probing: Probing): boolean;
|
|
11
|
-
terrain(probing: Probing, defaults: Defaults): Terrain;
|
|
12
|
-
};
|
|
13
|
-
export type KnownGround = {
|
|
14
|
-
readonly probe: GroundProbe;
|
|
15
|
-
readonly defaults: Defaults;
|
|
16
|
-
};
|
|
17
|
-
export declare const addGround: (probe: GroundProbe, defaults: Defaults) => void;
|
|
18
|
-
export declare const grounds: () => string[];
|
|
19
|
-
export declare const probeGround: (probing: Probing, among?: readonly KnownGround[]) => {
|
|
20
|
-
ground: string;
|
|
21
|
-
terrain: Terrain;
|
|
22
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
const known = [];
|
|
2
|
-
// A ground this process can stand on, known once by its name.
|
|
3
|
-
export const addGround = (probe, defaults) => {
|
|
4
|
-
if (!known.some((k) => k.probe.name === probe.name))
|
|
5
|
-
known.push({ probe, defaults });
|
|
6
|
-
};
|
|
7
|
-
// The grounds known, in the order they are tried.
|
|
8
|
-
export const grounds = () => known.map((k) => k.probe.name).reverse();
|
|
9
|
-
// The terrain of the first ground that fits, and its name.
|
|
10
|
-
export const probeGround = (probing, among = known) => {
|
|
11
|
-
for (const { probe, defaults } of [...among].reverse())
|
|
12
|
-
if (probe.fits(probing))
|
|
13
|
-
return { ground: probe.name, terrain: probe.terrain(probing, defaults) };
|
|
14
|
-
throw new Error('no ground fits here');
|
|
15
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Faculty, type BeingClass } from '../being/index.ts';
|
|
2
|
-
import type { Module } from '../contract/index.ts';
|
|
3
|
-
export declare const REGISTRY = "org.nervur.registry";
|
|
4
|
-
export declare abstract class RegistryFaculty extends Faculty {
|
|
5
|
-
static readonly kind: string;
|
|
6
|
-
abstract classOf(kind: string): BeingClass | undefined;
|
|
7
|
-
}
|
|
8
|
-
export declare const registers: (C: unknown) => C is typeof RegistryFaculty;
|
|
9
|
-
export declare class Registry {
|
|
10
|
-
#private;
|
|
11
|
-
constructor(kit: readonly BeingClass[], modules: readonly Module[]);
|
|
12
|
-
static refusal(kit: readonly BeingClass[], modules: readonly Module[]): string | null;
|
|
13
|
-
classOf(kind: string): BeingClass | undefined;
|
|
14
|
-
kindsOf(module: string): string[];
|
|
15
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// The catalogue's index: every kind the harbor runs, from the kit's own
|
|
3
|
-
// classes and the modules the catalogue loaded. It resolves a kind a row
|
|
4
|
-
// keeps, and decides nothing about what stands. It refuses any set of
|
|
5
|
-
// modules two readings could split:
|
|
6
|
-
//
|
|
7
|
-
// a module whose name is no kind, or is the kit's, or two of one name
|
|
8
|
-
// a class with no kind of its own, or one outside its module's domain
|
|
9
|
-
// two classes of one kind, or one kind in two modules
|
|
10
|
-
// a contract with no kind of its own, or one kind for two contracts
|
|
11
|
-
// a class above a module's class of a kit kind that the kit does not ship
|
|
12
|
-
// a kind that is a class and a contract
|
|
13
|
-
//
|
|
14
|
-
// A module's domain is its name's first two segments: `com.acme.shop`
|
|
15
|
-
// stands classes under `com.acme.` alone. A contract may be any domain's,
|
|
16
|
-
// so a faculty fulfils a contract another module declares. A module's
|
|
17
|
-
// class may extend any class or contract the kit ships, and never declares
|
|
18
|
-
// one of a kit kind itself. Two harbors hold two registries, and nothing
|
|
19
|
-
// between them names a class.
|
|
20
|
-
import { Faculty, isKind, KIT, kindOf, ownKind, shipped, ships } from '../being/index.js';
|
|
21
|
-
const domainOf = (name) => `${name.split('.').slice(0, 2).join('.')}.`;
|
|
22
|
-
export const REGISTRY = 'org.nervur.registry';
|
|
23
|
-
// The registry faculty: a faculty of the box ward that resolves the kind a
|
|
24
|
-
// row keeps to a class. The catalogue is the core's, and resolves through
|
|
25
|
-
// the DNA. Any other is an owner's, stood by the registry named on its row,
|
|
26
|
-
// and each being of the box, and each hosted ward whole, names the registry
|
|
27
|
-
// its classes come from.
|
|
28
|
-
export class RegistryFaculty extends Faculty {
|
|
29
|
-
static kind = REGISTRY;
|
|
30
|
-
static {
|
|
31
|
-
ships(this);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
// Whether a class is a registry faculty's.
|
|
35
|
-
export const registers = (C) => typeof C === 'function' && C.prototype instanceof RegistryFaculty;
|
|
36
|
-
export class Registry {
|
|
37
|
-
#classes = new Map();
|
|
38
|
-
#modules = new Map();
|
|
39
|
-
// `kit` holds the kit's own classes, which alone may be of its kinds.
|
|
40
|
-
constructor(kit, modules) {
|
|
41
|
-
const contracts = new Map();
|
|
42
|
-
const owners = new Map();
|
|
43
|
-
const add = (C, kind) => {
|
|
44
|
-
if (this.#classes.has(kind) && this.#classes.get(kind) !== C)
|
|
45
|
-
throw new Error(`two classes are of kind ${kind}`);
|
|
46
|
-
this.#classes.set(kind, C);
|
|
47
|
-
};
|
|
48
|
-
for (const C of kit)
|
|
49
|
-
add(C, kindOf(C));
|
|
50
|
-
for (const m of modules) {
|
|
51
|
-
if (!isKind(m.module) || m.module.startsWith(KIT))
|
|
52
|
-
throw new Error(`module ${String(m.module)} is no name a module may take`);
|
|
53
|
-
if (this.#modules.has(m.module))
|
|
54
|
-
throw new Error(`two modules are named ${m.module}`);
|
|
55
|
-
if (typeof m.version !== 'string' || m.version === '')
|
|
56
|
-
throw new Error(`module ${m.module} declares no version`);
|
|
57
|
-
const kinds = [];
|
|
58
|
-
for (const C of m.classes) {
|
|
59
|
-
if (typeof C !== 'function')
|
|
60
|
-
throw new Error(`module ${m.module} holds something that is no class`);
|
|
61
|
-
const kind = kindOf(C);
|
|
62
|
-
if (!kind.startsWith(domainOf(m.module)))
|
|
63
|
-
throw new Error(`kind ${kind} is outside module ${m.module}`);
|
|
64
|
-
const owner = owners.get(kind);
|
|
65
|
-
if (owner !== undefined && owner !== m.module)
|
|
66
|
-
throw new Error(`kind ${kind} is in modules ${owner} and ${m.module}`);
|
|
67
|
-
owners.set(kind, m.module);
|
|
68
|
-
add(C, kind);
|
|
69
|
-
kinds.push(kind);
|
|
70
|
-
for (let c = Object.getPrototypeOf(C); typeof c === 'function'; c = Object.getPrototypeOf(c)) {
|
|
71
|
-
if (ownKind(c)?.startsWith(KIT) && !shipped(c))
|
|
72
|
-
throw new Error(`kind ${ownKind(c)} is the kit's`);
|
|
73
|
-
}
|
|
74
|
-
if (!Faculty.fulfils(C))
|
|
75
|
-
continue;
|
|
76
|
-
for (let c = Object.getPrototypeOf(C); c !== Faculty; c = Object.getPrototypeOf(c)) {
|
|
77
|
-
const contract = kindOf(c);
|
|
78
|
-
if (shipped(c))
|
|
79
|
-
continue;
|
|
80
|
-
if (contracts.has(contract) && contracts.get(contract) !== c)
|
|
81
|
-
throw new Error(`two contracts are of kind ${contract}`);
|
|
82
|
-
contracts.set(contract, c);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
this.#modules.set(m.module, kinds);
|
|
86
|
-
}
|
|
87
|
-
for (const kind of contracts.keys()) {
|
|
88
|
-
if (this.#classes.has(kind))
|
|
89
|
-
throw new Error(`kind ${kind} is a class and a contract`);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
// Why a registry of these modules would be refused, or null.
|
|
93
|
-
static refusal(kit, modules) {
|
|
94
|
-
try {
|
|
95
|
-
const registry = new Registry(kit, modules);
|
|
96
|
-
void registry;
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
catch (e) {
|
|
100
|
-
return e.message;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
classOf(kind) {
|
|
104
|
-
return this.#classes.get(kind);
|
|
105
|
-
}
|
|
106
|
-
// The kinds a module stands, or none.
|
|
107
|
-
kindsOf(module) {
|
|
108
|
-
return [...(this.#modules.get(module) ?? [])];
|
|
109
|
-
}
|
|
110
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
const object = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
2
|
-
export const readRootRequest = (value) => {
|
|
3
|
-
if (!object(value))
|
|
4
|
-
return null;
|
|
5
|
-
const { ward, method, args } = value;
|
|
6
|
-
if ((ward !== undefined && typeof ward !== 'string') || (method !== undefined && typeof method !== 'string') || (args !== undefined && !object(args)))
|
|
7
|
-
return null;
|
|
8
|
-
return { ...(ward === undefined ? {} : { ward }), ...(method === undefined ? {} : { method }), ...(args === undefined ? {} : { args }) };
|
|
9
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { BeingClass } from '../being/index.ts';
|
|
2
|
-
import type { Carrier, Clock, Custody, Entropy, Loader, Memory } from '../contract/index.ts';
|
|
3
|
-
import type { Sockets, WebServe } from './carrying.ts';
|
|
4
|
-
import type { Harbor } from './harbor.ts';
|
|
5
|
-
export type Defaults = {
|
|
6
|
-
readonly dock: BeingClass;
|
|
7
|
-
readonly ward: BeingClass;
|
|
8
|
-
readonly classes: readonly BeingClass[];
|
|
9
|
-
};
|
|
10
|
-
export declare abstract class Terrain {
|
|
11
|
-
abstract readonly entropy: Entropy;
|
|
12
|
-
abstract readonly clock: Clock;
|
|
13
|
-
abstract readonly custody: Custody;
|
|
14
|
-
abstract readonly memory: Memory;
|
|
15
|
-
abstract readonly loader: Loader;
|
|
16
|
-
abstract readonly carrier: Carrier;
|
|
17
|
-
abstract readonly defaults: Defaults;
|
|
18
|
-
readonly tcp: (() => Sockets) | undefined;
|
|
19
|
-
readonly web: WebServe | undefined;
|
|
20
|
-
readonly wakes: boolean;
|
|
21
|
-
get foreground(): boolean;
|
|
22
|
-
claim(): Promise<void>;
|
|
23
|
-
stand(_harbor: Harbor): Promise<void>;
|
|
24
|
-
release(): Promise<void>;
|
|
25
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export class Terrain {
|
|
2
|
-
// The platform under the carriers, where this ground has one: the sockets
|
|
3
|
-
// TCP is spoken on, one set for each carrier that asks, and the listener
|
|
4
|
-
// the web carrier runs.
|
|
5
|
-
tcp = undefined;
|
|
6
|
-
web = undefined;
|
|
7
|
-
// Whether its carriers wake and listen where their cells say. A harbor
|
|
8
|
-
// opened for one ask and closed again dials and hears nothing.
|
|
9
|
-
wakes = true;
|
|
10
|
-
// Whether the harbor lives only as long as a screen: a tab's, or a worker
|
|
11
|
-
// one tab owns. It is reached only while that screen is open, and hears
|
|
12
|
-
// no push, so its census says so.
|
|
13
|
-
get foreground() {
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
// Before the harbor opens: a terrain whose ground another run holds
|
|
17
|
-
// refuses here. Once it stands: whatever the ground serves beside it.
|
|
18
|
-
// Once its carriers sleep: what that served, gone.
|
|
19
|
-
claim() {
|
|
20
|
-
return Promise.resolve();
|
|
21
|
-
}
|
|
22
|
-
stand(_harbor) {
|
|
23
|
-
return Promise.resolve();
|
|
24
|
-
}
|
|
25
|
-
release() {
|
|
26
|
-
return Promise.resolve();
|
|
27
|
-
}
|
|
28
|
-
}
|
package/dist/core/http/index.js
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// `nervur/http`: the web carrier's listener on Node's HTTP server, an entry
|
|
3
|
-
// that names a platform.
|
|
4
|
-
//
|
|
5
|
-
// webServe answers posts at a path, and held lines opened to that path
|
|
6
|
-
// with the subprotocol `quo`, for the ground it is handed:
|
|
7
|
-
// the body a Node terrain hands the web carrier
|
|
8
|
-
//
|
|
9
|
-
// A post is one ask: 200 with the reply's box, or 204 for nothing. A post
|
|
10
|
-
// to another path is 404, another method 405, a body that is no ask 400.
|
|
11
|
-
// A page of an origin the cells name, or of any origin under `*`, is
|
|
12
|
-
// answered as the CORS protocol says, its preflight included. A held line
|
|
13
|
-
// carries one frame body to a binary message; a text message, a body that
|
|
14
|
-
// is no frame, or bytes that break RFC 6455 close it, and nothing after
|
|
15
|
-
// them is read.
|
|
16
|
-
import { createServer } from 'node:http';
|
|
17
|
-
import { MAX_BODY, MAX_POST, nothingBody, readBody, readPost, replyBody } from '../line/index.js';
|
|
18
|
-
import { hex } from '../crypto/index.js';
|
|
19
|
-
import { tcpAt } from '../quo/index.js';
|
|
20
|
-
import { acceptKey, frameOf, isClientKey, OP, WsReader } from './websocket.js';
|
|
21
|
-
const pathOf = (url) => {
|
|
22
|
-
const at = (url ?? '/').indexOf('?');
|
|
23
|
-
return at < 0 ? (url ?? '/') : (url ?? '/').slice(0, at);
|
|
24
|
-
};
|
|
25
|
-
const originOf = (origins, origin) => {
|
|
26
|
-
if (origin === undefined)
|
|
27
|
-
return null;
|
|
28
|
-
if (origins.includes('*'))
|
|
29
|
-
return '*';
|
|
30
|
-
return origins.includes(origin) ? origin : null;
|
|
31
|
-
};
|
|
32
|
-
// The bytes of a request, up to one more than `max`, as they came.
|
|
33
|
-
const bodyOf = (request, max) => new Promise((resolve, reject) => {
|
|
34
|
-
const parts = [];
|
|
35
|
-
let length = 0;
|
|
36
|
-
request.on('data', (chunk) => {
|
|
37
|
-
if (length > max)
|
|
38
|
-
return;
|
|
39
|
-
parts.push(chunk);
|
|
40
|
-
length += chunk.length;
|
|
41
|
-
});
|
|
42
|
-
request.on('end', () => {
|
|
43
|
-
const out = new Uint8Array(length);
|
|
44
|
-
let at = 0;
|
|
45
|
-
for (const part of parts) {
|
|
46
|
-
out.set(part, at);
|
|
47
|
-
at += part.length;
|
|
48
|
-
}
|
|
49
|
-
resolve(out);
|
|
50
|
-
});
|
|
51
|
-
request.on('error', reject);
|
|
52
|
-
});
|
|
53
|
-
const post = async (ground, listen, request, response) => {
|
|
54
|
-
const allowed = originOf(listen.origins, request.headers.origin);
|
|
55
|
-
if (allowed !== null)
|
|
56
|
-
response.setHeader('access-control-allow-origin', allowed);
|
|
57
|
-
if (pathOf(request.url) !== listen.path)
|
|
58
|
-
return void response.writeHead(404).end();
|
|
59
|
-
if (request.method === 'OPTIONS') {
|
|
60
|
-
if (allowed !== null) {
|
|
61
|
-
response.setHeader('access-control-allow-methods', 'POST');
|
|
62
|
-
response.setHeader('access-control-allow-headers', 'content-type');
|
|
63
|
-
}
|
|
64
|
-
return void response.writeHead(204).end();
|
|
65
|
-
}
|
|
66
|
-
if (request.method !== 'POST')
|
|
67
|
-
return void response.writeHead(405, { allow: 'POST, OPTIONS' }).end();
|
|
68
|
-
const ask = readPost(await bodyOf(request, MAX_POST));
|
|
69
|
-
if (ask === null)
|
|
70
|
-
return void response.writeHead(400).end();
|
|
71
|
-
let reply = null;
|
|
72
|
-
try {
|
|
73
|
-
reply = await ground.arrive(ask.pk, ask.box);
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
reply = null;
|
|
77
|
-
}
|
|
78
|
-
if (reply === null || reply.length === 0)
|
|
79
|
-
return void response.writeHead(204).end();
|
|
80
|
-
response.writeHead(200, { 'content-type': 'application/octet-stream' }).end(reply);
|
|
81
|
-
};
|
|
82
|
-
const upgrade = (ground, listen, request, socket) => {
|
|
83
|
-
const key = request.headers['sec-websocket-key'];
|
|
84
|
-
const offered = String(request.headers['sec-websocket-protocol'] ?? '')
|
|
85
|
-
.split(',')
|
|
86
|
-
.map((p) => p.trim());
|
|
87
|
-
const fine = pathOf(request.url) === listen.path && request.headers['sec-websocket-version'] === '13' && isClientKey(key) && offered.includes('quo');
|
|
88
|
-
if (!fine) {
|
|
89
|
-
socket.end('HTTP/1.1 400 Bad Request\r\nconnection: close\r\ncontent-length: 0\r\n\r\n');
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
socket.write(`HTTP/1.1 101 Switching Protocols\r\nupgrade: websocket\r\nconnection: Upgrade\r\nsec-websocket-accept: ${acceptKey(key)}\r\nsec-websocket-protocol: quo\r\n\r\n`);
|
|
93
|
-
const reader = new WsReader(MAX_BODY);
|
|
94
|
-
const send = (opcode, payload) => {
|
|
95
|
-
if (!socket.destroyed)
|
|
96
|
-
socket.write(frameOf(opcode, payload));
|
|
97
|
-
};
|
|
98
|
-
const close = () => {
|
|
99
|
-
send(OP.close);
|
|
100
|
-
socket.end();
|
|
101
|
-
};
|
|
102
|
-
socket.on('data', (chunk) => {
|
|
103
|
-
for (const event of reader.push(chunk)) {
|
|
104
|
-
if (event.type === 'ping')
|
|
105
|
-
send(OP.pong, event.data);
|
|
106
|
-
else if (event.type !== 'binary')
|
|
107
|
-
return close();
|
|
108
|
-
else {
|
|
109
|
-
const frame = readBody(event.data);
|
|
110
|
-
if (frame === null)
|
|
111
|
-
return close();
|
|
112
|
-
if (frame.kind !== 'ask')
|
|
113
|
-
continue;
|
|
114
|
-
void ground
|
|
115
|
-
.arrive(hex(frame.pk), frame.box)
|
|
116
|
-
.catch(() => null)
|
|
117
|
-
.then((reply) => send(OP.binary, reply === null ? nothingBody(frame.id) : replyBody(frame.id, reply)));
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
socket.on('error', () => socket.destroy());
|
|
122
|
-
};
|
|
123
|
-
// A listener of the web carrier for one ground.
|
|
124
|
-
export const webServe = (ground, listen) => {
|
|
125
|
-
const sockets = new Set();
|
|
126
|
-
const server = createServer((request, response) => {
|
|
127
|
-
void post(ground, listen, request, response).catch(() => {
|
|
128
|
-
if (!response.headersSent)
|
|
129
|
-
response.writeHead(400);
|
|
130
|
-
response.end();
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
server.on('connection', (socket) => {
|
|
134
|
-
sockets.add(socket);
|
|
135
|
-
socket.on('close', () => sockets.delete(socket));
|
|
136
|
-
});
|
|
137
|
-
server.on('upgrade', (request, socket) => upgrade(ground, listen, request, socket));
|
|
138
|
-
return new Promise((resolve, reject) => {
|
|
139
|
-
server.once('error', reject);
|
|
140
|
-
server.listen(listen.port, listen.host, () => {
|
|
141
|
-
const { address, port } = server.address();
|
|
142
|
-
const authority = tcpAt(address, port).slice('tcp://'.length);
|
|
143
|
-
resolve({
|
|
144
|
-
port,
|
|
145
|
-
at: [`http://${authority}${listen.path}`, `ws://${authority}${listen.path}`],
|
|
146
|
-
close: () => {
|
|
147
|
-
for (const socket of sockets)
|
|
148
|
-
socket.destroy();
|
|
149
|
-
return new Promise((done) => server.close(() => done()));
|
|
150
|
-
},
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export declare const OP: {
|
|
2
|
-
readonly continuation: 0;
|
|
3
|
-
readonly text: 1;
|
|
4
|
-
readonly binary: 2;
|
|
5
|
-
readonly close: 8;
|
|
6
|
-
readonly ping: 9;
|
|
7
|
-
readonly pong: 10;
|
|
8
|
-
};
|
|
9
|
-
export declare const acceptKey: (key: string) => string;
|
|
10
|
-
export declare const isClientKey: (key: unknown) => key is string;
|
|
11
|
-
export declare const frameOf: (opcode: number, payload?: Uint8Array) => Uint8Array;
|
|
12
|
-
export type WsEvent = {
|
|
13
|
-
type: 'binary';
|
|
14
|
-
data: Uint8Array;
|
|
15
|
-
} | {
|
|
16
|
-
type: 'text';
|
|
17
|
-
} | {
|
|
18
|
-
type: 'ping';
|
|
19
|
-
data: Uint8Array;
|
|
20
|
-
} | {
|
|
21
|
-
type: 'close';
|
|
22
|
-
} | {
|
|
23
|
-
type: 'bad';
|
|
24
|
-
};
|
|
25
|
-
export declare class WsReader {
|
|
26
|
-
#private;
|
|
27
|
-
constructor(max: number);
|
|
28
|
-
push(chunk: Uint8Array): WsEvent[];
|
|
29
|
-
}
|