@nervur-org/dock 0.3.1 → 0.4.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 +22 -12
- package/{beings/GLOSSARY.md → GLOSSARY.md} +3 -3
- package/NOTICE +1 -1
- package/README.md +20 -16
- package/{beings/WORLDS.md → WORLDS.md} +6 -4
- package/api/route.ts +3 -3
- package/beings/avatar.ts +2 -2
- package/beings/carry.ts +2 -2
- package/beings/clock.ts +2 -2
- package/beings/courier.ts +2 -2
- package/beings/desk.ts +2 -2
- package/beings/doorbell.ts +2 -2
- package/beings/envoy.ts +2 -2
- package/beings/join.ts +2 -2
- package/beings/link.ts +5 -5
- package/beings/look.ts +1 -1
- package/beings/porter.ts +2 -2
- package/beings/presence.ts +1 -1
- package/beings/setup.ts +3 -3
- package/beings/side.ts +2 -2
- package/beings/user.ts +2 -2
- package/beings/way.ts +1 -1
- package/cli/client.ts +6 -6
- package/cli/daemon.ts +7 -7
- package/cli/estate/{quo.service → nervur.service} +12 -12
- package/cli/estate/org.nervur.plist +44 -0
- package/cli/estate.ts +6 -6
- package/cli/{quo.ts → nervur.ts} +43 -37
- package/cli/pilot.ts +3 -3
- package/cli/stand.ts +3 -3
- package/dist/api/route.d.ts +2 -2
- package/dist/api/route.js +2 -2
- package/dist/beings/avatar.d.ts +1 -1
- package/dist/beings/avatar.js +1 -1
- package/dist/beings/carry.d.ts +2 -2
- package/dist/beings/carry.js +1 -1
- package/dist/beings/clock.d.ts +2 -2
- package/dist/beings/clock.js +1 -1
- package/dist/beings/courier.d.ts +2 -2
- package/dist/beings/courier.js +1 -1
- package/dist/beings/desk.d.ts +3 -3
- package/dist/beings/desk.js +1 -1
- package/dist/beings/doorbell.d.ts +3 -3
- package/dist/beings/doorbell.js +1 -1
- package/dist/beings/envoy.d.ts +2 -2
- package/dist/beings/envoy.js +1 -1
- package/dist/beings/join.d.ts +2 -2
- package/dist/beings/link.d.ts +2 -2
- package/dist/beings/link.js +3 -3
- package/dist/beings/look.d.ts +1 -1
- package/dist/beings/porter.d.ts +2 -2
- package/dist/beings/porter.js +1 -1
- package/dist/beings/presence.d.ts +1 -1
- package/dist/beings/setup.d.ts +1 -1
- package/dist/beings/side.d.ts +1 -1
- package/dist/beings/side.js +1 -1
- package/dist/beings/user.d.ts +3 -3
- package/dist/beings/user.js +1 -1
- package/dist/beings/way.d.ts +1 -1
- package/dist/cli/client.js +4 -4
- package/dist/cli/daemon.d.ts +1 -1
- package/dist/cli/daemon.js +6 -6
- package/dist/cli/estate/{quo.service → nervur.service} +12 -12
- package/dist/cli/estate/org.nervur.plist +44 -0
- package/dist/cli/estate.js +6 -6
- package/dist/cli/{quo.js → nervur.js} +43 -37
- package/dist/cli/stand.d.ts +2 -2
- package/dist/dock/agents.d.ts +1 -1
- package/dist/dock/agents.js +1 -1
- package/dist/dock/apns.js +1 -1
- package/dist/dock/console.d.ts +1 -1
- package/dist/dock/dialers.d.ts +2 -2
- package/dist/dock/dialers.js +2 -2
- package/dist/dock/faculty.d.ts +2 -2
- package/dist/dock/faculty.js +1 -1
- package/dist/dock/grants.d.ts +1 -1
- package/dist/dock/grants.js +1 -1
- package/dist/dock/http2.js +1 -1
- package/dist/dock/index.d.ts +1 -1
- package/dist/dock/index.js +1 -1
- package/dist/dock/local.d.ts +2 -2
- package/dist/dock/location.d.ts +1 -1
- package/dist/dock/notifications.d.ts +1 -1
- package/dist/dock/notifications.js +1 -1
- package/dist/dock/push.d.ts +1 -1
- package/dist/dock/push.js +3 -3
- package/dist/dock/service.js +1 -1
- package/dist/dock/timer.d.ts +1 -1
- package/dist/harbor/browser.d.ts +2 -2
- package/dist/harbor/browser.js +4 -4
- package/dist/harbor/capacitor.d.ts +1 -1
- package/dist/harbor/capacitor.js +1 -1
- package/dist/harbor/disk.d.ts +4 -4
- package/dist/harbor/disk.js +5 -5
- package/dist/harbor/edge/edge.d.ts +2 -2
- package/dist/harbor/edge/edge.js +5 -5
- package/dist/harbor/edge/exercise.js +8 -8
- package/dist/harbor/edge/given.d.ts +1 -1
- package/dist/harbor/edge/platform.d.ts +1 -1
- package/dist/harbor/edge/storage.d.ts +1 -1
- package/dist/harbor/edge/storage.js +2 -2
- package/dist/harbor/edge/worker.js +2 -2
- package/dist/harbor/files.d.ts +1 -1
- package/dist/harbor/files.js +2 -2
- package/dist/harbor/http.d.ts +2 -2
- package/dist/harbor/http.js +1 -1
- package/dist/harbor/idb.d.ts +1 -1
- package/dist/harbor/idb.js +0 -0
- package/dist/harbor/quo.js +1 -1
- package/dist/harbor/seal.js +1 -1
- package/dist/harbor/sealed.d.ts +1 -1
- package/dist/harbor/sealed.js +4 -4
- package/dist/harbor/tauri.d.ts +1 -1
- package/dist/harbor/tauri.js +1 -1
- package/dist/harbor/ward.d.ts +1 -1
- package/dist/human/app.d.ts +2 -2
- package/dist/human/door.js +4 -4
- package/dist/human/guest.js +1 -1
- package/dist/human/html.d.ts +1 -1
- package/dist/human/html.js +1 -1
- package/dist/human/local.d.ts +1 -1
- package/dist/human/mark.js +2 -2
- package/dist/human/move.d.ts +2 -2
- package/dist/human/move.js +1 -1
- package/dist/human/screen.d.ts +1 -1
- package/dist/human/screen.js +3 -3
- package/dist/human/tab.bundle.txt +32 -32
- package/dist/human/tab.js +7 -7
- package/dist/human/tree.d.ts +1 -1
- package/dist/human/wake.d.ts +2 -2
- package/dist/human/wake.js +1 -1
- package/dist/human/web.d.ts +1 -1
- package/dist/human/web.js +4 -4
- package/dist/human/worker.bundle.txt +27 -27
- package/dist/human/worker.js +4 -4
- package/dist/human/worlds.d.ts +2 -2
- package/dist/human/worlds.js +4 -4
- package/dist/mcp/agent.d.ts +1 -1
- package/dist/mcp/allow.d.ts +1 -1
- package/dist/mcp/allow.js +2 -2
- package/dist/mcp/oauth.js +1 -1
- package/dist/mcp/runner.d.ts +1 -1
- package/dist/mcp/server.d.ts +2 -2
- package/dist/mcp/server.js +2 -2
- package/dock/agents.ts +2 -2
- package/dock/apns.ts +1 -1
- package/dock/console.ts +1 -1
- package/dock/dialers.ts +3 -3
- package/dock/faculty.ts +2 -2
- package/dock/grants.ts +2 -2
- package/dock/http2.ts +1 -1
- package/dock/index.ts +3 -3
- package/dock/local.ts +1 -1
- package/dock/location.ts +1 -1
- package/dock/notifications.ts +2 -2
- package/dock/push.ts +4 -4
- package/dock/service.ts +1 -1
- package/dock/timer.ts +1 -1
- package/harbor/browser.ts +5 -5
- package/harbor/capacitor.ts +2 -2
- package/harbor/disk.ts +8 -8
- package/harbor/edge/edge.ts +7 -7
- package/harbor/edge/exercise.ts +11 -11
- package/harbor/edge/given.ts +1 -1
- package/harbor/edge/platform.d.ts +1 -1
- package/harbor/edge/storage.ts +2 -2
- package/harbor/edge/worker.ts +2 -2
- package/harbor/edge/wrangler.toml +3 -3
- package/harbor/files.ts +2 -2
- package/harbor/http.ts +2 -2
- package/harbor/idb.ts +0 -0
- package/harbor/quo.ts +1 -1
- package/harbor/resolve.ts +1 -1
- package/harbor/seal.ts +1 -1
- package/harbor/sealed.ts +5 -5
- package/harbor/tauri.ts +2 -2
- package/harbor/ward.ts +1 -1
- package/human/app.ts +2 -2
- package/human/apps.ts +1 -1
- package/human/door.ts +4 -4
- package/human/guest.ts +2 -2
- package/human/html.ts +2 -2
- package/human/local.ts +1 -1
- package/human/mark.ts +2 -2
- package/human/move.ts +3 -3
- package/human/screen.ts +5 -5
- package/human/tab.bundle.txt +32 -32
- package/human/tab.ts +10 -10
- package/human/tree.ts +1 -1
- package/human/wake.ts +3 -3
- package/human/web.ts +5 -5
- package/human/worker.bundle.txt +27 -27
- package/human/worker.ts +6 -6
- package/human/worlds.ts +5 -5
- package/mcp/agent.ts +1 -1
- package/mcp/allow.ts +5 -5
- package/mcp/oauth.ts +1 -1
- package/mcp/runner.ts +1 -1
- package/mcp/server.ts +3 -3
- package/package.json +15 -7
- package/{api/quo-api.md → quo-api.md} +1 -1
- package/{beings/quo-dock.md → quo-dock.md} +74 -71
- package/{harbor/quo-harbor.md → quo-harbor.md} +54 -30
- package/{human/quo-human.md → quo-human.md} +7 -7
- package/{mcp/quo-mcp.md → quo-mcp.md} +10 -10
- package/cli/estate/systems.quo.plist +0 -44
- package/cli/quo-dock.md +0 -1942
- package/dist/cli/estate/systems.quo.plist +0 -44
- package/dock/quo-app-bells.md +0 -280
- package/dock/quo-dock.md +0 -1942
- /package/dist/cli/{quo.d.ts → nervur.d.ts} +0 -0
- /package/{beings/quo-app-bells.md → quo-app-bells.md} +0 -0
package/harbor/sealed.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
//
|
|
8
8
|
// <files>/<harbor>/wards/<name>.sealed
|
|
9
9
|
// <files>/<harbor>/reach.json
|
|
10
|
-
// <secrets>:
|
|
10
|
+
// <secrets>: nervur-<harbor> 32 bytes as hex
|
|
11
11
|
//
|
|
12
12
|
// Custody is the backup question, and opening the store answers it: a key
|
|
13
13
|
// with no folder is a reinstall, and the stale key is deleted; a folder
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
// What a platform gives is two small things, files and secrets, and the
|
|
18
18
|
// rest is here once: the phone hands its plugins, the desk hands its core,
|
|
19
19
|
// and the memory harbor hands a map, which is where the rule is proven.
|
|
20
|
-
import { arithmetic } from '
|
|
21
|
-
import type { Kept, Store, WardRecord } from '
|
|
20
|
+
import { arithmetic } from 'nervur/ward';
|
|
21
|
+
import type { Kept, Store, WardRecord } from 'nervur/harbor';
|
|
22
22
|
import { sealKey, seal, open } from './seal.ts';
|
|
23
23
|
|
|
24
24
|
// A folder the platform keeps for this app and no backup copies. Paths are
|
|
@@ -57,7 +57,7 @@ export class Sealed implements Store {
|
|
|
57
57
|
// Open one harbor's store, applying the custody rule, minting the key and
|
|
58
58
|
// the folder when this is a fresh install.
|
|
59
59
|
static async open(harbor: string, files: Files, secrets: Secrets): Promise<Sealed> {
|
|
60
|
-
const item = `
|
|
60
|
+
const item = `nervur-${harbor}`;
|
|
61
61
|
const root = `quo/${harbor}`;
|
|
62
62
|
let secret = await secrets.get(item);
|
|
63
63
|
const folder = await files.exists(root);
|
|
@@ -77,7 +77,7 @@ export class Sealed implements Store {
|
|
|
77
77
|
// Everything this harbor has, key and files: what a person does by hand
|
|
78
78
|
// to leave a device, and what a test does between two openings.
|
|
79
79
|
static async wipe(harbor: string, files: Files, secrets: Secrets): Promise<void> {
|
|
80
|
-
await secrets.remove(`
|
|
80
|
+
await secrets.remove(`nervur-${harbor}`);
|
|
81
81
|
if (await files.exists(`quo/${harbor}`)) await files.rmdir(`quo/${harbor}`);
|
|
82
82
|
}
|
|
83
83
|
|
package/harbor/tauri.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// a network nobody can address, so its harbor dials, holds no listener and
|
|
11
11
|
// ships no daemon. It has no ear, since no store rings a desk; a desk is
|
|
12
12
|
// reached while the app is open and drains what it missed when it opens.
|
|
13
|
-
import type { BeingClass, JsonObject } from '
|
|
13
|
+
import type { BeingClass, JsonObject } from 'nervur';
|
|
14
14
|
import { NOTIFICATIONS, Notifications } from '../dock/index.ts';
|
|
15
15
|
import { BrowserHarbor } from './browser.ts';
|
|
16
16
|
import { Sealed, type Files, type Secrets } from './sealed.ts';
|
|
@@ -65,7 +65,7 @@ export function deskSecrets(core: Core): Secrets {
|
|
|
65
65
|
// wards. The core hands the faculty its notification center by being in
|
|
66
66
|
// the class body the harbor holds, which is the one place a terrain's
|
|
67
67
|
// body may hold a live object.
|
|
68
|
-
export async function deskHarbor(core: Core, name = '
|
|
68
|
+
export async function deskHarbor(core: Core, name = 'nervur', classes: Record<string, BeingClass> = {}): Promise<BrowserHarbor> {
|
|
69
69
|
class Center extends DeskNotifications {
|
|
70
70
|
constructor(stance: ConstructorParameters<typeof DeskNotifications>[0]) {
|
|
71
71
|
super(stance, core);
|
package/harbor/ward.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// through the ask pointer and reads the describe, which is the same answer
|
|
8
8
|
// the owner gets on every other surface. Terrain-free: a daemon and a tab
|
|
9
9
|
// both hold a Hosted and both read it here.
|
|
10
|
-
import type { Hosted } from '
|
|
10
|
+
import type { Hosted } from 'nervur/harbor';
|
|
11
11
|
|
|
12
12
|
// One being of a ward, as her own ward describes her.
|
|
13
13
|
export type Row = { class: string | null; public: boolean; digest: string | null; absent?: boolean };
|
package/human/app.ts
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
// screen shows one world's relation at a time and the switcher moves
|
|
13
13
|
// between them. Everything under the switcher is `screen.ts` and a
|
|
14
14
|
// surface, the same as the tab: the app adds no way of showing a being.
|
|
15
|
-
import type { Harbor, Hosted } from '
|
|
16
|
-
import type { Blueprint, Invitation, JsonObject } from '
|
|
15
|
+
import type { Harbor, Hosted } from 'nervur/harbor';
|
|
16
|
+
import type { Blueprint, Invitation, JsonObject } from 'nervur';
|
|
17
17
|
import { screenSide } from './screen.ts';
|
|
18
18
|
import { domSurface } from './dom.ts';
|
|
19
19
|
import { guest } from './guest.ts';
|
package/human/apps.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// browser.
|
|
6
6
|
//
|
|
7
7
|
// Two hostnames say it and neither may say it differently. A world's web
|
|
8
|
-
// route says it for the estate that ships an app of its own, and the
|
|
8
|
+
// route says it for the estate that ships an app of its own, and the Nervur
|
|
9
9
|
// app's own domain says it for the app the stores carry, which serves no
|
|
10
10
|
// world and has no route. So the words are here, once, and both fetch them
|
|
11
11
|
// from the same place: Apple's format and Google's are the platforms' and
|
package/human/door.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// The door page: what a stranger sees where nothing lets them in. No
|
|
3
3
|
// invitation in the fragment, no relation in this tab's harbor, and nobody
|
|
4
4
|
// at the ward's door; or a harbor's root with no world to list. It is
|
|
5
|
-
//
|
|
5
|
+
// the dock's page and not the estate's: it says what this is and that a world
|
|
6
6
|
// here is entered by a link someone sends you, and it asks for nothing,
|
|
7
7
|
// since there is nothing a stranger could type that would let them in. A
|
|
8
8
|
// world that wants a face of its own has a public being with a page and a
|
|
@@ -21,7 +21,7 @@ export function doorTree(at: Door): Node {
|
|
|
21
21
|
as: 'hero',
|
|
22
22
|
of: [
|
|
23
23
|
{ kind: 'image', src: MARK, alt: '' },
|
|
24
|
-
{ kind: 'text', text: '
|
|
24
|
+
{ kind: 'text', text: 'Nervur', role: 'title' },
|
|
25
25
|
{ kind: 'text', text: at.world ? `${at.world} at ${at.host}` : at.host, role: 'label' },
|
|
26
26
|
{ kind: 'text', text: at.world ? 'This world is entered by invitation.' : 'The worlds here are entered by invitation.', role: 'lead' },
|
|
27
27
|
{ kind: 'text', text: 'An invitation is a link someone sends you. Open it here, and you are in: no account, no password, nothing to type. What you can do inside is what the world shows you, and it is yours to keep on this device.' },
|
|
@@ -60,13 +60,13 @@ export function held(at: Door): string {
|
|
|
60
60
|
return `<main data-door>${paint(heldTree(at), nobody)}</main>`;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
// The policy every page
|
|
63
|
+
// The policy every page the dock writes itself is served under, wherever it is
|
|
64
64
|
// served from. These pages run no script and want none, so nothing but
|
|
65
65
|
// their own form is allowed anywhere, an image is the mark and therefore
|
|
66
66
|
// data, and no referer carries what brought a human here off the page.
|
|
67
67
|
export const POLICY = "default-src 'none'; style-src 'unsafe-inline'; img-src data:; form-action 'self'; base-uri 'none'; frame-ancestors 'none'";
|
|
68
68
|
|
|
69
|
-
// A painter for
|
|
69
|
+
// A painter for the dock's own pages. It is `nobody` with links painted, and
|
|
70
70
|
// that is sound where the other painter's caution is not: the vouching rule
|
|
71
71
|
// exists because a far being names a place and the side cannot know where
|
|
72
72
|
// she is sending a human. On these pages the dock wrote the address itself,
|
package/human/guest.ts
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
// convention of the dock's like `hello`, `look` and `page`: a public being
|
|
14
14
|
// of any class takes proofs by writing an ask under that name, and one that
|
|
15
15
|
// writes none has no proof way in and loses nothing else.
|
|
16
|
-
import { isSilence, isWord, wordOf } from '
|
|
17
|
-
import type { Answer, Blueprint, Invitation, JsonObject, Wanted } from '
|
|
16
|
+
import { isSilence, isWord, wordOf } from 'nervur';
|
|
17
|
+
import type { Answer, Blueprint, Invitation, JsonObject, Wanted } from 'nervur';
|
|
18
18
|
import type { Avatar } from '../beings/avatar.ts';
|
|
19
19
|
import type { Subject } from '../beings/side.ts';
|
|
20
20
|
|
package/human/html.ts
CHANGED
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
// values(ask, raw) the submitted strings back as arguments, typed by the schema
|
|
10
10
|
// view(value, schema?) an answer as a view, ordered by the output schema
|
|
11
11
|
// page(model) the whole page: title, notice, forms, views, pushes
|
|
12
|
-
import type { Answer, Ask, Blueprint, Json, JsonObject } from '
|
|
12
|
+
import type { Answer, Ask, Blueprint, Json, JsonObject } from 'nervur';
|
|
13
13
|
import { SILENCE_TEXT, UNREACHED_TEXT, word, wordText, type Word } from '../beings/side.ts';
|
|
14
14
|
import { hint, hintFor, sanitise, groups as grouped, presentation, type Look, type Hint } from '../beings/look.ts';
|
|
15
15
|
import { paint, titled, type As, type Node, type Painter } from './tree.ts';
|
|
16
|
-
import { isInvitation } from '
|
|
16
|
+
import { isInvitation } from 'nervur';
|
|
17
17
|
import { link } from '../beings/link.ts';
|
|
18
18
|
|
|
19
19
|
// One property of an input schema, as the form needs it.
|
package/human/local.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// relation, since the local ward is the human's and she is on it. The ward
|
|
13
13
|
// names the asker, bounds the wait, judges her answer and saves before the
|
|
14
14
|
// pointer returns, so this file holds an id nobody minted no longer.
|
|
15
|
-
import type { Answer, Blueprint, JsonObject } from '
|
|
15
|
+
import type { Answer, Blueprint, JsonObject } from 'nervur';
|
|
16
16
|
import type { Subject } from '../beings/side.ts';
|
|
17
17
|
|
|
18
18
|
// The ward as its root holds it: the ask pointer, and nothing else of it.
|
package/human/mark.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
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
|
|
4
|
-
// door page, on the desk app's dock icon and on the phone's home screen,
|
|
3
|
+
// reaching another's door. It is the one mark the dock and the app wear, on
|
|
4
|
+
// the door page, on the desk app's dock icon and on the phone's home screen,
|
|
5
5
|
// and it is drawn once here so those can never drift apart.
|
|
6
6
|
//
|
|
7
7
|
// The glyph is strokes on nothing, coloured by whoever draws it: the door
|
package/human/move.ts
CHANGED
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
//
|
|
19
19
|
// The ward that travels is not the courier's, on either side, because a
|
|
20
20
|
// ward cannot carry itself.
|
|
21
|
-
import type { Harbor } from '
|
|
22
|
-
import type { Invitation, JsonObject } from '
|
|
23
|
-
import { arithmetic } from '
|
|
21
|
+
import type { Harbor } from 'nervur/harbor';
|
|
22
|
+
import type { Invitation, JsonObject } from 'nervur';
|
|
23
|
+
import { arithmetic } from 'nervur/ward';
|
|
24
24
|
import { Courier, MOVER } from '../beings/courier.ts';
|
|
25
25
|
import { link } from '../beings/link.ts';
|
|
26
26
|
import { localName, type World } from './worlds.ts';
|
package/human/screen.ts
CHANGED
|
@@ -6,15 +6,15 @@
|
|
|
6
6
|
// through `html.ts`, calls the avatar when a form comes back, and re-asks
|
|
7
7
|
// her describe after each call, so a digest that moved is a page that
|
|
8
8
|
// moved. A push is appended and shown the moment it lands.
|
|
9
|
-
import { digest } from '
|
|
10
|
-
import type { Blueprint, JsonObject } from '
|
|
9
|
+
import { digest } from 'nervur';
|
|
10
|
+
import type { Blueprint, JsonObject } from 'nervur';
|
|
11
11
|
import { word, type Serving, type Subject } from '../beings/side.ts';
|
|
12
|
-
import { isInvitation } from '
|
|
13
|
-
import type { Invitation } from '
|
|
12
|
+
import { isInvitation } from 'nervur';
|
|
13
|
+
import type { Invitation } from 'nervur';
|
|
14
14
|
import { page, values, hintFor, mine, asks, standing, stands, type Model, type Raw } from './html.ts';
|
|
15
15
|
import { sanitiseTree, answersIn } from './tree.ts';
|
|
16
16
|
import { groups, sanitise } from '../beings/look.ts';
|
|
17
|
-
import { isSilence, isWord } from '
|
|
17
|
+
import { isSilence, isWord } from 'nervur';
|
|
18
18
|
|
|
19
19
|
export type Surface = {
|
|
20
20
|
show(html: string): void;
|
package/human/tab.bundle.txt
CHANGED
|
@@ -4,7 +4,7 @@ var __export = (target, all) => {
|
|
|
4
4
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
// ../
|
|
7
|
+
// ../nervur/dist/being/being.js
|
|
8
8
|
var RESERVED = /* @__PURE__ */ new Set(["answer", "describe", "stance", "cells", "standings", "occupants", "occupant", "invite", "knock", "take", "boot", "lend", "constructor"]);
|
|
9
9
|
var wrote = (self, name) => {
|
|
10
10
|
for (let p = Object.getPrototypeOf(self); p !== null && p !== Object.prototype; p = Object.getPrototypeOf(p)) {
|
|
@@ -96,7 +96,7 @@ var Being = class {
|
|
|
96
96
|
}
|
|
97
97
|
};
|
|
98
98
|
|
|
99
|
-
// ../
|
|
99
|
+
// ../nervur/dist/being/types.js
|
|
100
100
|
var OWNER = "OWNER";
|
|
101
101
|
var PUBLIC = "PUBLIC";
|
|
102
102
|
var RESERVED_IDS = [OWNER, PUBLIC];
|
|
@@ -119,7 +119,7 @@ var isBlueprint = (v) => {
|
|
|
119
119
|
};
|
|
120
120
|
var WORD_KEY = /* @__PURE__ */ Symbol.for("quo.word");
|
|
121
121
|
|
|
122
|
-
// ../
|
|
122
|
+
// ../nervur/dist/being/silence.js
|
|
123
123
|
var silence = /* @__PURE__ */ Symbol.for("quo.silence");
|
|
124
124
|
var isSilence = (x) => x === silence;
|
|
125
125
|
var DOOR_WORDS = ["removed", "absent", "unannounced", "repeated", "threw"];
|
|
@@ -136,7 +136,7 @@ var wordOf = (x) => x[WORD_KEY];
|
|
|
136
136
|
var unreached = () => word("unreached");
|
|
137
137
|
var isUnreached = (x) => isWord(x) && wordOf(x) === "unreached";
|
|
138
138
|
|
|
139
|
-
// ../
|
|
139
|
+
// ../nervur/dist/being/digest.js
|
|
140
140
|
var absent = (v) => v === void 0 || typeof v === "function" || typeof v === "symbol";
|
|
141
141
|
var canonical = (v) => {
|
|
142
142
|
if (Array.isArray(v))
|
|
@@ -498,7 +498,7 @@ var Location = class extends Faculty {
|
|
|
498
498
|
}
|
|
499
499
|
};
|
|
500
500
|
|
|
501
|
-
// ../
|
|
501
|
+
// ../nervur/dist/ward/cells.js
|
|
502
502
|
var DEPTH = 64;
|
|
503
503
|
var BREADTH = 1 << 20;
|
|
504
504
|
var WELL_FORMED = /^(?:[^\uD800-\uDFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF])*$/;
|
|
@@ -636,7 +636,7 @@ var guardCells = (cells, wrote2 = () => {
|
|
|
636
636
|
}) => guard(cells, "cells", wrote2, true);
|
|
637
637
|
var unguarded = (cells) => targets.get(cells) ?? cells;
|
|
638
638
|
|
|
639
|
-
// ../
|
|
639
|
+
// ../nervur/dist/ward/partition.js
|
|
640
640
|
var VERSION = "pre-1.0.0";
|
|
641
641
|
var READS = [VERSION];
|
|
642
642
|
function upgrade(p) {
|
|
@@ -800,7 +800,7 @@ var fromRows = (rows) => {
|
|
|
800
800
|
return out;
|
|
801
801
|
};
|
|
802
802
|
|
|
803
|
-
// ../
|
|
803
|
+
// ../nervur/dist/ward/heirs.js
|
|
804
804
|
var SPAN = 64;
|
|
805
805
|
var Heirs = class {
|
|
806
806
|
#p;
|
|
@@ -909,7 +909,7 @@ var Heirs = class {
|
|
|
909
909
|
}
|
|
910
910
|
};
|
|
911
911
|
|
|
912
|
-
// ../
|
|
912
|
+
// ../nervur/dist/ward/arithmetic.js
|
|
913
913
|
var arithmetic_exports = {};
|
|
914
914
|
__export(arithmetic_exports, {
|
|
915
915
|
KEY: () => KEY,
|
|
@@ -1104,7 +1104,7 @@ async function unbox(bytes, padlockSecret) {
|
|
|
1104
1104
|
return decrypt(shared, bytes.subarray(KEY), ephemeralPk);
|
|
1105
1105
|
}
|
|
1106
1106
|
|
|
1107
|
-
// ../
|
|
1107
|
+
// ../nervur/dist/ward/seal.js
|
|
1108
1108
|
var utf8 = new TextEncoder();
|
|
1109
1109
|
var text2 = new TextDecoder();
|
|
1110
1110
|
var WARD_SIGN = new TextEncoder().encode("quo-ward-sign");
|
|
@@ -1194,7 +1194,7 @@ async function openReply(bytes, ephemeralSecret, signPk) {
|
|
|
1194
1194
|
}
|
|
1195
1195
|
}
|
|
1196
1196
|
|
|
1197
|
-
// ../
|
|
1197
|
+
// ../nervur/dist/ward/allowance.js
|
|
1198
1198
|
var DEFAULT = { time: 3e4 };
|
|
1199
1199
|
var CEILING = { time: 3e5 };
|
|
1200
1200
|
function allow(wanted, ceiling = CEILING, base = DEFAULT) {
|
|
@@ -1224,7 +1224,7 @@ async function within(ms, work, rang2) {
|
|
|
1224
1224
|
}
|
|
1225
1225
|
}
|
|
1226
1226
|
|
|
1227
|
-
// ../
|
|
1227
|
+
// ../nervur/dist/ward/door.js
|
|
1228
1228
|
var SILENCE = { silence: true };
|
|
1229
1229
|
var said = (quo) => ({ quo });
|
|
1230
1230
|
async function answered2(door2, asker, method, args, bound) {
|
|
@@ -1317,7 +1317,7 @@ function lid(bytes, random) {
|
|
|
1317
1317
|
return random(KEY);
|
|
1318
1318
|
}
|
|
1319
1319
|
|
|
1320
|
-
// ../
|
|
1320
|
+
// ../nervur/dist/ward/stance.js
|
|
1321
1321
|
var CALLS = ["knock", "take", "remove"];
|
|
1322
1322
|
function buildStance(inside, key, cells, bind) {
|
|
1323
1323
|
const named = (method) => method === void 0 || typeof method === "string";
|
|
@@ -1595,7 +1595,7 @@ function buildStance(inside, key, cells, bind) {
|
|
|
1595
1595
|
};
|
|
1596
1596
|
}
|
|
1597
1597
|
|
|
1598
|
-
// ../
|
|
1598
|
+
// ../nervur/dist/ward/owner.js
|
|
1599
1599
|
var str2 = { type: "string" };
|
|
1600
1600
|
var OWNER_ASKS = [
|
|
1601
1601
|
{ name: "boot", description: "boot a being by class name, under a key the owner chooses", input: { type: "object", properties: { key: str2, class: str2 }, required: ["key", "class"] } },
|
|
@@ -1738,7 +1738,7 @@ async function describe(w) {
|
|
|
1738
1738
|
};
|
|
1739
1739
|
}
|
|
1740
1740
|
|
|
1741
|
-
// ../
|
|
1741
|
+
// ../nervur/dist/ward/ward.js
|
|
1742
1742
|
async function Ward(ground) {
|
|
1743
1743
|
const w = await Self.boot(ground);
|
|
1744
1744
|
return { door: w.door, ask: w.ask };
|
|
@@ -2063,7 +2063,7 @@ var isToken = (v) => v !== null && typeof v === "object" && !Array.isArray(v) &&
|
|
|
2063
2063
|
var SEAL = 4096;
|
|
2064
2064
|
function banner(o) {
|
|
2065
2065
|
const text3 = (v) => typeof v === "string" && v.trim() ? v.trim() : "";
|
|
2066
|
-
const title2 = text3(o.title) || text3(o.from) || "
|
|
2066
|
+
const title2 = text3(o.title) || text3(o.from) || "Nervur";
|
|
2067
2067
|
const body = text3(o.body) || text3(o.said) || Object.entries(o).filter(([k]) => k !== "title" && k !== "from").map(([k, v]) => `${k}: ${typeof v === "string" ? v : JSON.stringify(v)}`).join(", ");
|
|
2068
2068
|
return { title: title2, body };
|
|
2069
2069
|
}
|
|
@@ -2913,7 +2913,7 @@ var MINUTE2 = 6e4;
|
|
|
2913
2913
|
var HOUR = 36e5;
|
|
2914
2914
|
var SPAN2 = 23 * HOUR + 59 * MINUTE2;
|
|
2915
2915
|
|
|
2916
|
-
// ../
|
|
2916
|
+
// ../nervur/dist/ward/ground.js
|
|
2917
2917
|
var maker = (objects, ...registries) => (className, stance) => {
|
|
2918
2918
|
const r = registries.find((reg) => reg !== void 0 && Object.hasOwn(reg, className));
|
|
2919
2919
|
const C = r?.[className];
|
|
@@ -2932,7 +2932,7 @@ async function learnPk(w) {
|
|
|
2932
2932
|
return pk;
|
|
2933
2933
|
}
|
|
2934
2934
|
|
|
2935
|
-
// ../
|
|
2935
|
+
// ../nervur/dist/harbor/reach.js
|
|
2936
2936
|
var never = () => new Promise(() => {
|
|
2937
2937
|
});
|
|
2938
2938
|
function request(url) {
|
|
@@ -3056,14 +3056,14 @@ var Socket = class {
|
|
|
3056
3056
|
}
|
|
3057
3057
|
};
|
|
3058
3058
|
|
|
3059
|
-
// ../
|
|
3059
|
+
// ../nervur/dist/harbor/store.js
|
|
3060
3060
|
var values = (p) => JSON.parse(JSON.stringify(p));
|
|
3061
3061
|
var rowsOf = (partition, rows) => rows.map((row) => {
|
|
3062
3062
|
const value = rowOf(partition, row);
|
|
3063
3063
|
return [row, value === void 0 ? void 0 : values(value)];
|
|
3064
3064
|
});
|
|
3065
3065
|
|
|
3066
|
-
// ../
|
|
3066
|
+
// ../nervur/dist/harbor/core.js
|
|
3067
3067
|
var DEFAULT_CODE = "classes/index.ts";
|
|
3068
3068
|
var PROBE = 1e4;
|
|
3069
3069
|
var ANNOUNCE = 64;
|
|
@@ -3559,7 +3559,7 @@ var Harbor = class {
|
|
|
3559
3559
|
}
|
|
3560
3560
|
};
|
|
3561
3561
|
|
|
3562
|
-
// ../
|
|
3562
|
+
// ../nervur/dist/harbor/dial.js
|
|
3563
3563
|
function dial(harbor, url) {
|
|
3564
3564
|
const d = { url, socket: null, wake: () => {
|
|
3565
3565
|
}, close: () => {
|
|
@@ -3730,10 +3730,10 @@ var BrowserHarbor = class extends Harbor {
|
|
|
3730
3730
|
// `lend` is what this box lends the beings of the wards it hosts: a name
|
|
3731
3731
|
// to an invitation on a being of its own ward. `stand` builds one; a bare
|
|
3732
3732
|
// tab hands none and every name answers null.
|
|
3733
|
-
constructor(store = "
|
|
3733
|
+
constructor(store = "nervur", classes = {}, lend) {
|
|
3734
3734
|
const s = typeof store === "string" ? new Idb(store) : store;
|
|
3735
3735
|
super(s, async () => ({ ...BUILT_IN, ...classes }), lend);
|
|
3736
|
-
this.name = typeof store === "string" ? store : "
|
|
3736
|
+
this.name = typeof store === "string" ? store : "nervur";
|
|
3737
3737
|
this.#locked = typeof store === "string";
|
|
3738
3738
|
}
|
|
3739
3739
|
// What this box lends, by name. A bare tab says nothing, stands no ward of
|
|
@@ -3776,7 +3776,7 @@ var BrowserHarbor = class extends Harbor {
|
|
|
3776
3776
|
const locks = globalThis.navigator?.locks;
|
|
3777
3777
|
if (!locks) return;
|
|
3778
3778
|
const granted = await new Promise((ok) => {
|
|
3779
|
-
void locks.request(`
|
|
3779
|
+
void locks.request(`nervur:${this.name}`, { ifAvailable: true }, (lock) => {
|
|
3780
3780
|
if (!lock) {
|
|
3781
3781
|
ok(false);
|
|
3782
3782
|
return;
|
|
@@ -3790,7 +3790,7 @@ var BrowserHarbor = class extends Harbor {
|
|
|
3790
3790
|
};
|
|
3791
3791
|
|
|
3792
3792
|
// beings/link.ts
|
|
3793
|
-
var KEY2 = "
|
|
3793
|
+
var KEY2 = "nervur";
|
|
3794
3794
|
var PROOF = "proof";
|
|
3795
3795
|
var HEX3 = (n) => `[0-9a-f]{${n}}`;
|
|
3796
3796
|
var FULL = new RegExp(`^(${HEX3(128)})\\.(${HEX3(64)})\\.(${HEX3(64)})$`);
|
|
@@ -3799,7 +3799,7 @@ function format(inv) {
|
|
|
3799
3799
|
return inv.heir && inv.secret ? `${inv.ward}.${inv.heir}.${inv.secret}` : inv.ward;
|
|
3800
3800
|
}
|
|
3801
3801
|
function parse(hash) {
|
|
3802
|
-
const m =
|
|
3802
|
+
const m = new RegExp(`(?:^#|&)${KEY2}=([^&]+)`).exec(hash.startsWith("#") ? hash : `#${hash}`);
|
|
3803
3803
|
if (!m) return null;
|
|
3804
3804
|
const v = decodeURIComponent(m[1]);
|
|
3805
3805
|
const full = FULL.exec(v);
|
|
@@ -4461,7 +4461,7 @@ function doorTree(at3) {
|
|
|
4461
4461
|
as: "hero",
|
|
4462
4462
|
of: [
|
|
4463
4463
|
{ kind: "image", src: MARK, alt: "" },
|
|
4464
|
-
{ kind: "text", text: "
|
|
4464
|
+
{ kind: "text", text: "Nervur", role: "title" },
|
|
4465
4465
|
{ kind: "text", text: at3.world ? `${at3.world} at ${at3.host}` : at3.host, role: "label" },
|
|
4466
4466
|
{ kind: "text", text: at3.world ? "This world is entered by invitation." : "The worlds here are entered by invitation.", role: "lead" },
|
|
4467
4467
|
{ kind: "text", text: "An invitation is a link someone sends you. Open it here, and you are in: no account, no password, nothing to type. What you can do inside is what the world shows you, and it is yours to keep on this device." },
|
|
@@ -4517,11 +4517,11 @@ var keep2 = (key, value) => {
|
|
|
4517
4517
|
} catch {
|
|
4518
4518
|
}
|
|
4519
4519
|
};
|
|
4520
|
-
var WORLDS = "
|
|
4520
|
+
var WORLDS = "nervur-worlds";
|
|
4521
4521
|
var worlds = () => kept(WORLDS, {});
|
|
4522
4522
|
var remember = (pk, url, name) => keep2(WORLDS, { ...worlds(), [pk]: { url, name } });
|
|
4523
|
-
var AT = (pk) => `
|
|
4524
|
-
var NAMES = (pk) => `
|
|
4523
|
+
var AT = (pk) => `nervur-at:${pk}`;
|
|
4524
|
+
var NAMES = (pk) => `nervur-names:${pk}`;
|
|
4525
4525
|
var el = (tag, text3 = "", attrs = {}) => {
|
|
4526
4526
|
const e = document.createElement(tag);
|
|
4527
4527
|
if (text3) e.textContent = text3;
|
|
@@ -4538,7 +4538,7 @@ async function start(cfg, root2 = document.body) {
|
|
|
4538
4538
|
const screen = el("div");
|
|
4539
4539
|
root2.append(nav, who, status, screen);
|
|
4540
4540
|
const say = (s) => status.textContent = s;
|
|
4541
|
-
const harbor = new BrowserHarbor("
|
|
4541
|
+
const harbor = new BrowserHarbor("nervur");
|
|
4542
4542
|
const classes = cfg.beings ? await import(`${cfg.web}/beings.js`).then((mod) => {
|
|
4543
4543
|
const out = {};
|
|
4544
4544
|
for (const [name, v] of Object.entries(mod)) if (typeof v === "function" && "prototype" in v) out[name] = v;
|
|
@@ -4556,7 +4556,7 @@ async function start(cfg, root2 = document.body) {
|
|
|
4556
4556
|
const pks = Object.values(cfg.wards).map((w) => w.pk);
|
|
4557
4557
|
let bell = cfg.bell ? await subscribe(cfg.web, cfg.bell) : null;
|
|
4558
4558
|
globalThis.navigator?.serviceWorker?.addEventListener("message", (e) => {
|
|
4559
|
-
if (e.data?.
|
|
4559
|
+
if (e.data?.nervur !== "wake") return;
|
|
4560
4560
|
const port = e.ports[0];
|
|
4561
4561
|
void (async () => {
|
|
4562
4562
|
harbor.wake();
|
|
@@ -4767,7 +4767,7 @@ async function start(cfg, root2 = document.body) {
|
|
|
4767
4767
|
}
|
|
4768
4768
|
await atDoor();
|
|
4769
4769
|
}
|
|
4770
|
-
var config = document.getElementById("
|
|
4770
|
+
var config = document.getElementById("nervur");
|
|
4771
4771
|
if (config?.textContent) void start(JSON.parse(config.textContent));
|
|
4772
4772
|
export {
|
|
4773
4773
|
USER,
|
package/human/tab.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// Three ways in and there is no fourth, the same act each time, a knock
|
|
9
9
|
// that ends in a standing, and each one a fresh avatar:
|
|
10
10
|
//
|
|
11
|
-
// a link the page with the invitation in its fragment, `#
|
|
11
|
+
// a link the page with the invitation in its fragment, `#nervur=...`,
|
|
12
12
|
// read and stripped before anything else runs, then joined.
|
|
13
13
|
// The invitation names its ward, so it is joined in that
|
|
14
14
|
// world's local ward whatever page it was opened on, and a
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
// is the human side in `screen.ts` over the DOM surface in `dom.ts`. This
|
|
31
31
|
// file is the shell: the harbor, the config, the switcher and the ways in,
|
|
32
32
|
// and it hands one avatar at a time to the side.
|
|
33
|
-
import type { Invitation, JsonObject } from '
|
|
33
|
+
import type { Invitation, JsonObject } from 'nervur';
|
|
34
34
|
import { BrowserHarbor } from '../harbor/browser.ts';
|
|
35
35
|
import { USER } from '../beings/avatar.ts';
|
|
36
|
-
import { isInvitation } from '
|
|
36
|
+
import { isInvitation } from 'nervur';
|
|
37
37
|
import { parse, parseProof, strip } from '../beings/link.ts';
|
|
38
38
|
import { giveWorld, type Giving } from './move.ts';
|
|
39
39
|
import { drained, subscribe } from './wake.ts';
|
|
@@ -44,7 +44,7 @@ import { guest } from './guest.ts';
|
|
|
44
44
|
import { door, held } from './door.ts';
|
|
45
45
|
import { world, relations, fresh, localName, type Relation } from './worlds.ts';
|
|
46
46
|
import { local } from './local.ts';
|
|
47
|
-
import type { BeingClass } from '
|
|
47
|
+
import type { BeingClass } from 'nervur';
|
|
48
48
|
|
|
49
49
|
// What the page is told by the daemon that served it: the world's routes,
|
|
50
50
|
// every ward on that harbor by name, its pk and whether a public being is
|
|
@@ -74,11 +74,11 @@ const keep = (key: string, value: unknown) => {
|
|
|
74
74
|
/* forgets */
|
|
75
75
|
}
|
|
76
76
|
};
|
|
77
|
-
const WORLDS = '
|
|
77
|
+
const WORLDS = 'nervur-worlds';
|
|
78
78
|
const worlds = (): Worlds => kept(WORLDS, {});
|
|
79
79
|
const remember = (pk: string, url: string, name: string) => keep(WORLDS, { ...worlds(), [pk]: { url, name } });
|
|
80
|
-
const AT = (pk: string) => `
|
|
81
|
-
const NAMES = (pk: string) => `
|
|
80
|
+
const AT = (pk: string) => `nervur-at:${pk}`;
|
|
81
|
+
const NAMES = (pk: string) => `nervur-names:${pk}`;
|
|
82
82
|
|
|
83
83
|
const el = <K extends keyof HTMLElementTagNameMap>(tag: K, text = '', attrs: Record<string, string> = {}): HTMLElementTagNameMap[K] => {
|
|
84
84
|
const e = document.createElement(tag);
|
|
@@ -107,7 +107,7 @@ export async function start(cfg: Config, root: HTMLElement = document.body): Pro
|
|
|
107
107
|
// boots, since a being kept from the last visit is booted by class name.
|
|
108
108
|
// A world that serves none has no beings in the tab, and the page is the
|
|
109
109
|
// far being's alone.
|
|
110
|
-
const harbor = new BrowserHarbor('
|
|
110
|
+
const harbor = new BrowserHarbor('nervur');
|
|
111
111
|
const classes = cfg.beings
|
|
112
112
|
? await import(`${cfg.web}/beings.js`).then((mod: Record<string, unknown>) => {
|
|
113
113
|
const out: Record<string, BeingClass> = {};
|
|
@@ -139,7 +139,7 @@ export async function start(cfg: Config, root: HTMLElement = document.body): Pro
|
|
|
139
139
|
const pks = Object.values(cfg.wards).map((w) => w.pk);
|
|
140
140
|
let bell = cfg.bell ? await subscribe(cfg.web, cfg.bell) : null;
|
|
141
141
|
globalThis.navigator?.serviceWorker?.addEventListener('message', (e: MessageEvent) => {
|
|
142
|
-
if ((e.data as {
|
|
142
|
+
if ((e.data as { nervur?: string } | null)?.nervur !== 'wake') return;
|
|
143
143
|
const port = e.ports[0];
|
|
144
144
|
void (async () => {
|
|
145
145
|
harbor.wake();
|
|
@@ -440,7 +440,7 @@ export async function start(cfg: Config, root: HTMLElement = document.body): Pro
|
|
|
440
440
|
|
|
441
441
|
// The page hands the config in a JSON script, which a content security
|
|
442
442
|
// policy allows where an inline script is not.
|
|
443
|
-
const config = document.getElementById('
|
|
443
|
+
const config = document.getElementById('nervur');
|
|
444
444
|
if (config?.textContent) void start(JSON.parse(config.textContent) as Config);
|
|
445
445
|
|
|
446
446
|
export { USER };
|
package/human/tree.ts
CHANGED
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
// a being never carries a layout. An answer says its kind the same way:
|
|
43
43
|
// `people` are rows of { name, line?, picture? }, and `feed` is rows of
|
|
44
44
|
// { at, text }; a value that is not that shape is shown by its own shape.
|
|
45
|
-
import type { Json } from '
|
|
45
|
+
import type { Json } from 'nervur';
|
|
46
46
|
import { escape } from './html.ts';
|
|
47
47
|
|
|
48
48
|
export type Role = 'title' | 'lead' | 'body' | 'quiet' | 'label';
|
package/human/wake.ts
CHANGED
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
// tab hands its browser endpoint instead and keeps no doorbell, because a
|
|
18
18
|
// browser endpoint is rung only by whoever holds the VAPID secret the
|
|
19
19
|
// subscription was made under, and that secret is the world's own.
|
|
20
|
-
import { isInvitation, isSilence, isWord } from '
|
|
21
|
-
import type { Invitation, JsonObject, Standing } from '
|
|
22
|
-
import type { Harbor } from '
|
|
20
|
+
import { isInvitation, isSilence, isWord } from 'nervur';
|
|
21
|
+
import type { Invitation, JsonObject, Standing } from 'nervur';
|
|
22
|
+
import type { Harbor } from 'nervur/harbor';
|
|
23
23
|
import { DOCK, CONSOLE, NOTIFICATIONS, facultyOf, type Token } from '../dock/index.ts';
|
|
24
24
|
import type { Notifications } from '../dock/notifications.ts';
|
|
25
25
|
import { banner } from '../dock/push.ts';
|
package/human/web.ts
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
// even a bug in a renderer cannot become a script, and no look can reach a
|
|
32
32
|
// server. The config crosses in a JSON script, which the policy allows.
|
|
33
33
|
import type { Handler } from '../harbor/http.ts';
|
|
34
|
-
import type { Hosted } from '
|
|
34
|
+
import type { Hosted } from 'nervur/harbor';
|
|
35
35
|
import { DOCK } from '../dock/index.ts';
|
|
36
36
|
import { publicKey } from '../harbor/ward.ts';
|
|
37
37
|
import { ANDROID, APPLE, association, type Apps } from './apps.ts';
|
|
@@ -106,7 +106,7 @@ const DESIGN = 'design';
|
|
|
106
106
|
const DESIGN_FILES: Record<string, string> = { 'tokens.css': 'text/css; charset=utf-8', 'fonts.css': 'text/css; charset=utf-8' };
|
|
107
107
|
const FONT = /^fonts\/[\w.-]+\.woff2$/;
|
|
108
108
|
|
|
109
|
-
// The origins
|
|
109
|
+
// The origins an app's webview speaks from: Tauri's on the desk,
|
|
110
110
|
// Capacitor's on iOS, and the plain loopback Android's webview uses. They
|
|
111
111
|
// are the only origins a world tells its config to, and the fetch is a
|
|
112
112
|
// plain GET asking for JSON, which no browser preflights.
|
|
@@ -158,7 +158,7 @@ export function webRoute(harbor: { wards: ReadonlyMap<string, Hosted> }, o: WebO
|
|
|
158
158
|
const fonts = worn.fonts ? `<link rel="stylesheet" href="${o.at.web}/${DESIGN}/fonts.css">` : '';
|
|
159
159
|
return `<style>${BARE}</style>${fonts}<link rel="stylesheet" href="${o.at.web}/${DESIGN}/tokens.css">`;
|
|
160
160
|
};
|
|
161
|
-
const shell = async (body: string) => `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>
|
|
161
|
+
const shell = async (body: string) => `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>nervur</title>
|
|
162
162
|
${await design()}
|
|
163
163
|
</head><body>${body}</body></html>`;
|
|
164
164
|
const esc = (v: string) => v.replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c] ?? c);
|
|
@@ -177,7 +177,7 @@ ${await design()}
|
|
|
177
177
|
const wards = async () => Object.fromEntries(await Promise.all([...harbor.wards].filter(([n]) => n !== DOCK).map(async ([n, h]) => [n, { pk: h.pk, public: shown(n) && (await publicKey(h)) !== null }] as const)));
|
|
178
178
|
const config = async (ward?: string, being?: string): Promise<Config> => ({ quo: o.at.quo, web: o.at.web, wards: await wards(), beings: await folder.serving(), ...(o.bell ? { bell: o.bell } : {}), ...(ward ? { ward } : {}), ...(being ? { being } : {}) });
|
|
179
179
|
const tab = async (ward?: string, being?: string) => {
|
|
180
|
-
return `<script id="
|
|
180
|
+
return `<script id="nervur" type="application/json">${JSON.stringify(await config(ward, being)).replace(/</g, '\\u003c')}</script><script type="module" src="${o.at.web}/tab.js"></script>`;
|
|
181
181
|
};
|
|
182
182
|
// The same config the tab is handed in its page, for an app that is not a
|
|
183
183
|
// tab: it learns a world by this one fetch and never loads the bundle,
|
|
@@ -220,7 +220,7 @@ ${await design()}
|
|
|
220
220
|
// doorbell serves no worker, and its pages register none.
|
|
221
221
|
if (rest === '/sw.js' && req.method === 'GET') {
|
|
222
222
|
if (!o.bell) return undefined;
|
|
223
|
-
const said = `self.
|
|
223
|
+
const said = `self.nervur=${JSON.stringify(await config()).replace(/</g, '\\u003c')};\n${o.code.worker}`;
|
|
224
224
|
return new Response(said, { headers: { 'content-type': 'text/javascript; charset=utf-8', 'cache-control': 'no-store', 'service-worker-allowed': '/' } });
|
|
225
225
|
}
|
|
226
226
|
// the design this world wears, when the harbor folder holds one: its
|