@nervur-org/dock 0.5.0 → 0.6.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 +7 -4
- package/api/route.ts +4 -72
- package/beings/avatar.ts +11 -7
- package/beings/carry.ts +129 -116
- package/beings/clock.ts +11 -7
- package/beings/desk.ts +7 -6
- package/beings/doorbell.ts +36 -7
- package/beings/index.ts +17 -4
- package/beings/join.ts +7 -4
- package/beings/link.ts +1 -1
- package/beings/porter.ts +5 -1
- package/beings/presence.ts +15 -5
- package/beings/setup.ts +27 -21
- package/beings/user.ts +26 -17
- package/beings/way.ts +1 -1
- package/{dock → box}/agents.ts +37 -44
- package/{dock → box}/apns.ts +4 -4
- package/box/box.ts +31 -0
- package/box/contract.ts +41 -0
- package/box/dialers.ts +88 -0
- package/box/dock.ts +148 -0
- package/box/envoy.ts +96 -0
- package/box/faculty.ts +111 -0
- package/{dock → box}/fcm.ts +1 -1
- package/box/grants.ts +90 -0
- package/box/http.ts +93 -0
- package/{dock → box}/http2.ts +7 -7
- package/box/index.ts +201 -0
- package/box/join.ts +78 -0
- package/box/local.ts +37 -0
- package/{dock → box}/location.ts +15 -3
- package/{dock → box}/notifications.ts +17 -5
- package/box/push.ts +85 -0
- package/box/ring.ts +85 -0
- package/{dock → box}/service.ts +2 -2
- package/box/timer.ts +150 -0
- package/box/tree.ts +22 -0
- package/{dock → box}/webpush.ts +2 -2
- package/cli/client.ts +1 -1
- package/cli/daemon.ts +101 -103
- package/cli/estate.ts +2 -3
- package/cli/nervur.ts +44 -25
- package/cli/stand.ts +1 -1
- package/dist/api/route.d.ts +1 -2
- package/dist/api/route.js +4 -76
- package/dist/beings/avatar.d.ts +4 -3
- package/dist/beings/avatar.js +9 -6
- package/dist/beings/carry.d.ts +10 -12
- package/dist/beings/carry.js +119 -127
- package/dist/beings/clock.js +10 -7
- package/dist/beings/desk.js +8 -7
- package/dist/beings/doorbell.d.ts +3 -1
- package/dist/beings/doorbell.js +37 -4
- package/dist/beings/index.d.ts +24 -4
- package/dist/beings/index.js +15 -4
- package/dist/beings/join.d.ts +1 -0
- package/dist/beings/join.js +6 -4
- package/dist/beings/link.d.ts +0 -1
- package/dist/beings/link.js +1 -1
- package/dist/beings/porter.js +5 -1
- package/dist/beings/presence.d.ts +1 -0
- package/dist/beings/presence.js +12 -3
- package/dist/beings/setup.d.ts +5 -2
- package/dist/beings/setup.js +16 -15
- package/dist/beings/user.d.ts +4 -3
- package/dist/beings/user.js +18 -11
- package/dist/{dock → box}/agents.d.ts +7 -4
- package/dist/{dock → box}/agents.js +30 -37
- package/dist/{dock → box}/apns.d.ts +1 -1
- package/dist/{dock → box}/apns.js +3 -3
- package/dist/box/box.d.ts +9 -0
- package/dist/box/box.js +18 -0
- package/dist/box/contract.d.ts +6 -0
- package/dist/box/contract.js +35 -0
- package/dist/{dock → box}/dialers.d.ts +7 -4
- package/dist/box/dialers.js +76 -0
- package/dist/box/dock.d.ts +182 -0
- package/dist/box/dock.js +128 -0
- package/dist/box/envoy.d.ts +44 -0
- package/dist/box/envoy.js +75 -0
- package/dist/box/faculty.d.ts +68 -0
- package/dist/box/faculty.js +97 -0
- package/dist/{dock → box}/fcm.d.ts +1 -1
- package/dist/{dock → box}/grants.d.ts +4 -3
- package/dist/box/grants.js +78 -0
- package/dist/box/http.d.ts +26 -0
- package/dist/box/http.js +89 -0
- package/dist/{dock → box}/http2.d.ts +1 -1
- package/dist/{dock → box}/http2.js +6 -6
- package/dist/box/index.d.ts +46 -0
- package/dist/box/index.js +179 -0
- package/dist/box/join.d.ts +19 -0
- package/dist/box/join.js +67 -0
- package/dist/{dock → box}/local.d.ts +3 -2
- package/dist/box/local.js +27 -0
- package/dist/{dock → box}/location.d.ts +3 -0
- package/dist/box/location.js +21 -0
- package/dist/{dock → box}/notifications.d.ts +3 -0
- package/dist/{dock → box}/notifications.js +14 -4
- package/dist/{dock → box}/push.d.ts +12 -18
- package/dist/box/push.js +83 -0
- package/dist/box/ring.d.ts +18 -0
- package/dist/box/ring.js +55 -0
- package/dist/{dock → box}/service.d.ts +1 -1
- package/dist/{dock → box}/service.js +1 -1
- package/dist/{dock → box}/timer.d.ts +2 -0
- package/dist/box/timer.js +127 -0
- package/dist/box/tree.d.ts +5 -0
- package/dist/box/tree.js +14 -0
- package/dist/{dock → box}/webpush.d.ts +1 -1
- package/dist/cli/client.d.ts +1 -0
- package/dist/cli/daemon.d.ts +2 -8
- package/dist/cli/daemon.js +102 -107
- package/dist/cli/estate.js +2 -3
- package/dist/cli/nervur.js +44 -24
- package/dist/cli/stand.d.ts +0 -14
- package/dist/cli/stand.js +1 -1
- package/dist/harbor/browser.d.ts +8 -5
- package/dist/harbor/browser.js +20 -21
- package/dist/harbor/capacitor.d.ts +3 -3
- package/dist/harbor/capacitor.js +9 -8
- package/dist/harbor/disk.d.ts +9 -9
- package/dist/harbor/disk.js +56 -51
- package/dist/harbor/edge/alarm.d.ts +4 -2
- package/dist/harbor/edge/alarm.js +9 -19
- package/dist/harbor/edge/edge.d.ts +7 -6
- package/dist/harbor/edge/edge.js +58 -53
- package/dist/harbor/edge/exercise.js +4 -4
- package/dist/harbor/edge/given.d.ts +0 -1
- package/dist/harbor/edge/given.js +0 -29
- package/dist/harbor/edge/storage.d.ts +0 -2
- package/dist/harbor/edge/storage.js +2 -2
- package/dist/harbor/http.js +4 -2
- package/dist/harbor/sealed.d.ts +0 -5
- package/dist/harbor/sealed.js +0 -39
- package/dist/harbor/tauri.d.ts +2 -2
- package/dist/harbor/tauri.js +13 -10
- package/dist/human/app.d.ts +1 -1
- package/dist/human/app.js +10 -12
- package/dist/human/door.d.ts +0 -1
- package/dist/human/door.js +1 -1
- package/dist/human/html.js +1 -1
- package/dist/human/move.js +1 -1
- package/dist/human/tab.bundle.txt +3629 -2824
- package/dist/human/wake.d.ts +5 -2
- package/dist/human/wake.js +23 -14
- package/dist/human/web.d.ts +0 -1
- package/dist/human/web.js +3 -3
- package/dist/human/worker.bundle.txt +2945 -2118
- package/dist/human/worlds.js +3 -3
- package/dist/mcp/agent.d.ts +0 -1
- package/dist/mcp/agent.js +1 -1
- package/dist/mcp/allow.js +3 -2
- package/dist/mcp/http.d.ts +0 -1
- package/dist/mcp/http.js +1 -1
- package/dist/mcp/oauth.d.ts +3 -4
- package/dist/mcp/oauth.js +4 -4
- package/dist/mcp/route.d.ts +1 -1
- package/dist/mcp/runner.d.ts +0 -1
- package/dist/mcp/runner.js +1 -1
- package/dist/mcp/server.d.ts +0 -1
- package/dist/mcp/server.js +1 -1
- package/harbor/browser.ts +22 -24
- package/harbor/capacitor.ts +9 -8
- package/harbor/disk.ts +53 -48
- package/harbor/edge/alarm.ts +15 -12
- package/harbor/edge/edge.ts +61 -55
- package/harbor/edge/exercise.ts +4 -4
- package/harbor/edge/given.ts +3 -33
- package/harbor/edge/storage.ts +2 -2
- package/harbor/http.ts +5 -3
- package/harbor/sealed.ts +0 -35
- package/harbor/tauri.ts +13 -10
- package/human/app.ts +12 -13
- package/human/door.ts +1 -1
- package/human/html.ts +1 -1
- package/human/local.ts +1 -1
- package/human/move.ts +1 -1
- package/human/tab.bundle.txt +3629 -2824
- package/human/wake.ts +36 -16
- package/human/web.ts +4 -4
- package/human/worker.bundle.txt +2945 -2118
- package/human/worlds.ts +3 -3
- package/mcp/agent.ts +1 -1
- package/mcp/allow.ts +2 -1
- package/mcp/http.ts +1 -1
- package/mcp/oauth.ts +4 -4
- package/mcp/route.ts +1 -1
- package/mcp/runner.ts +1 -1
- package/mcp/server.ts +1 -1
- package/package.json +9 -8
- package/beings/envoy.ts +0 -218
- package/dist/beings/envoy.d.ts +0 -54
- package/dist/beings/envoy.js +0 -211
- package/dist/dock/console.d.ts +0 -6
- package/dist/dock/console.js +0 -20
- package/dist/dock/dialers.js +0 -75
- package/dist/dock/faculty.d.ts +0 -24
- package/dist/dock/faculty.js +0 -142
- package/dist/dock/grants.js +0 -99
- package/dist/dock/index.d.ts +0 -41
- package/dist/dock/index.js +0 -113
- package/dist/dock/local.js +0 -44
- package/dist/dock/location.js +0 -11
- package/dist/dock/push.js +0 -132
- package/dist/dock/timer.js +0 -149
- package/dock/console.ts +0 -23
- package/dock/dialers.ts +0 -85
- package/dock/faculty.ts +0 -148
- package/dock/grants.ts +0 -111
- package/dock/index.ts +0 -133
- package/dock/local.ts +0 -48
- package/dock/push.ts +0 -161
- package/dock/timer.ts +0 -174
- /package/dist/{dock → box}/fcm.js +0 -0
- /package/dist/{dock → box}/webpush.js +0 -0
package/dist/harbor/browser.js
CHANGED
|
@@ -1,47 +1,46 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BEINGS } from '../beings/index.js';
|
|
2
2
|
import { Harbor, dial } from 'nervur/harbor';
|
|
3
|
-
import {
|
|
3
|
+
import { BOX_SEED, harborageOver, keyed, settled, standHarbor } from '../box/index.js';
|
|
4
4
|
import { Idb } from './idb.js';
|
|
5
|
-
export const BUILT_IN = { User, Desk, Avatar, Presence, Courier, ...FACULTY_CLASSES };
|
|
6
5
|
export class BrowserHarbor extends Harbor {
|
|
7
6
|
name;
|
|
8
7
|
dialers = [];
|
|
9
8
|
#locked;
|
|
10
9
|
#release;
|
|
11
|
-
|
|
12
|
-
// to an invitation on a being of its own ward. `stand` builds one; a bare
|
|
13
|
-
// tab hands none and every name answers null.
|
|
14
|
-
constructor(store = 'nervur', classes = {}, lend) {
|
|
10
|
+
constructor(store = 'nervur', classes = {}) {
|
|
15
11
|
const s = typeof store === 'string' ? new Idb(store) : store;
|
|
16
|
-
super(s, async () => ({ ...
|
|
12
|
+
super(s, async () => keyed({ ...BEINGS, classes }));
|
|
17
13
|
this.name = typeof store === 'string' ? store : 'nervur';
|
|
18
14
|
this.#locked = typeof store === 'string';
|
|
19
15
|
}
|
|
20
|
-
//
|
|
21
|
-
// its own and lends nothing.
|
|
22
|
-
|
|
23
|
-
// What this
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
16
|
+
// The classes this terrain brings to its own ward, as a tree. A bare tab
|
|
17
|
+
// brings none, stands no ward of its own and lends nothing.
|
|
18
|
+
faculties;
|
|
19
|
+
// What this harbor is to its faculties, up once it has booted.
|
|
20
|
+
box = harborageOver(() => this.wards.get(BOX_SEED)?.save() ?? Promise.resolve());
|
|
21
|
+
// What this box brings is said before it boots, and standing its own ward
|
|
22
|
+
// is act one of booting: a being born in any other ward takes the box at
|
|
23
|
+
// her ward's birth, and a box that was not standing yet would leave that
|
|
24
|
+
// ward holding nothing until its next boot.
|
|
25
|
+
async stand(faculties) {
|
|
26
|
+
this.faculties = faculties;
|
|
29
27
|
if (this.wards.size > 0)
|
|
30
|
-
|
|
28
|
+
await standHarbor(this, faculties, this.box);
|
|
31
29
|
}
|
|
32
30
|
// Take the lock and boot every ward kept here. A lock already held is
|
|
33
31
|
// another tab's harbor over this seed, and this one refuses to boot.
|
|
34
32
|
async boot() {
|
|
35
33
|
if (this.#locked)
|
|
36
34
|
await this.#lease();
|
|
37
|
-
if (this.
|
|
38
|
-
|
|
35
|
+
if (this.faculties)
|
|
36
|
+
await standHarbor(this, this.faculties, this.box);
|
|
39
37
|
await super.boot();
|
|
40
38
|
// Every being who takes what this box lends does it at her birth, and
|
|
41
39
|
// birth is synchronous while taking a standing is not. A box is up when
|
|
42
40
|
// they have landed, not before, here as on a daemon: a page painted
|
|
43
41
|
// ahead of them shows a device that can do nothing.
|
|
44
|
-
await settled();
|
|
42
|
+
await settled(this);
|
|
43
|
+
await this.box.raise();
|
|
45
44
|
}
|
|
46
45
|
// Hold one socket to a world's quo. route.
|
|
47
46
|
dial(url) {
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { Directory } from '@capacitor/filesystem';
|
|
2
2
|
import type { BeingClass, JsonObject } from 'nervur';
|
|
3
|
-
import { Location, Notifications, type Token, type Where } from '../
|
|
3
|
+
import { Location, Notifications, type Token, type Where } from '../box/index.ts';
|
|
4
4
|
import { BrowserHarbor } from './browser.ts';
|
|
5
5
|
import { Sealed, type Files, type Secrets } from './sealed.ts';
|
|
6
6
|
export declare class PhoneLocation extends Location {
|
|
7
|
+
static stands(): boolean;
|
|
7
8
|
where(): Promise<Where | JsonObject>;
|
|
8
9
|
}
|
|
9
10
|
export declare class PhoneNotifications extends Notifications {
|
|
11
|
+
static stands(): boolean;
|
|
10
12
|
notify(args: JsonObject): Promise<JsonObject>;
|
|
11
13
|
protected plant(pair: {
|
|
12
14
|
secret: Uint8Array;
|
|
13
15
|
}): Promise<void>;
|
|
14
16
|
}
|
|
15
|
-
export declare const PHONE_FACULTIES: Record<string, BeingClass>;
|
|
16
|
-
export declare const phoneLent: Record<string, string>;
|
|
17
17
|
export declare function phoneEar(sandbox?: boolean, within?: number, named?: {
|
|
18
18
|
bell?: string;
|
|
19
19
|
app?: string;
|
package/dist/harbor/capacitor.js
CHANGED
|
@@ -16,7 +16,7 @@ import { SecureStorage, KeychainAccess } from '@aparajita/capacitor-secure-stora
|
|
|
16
16
|
import { Geolocation } from '@capacitor/geolocation';
|
|
17
17
|
import { LocalNotifications } from '@capacitor/local-notifications';
|
|
18
18
|
import { PushNotifications } from '@capacitor/push-notifications';
|
|
19
|
-
import {
|
|
19
|
+
import { Location, Notifications } from '../box/index.js';
|
|
20
20
|
import { BrowserHarbor } from './browser.js';
|
|
21
21
|
import { Sealed } from './sealed.js';
|
|
22
22
|
// The phone's faculties, as its plugins give them: the two defaults extended,
|
|
@@ -31,6 +31,9 @@ const BANNER = 'banner';
|
|
|
31
31
|
const asked = (what) => new Error(`the human is being asked to allow ${what} on this device; ask again`);
|
|
32
32
|
const refused = (what) => new Error(`${what} is not allowed on this device`);
|
|
33
33
|
export class PhoneLocation extends Location {
|
|
34
|
+
static stands() {
|
|
35
|
+
return Capacitor.isPluginAvailable('Geolocation');
|
|
36
|
+
}
|
|
34
37
|
async where() {
|
|
35
38
|
const { location } = await Geolocation.checkPermissions();
|
|
36
39
|
if (location === 'prompt' || location === 'prompt-with-rationale') {
|
|
@@ -44,6 +47,9 @@ export class PhoneLocation extends Location {
|
|
|
44
47
|
}
|
|
45
48
|
}
|
|
46
49
|
export class PhoneNotifications extends Notifications {
|
|
50
|
+
static stands() {
|
|
51
|
+
return Capacitor.isPluginAvailable('LocalNotifications');
|
|
52
|
+
}
|
|
47
53
|
async notify(args) {
|
|
48
54
|
const title = typeof args.title === 'string' ? args.title : '';
|
|
49
55
|
const body = typeof args.body === 'string' ? args.body : '';
|
|
@@ -98,11 +104,6 @@ export class PhoneNotifications extends Notifications {
|
|
|
98
104
|
await PushNotifications.requestPermissions().catch(() => ({ receive: 'denied' }));
|
|
99
105
|
}
|
|
100
106
|
}
|
|
101
|
-
// What a phone lends: the two faculties above under the names every box
|
|
102
|
-
// lends them under, and nothing a phone has not. The harbor holds these
|
|
103
|
-
// class bodies for its own ward, and boots one being of each in it.
|
|
104
|
-
export const PHONE_FACULTIES = { Location: PhoneLocation, Notifications: PhoneNotifications };
|
|
105
|
-
export const phoneLent = { [LOCATION]: 'Location', [NOTIFICATIONS]: 'Notifications' };
|
|
106
107
|
// The phone's ear, as `human/app.ts` asks for one: the token this device is
|
|
107
108
|
// reachable at while it sleeps, or null.
|
|
108
109
|
//
|
|
@@ -159,8 +160,8 @@ export function phoneEar(sandbox = false, within = 10_000, named = {}) {
|
|
|
159
160
|
// told `wake` every time the app comes to the foreground, since a phone
|
|
160
161
|
// asleep loses its sockets silently.
|
|
161
162
|
export async function nativeHarbor(name = 'nervur', classes = {}) {
|
|
162
|
-
const h = new BrowserHarbor(await Native.open(name),
|
|
163
|
-
await h.stand(
|
|
163
|
+
const h = new BrowserHarbor(await Native.open(name), classes);
|
|
164
|
+
await h.stand({ harbor: { PhoneLocation, PhoneNotifications } });
|
|
164
165
|
await h.boot();
|
|
165
166
|
await App.addListener('appStateChange', ({ isActive }) => {
|
|
166
167
|
if (isActive)
|
package/dist/harbor/disk.d.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import {
|
|
1
|
+
import { Harbor, type Hosted } from 'nervur/harbor';
|
|
2
|
+
import { type Tree } from '../box/index.ts';
|
|
3
3
|
export type { Hosted, Bound } from 'nervur/harbor';
|
|
4
4
|
export type { WardRecord } from 'nervur/harbor';
|
|
5
|
-
export declare const BUILT_IN: Record<string, BeingClass>;
|
|
6
5
|
export declare function defaultWard(marked: string[], hosted: string[]): string;
|
|
7
6
|
export declare class DiskHarbor extends Harbor {
|
|
8
7
|
#private;
|
|
9
8
|
readonly dir: string;
|
|
10
9
|
defaultWard: string;
|
|
11
|
-
static
|
|
10
|
+
static say(dir: string, method: 'domain' | 'apps' | 'default', args: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
12
11
|
static setShown(dir: string, name: string, shown: boolean): Promise<void>;
|
|
13
12
|
static isShown(dir: string, name: string): boolean;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
constructor(dir: string);
|
|
14
|
+
faculties: Tree | undefined;
|
|
15
|
+
readonly box: import("../box/box.ts").Harborage & {
|
|
16
|
+
raise(): Promise<void>;
|
|
17
|
+
};
|
|
18
|
+
static init(dir: string, name?: string, user?: string, cls?: string, shown?: boolean): Promise<{
|
|
19
19
|
dir: string;
|
|
20
20
|
name: string;
|
|
21
21
|
pk: string;
|
package/dist/harbor/disk.js
CHANGED
|
@@ -10,9 +10,8 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
10
10
|
// The node daemon's harbor: the core over a folder on disk. The store is
|
|
11
11
|
// `files.ts`, one folder per ward; the class bodies come from a module the
|
|
12
12
|
// ward record names, loaded from the folder; the lease is a pid file. The
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// class source adds to them.
|
|
13
|
+
// dock's beings are held by every harbor here under `beings/`, and a
|
|
14
|
+
// folder's class source adds to them under the folder it sits in.
|
|
16
15
|
//
|
|
17
16
|
// <dir>/
|
|
18
17
|
// lease pid of the one process that holds this harbor
|
|
@@ -24,21 +23,20 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
24
23
|
// reach.json the directory's hints
|
|
25
24
|
import { mkdir, readFile, writeFile, unlink, stat } from 'node:fs/promises';
|
|
26
25
|
import { existsSync } from 'node:fs';
|
|
27
|
-
import { join, resolve, isAbsolute } from 'node:path';
|
|
26
|
+
import { dirname, join, resolve, isAbsolute, relative } from 'node:path';
|
|
28
27
|
import { pathToFileURL } from 'node:url';
|
|
29
28
|
import { register } from 'node:module';
|
|
30
29
|
import process from 'node:process';
|
|
31
|
-
import {
|
|
30
|
+
import { BEINGS } from '../beings/index.js';
|
|
32
31
|
import { setup } from '../beings/setup.js';
|
|
33
|
-
import { Harbor, DEFAULT_CODE } from 'nervur/harbor';
|
|
34
|
-
import {
|
|
32
|
+
import { Harbor, DEFAULT_CODE, BOX_SEED } from 'nervur/harbor';
|
|
33
|
+
import { BOX, harborageOver, keyed, settled, standHarbor } from '../box/index.js';
|
|
35
34
|
import { Files } from './files.js';
|
|
36
|
-
export const BUILT_IN = { User, Desk, Avatar, Presence, Clock, Courier, ...FACULTY_CLASSES };
|
|
37
35
|
// The default ward, the one a caller means when naming none: the one marked,
|
|
38
36
|
// or the one ward hosted when there is exactly one, which is every harbor an
|
|
39
37
|
// adopter stands with one `nervur init`. Several wards and none marked is
|
|
40
38
|
// refused by name, since agents and a door would otherwise hang off a
|
|
41
|
-
// guess. The
|
|
39
|
+
// guess. The box ward is furniture, never a candidate.
|
|
42
40
|
export function defaultWard(marked, hosted) {
|
|
43
41
|
if (marked.length > 1)
|
|
44
42
|
throw new Error(`this device marks ${marked.join(', ')} as default, and one at most may be`);
|
|
@@ -48,7 +46,7 @@ export function defaultWard(marked, hosted) {
|
|
|
48
46
|
throw new Error(`this device says its default ward is ${one}, and hosts no such ward`);
|
|
49
47
|
return one;
|
|
50
48
|
}
|
|
51
|
-
const [first, ...more] = hosted.filter((n) => n !==
|
|
49
|
+
const [first, ...more] = hosted.filter((n) => n !== BOX_SEED);
|
|
52
50
|
if (first !== undefined && more.length === 0)
|
|
53
51
|
return first;
|
|
54
52
|
const names = first === undefined ? [] : [first, ...more];
|
|
@@ -96,20 +94,32 @@ export class DiskHarbor extends Harbor {
|
|
|
96
94
|
// ward and nothing in Quo knows of it: a harbor is not a being and has no
|
|
97
95
|
// self to be, so it can only point at one of its wards. Its agents boot
|
|
98
96
|
// there, and its door answers for it when a caller names no ward. The one
|
|
99
|
-
// ward it hosts when there is one, the one
|
|
100
|
-
// the daemon at boot;
|
|
97
|
+
// ward it hosts when there is one, the one the Dock's cells say otherwise,
|
|
98
|
+
// placed by the root's `default` ask and resolved by the daemon at boot;
|
|
99
|
+
// empty until then.
|
|
101
100
|
defaultWard = '';
|
|
102
|
-
// The
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
|
|
101
|
+
// The root saying what the box is, with no daemon over the folder: the
|
|
102
|
+
// Dock's own asks, `domain`, `apps` and `default`, on the box ward stood
|
|
103
|
+
// alone, which the lease refuses while a daemon serves. The daemon reads
|
|
104
|
+
// what she keeps at its next boot, so a domain said is stop, say, start,
|
|
105
|
+
// like an init.
|
|
106
|
+
static async say(dir, method, args) {
|
|
106
107
|
const h = new DiskHarbor(dir);
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
108
|
+
h.faculties = {};
|
|
109
|
+
await h.boot();
|
|
110
|
+
try {
|
|
111
|
+
const ward = h.wards.get(BOX_SEED);
|
|
112
|
+
if (!ward)
|
|
113
|
+
throw new Error('this box stands no ward of its own');
|
|
114
|
+
const out = (await ward.ask('ask', { being: BOX, method, args }));
|
|
115
|
+
if (typeof out.error === 'string')
|
|
116
|
+
throw new Error(out.error);
|
|
117
|
+
await ward.save();
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
await h.close();
|
|
122
|
+
}
|
|
113
123
|
}
|
|
114
124
|
// Whether a ward is shown at the web route: listed at its root and its
|
|
115
125
|
// public being's page painted for a stranger. Hidden, it is not listed
|
|
@@ -130,51 +140,44 @@ export class DiskHarbor extends Harbor {
|
|
|
130
140
|
static isShown(dir, name) {
|
|
131
141
|
return existsSync(join(resolve(dir), 'wards', name, 'shown'));
|
|
132
142
|
}
|
|
133
|
-
static async marked(dir) {
|
|
134
|
-
const h = new DiskHarbor(dir);
|
|
135
|
-
return (await h.store.list()).filter((n) => existsSync(join(h.dir, 'wards', n, 'default')));
|
|
136
|
-
}
|
|
137
|
-
// The default ward read from the folder alone, for a command with no
|
|
138
|
-
// daemon in front of it and no `--ward` given.
|
|
139
|
-
static async defaultOf(dir) {
|
|
140
|
-
const h = new DiskHarbor(dir);
|
|
141
|
-
return defaultWard(await DiskHarbor.marked(dir), await h.store.list());
|
|
142
|
-
}
|
|
143
143
|
#held = false;
|
|
144
|
-
|
|
145
|
-
// an invitation on a being of its own ward, which `stand` puts up. A
|
|
146
|
-
// folder booted by a command lends nothing.
|
|
147
|
-
// `own` are this terrain's own class bodies, the faculty subclasses a box
|
|
148
|
-
// has: they stand in front of the built-ins, so a daemon that can ring
|
|
149
|
-
// hands its own `Push` and the dock ward boots that one.
|
|
150
|
-
constructor(dir, lend, own = {}) {
|
|
144
|
+
constructor(dir) {
|
|
151
145
|
const abs = resolve(dir);
|
|
152
146
|
// The key the environment gives, the edge's name for it: from the
|
|
153
147
|
// Keychain through the app that spawned this daemon, or nothing on a
|
|
154
148
|
// droplet, whose folder stays plain under its file modes.
|
|
155
|
-
|
|
149
|
+
// A class is keyed where it lives: the dock's under `beings/`, the
|
|
150
|
+
// folder's under the folder its source sits in, `classes/Corpus`.
|
|
151
|
+
const lookup = async (rec) => {
|
|
152
|
+
const path = isAbsolute(rec.code) ? rec.code : join(abs, rec.code);
|
|
153
|
+
return keyed({ ...BEINGS, [relative(abs, dirname(path))]: await loadClasses(path) });
|
|
154
|
+
};
|
|
155
|
+
super(new Files(abs, process.env.NERVUR_SEED_KEY), lookup);
|
|
156
156
|
this.dir = abs;
|
|
157
157
|
}
|
|
158
|
-
//
|
|
159
|
-
// that
|
|
160
|
-
|
|
158
|
+
// The classes this terrain brings to its own ward, as a tree. Set before
|
|
159
|
+
// `boot` and read there; a box that brings none stands no ward of its own
|
|
160
|
+
// and lends nothing. The folder's own classes join them under the folder
|
|
161
|
+
// they live in, so an estate's faculty stands beside the terrain's.
|
|
162
|
+
faculties;
|
|
163
|
+
// What this harbor is to its faculties. The terrain raises it once the box
|
|
164
|
+
// is up, which on a daemon is after its routes are mounted.
|
|
165
|
+
box = harborageOver(() => this.wards.get(BOX_SEED)?.save() ?? Promise.resolve());
|
|
161
166
|
// Create a harbor folder with one ward, and the root's setup in it: the
|
|
162
167
|
// front desk, public, and one user being, with the desk holding a standing
|
|
163
168
|
// to her placed by the root's knock. Boots the ward once, with no lease, to
|
|
164
169
|
// do that and to learn its pk, and writes the record. Refuses a folder that
|
|
165
170
|
// has one.
|
|
166
|
-
static async init(dir, name = 'main', user = 'me', cls
|
|
171
|
+
static async init(dir, name = 'main', user = 'me', cls, shown = false) {
|
|
167
172
|
const h = new DiskHarbor(dir);
|
|
168
173
|
if ((await h.store.list()).includes(name))
|
|
169
174
|
throw new Error(`ward ${name} already exists in ${h.dir}`);
|
|
170
175
|
await mkdir(join(h.dir, 'classes'), { recursive: true });
|
|
171
176
|
const classes = join(h.dir, DEFAULT_CODE);
|
|
172
177
|
if (!existsSync(classes))
|
|
173
|
-
await writeFile(classes,
|
|
178
|
+
await writeFile(classes, "// The classes this harbor holds beside the dock's beings. Each export is classes/<its name>.\nexport {};\n");
|
|
174
179
|
const hosted = await h.create(name, user);
|
|
175
|
-
await setup(hosted, user, cls);
|
|
176
|
-
if (mark)
|
|
177
|
-
await DiskHarbor.setDefault(h.dir, name);
|
|
180
|
+
await setup(hosted, user, cls ? { home: cls } : {});
|
|
178
181
|
if (shown)
|
|
179
182
|
await DiskHarbor.setShown(h.dir, name, true);
|
|
180
183
|
return { dir: h.dir, name, pk: hosted.pk, user };
|
|
@@ -188,13 +191,15 @@ export class DiskHarbor extends Harbor {
|
|
|
188
191
|
// it yet would leave her holding nothing until her next birth.
|
|
189
192
|
async boot() {
|
|
190
193
|
await this.#lease();
|
|
191
|
-
if (this.
|
|
192
|
-
this.
|
|
194
|
+
if (this.faculties) {
|
|
195
|
+
const tree = { ...this.faculties, [dirname(DEFAULT_CODE)]: await loadClasses(join(this.dir, DEFAULT_CODE)) };
|
|
196
|
+
await standHarbor(this, tree, this.box);
|
|
197
|
+
}
|
|
193
198
|
await super.boot();
|
|
194
199
|
// Every being who takes what this box lends does it at her birth, and
|
|
195
200
|
// birth is synchronous while taking a standing is not. A box is up when
|
|
196
201
|
// they have landed, not before.
|
|
197
|
-
await settled();
|
|
202
|
+
await settled(this);
|
|
198
203
|
}
|
|
199
204
|
// Every ward's writing finished, then the lease. A ward says it wrote and
|
|
200
205
|
// the harbor writes it after, so a close that only dropped the lease would
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Stance } from 'nervur';
|
|
2
|
+
import { Timer, type Harborage } from '../../box/index.ts';
|
|
2
3
|
import type { Storage } from './platform.d.ts';
|
|
3
4
|
export type Alarms = (at: number | null) => Promise<void>;
|
|
4
5
|
export declare const alarmsIn: (storage: Storage) => Alarms;
|
|
5
6
|
export declare class Alarm extends Timer {
|
|
6
7
|
#private;
|
|
7
|
-
alarms: Alarms | undefined;
|
|
8
|
+
readonly alarms: Alarms | undefined;
|
|
9
|
+
constructor(stance: Stance, box?: Harborage, alarms?: Alarms);
|
|
8
10
|
get setting(): Promise<void>;
|
|
9
11
|
protected arm(when: number | null): void;
|
|
10
12
|
}
|
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
// The box's timer on this terrain. One method of hers knows a platform, the
|
|
3
|
-
// arming, and this replaces it: the object's own storage alarm in place of a
|
|
4
|
-
// `setTimeout` that would die with the request. Everything else about her is
|
|
5
|
-
// the same class, the same door and the same suite, because when a box wakes
|
|
6
|
-
// is a terrain's answer and what it does when it wakes is not.
|
|
7
|
-
//
|
|
8
|
-
// One harbor is one Durable Object, and every ward of it lives in that
|
|
9
|
-
// object, so the alarm wakes the whole harbor and a tick from her to a home's
|
|
10
|
-
// Clock is in-process here as it is on a disk. Only the object may set its
|
|
11
|
-
// own alarm, so the two calls are handed to her after the box ward stands,
|
|
12
|
-
// the way the grants are handed their save: a faculty is built by her ward
|
|
13
|
-
// with a stance and nothing else.
|
|
14
|
-
import { Timer } from '../../dock/index.js';
|
|
1
|
+
import { Timer } from '../../box/index.js';
|
|
15
2
|
export const alarmsIn = (storage) => async (at) => {
|
|
16
3
|
if (at === null)
|
|
17
4
|
await storage.deleteAlarm();
|
|
@@ -19,10 +6,14 @@ export const alarmsIn = (storage) => async (at) => {
|
|
|
19
6
|
await storage.setAlarm(at);
|
|
20
7
|
};
|
|
21
8
|
export class Alarm extends Timer {
|
|
22
|
-
// Handed
|
|
23
|
-
// and wakes nobody
|
|
9
|
+
// Handed at birth by the object that brings her. A timer holding none arms
|
|
10
|
+
// nothing and wakes nobody.
|
|
24
11
|
alarms;
|
|
25
12
|
#setting = Promise.resolve();
|
|
13
|
+
constructor(stance, box, alarms) {
|
|
14
|
+
super(stance, box);
|
|
15
|
+
this.alarms = alarms;
|
|
16
|
+
}
|
|
26
17
|
// The arming written, for the device's own code and a suite: on this
|
|
27
18
|
// terrain an arming is a write to storage, and a reader of the alarm waits
|
|
28
19
|
// for it. It crosses no door.
|
|
@@ -30,9 +21,8 @@ export class Alarm extends Timer {
|
|
|
30
21
|
return this.#setting;
|
|
31
22
|
}
|
|
32
23
|
arm(when) {
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
// own. An alarm the platform refused is armed again by the next round.
|
|
24
|
+
// An arming is left to finish on its own; an alarm the platform refused is
|
|
25
|
+
// armed again by the next round.
|
|
36
26
|
this.#setting = (this.alarms?.(when) ?? Promise.resolve()).catch(() => { });
|
|
37
27
|
}
|
|
38
28
|
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import type { BeingClass } from 'nervur';
|
|
2
1
|
import { Harbor, Socket as Held } from 'nervur/harbor';
|
|
3
2
|
import { type Folder } from '../../human/web.ts';
|
|
4
|
-
import { Grants } from '../../
|
|
3
|
+
import { Grants, type Harborage, type Tree } from '../../box/index.ts';
|
|
5
4
|
import { type Routes } from '../../mcp/route.ts';
|
|
6
5
|
import { Exchange } from '../../mcp/allow.ts';
|
|
7
6
|
import { DurableStorage, danceInStorage, wearInStorage } from './storage.ts';
|
|
8
7
|
import { type Deployed, type Given, type SettingsStore } from './given.ts';
|
|
9
8
|
import type { State, Env } from './platform.d.ts';
|
|
10
|
-
export declare const BUILT_IN: Record<string, BeingClass>;
|
|
11
9
|
export declare class EdgeHarbor extends Harbor {
|
|
12
10
|
#private;
|
|
13
11
|
readonly sockets: Set<Held>;
|
|
@@ -20,18 +18,21 @@ export declare class EdgeHarbor extends Harbor {
|
|
|
20
18
|
static open(state: State, env: Env, deployed?: Deployed): Promise<EdgeHarbor>;
|
|
21
19
|
constructor(store: DurableStorage, root: string | undefined, deployed?: Deployed);
|
|
22
20
|
given(): Promise<Given>;
|
|
23
|
-
|
|
21
|
+
faculties: Tree | undefined;
|
|
22
|
+
readonly box: Harborage & {
|
|
23
|
+
raise(): Promise<void>;
|
|
24
|
+
};
|
|
24
25
|
ready(): Promise<void>;
|
|
25
26
|
boot(): Promise<void>;
|
|
26
27
|
rang(): Promise<void>;
|
|
27
|
-
|
|
28
|
+
grants(): Promise<Grants | undefined>;
|
|
28
29
|
web(request: Request, path: string, base: string): Promise<Response>;
|
|
29
30
|
routes(base: string): Promise<Routes & {
|
|
30
31
|
quo: string;
|
|
31
32
|
api: string;
|
|
32
33
|
}>;
|
|
33
34
|
here(): string;
|
|
34
|
-
api(request: Request, path: string
|
|
35
|
+
api(request: Request, path: string): Promise<Response>;
|
|
35
36
|
mcp(request: Request, path: string, base: string): Promise<Response>;
|
|
36
37
|
wellKnown(request: Request, path: string, base: string): Promise<Response>;
|
|
37
38
|
exchange(base: string): Promise<Exchange | undefined>;
|