@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/beings/envoy.js
DELETED
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// The envoy base: what every envoy is and no envoy has alone. An envoy is
|
|
3
|
-
// a being of the org's standing in for a ward she does not run, an account
|
|
4
|
-
// at a thing that speaks no Quo, and the trunk's envoy chapter says the
|
|
5
|
-
// seven things she is. This is those seven as one class an author extends,
|
|
6
|
-
// so that a vendor's envoy is her asks out, her signature and her decoding,
|
|
7
|
-
// and nothing else.
|
|
8
|
-
//
|
|
9
|
-
// Two gates, one credential, one way out, one way in, one memory, one way
|
|
10
|
-
// back. `credential` and `forget` are the owner's; `deliver`, for an envoy
|
|
11
|
-
// that is called in, is the owner's too, and the daemon asks it with the
|
|
12
|
-
// vendor's raw bytes and headers. What an occupant may ask is the class's
|
|
13
|
-
// asks out, gated by `occupant` or by her own reading of the notes.
|
|
14
|
-
//
|
|
15
|
-
// Nothing here knows a vendor's name. The signature is `verify`, the
|
|
16
|
-
// vocabulary is `decode`, and what a delivery wakes is `wake`, each a
|
|
17
|
-
// method the class fills; the base keeps the discipline around them: the
|
|
18
|
-
// bytes checked before anything is parsed, the id kept bounded so a retry
|
|
19
|
-
// lands once, `{ ok }` answered before the wake goes out, a wake that meets
|
|
20
|
-
// silence written down and never retried.
|
|
21
|
-
import { Being, isSilence, isWord, wordOf } from 'nervur';
|
|
22
|
-
// The two gates. The owner is the ward's ask pointer, `{ id: 'OWNER' }`,
|
|
23
|
-
// which is how the daemon asks `deliver` and how the root places a
|
|
24
|
-
// credential; an occupant is anyone holding a standing at her.
|
|
25
|
-
export const owner = (_rec, asker) => asker.id === 'OWNER';
|
|
26
|
-
export const occupant = (rec) => rec !== undefined;
|
|
27
|
-
// The third gate: who may place what the vendor gave this account. WORLDS
|
|
28
|
-
// has placing an envoy as an ask on home, shown by the gate to the org's
|
|
29
|
-
// presences and to its model, with the box never logged into for it, so
|
|
30
|
-
// this cannot be the owner alone. It is the owner or an occupant whose
|
|
31
|
-
// note says she may, placed with her standing the way every other note is,
|
|
32
|
-
// and it is never a default: an org that marked nobody has the root's
|
|
33
|
-
// shell and nothing else, which is where this began.
|
|
34
|
-
export const places = (rec, asker) => asker.id === 'OWNER' || rec?.notes.credential === true;
|
|
35
|
-
// A credential as a form, for a class that wants one. `at` is never among
|
|
36
|
-
// the fields and cannot be: it is where this box sends the org's key, so a
|
|
37
|
-
// form that set it would be a form that points the box at anywhere and
|
|
38
|
-
// makes it fetch there with the account's own secret. Where a vendor
|
|
39
|
-
// answers is the class's, since the class is the thing that speaks that
|
|
40
|
-
// vendor, and only the owner may name another.
|
|
41
|
-
export const CREDENTIAL = (properties, required) => ({
|
|
42
|
-
description: 'what the vendor gave this account: kept in her cells, and never shown again',
|
|
43
|
-
input: { type: 'object', properties, required },
|
|
44
|
-
for: places,
|
|
45
|
-
});
|
|
46
|
-
const SEEN = 200;
|
|
47
|
-
const FRESH = 5 * 60_000;
|
|
48
|
-
export class Envoy extends Being {
|
|
49
|
-
static cells = { credential: null, about: {}, seen: [], unwoken: [] };
|
|
50
|
-
static asks = {
|
|
51
|
-
credential: { description: 'what the vendor gave the account: kept in her cells, never shown', input: { type: 'object' }, for: places },
|
|
52
|
-
forget: { description: 'forget the credential', input: { type: 'object' }, for: places },
|
|
53
|
-
};
|
|
54
|
-
// The one ask in, for an envoy the vendor calls: a class that is called
|
|
55
|
-
// in spreads it into her asks, `{ ...Envoy.asks, ...Envoy.IN, ...hers }`,
|
|
56
|
-
// and a one-way envoy shows no deliver at all.
|
|
57
|
-
static IN = {
|
|
58
|
-
deliver: { description: 'the vendor delivers: its raw bytes and headers, from the daemon as the owner', input: { type: 'object', properties: { body: { type: 'string' }, headers: { type: 'object' } }, required: ['body', 'headers'] }, for: owner },
|
|
59
|
-
};
|
|
60
|
-
// 1. Her credential is in her cells, and she gets it herself. The owner
|
|
61
|
-
// places what the vendor gave, values only; `check` is the class's word
|
|
62
|
-
// on what it must hold, a reason or null.
|
|
63
|
-
check(c) {
|
|
64
|
-
for (const [k, v] of Object.entries(c))
|
|
65
|
-
if (typeof v !== 'string' || v === '')
|
|
66
|
-
return `${k} is a non-empty string`;
|
|
67
|
-
return Object.keys(c).length ? null : 'a credential has at least one field';
|
|
68
|
-
}
|
|
69
|
-
// Where the vendor answers, as the class that speaks that vendor knows
|
|
70
|
-
// it. A class that leaves it null has an owner who must name one once.
|
|
71
|
-
static at = null;
|
|
72
|
-
credential(args, asker) {
|
|
73
|
-
// `at` is the one field a form may not carry. From anyone but the
|
|
74
|
-
// owner it is dropped rather than refused, since a human pasting a key
|
|
75
|
-
// has said nothing about it either way, and what stands is the one
|
|
76
|
-
// already placed or the class's own.
|
|
77
|
-
const { at: named, ...rest } = args;
|
|
78
|
-
const at = asker.id === 'OWNER' && typeof named === 'string' ? named : (this.held?.at ?? this.constructor.at);
|
|
79
|
-
const c = { ...rest, ...(typeof at === 'string' ? { at } : {}) };
|
|
80
|
-
const why = this.check(c);
|
|
81
|
-
if (why)
|
|
82
|
-
return { error: why };
|
|
83
|
-
this.cells.credential = c;
|
|
84
|
-
return { kept: true };
|
|
85
|
-
}
|
|
86
|
-
forget() {
|
|
87
|
-
this.cells.credential = null;
|
|
88
|
-
return { kept: false };
|
|
89
|
-
}
|
|
90
|
-
get held() {
|
|
91
|
-
return this.cells.credential ?? null;
|
|
92
|
-
}
|
|
93
|
-
// 2. Her asks out are the vendor's surface, narrowed: one fetch, from
|
|
94
|
-
// `at` in her credential with `key` as the bearer, the answer as values.
|
|
95
|
-
// The class reshapes what it heard and passes nothing through raw.
|
|
96
|
-
async out(path, init = {}) {
|
|
97
|
-
const c = this.held;
|
|
98
|
-
if (!c || typeof c.at !== 'string')
|
|
99
|
-
return { ok: false, status: 0, body: { error: 'no credential: the owner has not placed one' } };
|
|
100
|
-
let r;
|
|
101
|
-
try {
|
|
102
|
-
r = await fetch(`${c.at}${path}`, {
|
|
103
|
-
method: init.method ?? (init.body ? 'POST' : 'GET'),
|
|
104
|
-
headers: { ...(typeof c.key === 'string' ? { authorization: `Bearer ${c.key}` } : {}), ...(init.body ? { 'content-type': 'application/json' } : {}), ...(init.headers ?? {}) },
|
|
105
|
-
...(init.body ? { body: JSON.stringify(init.body) } : {}),
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
return { ok: false, status: 0, body: { error: 'the vendor is unreachable' } };
|
|
110
|
-
}
|
|
111
|
-
const v = (await r.json().catch(() => ({})));
|
|
112
|
-
const body = v !== null && typeof v === 'object' && !Array.isArray(v) ? v : {};
|
|
113
|
-
return { ok: r.ok, status: r.status, body };
|
|
114
|
-
}
|
|
115
|
-
// The vendor's no, as an error object in her own words.
|
|
116
|
-
refused(h) {
|
|
117
|
-
return h.status === 0 ? h.body : { error: `the vendor refused: ${h.status}${typeof h.body.message === 'string' ? ` ${h.body.message}` : ''}` };
|
|
118
|
-
}
|
|
119
|
-
// 4. Her cells are what the vendor told her: the map from the vendor's id
|
|
120
|
-
// to whom it is about, written when she asked out, read when called in.
|
|
121
|
-
remember(vendorId, by, more = {}) {
|
|
122
|
-
this.cells.about[vendorId] = { by, ...more };
|
|
123
|
-
}
|
|
124
|
-
recall(vendorId) {
|
|
125
|
-
const m = this.cells.about;
|
|
126
|
-
return Object.hasOwn(m, vendorId) ? m[vendorId] : undefined;
|
|
127
|
-
}
|
|
128
|
-
// 3. `deliver` is her one ask in. The daemon asks it as the owner with
|
|
129
|
-
// the raw body and the headers; an empty body is a redirect landing,
|
|
130
|
-
// the query in the headers under `:query`. The signature is checked
|
|
131
|
-
// before anything is parsed; a delivery she has seen is `{ ok }` at once
|
|
132
|
-
// and wakes nobody twice; and 6, `{ ok }` goes back before the wake.
|
|
133
|
-
async deliver(args) {
|
|
134
|
-
const body = typeof args.body === 'string' ? args.body : '';
|
|
135
|
-
const headers = (args.headers && typeof args.headers === 'object' && !Array.isArray(args.headers) ? args.headers : {});
|
|
136
|
-
if (body === '')
|
|
137
|
-
return this.landed(headers[':query'] ?? '', headers);
|
|
138
|
-
if (!(await this.verify(body, headers)))
|
|
139
|
-
return { error: 'bad signature' };
|
|
140
|
-
const d = this.decode(body, headers);
|
|
141
|
-
if ('error' in d)
|
|
142
|
-
return d;
|
|
143
|
-
const seen = this.cells.seen;
|
|
144
|
-
const mark = `${d.kind}:${d.id}`;
|
|
145
|
-
if (seen.includes(mark))
|
|
146
|
-
return { ok: true };
|
|
147
|
-
seen.push(mark);
|
|
148
|
-
while (seen.length > SEEN)
|
|
149
|
-
seen.shift();
|
|
150
|
-
void this.#wake(d);
|
|
151
|
-
return { ok: true };
|
|
152
|
-
}
|
|
153
|
-
// The class's word on the vendor's signature, over the bytes as sent.
|
|
154
|
-
verify(_body, _headers) {
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
// The class's reading of the vendor's vocabulary.
|
|
158
|
-
decode(_body, _headers) {
|
|
159
|
-
return { error: 'not called in' };
|
|
160
|
-
}
|
|
161
|
-
// Where a redirect lands: an OAuth code in the query, for a class that
|
|
162
|
-
// begins its account that way. The base takes nothing from it.
|
|
163
|
-
landed(_query, _headers) {
|
|
164
|
-
return { ok: true };
|
|
165
|
-
}
|
|
166
|
-
// A signature over text with a shared secret, hex, the shape most
|
|
167
|
-
// vendors sign in: here once so a class writes the vendor's framing only.
|
|
168
|
-
async hmac(secret, text) {
|
|
169
|
-
const key = await crypto.subtle.importKey('raw', new TextEncoder().encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
|
|
170
|
-
return [...new Uint8Array(await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(text)))].map((x) => x.toString(16).padStart(2, '0')).join('');
|
|
171
|
-
}
|
|
172
|
-
// Whether a vendor's timestamp is within five minutes of now, in seconds
|
|
173
|
-
// or in milliseconds, since vendors sign in either and a class should
|
|
174
|
-
// not have to know which.
|
|
175
|
-
fresh(ts) {
|
|
176
|
-
const t = Number(ts);
|
|
177
|
-
if (!Number.isFinite(t))
|
|
178
|
-
return false;
|
|
179
|
-
const ms = t < 1e11 ? t * 1000 : t;
|
|
180
|
-
return Math.abs(Date.now() - ms) <= FRESH;
|
|
181
|
-
}
|
|
182
|
-
// 5. Her way back is a standing placed like any other, `to:<id>` for the
|
|
183
|
-
// occupant a vendor id was remembered for, handed to her at the knock.
|
|
184
|
-
// A delivery is one ask on it, in her own words, said by `wake`; the
|
|
185
|
-
// being woken cannot tell it from a clock.
|
|
186
|
-
wake(_d, _about) {
|
|
187
|
-
return null;
|
|
188
|
-
}
|
|
189
|
-
async #wake(d) {
|
|
190
|
-
const about = d.about === null ? undefined : this.recall(d.about);
|
|
191
|
-
const w = this.wake(d, about);
|
|
192
|
-
if (!w)
|
|
193
|
-
return;
|
|
194
|
-
const unwoken = this.cells.unwoken;
|
|
195
|
-
// a wake the class shaped wrong is written down, never dropped on the floor
|
|
196
|
-
if (typeof w.method !== 'string' || !w.method || w.args === null || typeof w.args !== 'object')
|
|
197
|
-
return void unwoken.push({ id: d.id, kind: d.kind, why: 'a wake is { method, args }' });
|
|
198
|
-
const back = about ? this.standings[`to:${about.by}`] : undefined;
|
|
199
|
-
if (!back)
|
|
200
|
-
return void unwoken.push({ id: d.id, kind: d.kind, why: about ? `no way back to ${about.by}` : 'about nobody she remembers' });
|
|
201
|
-
const out = await back.ask(w.method, w.args);
|
|
202
|
-
if (isSilence(out) || out === undefined)
|
|
203
|
-
unwoken.push({ id: d.id, kind: d.kind, why: 'silence' });
|
|
204
|
-
else if (isWord(out))
|
|
205
|
-
unwoken.push({ id: d.id, kind: d.kind, why: wordOf(out) });
|
|
206
|
-
}
|
|
207
|
-
// What she could not wake, for the device's own code and a suite.
|
|
208
|
-
get unwoken() {
|
|
209
|
-
return this.cells.unwoken;
|
|
210
|
-
}
|
|
211
|
-
}
|
package/dist/dock/console.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { Carrier } from '../beings/carry.ts';
|
|
2
|
-
import type { Asker, OccupantRecord } from 'nervur';
|
|
3
|
-
export declare const CONSOLE = "console";
|
|
4
|
-
export declare class Console extends Carrier {
|
|
5
|
-
static carries(occupant: OccupantRecord | undefined, _asker: Asker): boolean;
|
|
6
|
-
}
|
package/dist/dock/console.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// The box, as one being. A device has no surface of its own, so a box that
|
|
3
|
-
// has joined no world has nothing to draw: the Console is that page and only
|
|
4
|
-
// that. She carries the faculties her harbor stood, showing each one's asks
|
|
5
|
-
// as her own, and the ordinary screen draws her exactly as it draws a
|
|
6
|
-
// world's user being, through one avatar holding one standing.
|
|
7
|
-
//
|
|
8
|
-
// She exists because a fresh install otherwise asks for location and
|
|
9
|
-
// notifications in its manifest and shows nothing that ever asks for them,
|
|
10
|
-
// which is a store reviewer's first question and a human's second.
|
|
11
|
-
//
|
|
12
|
-
// She carries for whoever the harbor's root let in, and for nobody else: the
|
|
13
|
-
// root is the box, and it invites the one avatar its own screen runs.
|
|
14
|
-
import { Carrier } from '../beings/carry.js';
|
|
15
|
-
export const CONSOLE = 'console';
|
|
16
|
-
export class Console extends Carrier {
|
|
17
|
-
static carries(occupant, _asker) {
|
|
18
|
-
return occupant !== undefined;
|
|
19
|
-
}
|
|
20
|
-
}
|
package/dist/dock/dialers.js
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// The box's dialers: `dialers`, one faculty of the dock ward, standing for
|
|
3
|
-
// the sockets this box holds open to other harbors' `quo.` routes. A Mac
|
|
4
|
-
// behind NAT, a phone on the mobile network, a droplet dialing home: each
|
|
5
|
-
// is a dialer, and what it dials is a row in her cells, placed once by the
|
|
6
|
-
// root with `keep` the way a schedule is placed on the clock and an agent
|
|
7
|
-
// on the agents faculty, in no file.
|
|
8
|
-
//
|
|
9
|
-
// A row is one URL, the `quo.` route of the harbor dialed. She holds the
|
|
10
|
-
// socket from her birth on, as every faculty holds what the box holds: one
|
|
11
|
-
// line per row, announcing this harbor's wards on open, binding the far
|
|
12
|
-
// side's pks, reconnecting with backoff when the line drops, and closed
|
|
13
|
-
// when the row is dropped or the box goes down. The dialer itself is the
|
|
14
|
-
// library's, written on the standard socket surface, so this faculty holds
|
|
15
|
-
// on every terrain that has a socket; the daemon hands her the harbor to
|
|
16
|
-
// dial for, as it hands the agents faculty how to run a row.
|
|
17
|
-
import { OWNER } from 'nervur';
|
|
18
|
-
import { dial } from 'nervur/harbor';
|
|
19
|
-
import { Faculty } from './faculty.js';
|
|
20
|
-
// The name the dock ward holds her under.
|
|
21
|
-
export const DIALERS = 'dialers';
|
|
22
|
-
// The root and nobody else: a line held open is the device's own to place.
|
|
23
|
-
const root = (_occ, asker) => asker.id === OWNER;
|
|
24
|
-
const URL_ = { type: 'object', properties: { url: { type: 'string' } }, required: ['url'] };
|
|
25
|
-
export class Dialers extends Faculty {
|
|
26
|
-
static cells = { watched: {}, minted: 0, dialers: {} };
|
|
27
|
-
static asks = {
|
|
28
|
-
keep: { description: 'hold a socket to that quo. route, from now and from every boot, until it is dropped', input: URL_, for: root },
|
|
29
|
-
drop: { description: 'close the socket to that route and forget it', input: URL_, for: root },
|
|
30
|
-
list: { description: 'every route she dials, and whether the line is open now', input: { type: 'object' }, for: root },
|
|
31
|
-
};
|
|
32
|
-
harbor;
|
|
33
|
-
open = new Map();
|
|
34
|
-
get rows() {
|
|
35
|
-
return this.cells.dialers;
|
|
36
|
-
}
|
|
37
|
-
// Every row dialed, once the daemon has handed the harbor to dial for.
|
|
38
|
-
start(harbor) {
|
|
39
|
-
this.harbor = harbor;
|
|
40
|
-
for (const row of Object.values(this.rows))
|
|
41
|
-
this.#dial(row.url);
|
|
42
|
-
}
|
|
43
|
-
#dial(url) {
|
|
44
|
-
if (!this.harbor || this.open.has(url))
|
|
45
|
-
return;
|
|
46
|
-
this.open.set(url, dial(this.harbor, url));
|
|
47
|
-
}
|
|
48
|
-
keep(args) {
|
|
49
|
-
const url = args.url;
|
|
50
|
-
if (typeof url !== 'string' || !/^https?:\/\/\S+$/.test(url))
|
|
51
|
-
return { error: 'url is the quo. route of the harbor dialed, over http or https' };
|
|
52
|
-
const clean = url.replace(/\/$/, '');
|
|
53
|
-
this.rows[clean] = { url: clean };
|
|
54
|
-
this.#dial(clean);
|
|
55
|
-
return { kept: clean };
|
|
56
|
-
}
|
|
57
|
-
drop(args) {
|
|
58
|
-
const url = typeof args.url === 'string' ? args.url.replace(/\/$/, '') : '';
|
|
59
|
-
if (!this.rows[url])
|
|
60
|
-
return { error: 'no such route' };
|
|
61
|
-
this.open.get(url)?.close();
|
|
62
|
-
this.open.delete(url);
|
|
63
|
-
delete this.rows[url];
|
|
64
|
-
return { dropped: url };
|
|
65
|
-
}
|
|
66
|
-
list() {
|
|
67
|
-
return { dialers: Object.keys(this.rows).map((url) => ({ url, open: this.open.get(url)?.socket !== null && this.open.has(url) })) };
|
|
68
|
-
}
|
|
69
|
-
// The device puts the box down: every line closes, the rows stay.
|
|
70
|
-
close() {
|
|
71
|
-
for (const d of this.open.values())
|
|
72
|
-
d.close();
|
|
73
|
-
this.open.clear();
|
|
74
|
-
}
|
|
75
|
-
}
|
package/dist/dock/faculty.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Being } from 'nervur';
|
|
2
|
-
import type { Asker, JsonObject } from 'nervur';
|
|
3
|
-
export type Watched = {
|
|
4
|
-
by: string;
|
|
5
|
-
method: string;
|
|
6
|
-
args: JsonObject;
|
|
7
|
-
};
|
|
8
|
-
export type Woke = {
|
|
9
|
-
id: string;
|
|
10
|
-
by: string;
|
|
11
|
-
out: unknown;
|
|
12
|
-
};
|
|
13
|
-
export declare class Faculty extends Being {
|
|
14
|
-
static cells: JsonObject;
|
|
15
|
-
watch(args: JsonObject, asker: Asker): Promise<JsonObject>;
|
|
16
|
-
protected welcomed(_id: string): Promise<void>;
|
|
17
|
-
protected woke(round?: (w: Watched) => JsonObject, only?: string): Promise<Woke[] | null>;
|
|
18
|
-
get watching(): Record<string, Watched>;
|
|
19
|
-
}
|
|
20
|
-
export declare const settled: () => Promise<void>;
|
|
21
|
-
export declare function join(b: Being, name: string, watch?: {
|
|
22
|
-
method: string;
|
|
23
|
-
args?: JsonObject;
|
|
24
|
-
}, id?: string): Promise<string | null>;
|
package/dist/dock/faculty.js
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// A faculty: one being of the dock ward, standing for one thing the box can
|
|
3
|
-
// do. She is a being and nothing else, so what is here is not a second kind
|
|
4
|
-
// of object but the two moves every faculty shares.
|
|
5
|
-
//
|
|
6
|
-
// Out: whoever holds a standing at her asks her methods, and the occupant's
|
|
7
|
-
// notes say what that caller is, a prefix on a store, an account at a
|
|
8
|
-
// vendor. Her own cells say what the thing is.
|
|
9
|
-
//
|
|
10
|
-
// Back: `watch` is the one subscribe verb every faculty has. A being who
|
|
11
|
-
// wants waking mints an invitation and hands it over, this takes it as a
|
|
12
|
-
// standing, and from then on she is asked at her own door as the occupant
|
|
13
|
-
// she named. `occupants.remove` on her side is the whole of unsubscribe: the
|
|
14
|
-
// next wake hears `removed` and the row goes.
|
|
15
|
-
//
|
|
16
|
-
// She holds what the box holds and begins holding it at birth: the
|
|
17
|
-
// connection, the interval, the worker, the route are opened in her
|
|
18
|
-
// constructor, and she is born whether or not the thing is reachable,
|
|
19
|
-
// answering an error object while it is not.
|
|
20
|
-
import { Being, isInvitation, isSilence, isWord, wordOf } from 'nervur';
|
|
21
|
-
export class Faculty extends Being {
|
|
22
|
-
static cells = { watched: {}, minted: 0 };
|
|
23
|
-
// Someone wants waking. She hands the invitation she minted and says what
|
|
24
|
-
// to ask her; this knocks it, takes it under an id of this being's own,
|
|
25
|
-
// and files it. The id never crosses: it is this side's name for the
|
|
26
|
-
// relation, and the caller's name for the same relation is her own.
|
|
27
|
-
//
|
|
28
|
-
// The empty ask is the knock, because every being answers one and asking
|
|
29
|
-
// for a named ask would make every subscriber owe a method she does not
|
|
30
|
-
// otherwise need.
|
|
31
|
-
async watch(args, asker) {
|
|
32
|
-
const inv = args.invitation;
|
|
33
|
-
if (!isInvitation(inv) || typeof args.method !== 'string')
|
|
34
|
-
return { error: 'an invitation and a method' };
|
|
35
|
-
const extra = args.args;
|
|
36
|
-
if (extra !== undefined && (extra === null || typeof extra !== 'object' || Array.isArray(extra)))
|
|
37
|
-
return { error: 'args is one object' };
|
|
38
|
-
const out = await this.knock(inv);
|
|
39
|
-
if (isSilence(out) || isWord(out))
|
|
40
|
-
return { error: 'no way back' };
|
|
41
|
-
const cells = this.cells;
|
|
42
|
-
const id = await this.take(`wake:${(cells.minted += 1)}`, inv);
|
|
43
|
-
if (id === null)
|
|
44
|
-
return { error: 'not taken' };
|
|
45
|
-
cells.watched[id] = { by: asker.id ?? '', method: args.method, args: extra ?? {} };
|
|
46
|
-
await this.welcomed(id);
|
|
47
|
-
return { watching: id };
|
|
48
|
-
}
|
|
49
|
-
// Somebody new is filed, and the answer to her `watch` waits for this. A
|
|
50
|
-
// faculty that owes a new subscriber something at once says it here: the
|
|
51
|
-
// timer wakes her, learns when she is next due and arms the box for it, so
|
|
52
|
-
// a being born long after the box was up is not waiting for a round nobody
|
|
53
|
-
// scheduled. Most faculties owe nothing, and this is why they say nothing.
|
|
54
|
-
async welcomed(_id) { }
|
|
55
|
-
// One round of waking. Each subscriber is asked what she asked to be
|
|
56
|
-
// asked, with whatever this round adds. A subscriber who removed the
|
|
57
|
-
// occupant says `removed` once, and her row goes with the standing; there
|
|
58
|
-
// is nothing to retry and nothing to remember.
|
|
59
|
-
//
|
|
60
|
-
// `only` is one subscriber of the round's own choosing, named by this
|
|
61
|
-
// being's own id for the relation, and it is the same round down to one
|
|
62
|
-
// row: a faculty that wakes somebody just filed learns exactly what a full
|
|
63
|
-
// round would have learned about her.
|
|
64
|
-
//
|
|
65
|
-
// `dropped` is this being herself: her ward took her out, so the standings
|
|
66
|
-
// she holds reach nobody. Null says so, and whoever holds the interval puts
|
|
67
|
-
// it down rather than waking an empty room for as long as the box is up.
|
|
68
|
-
async woke(round = (w) => w.args, only) {
|
|
69
|
-
const cells = this.cells;
|
|
70
|
-
const out = [];
|
|
71
|
-
for (const [id, w] of Object.entries(cells.watched)) {
|
|
72
|
-
if (only !== undefined && id !== only)
|
|
73
|
-
continue;
|
|
74
|
-
const said = await this.standings[id]?.ask(w.method, round(w));
|
|
75
|
-
if (said === undefined || (isWord(said) && wordOf(said) === 'dropped'))
|
|
76
|
-
return null;
|
|
77
|
-
if (isWord(said) && wordOf(said) === 'removed') {
|
|
78
|
-
this.standings.remove(id);
|
|
79
|
-
delete cells.watched[id];
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
out.push({ id, by: w.by, out: said });
|
|
83
|
-
}
|
|
84
|
-
return out;
|
|
85
|
-
}
|
|
86
|
-
// Who is waiting, by this being's own id for the relation. For a device's
|
|
87
|
-
// own code and for a suite; it crosses no door.
|
|
88
|
-
get watching() {
|
|
89
|
-
return this.cells.watched;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
// The three moves a being makes at every birth to hold what her box lends.
|
|
93
|
-
// A standing points at a being and not at a box, so one she wakes up holding
|
|
94
|
-
// names a being on the box she was on when it was made; a restart and a
|
|
95
|
-
// migration are the same silent event to her, so she does these again every
|
|
96
|
-
// time she is constructed and is always pointed at the box she is on.
|
|
97
|
-
//
|
|
98
|
-
// `watch` says she wants waking too: her ward mints the occupant, the
|
|
99
|
-
// faculty takes the standing it makes, and from then on the wake arrives at
|
|
100
|
-
// her door under the id she chose.
|
|
101
|
-
// Every join in flight on this box. A being takes what her box lends at her
|
|
102
|
-
// birth, and birth is synchronous while taking a standing is not, so a
|
|
103
|
-
// harbor that answered "up" before they landed would be a box whose first
|
|
104
|
-
// tick woke nobody and whose first ring reached no platform. The terrain
|
|
105
|
-
// waits on this once, after its wards are hosted; nothing else reads it, and
|
|
106
|
-
// a join that fails leaves nothing behind but a being who asks again.
|
|
107
|
-
const flight = new Set();
|
|
108
|
-
export const settled = async () => {
|
|
109
|
-
while (flight.size) {
|
|
110
|
-
const now = [...flight];
|
|
111
|
-
await Promise.allSettled(now);
|
|
112
|
-
for (const p of now)
|
|
113
|
-
flight.delete(p);
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
export function join(b, name, watch, id = name) {
|
|
117
|
-
const p = joining(b, name, watch, id);
|
|
118
|
-
flight.add(p);
|
|
119
|
-
void p.catch(() => { });
|
|
120
|
-
return p;
|
|
121
|
-
}
|
|
122
|
-
async function joining(b, name, watch, id) {
|
|
123
|
-
// One turn, before anything is asked. A being is called at her door and
|
|
124
|
-
// holds her stance from her first line, but her ward sets that door after
|
|
125
|
-
// her constructor returns, so a stance call made inside it reaches a being
|
|
126
|
-
// her ward does not hold yet and is answered as one taken out. Every
|
|
127
|
-
// faculty relation is made at birth, so the wait belongs here rather than
|
|
128
|
-
// in each of them.
|
|
129
|
-
await Promise.resolve();
|
|
130
|
-
b.standings.remove(id);
|
|
131
|
-
b.occupants.remove(`${id}:wake`);
|
|
132
|
-
const got = await b.lend(name, id);
|
|
133
|
-
if (got === null)
|
|
134
|
-
return null;
|
|
135
|
-
if (!watch)
|
|
136
|
-
return got;
|
|
137
|
-
const back = await b.invite(`${id}:wake`);
|
|
138
|
-
if (!back)
|
|
139
|
-
return got;
|
|
140
|
-
await b.standings[id]?.ask('watch', { invitation: back, method: watch.method, ...(watch.args ? { args: watch.args } : {}) });
|
|
141
|
-
return got;
|
|
142
|
-
}
|
package/dist/dock/grants.js
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// The box's grants: `grants`, one faculty of the dock ward. A bearer to an
|
|
3
|
-
// identity in a world, honoured on every route alike. A route says the
|
|
4
|
-
// grammar a caller speaks, forms, tools or JSON, and a grant says who the
|
|
5
|
-
// caller is; no route holds a table of its own. She spans every world the
|
|
6
|
-
// box hosts, and a grant maps a token to an identity and nothing else: the
|
|
7
|
-
// credential is the invitation the avatar knocked with, spent once, and a
|
|
8
|
-
// grant only remembers which avatar a client speaks through. No secret of
|
|
9
|
-
// Quo's is ever here.
|
|
10
|
-
//
|
|
11
|
-
// Her tokens are her cells, kept by the dock ward's partition like every
|
|
12
|
-
// faculty's and by no file of her own, so a box has one place its state is
|
|
13
|
-
// and the harbor's one secret wraps them. Issuing, refreshing and revoking
|
|
14
|
-
// are the routes' to call on her in this process, as the daemon mints a
|
|
15
|
-
// nonce on `local`: none is an ask, none crosses a door, and she answers
|
|
16
|
-
// nothing at hers.
|
|
17
|
-
//
|
|
18
|
-
// A grant is issued by whoever finished a way in: the OAuth exchange on the
|
|
19
|
-
// model side, or the api route trading an invitation straight for tokens.
|
|
20
|
-
// An access token lives an hour and a refresh token thirty days, and
|
|
21
|
-
// refresh rotates. Revocation is the user being removing the occupant,
|
|
22
|
-
// and the route that hears `removed` asks for the grants to go with it.
|
|
23
|
-
import { Faculty } from './faculty.js';
|
|
24
|
-
// The name the dock ward holds her under.
|
|
25
|
-
export const GRANTS = 'grants';
|
|
26
|
-
export const ACCESS_TTL = 60 * 60 * 1000; // an access token, one hour
|
|
27
|
-
export const REFRESH_TTL = 30 * 24 * 60 * 60 * 1000; // a refresh token, thirty days
|
|
28
|
-
// A token is a string the far side offers, and a bare lookup would find
|
|
29
|
-
// `__proto__` and hand back an object with no identity. Own keys only.
|
|
30
|
-
const own = (rec, key) => (Object.hasOwn(rec, key) ? rec[key] : undefined);
|
|
31
|
-
// Thirty-two random bytes as base64url, from the web crypto and the base64
|
|
32
|
-
// every runtime has, so nothing of node stands in a file a tab bundles or a
|
|
33
|
-
// worker imports. `Buffer` is not among those: a worker has one only when a
|
|
34
|
-
// deploy asks for node's shims, and the box's grants are the same code on
|
|
35
|
-
// every terrain.
|
|
36
|
-
const token = () => {
|
|
37
|
-
const bytes = globalThis.crypto.getRandomValues(new Uint8Array(32));
|
|
38
|
-
let binary = '';
|
|
39
|
-
for (const b of bytes)
|
|
40
|
-
binary += String.fromCharCode(b);
|
|
41
|
-
return btoa(binary).replaceAll('+', '-').replaceAll('/', '_').replaceAll('=', '');
|
|
42
|
-
};
|
|
43
|
-
export class Grants extends Faculty {
|
|
44
|
-
static cells = { ...Faculty.cells, access: {}, refresh: {} };
|
|
45
|
-
static asks = {};
|
|
46
|
-
// The ward's save, set by whoever holds her ward: a token issued is a
|
|
47
|
-
// cell written, and the routes answer with a token the partition keeps.
|
|
48
|
-
persist = async () => { };
|
|
49
|
-
// The clock, a suite's to move.
|
|
50
|
-
now = () => Date.now();
|
|
51
|
-
get kept() {
|
|
52
|
-
return this.cells;
|
|
53
|
-
}
|
|
54
|
-
async issue(identity, ward, client) {
|
|
55
|
-
const access_token = token(), refresh_token = token();
|
|
56
|
-
this.kept.access[access_token] = { identity, ward, client, exp: this.now() + ACCESS_TTL };
|
|
57
|
-
this.kept.refresh[refresh_token] = { identity, ward, client, exp: this.now() + REFRESH_TTL };
|
|
58
|
-
this.sweep();
|
|
59
|
-
await this.persist();
|
|
60
|
-
return { access_token, token_type: 'Bearer', expires_in: ACCESS_TTL / 1000, refresh_token, scope: 'nervur' };
|
|
61
|
-
}
|
|
62
|
-
// Rotated: the old one is gone with the new one's birth. Null is a token
|
|
63
|
-
// nobody issued, or one that died.
|
|
64
|
-
async refresh(refresh_token) {
|
|
65
|
-
const r = own(this.kept.refresh, refresh_token);
|
|
66
|
-
if (!r || r.exp < this.now())
|
|
67
|
-
return null;
|
|
68
|
-
delete this.kept.refresh[refresh_token];
|
|
69
|
-
return this.issue(r.identity, r.ward, r.client);
|
|
70
|
-
}
|
|
71
|
-
// The bearer on a request, to an identity in a world. Null is a stranger,
|
|
72
|
-
// or a token that died; a route tells the two apart by whether the
|
|
73
|
-
// request offered one at all.
|
|
74
|
-
bearer(req) {
|
|
75
|
-
const g = own(this.kept.access, offered(req));
|
|
76
|
-
return g && g.exp >= this.now() && typeof g.identity === 'string' ? { identity: g.identity, ward: g.ward } : null;
|
|
77
|
-
}
|
|
78
|
-
// Every grant an identity holds in a world, gone: the box's half of
|
|
79
|
-
// revocation. The other half is the user being removing the occupant.
|
|
80
|
-
async revoke(identity, ward) {
|
|
81
|
-
for (const k of ['access', 'refresh'])
|
|
82
|
-
for (const [t, g] of Object.entries(this.kept[k]))
|
|
83
|
-
if (g.identity === identity && g.ward === ward)
|
|
84
|
-
delete this.kept[k][t];
|
|
85
|
-
await this.persist();
|
|
86
|
-
}
|
|
87
|
-
sweep() {
|
|
88
|
-
const now = this.now();
|
|
89
|
-
for (const k of ['access', 'refresh'])
|
|
90
|
-
for (const [t, g] of Object.entries(this.kept[k]))
|
|
91
|
-
if (!(g.exp >= now))
|
|
92
|
-
delete this.kept[k][t];
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
// What a request offered as its bearer, or nothing.
|
|
96
|
-
export const offered = (req) => {
|
|
97
|
-
const h = req.headers.get('authorization') ?? '';
|
|
98
|
-
return h.startsWith('Bearer ') ? h.slice(7) : '';
|
|
99
|
-
};
|
package/dist/dock/index.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { Harbor, Lend } from 'nervur/harbor';
|
|
2
|
-
import { Faculty } from './faculty.ts';
|
|
3
|
-
import { Console } from './console.ts';
|
|
4
|
-
import { Local } from './local.ts';
|
|
5
|
-
import { Location } from './location.ts';
|
|
6
|
-
import { Notifications } from './notifications.ts';
|
|
7
|
-
import { Push } from './push.ts';
|
|
8
|
-
import { Timer } from './timer.ts';
|
|
9
|
-
export { Console, CONSOLE } from './console.ts';
|
|
10
|
-
export { Faculty, join, settled, type Watched, type Woke } from './faculty.ts';
|
|
11
|
-
export { Local, LOCAL } from './local.ts';
|
|
12
|
-
export { Location, type Where } from './location.ts';
|
|
13
|
-
export { Notifications } from './notifications.ts';
|
|
14
|
-
export { Push, isToken, bellOf, banner, sealBanner, SEAL, type Token, type Ring, type Line } from './push.ts';
|
|
15
|
-
export { Timer } from './timer.ts';
|
|
16
|
-
export { webPush, mintVapid, publicOf, type Vapid } from './webpush.ts';
|
|
17
|
-
export { apnsPush, pkcs8, HOSTS, type Apns } from './apns.ts';
|
|
18
|
-
export { fcmPush, isAccount, DOORS, type Account, type Doors } from './fcm.ts';
|
|
19
|
-
export { handedTo, ringing, routed } from './service.ts';
|
|
20
|
-
export declare const LOCATION = "location";
|
|
21
|
-
export declare const NOTIFICATIONS = "notifications";
|
|
22
|
-
export declare const PUSH = "push";
|
|
23
|
-
export declare const TIMER = "timer";
|
|
24
|
-
export declare const FACULTIES: Record<string, string>;
|
|
25
|
-
export declare const FACULTY_CLASSES: {
|
|
26
|
-
Console: typeof Console;
|
|
27
|
-
Local: typeof Local;
|
|
28
|
-
Location: typeof Location;
|
|
29
|
-
Notifications: typeof Notifications;
|
|
30
|
-
Push: typeof Push;
|
|
31
|
-
Timer: typeof Timer;
|
|
32
|
-
};
|
|
33
|
-
export declare const DOCK = "dock";
|
|
34
|
-
export declare function stand(harbor: Harbor, lent?: Record<string, string>): Promise<Lend>;
|
|
35
|
-
export type Rooted = {
|
|
36
|
-
ask(method?: string, args?: Record<string, unknown>): Promise<unknown>;
|
|
37
|
-
save?(): Promise<void>;
|
|
38
|
-
};
|
|
39
|
-
export declare function standOn(ward: Rooted, lent?: Record<string, string>): Promise<Lend>;
|
|
40
|
-
export declare function lending(ward: Rooted): Lend;
|
|
41
|
-
export declare function facultyOf<F extends Faculty>(harbor: Harbor, name: string): F | undefined;
|