nervur 0.21.4 → 0.22.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/README.md +215 -158
- package/dist/browser.js +4 -3
- package/dist/cli.js +16 -0
- package/dist/{being → core/being}/being.js +10 -0
- package/dist/{being → core/being}/faculty.js +5 -2
- package/dist/{being → core/being}/index.d.ts +1 -1
- package/dist/{being → core/being}/index.js +1 -1
- package/dist/{being → core/being}/kind.d.ts +2 -0
- package/dist/{being → core/being}/kind.js +6 -0
- package/dist/{being → core/being}/types.js +1 -1
- package/dist/{browser → core/browser}/index.d.ts +6 -5
- package/dist/{browser → core/browser}/index.js +10 -10
- package/dist/{browser → core/browser}/worker.d.ts +2 -3
- package/dist/{browser → core/browser}/worker.js +8 -11
- package/dist/{cli → core/cli}/command.d.ts +4 -4
- package/dist/{cli → core/cli}/command.js +116 -66
- package/dist/{cli → core/cli}/edge.js +4 -2
- package/dist/core/cli/harbor.d.ts +25 -0
- package/dist/{cli → core/cli}/harbor.js +45 -33
- package/dist/{contract → core/contract}/index.d.ts +6 -5
- package/dist/{contract → core/contract}/index.js +8 -9
- package/dist/core/contract/link.d.ts +4 -0
- package/dist/core/contract/link.js +45 -0
- package/dist/{crypto → core/crypto}/ed25519.js +22 -14
- package/dist/core/crypto/subtle.d.ts +3 -0
- package/dist/core/crypto/subtle.js +11 -0
- package/dist/core/crypto/x25519.js +24 -0
- package/dist/core/edge/index.d.ts +164 -0
- package/dist/core/edge/index.js +739 -0
- package/dist/core/edge/kit.d.ts +2 -0
- package/dist/core/edge/kit.js +2 -0
- package/dist/core/git/http.d.ts +6 -0
- package/dist/core/git/http.js +102 -0
- package/dist/core/git/index.d.ts +5 -0
- package/dist/core/git/index.js +10 -0
- package/dist/core/git/object.d.ts +40 -0
- package/dist/core/git/object.js +103 -0
- package/dist/core/git/pack.d.ts +9 -0
- package/dist/core/git/pack.js +171 -0
- package/dist/core/git/store.d.ts +23 -0
- package/dist/core/git/store.js +120 -0
- package/dist/core/git/zlib.d.ts +6 -0
- package/dist/core/git/zlib.js +210 -0
- package/dist/core/harbor/carrying.d.ts +51 -0
- package/dist/core/harbor/carrying.js +69 -0
- package/dist/core/harbor/catalogue.d.ts +33 -0
- package/dist/core/harbor/catalogue.js +365 -0
- package/dist/core/harbor/dna.d.ts +13 -0
- package/dist/core/harbor/dna.js +120 -0
- package/dist/{harbor → core/harbor}/dock.d.ts +22 -13
- package/dist/core/harbor/dock.js +381 -0
- package/dist/core/harbor/harbor.d.ts +16 -0
- package/dist/core/harbor/harbor.js +438 -0
- package/dist/core/harbor/index.d.ts +11 -0
- package/dist/{harbor → core/harbor}/index.js +5 -5
- package/dist/core/harbor/memory.d.ts +10 -0
- package/dist/core/harbor/memory.js +25 -0
- package/dist/{harbor → core/harbor}/package.d.ts +0 -1
- package/dist/{harbor → core/harbor}/package.js +9 -9
- package/dist/core/harbor/probe.d.ts +22 -0
- package/dist/core/harbor/probe.js +15 -0
- package/dist/core/harbor/registry.d.ts +15 -0
- package/dist/{harbor → core/harbor}/registry.js +26 -10
- package/dist/core/harbor/root-line.d.ts +7 -0
- package/dist/core/harbor/root-line.js +9 -0
- package/dist/{harbor → core/harbor}/terrain.d.ts +9 -6
- package/dist/{harbor → core/harbor}/terrain.js +5 -4
- package/dist/core/http/index.d.ts +2 -0
- package/dist/{http → core/http}/index.js +3 -5
- package/dist/{line → core/line}/answer.d.ts +2 -2
- package/dist/{line → core/line}/frame.d.ts +0 -5
- package/dist/{line → core/line}/frame.js +0 -4
- package/dist/core/line/ground.js +7 -0
- package/dist/core/line/index.d.ts +4 -0
- package/dist/core/line/index.js +8 -0
- package/dist/core/line/web.d.ts +12 -0
- package/dist/{line → core/line}/web.js +13 -77
- package/dist/{node → core/node}/index.d.ts +2 -15
- package/dist/core/node/index.js +124 -0
- package/dist/{pointer → core/pointer}/bodies.d.ts +7 -5
- package/dist/core/pointer/bodies.js +118 -0
- package/dist/core/pointer/index.d.ts +2 -0
- package/dist/{pointer → core/pointer}/index.js +1 -1
- package/dist/{pointer → core/pointer}/world.d.ts +13 -9
- package/dist/{pointer → core/pointer}/world.js +31 -16
- package/dist/{proof → core/proof}/contracts.d.ts +6 -2
- package/dist/{proof → core/proof}/contracts.js +11 -10
- package/dist/core/proof/index.d.ts +3 -0
- package/dist/{proof → core/proof}/index.js +2 -2
- package/dist/core/proof/law.d.ts +25 -0
- package/dist/core/proof/law.js +715 -0
- package/dist/{tcp → core/tcp}/index.d.ts +7 -4
- package/dist/{tcp → core/tcp}/index.js +11 -62
- package/dist/{ward/ward.d.ts → core/ward/house.d.ts} +24 -10
- package/dist/core/ward/house.js +473 -0
- package/dist/core/ward/index.d.ts +5 -0
- package/dist/core/ward/index.js +7 -0
- package/dist/{ward → core/ward}/partition.d.ts +1 -0
- package/dist/{ward → core/ward}/stance.d.ts +2 -2
- package/dist/{ward → core/ward}/stance.js +5 -2
- package/dist/{ward/ward-being.d.ts → core/ward/ward.d.ts} +14 -6
- package/dist/core/ward/ward.js +140 -0
- package/dist/core.d.ts +10 -0
- package/dist/core.js +19 -0
- package/dist/defaults/dock/index.d.ts +4 -0
- package/dist/defaults/dock/index.js +11 -0
- package/dist/defaults/index.d.ts +5 -0
- package/dist/defaults/index.js +10 -0
- package/dist/defaults/memory/index.d.ts +12 -0
- package/dist/defaults/memory/index.js +39 -0
- package/dist/defaults/tcp/index.d.ts +16 -0
- package/dist/defaults/tcp/index.js +82 -0
- package/dist/defaults/ward/index.d.ts +4 -0
- package/dist/defaults/ward/index.js +11 -0
- package/dist/defaults/web/index.d.ts +15 -0
- package/dist/defaults/web/index.js +90 -0
- package/dist/edge.js +4 -3
- package/dist/index.d.ts +1 -8
- package/dist/index.js +13 -18
- package/dist/kit.d.ts +4 -0
- package/dist/kit.js +12 -0
- package/dist/node.js +4 -3
- package/package.json +23 -18
- package/src/browser.ts +4 -3
- package/src/cli.ts +15 -0
- package/src/{being → core/being}/being.ts +4 -0
- package/src/{being → core/being}/faculty.ts +5 -2
- package/src/{being → core/being}/index.ts +1 -1
- package/src/{being → core/being}/kind.ts +7 -0
- package/src/{being → core/being}/types.ts +1 -1
- package/src/{browser → core/browser}/index.ts +16 -13
- package/src/{browser → core/browser}/worker.ts +11 -14
- package/src/{cli → core/cli}/command.ts +113 -66
- package/src/{cli → core/cli}/edge.ts +4 -2
- package/src/{cli → core/cli}/harbor.ts +48 -31
- package/src/{contract → core/contract}/index.ts +14 -14
- package/src/core/contract/link.ts +58 -0
- package/src/{crypto → core/crypto}/ed25519.ts +22 -14
- package/src/core/crypto/subtle.ts +13 -0
- package/src/core/crypto/x25519.ts +23 -0
- package/src/core/edge/index.ts +865 -0
- package/src/core/git/http.ts +103 -0
- package/src/core/git/index.ts +10 -0
- package/src/core/git/object.ts +116 -0
- package/src/core/git/pack.ts +147 -0
- package/src/core/git/store.ts +122 -0
- package/src/core/git/zlib.ts +197 -0
- package/src/core/harbor/carrying.ts +124 -0
- package/src/core/harbor/catalogue.ts +386 -0
- package/src/core/harbor/dna.ts +116 -0
- package/src/core/harbor/dock.ts +420 -0
- package/src/core/harbor/harbor.ts +433 -0
- package/src/core/harbor/index.ts +14 -0
- package/src/core/harbor/memory.ts +31 -0
- package/src/{harbor → core/harbor}/package.ts +15 -15
- package/src/core/harbor/probe.ts +39 -0
- package/src/{harbor → core/harbor}/registry.ts +28 -11
- package/src/core/harbor/root-line.ts +19 -0
- package/src/{harbor → core/harbor}/terrain.ts +14 -7
- package/src/{http → core/http}/index.ts +5 -8
- package/src/{line → core/line}/answer.ts +3 -2
- package/src/{line → core/line}/frame.ts +0 -5
- package/src/core/line/ground.ts +18 -0
- package/src/core/line/index.ts +8 -0
- package/src/{line → core/line}/web.ts +1 -105
- package/src/core/node/index.ts +139 -0
- package/src/core/pointer/bodies.ts +122 -0
- package/src/core/pointer/index.ts +4 -0
- package/src/{pointer → core/pointer}/world.ts +45 -21
- package/src/{proof → core/proof}/contracts.ts +18 -13
- package/src/{proof → core/proof}/index.ts +3 -3
- package/src/core/proof/law.ts +742 -0
- package/src/{stand → core/stand}/stand.ts +2 -2
- package/src/{tcp → core/tcp}/index.ts +17 -74
- package/src/core/ward/house.ts +524 -0
- package/src/core/ward/index.ts +7 -0
- package/src/{ward → core/ward}/partition.ts +5 -1
- package/src/{ward → core/ward}/stance.ts +5 -2
- package/src/core/ward/ward.ts +166 -0
- package/src/core.ts +55 -0
- package/src/defaults/dock/index.ts +12 -0
- package/src/defaults/index.ts +10 -0
- package/src/defaults/memory/index.ts +50 -0
- package/src/defaults/tcp/index.ts +89 -0
- package/src/defaults/ward/index.ts +12 -0
- package/src/defaults/web/index.ts +97 -0
- package/src/edge.ts +4 -3
- package/src/index.ts +13 -50
- package/src/kit.ts +15 -0
- package/src/node.ts +4 -3
- package/dist/cli/harbor.d.ts +0 -16
- package/dist/cli/main.js +0 -14
- package/dist/crypto/subtle.d.ts +0 -10
- package/dist/crypto/subtle.js +0 -29
- package/dist/crypto/x25519.js +0 -21
- package/dist/edge/index.d.ts +0 -81
- package/dist/edge/index.js +0 -400
- package/dist/harbor/carrying.d.ts +0 -17
- package/dist/harbor/carrying.js +0 -38
- package/dist/harbor/catalogue.d.ts +0 -28
- package/dist/harbor/catalogue.js +0 -109
- package/dist/harbor/dock.js +0 -236
- package/dist/harbor/harbor.d.ts +0 -45
- package/dist/harbor/harbor.js +0 -347
- package/dist/harbor/index.d.ts +0 -11
- package/dist/harbor/probe.d.ts +0 -18
- package/dist/harbor/probe.js +0 -15
- package/dist/harbor/registry.d.ts +0 -10
- package/dist/harbor/relay.d.ts +0 -15
- package/dist/harbor/relay.js +0 -406
- package/dist/harbor/root-line.d.ts +0 -9
- package/dist/harbor/root-line.js +0 -38
- package/dist/harbor/store.d.ts +0 -13
- package/dist/harbor/store.js +0 -53
- package/dist/http/index.d.ts +0 -4
- package/dist/line/ground.js +0 -9
- package/dist/line/index.d.ts +0 -5
- package/dist/line/index.js +0 -9
- package/dist/line/push.d.ts +0 -7
- package/dist/line/push.js +0 -92
- package/dist/line/web.d.ts +0 -30
- package/dist/node/index.js +0 -236
- package/dist/pointer/bodies.js +0 -80
- package/dist/pointer/index.d.ts +0 -2
- package/dist/proof/index.d.ts +0 -3
- package/dist/proof/law.d.ts +0 -90
- package/dist/proof/law.js +0 -591
- package/dist/tcp/frame.d.ts +0 -25
- package/dist/tcp/frame.js +0 -64
- package/dist/ward/index.d.ts +0 -6
- package/dist/ward/index.js +0 -8
- package/dist/ward/pilot.d.ts +0 -8
- package/dist/ward/pilot.js +0 -50
- package/dist/ward/ward-being.js +0 -82
- package/dist/ward/ward.js +0 -290
- package/src/cli/main.ts +0 -13
- package/src/crypto/subtle.ts +0 -33
- package/src/crypto/x25519.ts +0 -21
- package/src/edge/index.ts +0 -490
- package/src/harbor/carrying.ts +0 -56
- package/src/harbor/catalogue.ts +0 -134
- package/src/harbor/dock.ts +0 -265
- package/src/harbor/harbor.ts +0 -381
- package/src/harbor/index.ts +0 -14
- package/src/harbor/probe.ts +0 -34
- package/src/harbor/relay.ts +0 -418
- package/src/harbor/root-line.ts +0 -39
- package/src/harbor/store.ts +0 -69
- package/src/line/ground.ts +0 -19
- package/src/line/index.ts +0 -9
- package/src/line/push.ts +0 -112
- package/src/node/index.ts +0 -241
- package/src/pointer/bodies.ts +0 -82
- package/src/pointer/index.ts +0 -4
- package/src/proof/law.ts +0 -591
- package/src/ward/index.ts +0 -8
- package/src/ward/pilot.ts +0 -50
- package/src/ward/ward-being.ts +0 -103
- package/src/ward/ward.ts +0 -328
- /package/dist/{cli/main.d.ts → cli.d.ts} +0 -0
- /package/dist/{being → core/being}/being.d.ts +0 -0
- /package/dist/{being → core/being}/digest.d.ts +0 -0
- /package/dist/{being → core/being}/digest.js +0 -0
- /package/dist/{being → core/being}/faculty.d.ts +0 -0
- /package/dist/{being → core/being}/types.d.ts +0 -0
- /package/dist/{being → core/being}/words.d.ts +0 -0
- /package/dist/{being → core/being}/words.js +0 -0
- /package/dist/{cli → core/cli}/edge.d.ts +0 -0
- /package/dist/{crypto → core/crypto}/aes.d.ts +0 -0
- /package/dist/{crypto → core/crypto}/aes.js +0 -0
- /package/dist/{crypto → core/crypto}/bytes.d.ts +0 -0
- /package/dist/{crypto → core/crypto}/bytes.js +0 -0
- /package/dist/{crypto → core/crypto}/ed25519.d.ts +0 -0
- /package/dist/{crypto → core/crypto}/hash.d.ts +0 -0
- /package/dist/{crypto → core/crypto}/hash.js +0 -0
- /package/dist/{crypto → core/crypto}/index.d.ts +0 -0
- /package/dist/{crypto → core/crypto}/index.js +0 -0
- /package/dist/{crypto → core/crypto}/json.d.ts +0 -0
- /package/dist/{crypto → core/crypto}/json.js +0 -0
- /package/dist/{crypto → core/crypto}/mlkem.d.ts +0 -0
- /package/dist/{crypto → core/crypto}/mlkem.js +0 -0
- /package/dist/{crypto → core/crypto}/x25519.d.ts +0 -0
- /package/dist/{folder → core/folder}/index.d.ts +0 -0
- /package/dist/{folder → core/folder}/index.js +0 -0
- /package/dist/{http → core/http}/websocket.d.ts +0 -0
- /package/dist/{http → core/http}/websocket.js +0 -0
- /package/dist/{line → core/line}/answer.js +0 -0
- /package/dist/{line → core/line}/ground.d.ts +0 -0
- /package/dist/{proof → core/proof}/expect.d.ts +0 -0
- /package/dist/{proof → core/proof}/expect.js +0 -0
- /package/dist/{quo → core/quo}/address.d.ts +0 -0
- /package/dist/{quo → core/quo}/address.js +0 -0
- /package/dist/{quo → core/quo}/door.d.ts +0 -0
- /package/dist/{quo → core/quo}/door.js +0 -0
- /package/dist/{quo → core/quo}/index.d.ts +0 -0
- /package/dist/{quo → core/quo}/index.js +0 -0
- /package/dist/{quo → core/quo}/invitation.d.ts +0 -0
- /package/dist/{quo → core/quo}/invitation.js +0 -0
- /package/dist/{quo → core/quo}/keys.d.ts +0 -0
- /package/dist/{quo → core/quo}/keys.js +0 -0
- /package/dist/{quo → core/quo}/payload.d.ts +0 -0
- /package/dist/{quo → core/quo}/payload.js +0 -0
- /package/dist/{quo → core/quo}/relations.d.ts +0 -0
- /package/dist/{quo → core/quo}/relations.js +0 -0
- /package/dist/{quo → core/quo}/reply.d.ts +0 -0
- /package/dist/{quo → core/quo}/reply.js +0 -0
- /package/dist/{quo → core/quo}/seal.d.ts +0 -0
- /package/dist/{quo → core/quo}/seal.js +0 -0
- /package/dist/{quo → core/quo}/standing.d.ts +0 -0
- /package/dist/{quo → core/quo}/standing.js +0 -0
- /package/dist/{ward → core/ward}/allowance.d.ts +0 -0
- /package/dist/{ward → core/ward}/allowance.js +0 -0
- /package/dist/{ward → core/ward}/cells.d.ts +0 -0
- /package/dist/{ward → core/ward}/cells.js +0 -0
- /package/dist/{ward → core/ward}/partition.js +0 -0
- /package/src/{being → core/being}/digest.ts +0 -0
- /package/src/{being → core/being}/words.ts +0 -0
- /package/src/{crypto → core/crypto}/aes.ts +0 -0
- /package/src/{crypto → core/crypto}/bytes.ts +0 -0
- /package/src/{crypto → core/crypto}/hash.ts +0 -0
- /package/src/{crypto → core/crypto}/index.ts +0 -0
- /package/src/{crypto → core/crypto}/json.ts +0 -0
- /package/src/{crypto → core/crypto}/mlkem.ts +0 -0
- /package/src/{folder → core/folder}/index.ts +0 -0
- /package/src/{http → core/http}/websocket.ts +0 -0
- /package/src/{proof → core/proof}/expect.ts +0 -0
- /package/src/{quo → core/quo}/address.ts +0 -0
- /package/src/{quo → core/quo}/door.ts +0 -0
- /package/src/{quo → core/quo}/index.ts +0 -0
- /package/src/{quo → core/quo}/invitation.ts +0 -0
- /package/src/{quo → core/quo}/keys.ts +0 -0
- /package/src/{quo → core/quo}/payload.ts +0 -0
- /package/src/{quo → core/quo}/relations.ts +0 -0
- /package/src/{quo → core/quo}/reply.ts +0 -0
- /package/src/{quo → core/quo}/seal.ts +0 -0
- /package/src/{quo → core/quo}/standing.ts +0 -0
- /package/src/{stand → core/stand}/main.ts +0 -0
- /package/src/{ward → core/ward}/allowance.ts +0 -0
- /package/src/{ward → core/ward}/cells.ts +0 -0
package/dist/cli/main.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
// The `nervur` program: `command.ts` over this process's arguments. A
|
|
4
|
-
// command that cannot run exits 2 and says why on stderr.
|
|
5
|
-
import { main, SERVING } from './command.js';
|
|
6
|
-
try {
|
|
7
|
-
const code = await main(process.argv.slice(2), process.env, (line) => process.stdout.write(`${line}\n`));
|
|
8
|
-
if (code !== SERVING)
|
|
9
|
-
process.exitCode = code;
|
|
10
|
-
}
|
|
11
|
-
catch (e) {
|
|
12
|
-
process.stderr.write(`nervur: ${e.message}\n`);
|
|
13
|
-
process.exitCode = 2;
|
|
14
|
-
}
|
package/dist/crypto/subtle.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export declare const subtle: () => SubtleCrypto;
|
|
2
|
-
export type Bytes = Uint8Array<ArrayBuffer>;
|
|
3
|
-
export declare const own: (bytes: Uint8Array) => Bytes;
|
|
4
|
-
declare const PKCS8: {
|
|
5
|
-
readonly Ed25519: '302e020100300506032b657004220420';
|
|
6
|
-
readonly X25519: '302e020100300506032b656e04220420';
|
|
7
|
-
};
|
|
8
|
-
export declare const importSecret: (curve: keyof typeof PKCS8, secret: Uint8Array, uses: KeyUsage[]) => Promise<CryptoKey>;
|
|
9
|
-
export declare const publicOf: (key: CryptoKey) => Promise<Uint8Array>;
|
|
10
|
-
export {};
|
package/dist/crypto/subtle.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// Web Crypto, read at every use. A page on a plain http origin has `crypto`
|
|
3
|
-
// without `subtle`, and a terrain may install it after this module loads.
|
|
4
|
-
export const subtle = () => {
|
|
5
|
-
const found = globalThis.crypto?.subtle;
|
|
6
|
-
if (!found)
|
|
7
|
-
throw new Error('this terrain has no crypto.subtle: a ward needs a secure context');
|
|
8
|
-
return found;
|
|
9
|
-
};
|
|
10
|
-
// Web Crypto takes a buffer it owns, so every input is copied into one.
|
|
11
|
-
export const own = (bytes) => Uint8Array.from(bytes);
|
|
12
|
-
// The PKCS#8 wrapping of a thirty-two byte secret, which is the whole of it
|
|
13
|
-
// for both curves.
|
|
14
|
-
const PKCS8 = { Ed25519: '302e020100300506032b657004220420', X25519: '302e020100300506032b656e04220420' };
|
|
15
|
-
export const importSecret = (curve, secret, uses) => {
|
|
16
|
-
if (secret.length !== 32)
|
|
17
|
-
throw new TypeError('a secret is thirty-two bytes');
|
|
18
|
-
const prefix = Uint8Array.from(PKCS8[curve].match(/../g), (b) => parseInt(b, 16));
|
|
19
|
-
const wrapped = new Uint8Array(48);
|
|
20
|
-
wrapped.set(prefix);
|
|
21
|
-
wrapped.set(secret, 16);
|
|
22
|
-
return subtle().importKey('pkcs8', wrapped, { name: curve }, true, uses);
|
|
23
|
-
};
|
|
24
|
-
// Web Crypto gives a private key's public half only through a JWK.
|
|
25
|
-
export const publicOf = async (key) => {
|
|
26
|
-
const { x } = await subtle().exportKey('jwk', key);
|
|
27
|
-
const binary = atob(x.replaceAll('-', '+').replaceAll('_', '/'));
|
|
28
|
-
return Uint8Array.from(binary, (c) => c.charCodeAt(0));
|
|
29
|
-
};
|
package/dist/crypto/x25519.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// X25519 agrees. A secret is thirty-two bytes, clamped by the function and
|
|
3
|
-
// never before.
|
|
4
|
-
import { zero } from './bytes.js';
|
|
5
|
-
import { importSecret, own, publicOf, subtle } from './subtle.js';
|
|
6
|
-
export const x25519Public = async (secret) => publicOf(await importSecret('X25519', secret, ['deriveBits']));
|
|
7
|
-
// The agreement, or null for a public key that takes no seal: one whose
|
|
8
|
-
// agreement is thirty-two zero bytes, or one the terrain refuses to read.
|
|
9
|
-
export const agree = async (secret, pk) => {
|
|
10
|
-
if (pk.length !== 32)
|
|
11
|
-
return null;
|
|
12
|
-
try {
|
|
13
|
-
const mine = await importSecret('X25519', secret, ['deriveBits']);
|
|
14
|
-
const theirs = await subtle().importKey('raw', own(pk), { name: 'X25519' }, false, []);
|
|
15
|
-
const shared = new Uint8Array(await subtle().deriveBits({ name: 'X25519', public: theirs }, mine, 256));
|
|
16
|
-
return zero(shared) ? null : shared;
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
};
|
package/dist/edge/index.d.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { Custody, Memory, type Entropy, type Module } from '../contract/index.ts';
|
|
2
|
-
import { Harbor, type Carried, type GroundFaculty, type GroundProbe } from '../harbor/index.ts';
|
|
3
|
-
import { type WebListen } from '../line/index.ts';
|
|
4
|
-
import { PointerTerrain } from '../pointer/index.ts';
|
|
5
|
-
export type { Carried } from '../harbor/index.ts';
|
|
6
|
-
export declare const EDGE = "edge";
|
|
7
|
-
export interface EdgeStorage {
|
|
8
|
-
get(key: string): Promise<unknown>;
|
|
9
|
-
put(entries: Record<string, unknown>): Promise<void>;
|
|
10
|
-
delete(keys: string[]): Promise<number>;
|
|
11
|
-
list(options: {
|
|
12
|
-
prefix: string;
|
|
13
|
-
}): Promise<Map<string, unknown>>;
|
|
14
|
-
transaction<T>(work: (txn: EdgeStorage) => Promise<T>): Promise<T>;
|
|
15
|
-
}
|
|
16
|
-
export interface EdgeState {
|
|
17
|
-
readonly storage: EdgeStorage;
|
|
18
|
-
blockConcurrencyWhile<T>(work: () => Promise<T>): Promise<T>;
|
|
19
|
-
}
|
|
20
|
-
export type EdgeEnv = {
|
|
21
|
-
readonly NERVUR_SECRET?: string;
|
|
22
|
-
};
|
|
23
|
-
export type EdgeGiven = {
|
|
24
|
-
readonly state: EdgeState;
|
|
25
|
-
readonly env: EdgeEnv;
|
|
26
|
-
readonly package?: Packed;
|
|
27
|
-
};
|
|
28
|
-
export type Packed = {
|
|
29
|
-
readonly sealed: string;
|
|
30
|
-
readonly places: Carried['places'];
|
|
31
|
-
};
|
|
32
|
-
export type Pack = Record<string, Packed>;
|
|
33
|
-
export declare const isHarborName: (name: unknown) => name is string;
|
|
34
|
-
export declare const readPack: (value: unknown) => Pack | null;
|
|
35
|
-
export declare const sealSeed: (secret: string, seed: Uint8Array, entropy?: Entropy) => Promise<string>;
|
|
36
|
-
export declare class EdgeMemory extends Memory {
|
|
37
|
-
#private;
|
|
38
|
-
constructor(storage: EdgeStorage, root?: string);
|
|
39
|
-
read(place: string): Promise<Map<string, Uint8Array>>;
|
|
40
|
-
write(place: string, entries: ReadonlyMap<string, Uint8Array | null>): Promise<void>;
|
|
41
|
-
places(): Promise<string[]>;
|
|
42
|
-
forget(place: string): Promise<void>;
|
|
43
|
-
}
|
|
44
|
-
export declare class EdgeCustody extends Custody {
|
|
45
|
-
#private;
|
|
46
|
-
constructor(storage: EdgeStorage, secret: string | undefined, entropy?: Entropy, root?: string);
|
|
47
|
-
kept(): Promise<boolean>;
|
|
48
|
-
land(sealed: string, txn?: EdgeStorage): Promise<void>;
|
|
49
|
-
seed(): Promise<Uint8Array>;
|
|
50
|
-
}
|
|
51
|
-
export declare const edgeTcp: GroundFaculty;
|
|
52
|
-
export type EdgeParts = {
|
|
53
|
-
readonly given: EdgeGiven;
|
|
54
|
-
readonly modules?: readonly Module[];
|
|
55
|
-
};
|
|
56
|
-
export declare class EdgeTerrain extends PointerTerrain {
|
|
57
|
-
#private;
|
|
58
|
-
readonly given: EdgeGiven;
|
|
59
|
-
listening: WebListen | undefined;
|
|
60
|
-
constructor(parts: EdgeParts);
|
|
61
|
-
claim(): Promise<void>;
|
|
62
|
-
stand(harbor: Harbor): Promise<void>;
|
|
63
|
-
answer(request: Request): Promise<Response>;
|
|
64
|
-
}
|
|
65
|
-
export declare const edgeGround: GroundProbe;
|
|
66
|
-
export declare const harborNameOf: (request: Request) => string | null;
|
|
67
|
-
export type HarborObjectParts = {
|
|
68
|
-
readonly modules: readonly Module[];
|
|
69
|
-
readonly pack?: Pack | ((env: EdgeEnv) => Pack | undefined);
|
|
70
|
-
readonly born?: (name: string) => boolean;
|
|
71
|
-
readonly stood?: (harbor: Harbor, name: string) => Promise<void>;
|
|
72
|
-
};
|
|
73
|
-
export type HarborObject = {
|
|
74
|
-
harborFor(request: Request): Promise<Harbor | null>;
|
|
75
|
-
fetch(request: Request): Promise<Response>;
|
|
76
|
-
};
|
|
77
|
-
export type HarborObjectClass = new (state: EdgeState, env: EdgeEnv) => HarborObject;
|
|
78
|
-
export declare const harborObject: ({ modules, pack, born, stood }: HarborObjectParts) => HarborObjectClass;
|
|
79
|
-
export declare const harborWorker: (binding?: string) => {
|
|
80
|
-
fetch(request: Request, env: Record<string, unknown>): Promise<Response>;
|
|
81
|
-
};
|
package/dist/edge/index.js
DELETED
|
@@ -1,400 +0,0 @@
|
|
|
1
|
-
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
-
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
-
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
-
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
-
});
|
|
6
|
-
}
|
|
7
|
-
return path;
|
|
8
|
-
};
|
|
9
|
-
import { Custody, Memory } from '../contract/index.js';
|
|
10
|
-
import { concat, decrypt, encrypt, hex, hkdf, isHex, unhex, utf8 } from '../crypto/index.js';
|
|
11
|
-
import { addGround, CarrierFaculty, Harbor, landPlaces, readCarried, UNDIALED } from '../harbor/index.js';
|
|
12
|
-
import { answerHeld, answerPost, askFrame, FrameReader, TCP, TCP_OPENING, WEB_OPENING, webFaculty, webPush } from '../line/index.js';
|
|
13
|
-
import { CryptoEntropy, HeldLoader, PointerTerrain } from '../pointer/index.js';
|
|
14
|
-
import { tcpAddress, tcpAt } from '../quo/index.js';
|
|
15
|
-
import { ownerAsk } from '../ward/index.js';
|
|
16
|
-
export const EDGE = 'edge';
|
|
17
|
-
const ENTRY = 'm/';
|
|
18
|
-
const SEED = 'c/seed';
|
|
19
|
-
// The most keys one storage call takes.
|
|
20
|
-
const BATCH = 128;
|
|
21
|
-
const SEAL_INFO = utf8('nervur edge custody');
|
|
22
|
-
const MAX_ID = 0xffff_ffff;
|
|
23
|
-
// A harbor's name on the edge: one path segment, so it is where the
|
|
24
|
-
// harbor answers, `/<name>/quo`.
|
|
25
|
-
export const isHarborName = (name) => typeof name === 'string' && /^[a-z0-9][a-z0-9-]{0,62}$/.test(name);
|
|
26
|
-
const NONCE = 12;
|
|
27
|
-
// A pack as JSON reads, or null for anything else.
|
|
28
|
-
export const readPack = (value) => {
|
|
29
|
-
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
30
|
-
return null;
|
|
31
|
-
const pack = {};
|
|
32
|
-
for (const [name, entry] of Object.entries(value)) {
|
|
33
|
-
const { sealed, places } = (entry ?? {});
|
|
34
|
-
const carried = readCarried({ places });
|
|
35
|
-
if (!isHarborName(name) || !isHex(sealed) || sealed.length <= NONCE * 2 || carried === null)
|
|
36
|
-
return null;
|
|
37
|
-
pack[name] = { sealed: sealed, places: carried.places };
|
|
38
|
-
}
|
|
39
|
-
return pack;
|
|
40
|
-
};
|
|
41
|
-
const sealKey = (secret) => hkdf(utf8(secret), SEAL_INFO, 32);
|
|
42
|
-
// A seed sealed under a worker's secret, as a pack keeps it.
|
|
43
|
-
export const sealSeed = async (secret, seed, entropy = new CryptoEntropy()) => {
|
|
44
|
-
const nonce = entropy.draw(NONCE);
|
|
45
|
-
return hex(concat(nonce, await encrypt(await sealKey(secret), nonce, new Uint8Array(0), seed)));
|
|
46
|
-
};
|
|
47
|
-
const chunks = (items) => Array.from({ length: Math.ceil(items.length / BATCH) }, (_, i) => items.slice(i * BATCH, (i + 1) * BATCH));
|
|
48
|
-
const bytesOf = (value) => new Uint8Array(value instanceof ArrayBuffer ? value : value);
|
|
49
|
-
// A body keeps its keys under `root`, so one object may hold more than one
|
|
50
|
-
// keeping.
|
|
51
|
-
export class EdgeMemory extends Memory {
|
|
52
|
-
#storage;
|
|
53
|
-
#entry;
|
|
54
|
-
constructor(storage, root = '') {
|
|
55
|
-
super();
|
|
56
|
-
this.#storage = storage;
|
|
57
|
-
this.#entry = `${root}${ENTRY}`;
|
|
58
|
-
}
|
|
59
|
-
async read(place) {
|
|
60
|
-
const prefix = `${this.#entry}${place}/`;
|
|
61
|
-
const listed = await this.#storage.list({ prefix });
|
|
62
|
-
return new Map([...listed].map(([key, value]) => [key.slice(prefix.length), bytesOf(value).slice()]));
|
|
63
|
-
}
|
|
64
|
-
write(place, entries) {
|
|
65
|
-
const put = [];
|
|
66
|
-
const gone = [];
|
|
67
|
-
for (const [name, bytes] of entries) {
|
|
68
|
-
if (bytes === null)
|
|
69
|
-
gone.push(`${this.#entry}${place}/${name}`);
|
|
70
|
-
else
|
|
71
|
-
put.push([`${this.#entry}${place}/${name}`, bytes.slice()]);
|
|
72
|
-
}
|
|
73
|
-
return this.#storage.transaction(async (txn) => {
|
|
74
|
-
for (const batch of chunks(put))
|
|
75
|
-
await txn.put(Object.fromEntries(batch));
|
|
76
|
-
for (const batch of chunks(gone))
|
|
77
|
-
await txn.delete(batch);
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
async places() {
|
|
81
|
-
const entry = this.#entry;
|
|
82
|
-
const keys = [...(await this.#storage.list({ prefix: entry })).keys()];
|
|
83
|
-
return [...new Set(keys.map((key) => key.slice(entry.length, key.indexOf('/', entry.length))))];
|
|
84
|
-
}
|
|
85
|
-
async forget(place) {
|
|
86
|
-
const keys = [...(await this.#storage.list({ prefix: `${this.#entry}${place}/` })).keys()];
|
|
87
|
-
await this.#storage.transaction(async (txn) => {
|
|
88
|
-
for (const batch of chunks(keys))
|
|
89
|
-
await txn.delete(batch);
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// The seed, kept sealed under a key the worker's secret gives, so the
|
|
94
|
-
// storage alone opens nothing: the one a pack landed, or one drawn the
|
|
95
|
-
// first time it is asked for. A worker with no secret stands no harbor.
|
|
96
|
-
export class EdgeCustody extends Custody {
|
|
97
|
-
#storage;
|
|
98
|
-
#secret;
|
|
99
|
-
#entropy;
|
|
100
|
-
#key;
|
|
101
|
-
constructor(storage, secret, entropy = new CryptoEntropy(), root = '') {
|
|
102
|
-
super();
|
|
103
|
-
this.#storage = storage;
|
|
104
|
-
this.#secret = secret;
|
|
105
|
-
this.#entropy = entropy;
|
|
106
|
-
this.#key = `${root}${SEED}`;
|
|
107
|
-
}
|
|
108
|
-
// Whether a seed is kept, so a pack lands only where none is.
|
|
109
|
-
async kept() {
|
|
110
|
-
return (await this.#storage.get(this.#key)) !== undefined;
|
|
111
|
-
}
|
|
112
|
-
// A packed seed, sealed as `sealSeed` sealed it, kept as it came.
|
|
113
|
-
async land(sealed, txn = this.#storage) {
|
|
114
|
-
const bytes = unhex(sealed);
|
|
115
|
-
await txn.put({ [this.#key]: { nonce: bytes.slice(0, NONCE), sealed: bytes.slice(NONCE) } });
|
|
116
|
-
}
|
|
117
|
-
async seed() {
|
|
118
|
-
if (!this.#secret)
|
|
119
|
-
throw new Error('the worker holds no NERVUR_SECRET');
|
|
120
|
-
const key = await sealKey(this.#secret);
|
|
121
|
-
return this.#storage.transaction(async (txn) => {
|
|
122
|
-
const kept = (await txn.get(this.#key));
|
|
123
|
-
if (kept) {
|
|
124
|
-
const seed = await decrypt(key, bytesOf(kept.nonce), new Uint8Array(0), bytesOf(kept.sealed));
|
|
125
|
-
if (seed === null)
|
|
126
|
-
throw new Error('the seed does not open under this NERVUR_SECRET');
|
|
127
|
-
return seed;
|
|
128
|
-
}
|
|
129
|
-
const seed = this.#entropy.draw(32);
|
|
130
|
-
const nonce = this.#entropy.draw(NONCE);
|
|
131
|
-
await txn.put({ [this.#key]: { nonce, sealed: await encrypt(key, nonce, new Uint8Array(0), seed) } });
|
|
132
|
-
return seed.slice();
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
class EdgeLine {
|
|
137
|
-
#socket;
|
|
138
|
-
#writer;
|
|
139
|
-
#waiting = new Map();
|
|
140
|
-
#next = 1;
|
|
141
|
-
#closed = false;
|
|
142
|
-
constructor(socket, onClose) {
|
|
143
|
-
this.#socket = socket;
|
|
144
|
-
this.#writer = socket.writable.getWriter();
|
|
145
|
-
const reader = new FrameReader();
|
|
146
|
-
void (async () => {
|
|
147
|
-
try {
|
|
148
|
-
for await (const chunk of socket.readable) {
|
|
149
|
-
for (const frame of reader.push(new Uint8Array(chunk))) {
|
|
150
|
-
if (frame.kind === 'ask')
|
|
151
|
-
continue;
|
|
152
|
-
const done = this.#waiting.get(frame.id);
|
|
153
|
-
this.#waiting.delete(frame.id);
|
|
154
|
-
done?.(frame.kind === 'reply' ? frame.box : null);
|
|
155
|
-
}
|
|
156
|
-
if (reader.bad)
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
catch {
|
|
161
|
-
// A line that broke answers nothing more.
|
|
162
|
-
}
|
|
163
|
-
this.#closed = true;
|
|
164
|
-
onClose();
|
|
165
|
-
for (const done of this.#waiting.values())
|
|
166
|
-
done(null);
|
|
167
|
-
this.#waiting.clear();
|
|
168
|
-
await socket.close().catch(() => undefined);
|
|
169
|
-
})();
|
|
170
|
-
}
|
|
171
|
-
ask(pk, box) {
|
|
172
|
-
if (this.#closed)
|
|
173
|
-
return Promise.resolve(null);
|
|
174
|
-
const id = this.#next;
|
|
175
|
-
this.#next = this.#next === MAX_ID ? 1 : this.#next + 1;
|
|
176
|
-
return new Promise((resolve) => {
|
|
177
|
-
this.#waiting.set(id, resolve);
|
|
178
|
-
this.#writer.write(askFrame(id, pk, box)).catch(() => resolve(null));
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
close() {
|
|
182
|
-
this.#closed = true;
|
|
183
|
-
return this.#socket.close().catch(() => undefined);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
const sockets = 'cloudflare:sockets';
|
|
187
|
-
const connector = async () => {
|
|
188
|
-
try {
|
|
189
|
-
return (await import(__rewriteRelativeImportExtension(/* @vite-ignore */ sockets))).connect;
|
|
190
|
-
}
|
|
191
|
-
catch {
|
|
192
|
-
return null;
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
// Quo over TCP from a worker: it dials, and takes no inbound TCP.
|
|
196
|
-
export const edgeTcp = () => class EdgeTcp extends CarrierFaculty {
|
|
197
|
-
static kind = TCP;
|
|
198
|
-
static asks = {
|
|
199
|
-
listen: ownerAsk('an edge takes no inbound TCP'),
|
|
200
|
-
deaf: ownerAsk('listen nowhere'),
|
|
201
|
-
};
|
|
202
|
-
#lines = new Map();
|
|
203
|
-
accepts(address) {
|
|
204
|
-
return tcpAddress(address) !== null;
|
|
205
|
-
}
|
|
206
|
-
async dial(address, pk, bytes) {
|
|
207
|
-
const at = tcpAddress(address);
|
|
208
|
-
if (at === null || !isHex(pk, 64))
|
|
209
|
-
return UNDIALED;
|
|
210
|
-
const line = await this.#line(at);
|
|
211
|
-
return line ? line.ask(unhex(pk), bytes) : UNDIALED;
|
|
212
|
-
}
|
|
213
|
-
#line({ host, port }) {
|
|
214
|
-
const at = tcpAt(host, port);
|
|
215
|
-
let line = this.#lines.get(at);
|
|
216
|
-
if (!line) {
|
|
217
|
-
line = (async () => {
|
|
218
|
-
const connect = await connector();
|
|
219
|
-
if (!connect)
|
|
220
|
-
return null;
|
|
221
|
-
try {
|
|
222
|
-
const socket = connect({ hostname: host, port });
|
|
223
|
-
await socket.opened;
|
|
224
|
-
return new EdgeLine(socket, () => this.#lines.delete(at));
|
|
225
|
-
}
|
|
226
|
-
catch {
|
|
227
|
-
return null;
|
|
228
|
-
}
|
|
229
|
-
})();
|
|
230
|
-
this.#lines.set(at, line);
|
|
231
|
-
void line.then((open) => open ?? this.#lines.delete(at));
|
|
232
|
-
}
|
|
233
|
-
return line;
|
|
234
|
-
}
|
|
235
|
-
async sleep() {
|
|
236
|
-
const lines = [...this.#lines.values()];
|
|
237
|
-
this.#lines.clear();
|
|
238
|
-
for (const line of await Promise.all(lines))
|
|
239
|
-
await line?.close();
|
|
240
|
-
}
|
|
241
|
-
listen() {
|
|
242
|
-
return { error: 'an edge takes no inbound TCP' };
|
|
243
|
-
}
|
|
244
|
-
deaf() {
|
|
245
|
-
return { deaf: true };
|
|
246
|
-
}
|
|
247
|
-
};
|
|
248
|
-
// Where the edge's web carrier listens: the object's own requests, at the
|
|
249
|
-
// host and path its cells name. A port of 0 is the edge's own https.
|
|
250
|
-
const edgeServe = (ground, listen) => {
|
|
251
|
-
const terrain = ground.terrain;
|
|
252
|
-
if (!(terrain instanceof EdgeTerrain))
|
|
253
|
-
return Promise.reject(new Error('this harbor stands on no edge'));
|
|
254
|
-
terrain.listening = listen;
|
|
255
|
-
const authority = listen.port === 0 ? listen.host : `${tcpAt(listen.host, listen.port).slice('tcp://'.length)}`;
|
|
256
|
-
const [post, held] = listen.port === 0 ? ['https', 'wss'] : ['http', 'ws'];
|
|
257
|
-
return Promise.resolve({
|
|
258
|
-
port: listen.port,
|
|
259
|
-
at: [`${post}://${authority}${listen.path}`, `${held}://${authority}${listen.path}`],
|
|
260
|
-
close: () => {
|
|
261
|
-
if (terrain.listening === listen)
|
|
262
|
-
terrain.listening = undefined;
|
|
263
|
-
return Promise.resolve();
|
|
264
|
-
},
|
|
265
|
-
});
|
|
266
|
-
};
|
|
267
|
-
export class EdgeTerrain extends PointerTerrain {
|
|
268
|
-
given;
|
|
269
|
-
// Where the web carrier listens now, as the object answers requests.
|
|
270
|
-
listening;
|
|
271
|
-
#harbor;
|
|
272
|
-
constructor(parts) {
|
|
273
|
-
const entropy = new CryptoEntropy();
|
|
274
|
-
const { storage } = parts.given.state;
|
|
275
|
-
super({
|
|
276
|
-
entropy,
|
|
277
|
-
loader: new HeldLoader(parts.modules ?? []),
|
|
278
|
-
custody: new EdgeCustody(storage, parts.given.env.NERVUR_SECRET, entropy),
|
|
279
|
-
memory: new EdgeMemory(storage),
|
|
280
|
-
faculties: [edgeTcp, webFaculty(edgeServe), webPush],
|
|
281
|
-
opens: [TCP_OPENING, WEB_OPENING],
|
|
282
|
-
});
|
|
283
|
-
this.given = parts.given;
|
|
284
|
-
}
|
|
285
|
-
// A packed harbor lands where the object keeps no seed yet: its places
|
|
286
|
-
// first and its seed last, so a start cut short lands it whole again,
|
|
287
|
-
// and once the seed is kept the storage is the harbor and a new deploy
|
|
288
|
-
// leaves it be. A seed sealed under another secret does not open.
|
|
289
|
-
async claim() {
|
|
290
|
-
const packed = this.given.package;
|
|
291
|
-
const custody = this.custody;
|
|
292
|
-
if (!packed || (await custody.kept()))
|
|
293
|
-
return;
|
|
294
|
-
await landPlaces(this.memory, { places: packed.places });
|
|
295
|
-
await custody.land(packed.sealed);
|
|
296
|
-
}
|
|
297
|
-
stand(harbor) {
|
|
298
|
-
this.#harbor = harbor;
|
|
299
|
-
return Promise.resolve();
|
|
300
|
-
}
|
|
301
|
-
// One request to the object: a post, or a held line opened, where the
|
|
302
|
-
// web carrier listens.
|
|
303
|
-
answer(request) {
|
|
304
|
-
const listen = this.listening;
|
|
305
|
-
const harbor = this.#harbor;
|
|
306
|
-
if (!listen || !harbor)
|
|
307
|
-
return Promise.resolve(new Response(null, { status: 404 }));
|
|
308
|
-
if (request.headers.get('upgrade')?.toLowerCase() !== 'websocket')
|
|
309
|
-
return answerPost(harbor, listen, request);
|
|
310
|
-
const offered = (request.headers.get('sec-websocket-protocol') ?? '').split(',').map((p) => p.trim());
|
|
311
|
-
if (new URL(request.url).pathname !== listen.path || !offered.includes('quo'))
|
|
312
|
-
return Promise.resolve(new Response(null, { status: 400 }));
|
|
313
|
-
const Pair = globalThis.WebSocketPair;
|
|
314
|
-
const pair = new Pair();
|
|
315
|
-
const [client, server] = [pair[0], pair[1]];
|
|
316
|
-
server.accept();
|
|
317
|
-
const side = { send: (body) => server.send(new Uint8Array(body)), close: () => server.close() };
|
|
318
|
-
server.addEventListener('message', (event) => answerHeld(harbor, side, typeof event.data === 'string' ? event.data : new Uint8Array(event.data)));
|
|
319
|
-
return Promise.resolve(new Response(null, { status: 101, webSocket: client, headers: { 'sec-websocket-protocol': 'quo' } }));
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
const isGiven = (value) => {
|
|
323
|
-
const given = value;
|
|
324
|
-
return typeof given?.state?.storage?.transaction === 'function' && typeof given.env === 'object';
|
|
325
|
-
};
|
|
326
|
-
// A harbor handed a Durable Object's state and environment.
|
|
327
|
-
export const edgeGround = {
|
|
328
|
-
name: EDGE,
|
|
329
|
-
fits: ({ given }) => isGiven(given),
|
|
330
|
-
terrain: ({ given, modules }) => new EdgeTerrain({ given: given, ...(modules ? { modules } : {}) }),
|
|
331
|
-
};
|
|
332
|
-
// The harbor a request is for: the first segment of its path.
|
|
333
|
-
export const harborNameOf = (request) => {
|
|
334
|
-
const name = new URL(request.url).pathname.split('/')[1];
|
|
335
|
-
return isHarborName(name) ? name : null;
|
|
336
|
-
};
|
|
337
|
-
// A Durable Object class whose every instance is one harbor, by the name
|
|
338
|
-
// the worker reached it under: opened at its first request, the one its
|
|
339
|
-
// pack holds under that name or one `born` allows, its web carrier opened,
|
|
340
|
-
// and every request it receives answered by that carrier at
|
|
341
|
-
// `/<name>/quo`. An object answers the one name it opened under, and a
|
|
342
|
-
// name it may not open is 404, with nothing written.
|
|
343
|
-
export const harborObject = ({ modules, pack, born, stood }) => class {
|
|
344
|
-
#state;
|
|
345
|
-
#env;
|
|
346
|
-
#name;
|
|
347
|
-
#opening;
|
|
348
|
-
constructor(state, env) {
|
|
349
|
-
addGround(edgeGround);
|
|
350
|
-
this.#state = state;
|
|
351
|
-
this.#env = env;
|
|
352
|
-
}
|
|
353
|
-
// The harbor a request names, opened once, or null where it names
|
|
354
|
-
// another harbor or none.
|
|
355
|
-
harborFor(request) {
|
|
356
|
-
const name = harborNameOf(request);
|
|
357
|
-
if (name === null || (this.#name !== undefined && this.#name !== name))
|
|
358
|
-
return Promise.resolve(null);
|
|
359
|
-
const packed = typeof pack === 'function' ? pack(this.#env) : pack;
|
|
360
|
-
const held = packed && Object.hasOwn(packed, name) ? packed[name] : undefined;
|
|
361
|
-
if (this.#name === undefined && !held && !born?.(name))
|
|
362
|
-
return Promise.resolve(null);
|
|
363
|
-
this.#name = name;
|
|
364
|
-
// Opened inside the object's block, so no request reaches it half
|
|
365
|
-
// open and its storage answers the opening.
|
|
366
|
-
this.#opening ??= this.#state.blockConcurrencyWhile(async () => {
|
|
367
|
-
const given = { state: this.#state, env: this.#env, ...(held ? { package: held } : {}) };
|
|
368
|
-
const harbor = await Harbor.open({ modules, given });
|
|
369
|
-
if (!harbor.box.being(WEB_OPENING.key))
|
|
370
|
-
await harbor.root('open', { key: WEB_OPENING.key, class: WEB_OPENING.kind });
|
|
371
|
-
await stood?.(harbor, name);
|
|
372
|
-
return harbor;
|
|
373
|
-
});
|
|
374
|
-
return this.#opening;
|
|
375
|
-
}
|
|
376
|
-
async fetch(request) {
|
|
377
|
-
const harbor = await this.harborFor(request);
|
|
378
|
-
if (!harbor)
|
|
379
|
-
return new Response(null, { status: 404 });
|
|
380
|
-
const terrain = harbor.terrain;
|
|
381
|
-
const path = `/${this.#name}/quo`;
|
|
382
|
-
if (terrain.listening?.path !== path) {
|
|
383
|
-
const url = new URL(request.url);
|
|
384
|
-
await harbor.root('ask', { being: WEB_OPENING.key, method: 'listen', args: { host: url.hostname, port: url.port === '' ? 0 : Number(url.port), path } });
|
|
385
|
-
}
|
|
386
|
-
return terrain.answer(request);
|
|
387
|
-
}
|
|
388
|
-
};
|
|
389
|
-
// A worker of many harbors: each request goes to the object of the
|
|
390
|
-
// harbor its path names, in the Durable Object namespace bound as
|
|
391
|
-
// `binding`, and a path naming none is 404.
|
|
392
|
-
export const harborWorker = (binding = 'HARBOR') => ({
|
|
393
|
-
fetch(request, env) {
|
|
394
|
-
const name = harborNameOf(request);
|
|
395
|
-
const objects = env[binding];
|
|
396
|
-
if (name === null || !objects)
|
|
397
|
-
return Promise.resolve(new Response(null, { status: 404 }));
|
|
398
|
-
return objects.get(objects.idFromName(name)).fetch(request);
|
|
399
|
-
},
|
|
400
|
-
});
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Faculty, type BeingClass } from '../being/index.ts';
|
|
2
|
-
export interface Ground {
|
|
3
|
-
arrive(pk: string, bytes: Uint8Array): Promise<Uint8Array | null>;
|
|
4
|
-
}
|
|
5
|
-
export type GroundFaculty = (ground: Ground) => BeingClass;
|
|
6
|
-
export declare const UNDIALED: unique symbol;
|
|
7
|
-
export type Dialed = Uint8Array | null | typeof UNDIALED;
|
|
8
|
-
export declare abstract class CarrierFaculty extends Faculty {
|
|
9
|
-
static readonly kind: string;
|
|
10
|
-
abstract accepts(address: string): boolean;
|
|
11
|
-
abstract dial(address: string, pk: string, bytes: Uint8Array): Promise<Dialed>;
|
|
12
|
-
listening(): string[];
|
|
13
|
-
relays(_pk: string): boolean;
|
|
14
|
-
relay(_pk: string, _bytes: Uint8Array): Promise<Uint8Array | null>;
|
|
15
|
-
awake(): Promise<void>;
|
|
16
|
-
sleep(): Promise<void>;
|
|
17
|
-
}
|
package/dist/harbor/carrying.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// A carrier is a faculty. It speaks the schemes of the addresses it dials,
|
|
3
|
-
// dials an address when the harbor carries a box there, and listens where
|
|
4
|
-
// its cells say, handing each box it hears to the harbor. The harbor keeps
|
|
5
|
-
// every route and walks it in order, handing each address to the carrier
|
|
6
|
-
// that speaks its scheme.
|
|
7
|
-
//
|
|
8
|
-
// A ground ships its carriers as classes the terrain names, each made for
|
|
9
|
-
// one harbor, so the class holds the harbor it hands boxes to. They are
|
|
10
|
-
// the kit's, of kinds under `org.nervur.`, and the dock opens them as
|
|
11
|
-
// faculties, at genesis where the terrain says, and on the root's `open`.
|
|
12
|
-
import { Faculty } from '../being/index.js';
|
|
13
|
-
// Beside a reply and nothing, a dial answers `undialed` when the address
|
|
14
|
-
// could not be reached at all, so the harbor tries the next one. A box a
|
|
15
|
-
// line took may have been heard, so after it no other address is tried.
|
|
16
|
-
export const UNDIALED = Symbol('undialed');
|
|
17
|
-
export class CarrierFaculty extends Faculty {
|
|
18
|
-
static kind = 'org.nervur.carrier';
|
|
19
|
-
// The addresses it listens at now.
|
|
20
|
-
listening() {
|
|
21
|
-
return [];
|
|
22
|
-
}
|
|
23
|
-
// Whether it answers for a ward pk no door of this harbor holds, as a
|
|
24
|
-
// relay does, and its answer.
|
|
25
|
-
relays(_pk) {
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
relay(_pk, _bytes) {
|
|
29
|
-
return Promise.resolve(null);
|
|
30
|
-
}
|
|
31
|
-
// Once the harbor has unpacked, and once before it closes.
|
|
32
|
-
awake() {
|
|
33
|
-
return Promise.resolve();
|
|
34
|
-
}
|
|
35
|
-
sleep() {
|
|
36
|
-
return Promise.resolve();
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { Faculty, type AskSpec, type BeingClass, type JsonObject, type Stance } from '../being/index.ts';
|
|
2
|
-
import type { Loaded } from '../contract/index.ts';
|
|
3
|
-
export declare const CATALOGUE = "catalogue";
|
|
4
|
-
export type ModuleRow = {
|
|
5
|
-
version: string;
|
|
6
|
-
from: string;
|
|
7
|
-
kinds: string[];
|
|
8
|
-
};
|
|
9
|
-
export interface Cataloguing {
|
|
10
|
-
load(from: string): Promise<Loaded | null>;
|
|
11
|
-
missing(from: string): string | null;
|
|
12
|
-
check(modules: readonly Loaded[]): string | null;
|
|
13
|
-
run(modules: readonly Loaded[]): string | null;
|
|
14
|
-
stands(kinds: readonly string[]): boolean;
|
|
15
|
-
kindsOf(module: string): string[];
|
|
16
|
-
}
|
|
17
|
-
export declare class Catalogue extends Faculty {
|
|
18
|
-
#private;
|
|
19
|
-
static readonly kind: string;
|
|
20
|
-
static cells: JsonObject;
|
|
21
|
-
static asks: Record<string, AskSpec>;
|
|
22
|
-
constructor(stance: Stance, harbor: Cataloguing);
|
|
23
|
-
wake(): Promise<void>;
|
|
24
|
-
add(args: JsonObject): Promise<JsonObject>;
|
|
25
|
-
remove(args: JsonObject): JsonObject;
|
|
26
|
-
modules(): JsonObject;
|
|
27
|
-
}
|
|
28
|
-
export declare const catalogueFor: (harbor: Cataloguing) => BeingClass;
|