@nervur-org/dock 0.3.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/GETTING_STARTED.md +128 -0
- package/LICENSE +202 -0
- package/NOTICE +6 -0
- package/README.md +37 -0
- package/api/quo-api.md +196 -0
- package/api/route.ts +227 -0
- package/beings/GLOSSARY.md +118 -0
- package/beings/WORLDS.md +567 -0
- package/beings/avatar.ts +101 -0
- package/beings/carry.ts +159 -0
- package/beings/clock.ts +552 -0
- package/beings/courier.ts +107 -0
- package/beings/desk.ts +128 -0
- package/beings/doorbell.ts +129 -0
- package/beings/envoy.ts +218 -0
- package/beings/index.ts +16 -0
- package/beings/join.ts +51 -0
- package/beings/link.ts +104 -0
- package/beings/look.ts +139 -0
- package/beings/porter.ts +43 -0
- package/beings/presence.ts +39 -0
- package/beings/quo-app-bells.md +280 -0
- package/beings/quo-dock.md +1942 -0
- package/beings/setup.ts +45 -0
- package/beings/side.ts +60 -0
- package/beings/user.ts +459 -0
- package/beings/way.ts +65 -0
- package/cli/bundles.ts +20 -0
- package/cli/client.ts +73 -0
- package/cli/daemon.ts +581 -0
- package/cli/estate/Caddyfile +33 -0
- package/cli/estate/quo.service +35 -0
- package/cli/estate/systems.quo.plist +44 -0
- package/cli/estate.ts +48 -0
- package/cli/folder.ts +27 -0
- package/cli/oauth.ts +32 -0
- package/cli/pilot.ts +38 -0
- package/cli/quo-dock.md +1942 -0
- package/cli/quo.ts +203 -0
- package/cli/stand.ts +160 -0
- package/dist/api/route.d.ts +21 -0
- package/dist/api/route.js +193 -0
- package/dist/beings/avatar.d.ts +32 -0
- package/dist/beings/avatar.js +100 -0
- package/dist/beings/carry.d.ts +12 -0
- package/dist/beings/carry.js +174 -0
- package/dist/beings/clock.d.ts +161 -0
- package/dist/beings/clock.js +528 -0
- package/dist/beings/courier.d.ts +50 -0
- package/dist/beings/courier.js +96 -0
- package/dist/beings/desk.d.ts +53 -0
- package/dist/beings/desk.js +135 -0
- package/dist/beings/doorbell.d.ts +78 -0
- package/dist/beings/doorbell.js +133 -0
- package/dist/beings/envoy.d.ts +54 -0
- package/dist/beings/envoy.js +211 -0
- package/dist/beings/index.d.ts +14 -0
- package/dist/beings/index.js +16 -0
- package/dist/beings/join.d.ts +15 -0
- package/dist/beings/join.js +42 -0
- package/dist/beings/link.d.ts +14 -0
- package/dist/beings/link.js +91 -0
- package/dist/beings/look.d.ts +30 -0
- package/dist/beings/look.js +104 -0
- package/dist/beings/porter.d.ts +14 -0
- package/dist/beings/porter.js +41 -0
- package/dist/beings/presence.d.ts +8 -0
- package/dist/beings/presence.js +21 -0
- package/dist/beings/setup.d.ts +3 -0
- package/dist/beings/setup.js +39 -0
- package/dist/beings/side.d.ts +32 -0
- package/dist/beings/side.js +37 -0
- package/dist/beings/user.d.ts +315 -0
- package/dist/beings/user.js +462 -0
- package/dist/beings/way.d.ts +19 -0
- package/dist/beings/way.js +28 -0
- package/dist/cli/bundles.d.ts +5 -0
- package/dist/cli/bundles.js +17 -0
- package/dist/cli/client.d.ts +15 -0
- package/dist/cli/client.js +58 -0
- package/dist/cli/daemon.d.ts +50 -0
- package/dist/cli/daemon.js +584 -0
- package/dist/cli/estate/Caddyfile +33 -0
- package/dist/cli/estate/quo.service +35 -0
- package/dist/cli/estate/systems.quo.plist +44 -0
- package/dist/cli/estate.d.ts +5 -0
- package/dist/cli/estate.js +50 -0
- package/dist/cli/folder.d.ts +2 -0
- package/dist/cli/folder.js +25 -0
- package/dist/cli/oauth.d.ts +2 -0
- package/dist/cli/oauth.js +32 -0
- package/dist/cli/pilot.d.ts +5 -0
- package/dist/cli/pilot.js +22 -0
- package/dist/cli/quo.d.ts +2 -0
- package/dist/cli/quo.js +201 -0
- package/dist/cli/stand.d.ts +37 -0
- package/dist/cli/stand.js +110 -0
- package/dist/dock/agents.d.ts +102 -0
- package/dist/dock/agents.js +105 -0
- package/dist/dock/apns.d.ts +27 -0
- package/dist/dock/apns.js +98 -0
- package/dist/dock/console.d.ts +6 -0
- package/dist/dock/console.js +20 -0
- package/dist/dock/dialers.d.ts +56 -0
- package/dist/dock/dialers.js +75 -0
- package/dist/dock/faculty.d.ts +24 -0
- package/dist/dock/faculty.js +142 -0
- package/dist/dock/fcm.d.ts +13 -0
- package/dist/dock/fcm.js +77 -0
- package/dist/dock/grants.d.ts +41 -0
- package/dist/dock/grants.js +99 -0
- package/dist/dock/http2.d.ts +4 -0
- package/dist/dock/http2.js +68 -0
- package/dist/dock/index.d.ts +41 -0
- package/dist/dock/index.js +113 -0
- package/dist/dock/local.d.ts +13 -0
- package/dist/dock/local.js +44 -0
- package/dist/dock/location.d.ts +19 -0
- package/dist/dock/location.js +11 -0
- package/dist/dock/notifications.d.ts +38 -0
- package/dist/dock/notifications.js +60 -0
- package/dist/dock/push.d.ts +79 -0
- package/dist/dock/push.js +132 -0
- package/dist/dock/service.d.ts +4 -0
- package/dist/dock/service.js +107 -0
- package/dist/dock/timer.d.ts +52 -0
- package/dist/dock/timer.js +149 -0
- package/dist/dock/webpush.d.ts +12 -0
- package/dist/dock/webpush.js +144 -0
- package/dist/harbor/browser.d.ts +15 -0
- package/dist/harbor/browser.js +82 -0
- package/dist/harbor/capacitor.d.ts +28 -0
- package/dist/harbor/capacitor.js +218 -0
- package/dist/harbor/disk.d.ts +27 -0
- package/dist/harbor/disk.js +249 -0
- package/dist/harbor/edge/alarm.d.ts +10 -0
- package/dist/harbor/edge/alarm.js +38 -0
- package/dist/harbor/edge/edge.d.ts +54 -0
- package/dist/harbor/edge/edge.js +370 -0
- package/dist/harbor/edge/exercise.d.ts +7 -0
- package/dist/harbor/edge/exercise.js +232 -0
- package/dist/harbor/edge/given.d.ts +26 -0
- package/dist/harbor/edge/given.js +42 -0
- package/dist/harbor/edge/platform.d.ts +39 -0
- package/dist/harbor/edge/storage.d.ts +30 -0
- package/dist/harbor/edge/storage.js +180 -0
- package/dist/harbor/edge/worker.d.ts +17 -0
- package/dist/harbor/edge/worker.js +67 -0
- package/dist/harbor/files.d.ts +15 -0
- package/dist/harbor/files.js +220 -0
- package/dist/harbor/http.d.ts +19 -0
- package/dist/harbor/http.js +177 -0
- package/dist/harbor/idb.d.ts +15 -0
- package/dist/harbor/idb.js +0 -0
- package/dist/harbor/quo.d.ts +10 -0
- package/dist/harbor/quo.js +42 -0
- package/dist/harbor/resolve.d.ts +16 -0
- package/dist/harbor/resolve.js +17 -0
- package/dist/harbor/seal.d.ts +3 -0
- package/dist/harbor/seal.js +25 -0
- package/dist/harbor/sealed.d.ts +35 -0
- package/dist/harbor/sealed.js +162 -0
- package/dist/harbor/tauri.d.ts +16 -0
- package/dist/harbor/tauri.js +59 -0
- package/dist/harbor/ward.d.ts +9 -0
- package/dist/harbor/ward.js +15 -0
- package/dist/human/app.d.ts +32 -0
- package/dist/human/app.js +527 -0
- package/dist/human/apps.d.ts +10 -0
- package/dist/human/apps.js +29 -0
- package/dist/human/dom.d.ts +2 -0
- package/dist/human/dom.js +15 -0
- package/dist/human/door.d.ts +19 -0
- package/dist/human/door.js +92 -0
- package/dist/human/guest.d.ts +3 -0
- package/dist/human/guest.js +33 -0
- package/dist/human/html.d.ts +55 -0
- package/dist/human/html.js +451 -0
- package/dist/human/local.d.ts +7 -0
- package/dist/human/local.js +10 -0
- package/dist/human/mark.d.ts +8 -0
- package/dist/human/mark.js +47 -0
- package/dist/human/move.d.ts +17 -0
- package/dist/human/move.js +90 -0
- package/dist/human/screen.d.ts +19 -0
- package/dist/human/screen.js +119 -0
- package/dist/human/style.d.ts +2 -0
- package/dist/human/style.js +60 -0
- package/dist/human/tab.bundle.txt +4775 -0
- package/dist/human/tab.d.ts +15 -0
- package/dist/human/tab.js +409 -0
- package/dist/human/tree.d.ts +50 -0
- package/dist/human/tree.js +157 -0
- package/dist/human/wake.d.ts +34 -0
- package/dist/human/wake.js +179 -0
- package/dist/human/web.d.ts +33 -0
- package/dist/human/web.js +184 -0
- package/dist/human/worker.bundle.txt +3868 -0
- package/dist/human/worker.d.ts +1 -0
- package/dist/human/worker.js +81 -0
- package/dist/human/worlds.d.ts +24 -0
- package/dist/human/worlds.js +99 -0
- package/dist/mcp/agent.d.ts +10 -0
- package/dist/mcp/agent.js +78 -0
- package/dist/mcp/allow.d.ts +20 -0
- package/dist/mcp/allow.js +88 -0
- package/dist/mcp/http.d.ts +27 -0
- package/dist/mcp/http.js +92 -0
- package/dist/mcp/oauth.d.ts +91 -0
- package/dist/mcp/oauth.js +241 -0
- package/dist/mcp/route.d.ts +15 -0
- package/dist/mcp/route.js +42 -0
- package/dist/mcp/runner.d.ts +45 -0
- package/dist/mcp/runner.js +99 -0
- package/dist/mcp/server.d.ts +11 -0
- package/dist/mcp/server.js +102 -0
- package/dock/agents.ts +121 -0
- package/dock/apns.ts +138 -0
- package/dock/console.ts +23 -0
- package/dock/dialers.ts +85 -0
- package/dock/faculty.ts +148 -0
- package/dock/fcm.ts +103 -0
- package/dock/grants.ts +111 -0
- package/dock/http2.ts +70 -0
- package/dock/index.ts +133 -0
- package/dock/local.ts +48 -0
- package/dock/location.ts +22 -0
- package/dock/notifications.ts +67 -0
- package/dock/push.ts +161 -0
- package/dock/quo-app-bells.md +280 -0
- package/dock/quo-dock.md +1942 -0
- package/dock/service.ts +100 -0
- package/dock/timer.ts +174 -0
- package/dock/webpush.ts +182 -0
- package/harbor/browser.ts +97 -0
- package/harbor/capacitor.ts +223 -0
- package/harbor/disk.ts +237 -0
- package/harbor/edge/alarm.ts +48 -0
- package/harbor/edge/edge.ts +407 -0
- package/harbor/edge/exercise.ts +241 -0
- package/harbor/edge/given.ts +106 -0
- package/harbor/edge/platform.d.ts +39 -0
- package/harbor/edge/storage.ts +179 -0
- package/harbor/edge/text.d.ts +15 -0
- package/harbor/edge/worker.ts +70 -0
- package/harbor/edge/wrangler.toml +30 -0
- package/harbor/files.ts +221 -0
- package/harbor/http.ts +188 -0
- package/harbor/idb.ts +0 -0
- package/harbor/quo-harbor.md +850 -0
- package/harbor/quo.ts +44 -0
- package/harbor/resolve.ts +31 -0
- package/harbor/seal.ts +26 -0
- package/harbor/sealed.ts +183 -0
- package/harbor/tauri.ts +79 -0
- package/harbor/ward.ts +28 -0
- package/human/app.ts +580 -0
- package/human/apps.ts +47 -0
- package/human/dom.ts +21 -0
- package/human/door.ts +113 -0
- package/human/guest.ts +34 -0
- package/human/html.ts +490 -0
- package/human/local.ts +30 -0
- package/human/mark.ts +53 -0
- package/human/move.ts +122 -0
- package/human/quo-human.md +1042 -0
- package/human/screen.ts +136 -0
- package/human/style.ts +63 -0
- package/human/tab.bundle.txt +4775 -0
- package/human/tab.ts +446 -0
- package/human/tree.ts +217 -0
- package/human/wake.ts +191 -0
- package/human/web.ts +259 -0
- package/human/worker.bundle.txt +3868 -0
- package/human/worker.ts +124 -0
- package/human/worlds.ts +127 -0
- package/mcp/agent.ts +94 -0
- package/mcp/allow.ts +131 -0
- package/mcp/http.ts +92 -0
- package/mcp/oauth.ts +270 -0
- package/mcp/quo-mcp.md +343 -0
- package/mcp/route.ts +45 -0
- package/mcp/runner.ts +136 -0
- package/mcp/server.ts +101 -0
- package/package.json +121 -0
package/human/local.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// A being in the tab's own ward, as a subject the screen renders: a world's
|
|
3
|
+
// code running on the device, booted from the bundle that world serves on
|
|
4
|
+
// its origin. Her cells are in the tab's store and migrate with the ward;
|
|
5
|
+
// her asks are the forms; her page is computed from her cells at every
|
|
6
|
+
// digest, the same painter and the same side as a far being's, so one
|
|
7
|
+
// grammar has two sources and no second verb. A push never reaches her:
|
|
8
|
+
// nothing outside the tab holds her.
|
|
9
|
+
//
|
|
10
|
+
// The tab holds the ward's ask pointer, so the tab is the root owner, and
|
|
11
|
+
// the subject is the owner's `ask` and nothing else: no standing and no
|
|
12
|
+
// relation, since the local ward is the human's and she is on it. The ward
|
|
13
|
+
// names the asker, bounds the wait, judges her answer and saves before the
|
|
14
|
+
// pointer returns, so this file holds an id nobody minted no longer.
|
|
15
|
+
import type { Answer, Blueprint, JsonObject } from '@nervur-org/nervur';
|
|
16
|
+
import type { Subject } from '../beings/side.ts';
|
|
17
|
+
|
|
18
|
+
// The ward as its root holds it: the ask pointer, and nothing else of it.
|
|
19
|
+
type Owner = { ask(method?: string, args?: JsonObject): Promise<unknown> };
|
|
20
|
+
|
|
21
|
+
export function local(ward: Owner, key: string): Subject {
|
|
22
|
+
// A named ask names it; the empty ask says nothing at all, which is how
|
|
23
|
+
// the owner's ask says the empty ask too.
|
|
24
|
+
const one = (method?: string, args: JsonObject = {}) => ward.ask('ask', method === undefined ? { being: key } : { being: key, method, args });
|
|
25
|
+
return {
|
|
26
|
+
tools: async () => (await one()) as Blueprint,
|
|
27
|
+
call: (name: string, args: JsonObject = {}) => one(name, args) as Promise<Answer>,
|
|
28
|
+
ears: new Set(),
|
|
29
|
+
};
|
|
30
|
+
}
|
package/human/mark.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// The mark: a ring with a gap and a point at the centre, one being's voice
|
|
3
|
+
// reaching another's door. It is the one mark every Quo app wears, on the
|
|
4
|
+
// door page, on the desk app's dock icon and on the phone's home screen,
|
|
5
|
+
// and it is drawn once here so those can never drift apart.
|
|
6
|
+
//
|
|
7
|
+
// The glyph is strokes on nothing, coloured by whoever draws it: the door
|
|
8
|
+
// page inherits `currentColor` and the app icons are given the two colours
|
|
9
|
+
// below. `app/icon/build.ts` is what makes the icons of it.
|
|
10
|
+
export const RING = '<circle cx="32" cy="32" r="22" stroke-dasharray="110 30" transform="rotate(-60 32 32)"/><circle cx="32" cy="32" r="5" fill="currentColor" stroke="none"/>';
|
|
11
|
+
|
|
12
|
+
// The mark as a page uses it: strokes in the colour of the text around it.
|
|
13
|
+
export const MARK_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round">${RING}</svg>`;
|
|
14
|
+
|
|
15
|
+
// And as a data URI, since a look carries a logo that way and no request
|
|
16
|
+
// for an image ever leaves a page.
|
|
17
|
+
export const MARK = 'data:image/svg+xml;base64,' + btoa(MARK_SVG);
|
|
18
|
+
|
|
19
|
+
// The app icon's two colours, the dock's own accent and paper: an icon is
|
|
20
|
+
// the product's palette or it is somebody else's product.
|
|
21
|
+
export const ICON_GROUND = '#3b6ef5';
|
|
22
|
+
export const ICON_MARK = '#fbfaf7';
|
|
23
|
+
|
|
24
|
+
// The mark alone on nothing, at the size a layer wants it. Android draws an
|
|
25
|
+
// icon in two layers and crops both to whatever shape the phone likes, a
|
|
26
|
+
// circle among them, so its foreground is the mark small enough to survive
|
|
27
|
+
// the crop, roughly the middle half, and its background is the ground.
|
|
28
|
+
export function markLayer(fraction = 0.5): string {
|
|
29
|
+
const scale = fraction;
|
|
30
|
+
const shift = (64 - 64 * scale) / 2;
|
|
31
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><g transform="translate(${shift} ${shift}) scale(${scale})" fill="none" stroke="${ICON_MARK}" stroke-width="4" stroke-linecap="round" color="${ICON_MARK}">${RING}</g></svg>`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function groundLayer(): string {
|
|
35
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" fill="${ICON_GROUND}"/></svg>`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// The mark as an app icon, on its ground. `radius` is the corner in the
|
|
39
|
+
// viewBox's own units: 0 for a full square, which is what iOS and Android
|
|
40
|
+
// want since the platform masks it, and a rounded one for macOS, which
|
|
41
|
+
// masks nothing and where every icon in the dock is a rounded square with
|
|
42
|
+
// air around it.
|
|
43
|
+
export function iconSVG(radius = 0): string {
|
|
44
|
+
const inset = radius === 0 ? 0 : 5;
|
|
45
|
+
const size = 64 - inset * 2;
|
|
46
|
+
const glyph = radius === 0 ? '' : ` transform="translate(${inset} ${inset}) scale(${size / 64})"`;
|
|
47
|
+
return [
|
|
48
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">',
|
|
49
|
+
`<rect x="${inset}" y="${inset}" width="${size}" height="${size}" rx="${radius}" fill="${ICON_GROUND}"/>`,
|
|
50
|
+
`<g${glyph} fill="none" stroke="${ICON_MARK}" stroke-width="4" stroke-linecap="round" color="${ICON_MARK}">${RING}</g>`,
|
|
51
|
+
'</svg>',
|
|
52
|
+
].join('');
|
|
53
|
+
}
|
package/human/move.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Moving a world from one device to another, as both shells do it. A device
|
|
3
|
+
// holds one local ward per world, on its own seed, and everything it is in
|
|
4
|
+
// that world is in there: the avatars, their standings, what each was told.
|
|
5
|
+
// So a human moving a world to a new device moves that ward, whole, and
|
|
6
|
+
// nothing else happens: the far world is never asked, never told and never
|
|
7
|
+
// notices, because a pk is permanent and every standing still points at the
|
|
8
|
+
// same ward.
|
|
9
|
+
//
|
|
10
|
+
// Two halves, and the being between them is `beings/courier.ts`. The device
|
|
11
|
+
// giving offers: a courier in a ward of her own, an invitation minted on
|
|
12
|
+
// her, and beside it the reach note of the rendezvous this device dials,
|
|
13
|
+
// since the other one may dial nothing yet and a device reaches a pk only
|
|
14
|
+
// through a listener it holds a socket to. Both travel as one link, and a
|
|
15
|
+
// human carries them by eye or by camera. The device taking dials that
|
|
16
|
+
// note, knocks, puts the ward on its harbor, and says so; the copy on the
|
|
17
|
+
// device giving goes at that word and not before.
|
|
18
|
+
//
|
|
19
|
+
// The ward that travels is not the courier's, on either side, because a
|
|
20
|
+
// ward cannot carry itself.
|
|
21
|
+
import type { Harbor } from '@nervur-org/nervur/harbor';
|
|
22
|
+
import type { Invitation, JsonObject } from '@nervur-org/nervur';
|
|
23
|
+
import { arithmetic } from '@nervur-org/nervur/ward';
|
|
24
|
+
import { Courier, MOVER } from '../beings/courier.ts';
|
|
25
|
+
import { link } from '../beings/link.ts';
|
|
26
|
+
import { localName, type World } from './worlds.ts';
|
|
27
|
+
|
|
28
|
+
const { hex, unhex } = arithmetic;
|
|
29
|
+
|
|
30
|
+
// The ward a device's courier lives in, minted when a move starts and gone
|
|
31
|
+
// when it ends: nothing of a move outlives it.
|
|
32
|
+
export const COURIER = 'courier';
|
|
33
|
+
const KEY = 'courier';
|
|
34
|
+
|
|
35
|
+
async function courier(harbor: Harbor): Promise<Courier> {
|
|
36
|
+
const ward = harbor.wards.get(COURIER) ?? (await harbor.create(COURIER, 'me'));
|
|
37
|
+
if (!ward.being(KEY)) {
|
|
38
|
+
const out = (await ward.ask('boot', { key: KEY, class: 'Courier' })) as { error?: string };
|
|
39
|
+
if (out.error) throw new Error(`no courier on this device: ${out.error}`);
|
|
40
|
+
}
|
|
41
|
+
return ward.being(KEY) as Courier;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const away = async (harbor: Harbor) => {
|
|
45
|
+
const c = harbor.wards.get(COURIER)?.being(KEY) as Courier | undefined;
|
|
46
|
+
if (c) {
|
|
47
|
+
c.giving = undefined;
|
|
48
|
+
c.gone = undefined;
|
|
49
|
+
}
|
|
50
|
+
await harbor.drop(COURIER);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type Giving = {
|
|
54
|
+
// The one thing the human carries to the other device: the invitation and
|
|
55
|
+
// the rendezvous to reach this one through, written as a link. Single-use,
|
|
56
|
+
// so one offer moves one ward.
|
|
57
|
+
offer: string;
|
|
58
|
+
invitation: Invitation;
|
|
59
|
+
// Whether the ward has gone, once the other device says it landed.
|
|
60
|
+
moved: Promise<string>;
|
|
61
|
+
// Stop offering: the courier and her ward are gone, and a knock arriving
|
|
62
|
+
// after this reaches nobody. The world stays here unless it was taken.
|
|
63
|
+
close(): Promise<void>;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// This device, offering one world to whichever device takes the offer.
|
|
67
|
+
// `at` is the rendezvous this device dials, which is the world's own `quo.`
|
|
68
|
+
// route: the other device has no reach to anything yet and this is what it
|
|
69
|
+
// dials to answer.
|
|
70
|
+
export async function giveWorld(harbor: Harbor, world: World, at: string): Promise<Giving> {
|
|
71
|
+
const name = localName(world.pk);
|
|
72
|
+
if (!harbor.wards.has(name)) throw new Error('this device does not hold that world');
|
|
73
|
+
const c = await courier(harbor);
|
|
74
|
+
const invitation = await c.invite(MOVER);
|
|
75
|
+
if (!invitation) {
|
|
76
|
+
await away(harbor);
|
|
77
|
+
throw new Error('this device is already offering a world');
|
|
78
|
+
}
|
|
79
|
+
let landed: (pk: string) => void = () => {};
|
|
80
|
+
const moved = new Promise<string>((ok) => (landed = ok));
|
|
81
|
+
c.giving = async () => {
|
|
82
|
+
const ward = harbor.wards.get(name);
|
|
83
|
+
if (!ward) return { error: 'this device no longer holds that world' };
|
|
84
|
+
await ward.save();
|
|
85
|
+
const kept = await harbor.store.load(name);
|
|
86
|
+
if (!kept) return { error: 'this device no longer holds that world' };
|
|
87
|
+
// The partition crosses as the values it is: a ward's partition is
|
|
88
|
+
// I-JSON already, since that is all a ward ever writes into one.
|
|
89
|
+
return { world: world.pk, at: world.at, name: world.name, seed: hex(kept.seed), partition: kept.partition as JsonObject, record: kept.record as unknown as JsonObject };
|
|
90
|
+
};
|
|
91
|
+
c.gone = async () => {
|
|
92
|
+
const gone = await harbor.drop(name);
|
|
93
|
+
if (!gone) return { error: 'this device no longer holds that world' };
|
|
94
|
+
landed(world.pk);
|
|
95
|
+
return { deleted: world.pk };
|
|
96
|
+
};
|
|
97
|
+
await harbor.wards.get(COURIER)!.save();
|
|
98
|
+
return { offer: link(at, invitation), invitation, moved, close: () => away(harbor) };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// This device, taking the world the other one offers. The harbor must
|
|
102
|
+
// already be dialing the reach note in the offer: dialing is the shell's,
|
|
103
|
+
// since only a shell knows which harbor its terrain gave it.
|
|
104
|
+
export async function takeWorld(harbor: Harbor, invitation: Invitation): Promise<{ took: string; world: World } | { error: string }> {
|
|
105
|
+
const c = await courier(harbor);
|
|
106
|
+
try {
|
|
107
|
+
const moving = await c.fetch(invitation);
|
|
108
|
+
if ('error' in moving) return moving;
|
|
109
|
+
const name = localName(moving.world);
|
|
110
|
+
if (harbor.wards.has(name)) return { error: 'this device is already in that world' };
|
|
111
|
+
const hosted = await harbor.adopt(name, { seed: unhex(moving.seed), partition: moving.partition, record: moving.record as unknown as { pk: string; code: string; user: string } });
|
|
112
|
+
// it is here: the other device may let go, and if that word never
|
|
113
|
+
// arrives the human is told, since two copies is what the next move
|
|
114
|
+
// has to be told about
|
|
115
|
+
const let_go = await c.landed();
|
|
116
|
+
return 'error' in let_go ? { error: `it is here, but the other device still has it: ${let_go.error}` } : { took: hosted.pk, world: { pk: moving.world, at: moving.at, name: moving.name } };
|
|
117
|
+
} catch (e) {
|
|
118
|
+
return { error: e instanceof Error ? e.message : String(e) };
|
|
119
|
+
} finally {
|
|
120
|
+
await away(harbor);
|
|
121
|
+
}
|
|
122
|
+
}
|