@argentic/chest-sdk 0.4.0 → 0.5.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 +508 -80
- package/client/index.ts +11 -7
- package/client/src/api.ts +19 -18
- package/client/src/database.ts +6 -1
- package/client/src/errors.ts +50 -0
- package/client/src/eventrules.ts +117 -0
- package/client/src/events.ts +181 -39
- package/client/src/files.ts +37 -7
- package/client/src/member.ts +15 -9
- package/client/src/members.ts +34 -16
- package/client/src/notifications.ts +84 -27
- package/client/src/realtime-client.ts +516 -0
- package/client/src/realtime.ts +118 -0
- package/client/src/sealed.ts +158 -0
- package/client/src/signed.ts +8 -4
- package/client/src/testing-realtime.ts +361 -0
- package/client/src/testing.ts +391 -94
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -7
- package/dist/index.js.map +1 -1
- package/dist/src/api.d.ts +2 -1
- package/dist/src/api.d.ts.map +1 -1
- package/dist/src/api.js +18 -16
- package/dist/src/api.js.map +1 -1
- package/dist/src/database.d.ts.map +1 -1
- package/dist/src/database.js +5 -1
- package/dist/src/database.js.map +1 -1
- package/dist/src/errors.d.ts +18 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +44 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/eventrules.d.ts +23 -0
- package/dist/src/eventrules.d.ts.map +1 -0
- package/dist/src/eventrules.js +107 -0
- package/dist/src/eventrules.js.map +1 -0
- package/dist/src/events.d.ts +31 -6
- package/dist/src/events.d.ts.map +1 -1
- package/dist/src/events.js +130 -26
- package/dist/src/events.js.map +1 -1
- package/dist/src/files.d.ts +1 -0
- package/dist/src/files.d.ts.map +1 -1
- package/dist/src/files.js +34 -3
- package/dist/src/files.js.map +1 -1
- package/dist/src/member.d.ts +1 -1
- package/dist/src/member.d.ts.map +1 -1
- package/dist/src/member.js +9 -6
- package/dist/src/member.js.map +1 -1
- package/dist/src/members.d.ts +9 -2
- package/dist/src/members.d.ts.map +1 -1
- package/dist/src/members.js +29 -13
- package/dist/src/members.js.map +1 -1
- package/dist/src/notifications.d.ts +12 -1
- package/dist/src/notifications.d.ts.map +1 -1
- package/dist/src/notifications.js +60 -19
- package/dist/src/notifications.js.map +1 -1
- package/dist/src/realtime-client.d.ts +45 -0
- package/dist/src/realtime-client.d.ts.map +1 -0
- package/dist/src/realtime-client.js +453 -0
- package/dist/src/realtime-client.js.map +1 -0
- package/dist/src/realtime.d.ts +22 -0
- package/dist/src/realtime.d.ts.map +1 -0
- package/dist/src/realtime.js +99 -0
- package/dist/src/realtime.js.map +1 -0
- package/dist/src/sealed.d.ts +20 -0
- package/dist/src/sealed.d.ts.map +1 -0
- package/dist/src/sealed.js +121 -0
- package/dist/src/sealed.js.map +1 -0
- package/dist/src/signed.d.ts.map +1 -1
- package/dist/src/signed.js +6 -2
- package/dist/src/signed.js.map +1 -1
- package/dist/src/testing-realtime.d.ts +54 -0
- package/dist/src/testing-realtime.d.ts.map +1 -0
- package/dist/src/testing-realtime.js +376 -0
- package/dist/src/testing-realtime.js.map +1 -0
- package/dist/src/testing.d.ts +40 -3
- package/dist/src/testing.d.ts.map +1 -1
- package/dist/src/testing.js +368 -81
- package/dist/src/testing.js.map +1 -1
- package/package.json +23 -4
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
// The browser's side of a tool's live updates: the one module of the SDK
|
|
2
|
+
// that runs in a page (no node: import, nothing read from the environment).
|
|
3
|
+
// A page of the tool's private part (/chest) connects to the Chest on its
|
|
4
|
+
// own host — the member's session is the identity, no token —, joins the
|
|
5
|
+
// channels its tool declares and hears what reaches them: the rows of its
|
|
6
|
+
// feeds as they are committed and the tool's events (on), the other
|
|
7
|
+
// members' ephemeral messages (peers, never mixed with the Chest's), who is
|
|
8
|
+
// present. The connection is the Chest's: the tool may sleep meanwhile.
|
|
9
|
+
//
|
|
10
|
+
// import { connect } from "@argentic/chest-sdk/realtime/client";
|
|
11
|
+
// const live = connect();
|
|
12
|
+
// const room = live.channel("room:42");
|
|
13
|
+
// room.on("messages.insert", row => show(row));
|
|
14
|
+
// room.onJoined(({ replayed }) => replayed || refetchAfter(lastId)); // joined: fetch, unless what was missed came again
|
|
15
|
+
// room.onResync(() => refetchAfter(lastId)); // what was missed is not all kept: ask the tool
|
|
16
|
+
// room.peers.on("typing", (_, from) => showTyping(from));
|
|
17
|
+
// room.peers.send("typing");
|
|
18
|
+
// room.presence.track({ active: true });
|
|
19
|
+
// room.presence.on(list => showOnline(list));
|
|
20
|
+
// live.focus("room:42"); // the conversation on screen: the tool notifies those not watching it
|
|
21
|
+
// live.on("closed", reason => reason === "access_removed" ? showAccessRemoved() : location.reload());
|
|
22
|
+
//
|
|
23
|
+
// It reconnects by itself, unseen: a cut is told (status false) only once
|
|
24
|
+
// it lasts 3 s; it tries again 0.5 s to 30 s apart — at once when the page
|
|
25
|
+
// comes back to the foreground, from the cache or to the network, never
|
|
26
|
+
// while the browser is offline (going offline drops the connection at
|
|
27
|
+
// once), and no sooner than the Chest asks when it is full —, joins its channels again with where each stood, and the Chest
|
|
28
|
+
// gives what was missed however long the page was away: the tool's events
|
|
29
|
+
// of the last 2 minutes, the feeds' rows of the last 7 days — or says
|
|
30
|
+
// resync. A join the Chest has no room for is tried again with the same
|
|
31
|
+
// backoff, unseen. While connected it renews the member's session every 5
|
|
32
|
+
// minutes.
|
|
33
|
+
// It stops for good when access was removed (closed "access_removed") or
|
|
34
|
+
// the session ended (closed "signed_out": a reload signs in again, silently
|
|
35
|
+
// while the provider's session lasts). Content is the tool's: render it as
|
|
36
|
+
// text, never as HTML.
|
|
37
|
+
// The subprotocol of the Chest's realtime, and where it is.
|
|
38
|
+
const protocol = "chest-realtime.v1";
|
|
39
|
+
const path = "/_chest/realtime";
|
|
40
|
+
// The rhythm: the backoff's first and last delay; the ping that finds a
|
|
41
|
+
// dead network, how long its answer may take, and how long when the page
|
|
42
|
+
// wakes; how often the session is renewed; how long a cut stays untold.
|
|
43
|
+
const firstDelay = 500, lastDelay = 30000, pingEvery = 25000, pingWait = 10000, wakeWait = 5000, renewEvery = 300000, quietFor = 3000;
|
|
44
|
+
// The grammar of a member's message: 1 to 64 of a-z 0-9 _ -, never a dot —
|
|
45
|
+
// dotted names are the tool's and the feeds' ("messages.insert",
|
|
46
|
+
// "rooms.changed"), so a member never speaks as them.
|
|
47
|
+
export const peerEventPattern = /^[a-z0-9_-]{1,64}$/u;
|
|
48
|
+
// listen adds a listener to a set, and returns what removes it.
|
|
49
|
+
function listen(set, listener) {
|
|
50
|
+
set.add(listener);
|
|
51
|
+
return () => { set.delete(listener); };
|
|
52
|
+
}
|
|
53
|
+
// listenTo adds a listener of one event.
|
|
54
|
+
function listenTo(map, event, listener) {
|
|
55
|
+
let set = map.get(event);
|
|
56
|
+
if (!set)
|
|
57
|
+
map.set(event, set = new Set());
|
|
58
|
+
return listen(set, listener);
|
|
59
|
+
}
|
|
60
|
+
// connect connects the page to the Chest — on its own host, or url (a
|
|
61
|
+
// test's) —, and stays connected until closed.
|
|
62
|
+
export function connect(options = {}) {
|
|
63
|
+
const page = globalThis;
|
|
64
|
+
const url = options.url ?? (page.location ? (page.location.protocol === "https:" ? "wss://" : "ws://") + page.location.host + path : "");
|
|
65
|
+
if (!url)
|
|
66
|
+
throw new Error("connect runs in a page of the tool, or is given a url");
|
|
67
|
+
const channels = new Map();
|
|
68
|
+
const direct = new Set();
|
|
69
|
+
const status = new Set();
|
|
70
|
+
const closed = new Set();
|
|
71
|
+
const answers = new Map();
|
|
72
|
+
// connected: the Chest said hello on the socket; asking: a question before
|
|
73
|
+
// connecting is on its way; told: the status the page was last told;
|
|
74
|
+
// focused: the channel the page has on screen, focusSent what the Chest
|
|
75
|
+
// was last told of it on this connection ("" none).
|
|
76
|
+
let socket, ref = 0, attempts = 0, ended = false, connected = false, asking = false;
|
|
77
|
+
let epoch, member, told, focused = null, focusSent = "";
|
|
78
|
+
let timer, quiet, silence;
|
|
79
|
+
let pinger, renewer;
|
|
80
|
+
const emit = (listeners, ...args) => {
|
|
81
|
+
for (const listener of [...listeners]) {
|
|
82
|
+
try {
|
|
83
|
+
listener(...args);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
setTimeout(() => { throw error; });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const fire = (listeners, event, ...args) => {
|
|
91
|
+
const set = listeners.get(event);
|
|
92
|
+
if (set)
|
|
93
|
+
emit(set, ...args);
|
|
94
|
+
};
|
|
95
|
+
const tell = (up) => {
|
|
96
|
+
told = up;
|
|
97
|
+
emit(status, up);
|
|
98
|
+
};
|
|
99
|
+
const presenceChanged = (ch) => emit(ch.presenceListeners, [...ch.present].map(([id, state]) => ({ id, state })));
|
|
100
|
+
const write = (message, answer) => {
|
|
101
|
+
if (!socket || socket.readyState !== 1)
|
|
102
|
+
return false;
|
|
103
|
+
if (answer) {
|
|
104
|
+
ref = ref % 0xffffffff + 1;
|
|
105
|
+
message["ref"] = ref;
|
|
106
|
+
answers.set(ref, answer);
|
|
107
|
+
}
|
|
108
|
+
socket.send(JSON.stringify(message));
|
|
109
|
+
return true;
|
|
110
|
+
};
|
|
111
|
+
// shown: the page is in the foreground (always, without a document).
|
|
112
|
+
const shown = () => (page.document?.visibilityState ?? "visible") === "visible";
|
|
113
|
+
// tellFocus tells the Chest the channel the page has on screen: the one
|
|
114
|
+
// focused once joined and while shown, none otherwise — only when it
|
|
115
|
+
// changes.
|
|
116
|
+
const tellFocus = () => {
|
|
117
|
+
const ch = focused === null ? undefined : channels.get(focused);
|
|
118
|
+
const now = ch?.joined && shown() ? ch.name : "";
|
|
119
|
+
if (now !== focusSent && write({ op: "focus", ch: now }, () => { }))
|
|
120
|
+
focusSent = now;
|
|
121
|
+
};
|
|
122
|
+
// join joins a channel — again, from where it stood: the Chest gives
|
|
123
|
+
// what was missed, then what comes; or says resync. A Chest without room
|
|
124
|
+
// for it is asked again after the backoff, unseen.
|
|
125
|
+
const join = (ch) => {
|
|
126
|
+
const since = ch.epoch === undefined ? undefined : { epoch: ch.epoch, seq: ch.seq, ...(ch.pos > 0 ? { pos: ch.pos } : {}) };
|
|
127
|
+
write({ op: "join", ch: ch.name, ...(since ? { since } : {}) }, answer => {
|
|
128
|
+
if (answer["code"] === "full") {
|
|
129
|
+
ch.retry = setTimeout(() => {
|
|
130
|
+
ch.retry = undefined;
|
|
131
|
+
if (connected && channels.get(ch.name) === ch)
|
|
132
|
+
join(ch);
|
|
133
|
+
}, delay(ch.full++));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (answer["op"] !== "ok") {
|
|
137
|
+
ch.joined = false;
|
|
138
|
+
emit(ch.refusedListeners, String(answer["code"]));
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
ch.joined = true;
|
|
142
|
+
ch.full = 0;
|
|
143
|
+
const replayed = since !== undefined && answer["resync"] !== true;
|
|
144
|
+
// Replayed in the same epoch, the numbers go on from the page's own;
|
|
145
|
+
// otherwise from the Chest's.
|
|
146
|
+
if (!replayed || since.epoch !== epoch)
|
|
147
|
+
ch.seq = answer["seq"];
|
|
148
|
+
ch.epoch = epoch;
|
|
149
|
+
if (typeof answer["pos"] === "number")
|
|
150
|
+
ch.pos = answer["pos"];
|
|
151
|
+
ch.present = new Map((Array.isArray(answer["presence"]) ? answer["presence"] : []).map(p => [p.id, p.state]));
|
|
152
|
+
if (ch.tracked && member !== undefined)
|
|
153
|
+
ch.present.set(member, ch.tracked);
|
|
154
|
+
if (ch.tracked)
|
|
155
|
+
write({ op: "track", ch: ch.name, state: ch.tracked });
|
|
156
|
+
if (answer["presence"] !== undefined || since !== undefined)
|
|
157
|
+
presenceChanged(ch);
|
|
158
|
+
tellFocus();
|
|
159
|
+
emit(ch.joinedListeners, { replayed });
|
|
160
|
+
if (answer["resync"] === true)
|
|
161
|
+
emit(ch.resyncListeners);
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
const receive = (m) => {
|
|
165
|
+
const answer = typeof m["ref"] === "number" ? answers.get(m["ref"]) : undefined;
|
|
166
|
+
if (answer) {
|
|
167
|
+
answers.delete(m["ref"]);
|
|
168
|
+
answer(m);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const ch = typeof m["ch"] === "string" ? channels.get(m["ch"]) : undefined;
|
|
172
|
+
switch (m["op"]) {
|
|
173
|
+
case "hello":
|
|
174
|
+
epoch = m["epoch"];
|
|
175
|
+
member = m["member"];
|
|
176
|
+
attempts = 0;
|
|
177
|
+
connected = true;
|
|
178
|
+
focusSent = "";
|
|
179
|
+
clearTimeout(quiet);
|
|
180
|
+
quiet = undefined;
|
|
181
|
+
if (told !== true)
|
|
182
|
+
tell(true);
|
|
183
|
+
pinger = setInterval(() => check(pingWait), pingEvery);
|
|
184
|
+
renewer = setInterval(() => void ask(), renewEvery);
|
|
185
|
+
for (const c of channels.values())
|
|
186
|
+
if (!c.kicked)
|
|
187
|
+
join(c);
|
|
188
|
+
return;
|
|
189
|
+
case "msg":
|
|
190
|
+
if (!ch || !ch.joined)
|
|
191
|
+
return;
|
|
192
|
+
// A feed's row: its position in the tool's change log says whether
|
|
193
|
+
// the page has it already (given again by a replay).
|
|
194
|
+
if (typeof m["pos"] === "number") {
|
|
195
|
+
if (m["pos"] <= ch.pos)
|
|
196
|
+
return;
|
|
197
|
+
ch.pos = m["pos"];
|
|
198
|
+
}
|
|
199
|
+
if (typeof m["seq"] === "number")
|
|
200
|
+
ch.seq = m["seq"];
|
|
201
|
+
fire(ch.listeners, m["event"], m["payload"], { ...(typeof m["pos"] === "number" ? { pos: m["pos"] } : {}), ...(m["partial"] === true ? { partial: true } : {}) });
|
|
202
|
+
return;
|
|
203
|
+
case "peer":
|
|
204
|
+
if (ch?.joined)
|
|
205
|
+
fire(ch.peerListeners, m["event"], m["payload"], m["from"]);
|
|
206
|
+
return;
|
|
207
|
+
case "presence":
|
|
208
|
+
if (!ch)
|
|
209
|
+
return;
|
|
210
|
+
for (const p of m["joins"] ?? [])
|
|
211
|
+
ch.present.set(p.id, p.state);
|
|
212
|
+
for (const id of m["leaves"] ?? [])
|
|
213
|
+
ch.present.delete(id);
|
|
214
|
+
presenceChanged(ch);
|
|
215
|
+
return;
|
|
216
|
+
case "kicked":
|
|
217
|
+
if (!ch)
|
|
218
|
+
return;
|
|
219
|
+
ch.joined = false;
|
|
220
|
+
ch.kicked = true;
|
|
221
|
+
if (focusSent === ch.name)
|
|
222
|
+
focusSent = "";
|
|
223
|
+
emit(ch.kickedListeners);
|
|
224
|
+
return;
|
|
225
|
+
case "direct":
|
|
226
|
+
emit(direct, m["event"], m["payload"]);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
// check pings the Chest: no answer within wait, the connection is dead
|
|
230
|
+
// and another is opened at once.
|
|
231
|
+
const check = (wait) => {
|
|
232
|
+
const s = socket;
|
|
233
|
+
if (!s || !connected)
|
|
234
|
+
return;
|
|
235
|
+
clearTimeout(silence);
|
|
236
|
+
silence = setTimeout(() => lost(s, true), wait);
|
|
237
|
+
write({ op: "ping" }, () => clearTimeout(silence));
|
|
238
|
+
};
|
|
239
|
+
// unwatch stops what runs while connected.
|
|
240
|
+
const unwatch = () => {
|
|
241
|
+
clearInterval(pinger);
|
|
242
|
+
clearInterval(renewer);
|
|
243
|
+
clearTimeout(silence);
|
|
244
|
+
};
|
|
245
|
+
// lost forgets a connection that closed or went silent, tells the page
|
|
246
|
+
// only if no other comes within quietFor, and connects again: at once, or
|
|
247
|
+
// after the backoff.
|
|
248
|
+
const lost = (s, now) => {
|
|
249
|
+
if (socket !== s)
|
|
250
|
+
return;
|
|
251
|
+
socket = undefined;
|
|
252
|
+
connected = false;
|
|
253
|
+
unwatch();
|
|
254
|
+
if (s.readyState <= 1)
|
|
255
|
+
s.close(4000);
|
|
256
|
+
answers.clear();
|
|
257
|
+
for (const c of channels.values()) {
|
|
258
|
+
c.joined = false;
|
|
259
|
+
clearTimeout(c.retry);
|
|
260
|
+
c.retry = undefined;
|
|
261
|
+
}
|
|
262
|
+
if (told === true && quiet === undefined)
|
|
263
|
+
quiet = setTimeout(() => { quiet = undefined; tell(false); }, quietFor);
|
|
264
|
+
reconnect(now ? 0 : backoff());
|
|
265
|
+
};
|
|
266
|
+
// stop stops everything, for good.
|
|
267
|
+
const stop = () => {
|
|
268
|
+
ended = true;
|
|
269
|
+
unwatch();
|
|
270
|
+
clearTimeout(timer);
|
|
271
|
+
clearTimeout(quiet);
|
|
272
|
+
for (const c of channels.values())
|
|
273
|
+
clearTimeout(c.retry);
|
|
274
|
+
if (socket && socket.readyState <= 1)
|
|
275
|
+
socket.close(1000);
|
|
276
|
+
socket = undefined;
|
|
277
|
+
page.removeEventListener?.("online", wake);
|
|
278
|
+
page.removeEventListener?.("offline", gone);
|
|
279
|
+
page.removeEventListener?.("pageshow", restored);
|
|
280
|
+
page.document?.removeEventListener("visibilitychange", visible);
|
|
281
|
+
};
|
|
282
|
+
// end ends for good, and says why.
|
|
283
|
+
const end = (reason) => {
|
|
284
|
+
if (ended)
|
|
285
|
+
return;
|
|
286
|
+
stop();
|
|
287
|
+
emit(closed, reason);
|
|
288
|
+
};
|
|
289
|
+
// delay is the wait before the next attempt, the longer the more failed
|
|
290
|
+
// before it; backoff the wait before connecting again.
|
|
291
|
+
const delay = (failed) => Math.random() * Math.min(lastDelay, firstDelay * 2 ** failed);
|
|
292
|
+
const backoff = () => delay(attempts++);
|
|
293
|
+
// reconnect attempts again after delay (none: at once), unless an
|
|
294
|
+
// attempt is already on its way.
|
|
295
|
+
const reconnect = (delay) => {
|
|
296
|
+
if (ended || socket || asking || timer !== undefined)
|
|
297
|
+
return;
|
|
298
|
+
if (delay === 0)
|
|
299
|
+
return void attempt();
|
|
300
|
+
timer = setTimeout(attempt, delay);
|
|
301
|
+
};
|
|
302
|
+
// attempt asks the Chest before opening: whether the member still may
|
|
303
|
+
// connect, and whether it has room — when full, it waits as long as the
|
|
304
|
+
// Chest asks. Offline, it waits for the network ("online").
|
|
305
|
+
const attempt = async () => {
|
|
306
|
+
timer = undefined;
|
|
307
|
+
if (page.navigator?.onLine === false)
|
|
308
|
+
return;
|
|
309
|
+
asking = true;
|
|
310
|
+
const answer = await ask();
|
|
311
|
+
asking = false;
|
|
312
|
+
if (ended || socket)
|
|
313
|
+
return;
|
|
314
|
+
if (answer?.status === 503)
|
|
315
|
+
return reconnect(Math.max(backoff(), answer.retryAfter * 1000));
|
|
316
|
+
open();
|
|
317
|
+
};
|
|
318
|
+
// ask asks the Chest over HTTPS, without upgrading, whether the member
|
|
319
|
+
// may connect — which renews their session: 401 ends as signed out, 403
|
|
320
|
+
// as access removed, 503 says when there is room again (Retry-After, in
|
|
321
|
+
// seconds). A network down gives no answer.
|
|
322
|
+
const ask = async () => {
|
|
323
|
+
try {
|
|
324
|
+
const answer = await fetch(url.replace(/^ws/u, "http"), { credentials: "same-origin", cache: "no-store" });
|
|
325
|
+
await answer.body?.cancel();
|
|
326
|
+
if (answer.status === 401)
|
|
327
|
+
end("signed_out");
|
|
328
|
+
if (answer.status === 403)
|
|
329
|
+
end("access_removed");
|
|
330
|
+
return { status: answer.status, retryAfter: Number(answer.headers.get("Retry-After")) || 0 };
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
return undefined;
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
const open = () => {
|
|
337
|
+
const s = new WebSocket(url, protocol);
|
|
338
|
+
socket = s;
|
|
339
|
+
s.onmessage = event => {
|
|
340
|
+
let m;
|
|
341
|
+
try {
|
|
342
|
+
m = JSON.parse(String(event.data));
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
if (m !== null && typeof m === "object" && !Array.isArray(m))
|
|
348
|
+
receive(m);
|
|
349
|
+
};
|
|
350
|
+
// Every close but access removed is a cut: a session that ended
|
|
351
|
+
// (1008 session_ended) is told by the question before connecting again.
|
|
352
|
+
s.onclose = event => {
|
|
353
|
+
if (socket === s && event.code === 1008 && event.reason === "access_removed")
|
|
354
|
+
return end("access_removed");
|
|
355
|
+
lost(s, false);
|
|
356
|
+
};
|
|
357
|
+
};
|
|
358
|
+
// wake: the page is back — in the foreground, on the network, from the
|
|
359
|
+
// browser's cache. A connection is checked at once; without one, one is
|
|
360
|
+
// opened at once.
|
|
361
|
+
const wake = () => {
|
|
362
|
+
if (ended)
|
|
363
|
+
return;
|
|
364
|
+
if (connected)
|
|
365
|
+
return check(wakeWait);
|
|
366
|
+
if (socket || asking)
|
|
367
|
+
return;
|
|
368
|
+
clearTimeout(timer);
|
|
369
|
+
timer = undefined;
|
|
370
|
+
attempts = 0;
|
|
371
|
+
reconnect(0);
|
|
372
|
+
};
|
|
373
|
+
// gone: the browser says the network is gone — a Wi-Fi left, a cable
|
|
374
|
+
// pulled —: the connection is dropped at once, and the page waits for it
|
|
375
|
+
// to come back ("online") rather than for a ping to go unanswered.
|
|
376
|
+
const gone = () => { if (!ended && socket)
|
|
377
|
+
lost(socket, false); };
|
|
378
|
+
// visibilitychange: shown, the page wakes; shown or hidden, the Chest is
|
|
379
|
+
// told what it has on screen.
|
|
380
|
+
const visible = () => {
|
|
381
|
+
if (shown())
|
|
382
|
+
wake();
|
|
383
|
+
tellFocus();
|
|
384
|
+
};
|
|
385
|
+
const restored = (event) => { if (event.persisted)
|
|
386
|
+
wake(); };
|
|
387
|
+
page.addEventListener?.("online", wake);
|
|
388
|
+
page.addEventListener?.("offline", gone);
|
|
389
|
+
page.addEventListener?.("pageshow", restored);
|
|
390
|
+
page.document?.addEventListener("visibilitychange", visible);
|
|
391
|
+
open();
|
|
392
|
+
return {
|
|
393
|
+
get member() { return member; },
|
|
394
|
+
channel(name) {
|
|
395
|
+
let ch = channels.get(name);
|
|
396
|
+
if (!ch) {
|
|
397
|
+
ch = { name, listeners: new Map(), peerListeners: new Map(), joinedListeners: new Set(), resyncListeners: new Set(), kickedListeners: new Set(), refusedListeners: new Set(), presenceListeners: new Set(), present: new Map(), epoch: undefined, seq: 0, pos: 0, joined: false, kicked: false, full: 0, retry: undefined };
|
|
398
|
+
channels.set(name, ch);
|
|
399
|
+
if (connected)
|
|
400
|
+
join(ch);
|
|
401
|
+
}
|
|
402
|
+
const state = ch;
|
|
403
|
+
return {
|
|
404
|
+
on: (event, listener) => listenTo(state.listeners, event, listener),
|
|
405
|
+
onJoined: listener => listen(state.joinedListeners, listener),
|
|
406
|
+
onResync: listener => listen(state.resyncListeners, listener),
|
|
407
|
+
onKicked: listener => listen(state.kickedListeners, listener),
|
|
408
|
+
onRefused: listener => listen(state.refusedListeners, listener),
|
|
409
|
+
peers: {
|
|
410
|
+
on: (event, listener) => listenTo(state.peerListeners, event, listener),
|
|
411
|
+
send(event, payload) {
|
|
412
|
+
if (typeof event !== "string" || !peerEventPattern.test(event))
|
|
413
|
+
throw new TypeError("invalid_event: a member's message is 1 to 64 of a-z 0-9 _ -, without a dot");
|
|
414
|
+
if (state.joined)
|
|
415
|
+
write({ op: "send", ch: state.name, event, payload: payload ?? null });
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
presence: {
|
|
419
|
+
track(value) {
|
|
420
|
+
state.tracked = value;
|
|
421
|
+
if (member !== undefined) {
|
|
422
|
+
state.present.set(member, value);
|
|
423
|
+
presenceChanged(state);
|
|
424
|
+
}
|
|
425
|
+
if (state.joined)
|
|
426
|
+
write({ op: "track", ch: state.name, state: value });
|
|
427
|
+
},
|
|
428
|
+
list: () => [...state.present].map(([id, value]) => ({ id, state: value })),
|
|
429
|
+
on: listener => listen(state.presenceListeners, listener),
|
|
430
|
+
},
|
|
431
|
+
// leave leaves the channel: the Chest forgets the page's focus on it.
|
|
432
|
+
leave() {
|
|
433
|
+
channels.delete(state.name);
|
|
434
|
+
clearTimeout(state.retry);
|
|
435
|
+
if (state.joined)
|
|
436
|
+
write({ op: "leave", ch: state.name });
|
|
437
|
+
state.joined = false;
|
|
438
|
+
if (focusSent === state.name)
|
|
439
|
+
focusSent = "";
|
|
440
|
+
},
|
|
441
|
+
};
|
|
442
|
+
},
|
|
443
|
+
focus(name) {
|
|
444
|
+
focused = name;
|
|
445
|
+
tellFocus();
|
|
446
|
+
},
|
|
447
|
+
on(event, listener) {
|
|
448
|
+
return listen((event === "direct" ? direct : event === "status" ? status : closed), listener);
|
|
449
|
+
},
|
|
450
|
+
close: stop,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
//# sourceMappingURL=realtime-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-client.js","sourceRoot":"","sources":["../../client/src/realtime-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type Present = {
|
|
2
|
+
id: string;
|
|
3
|
+
state: Record<string, unknown>;
|
|
4
|
+
};
|
|
5
|
+
export declare const channelPattern: RegExp;
|
|
6
|
+
export declare const eventPattern: RegExp;
|
|
7
|
+
export declare function publish(channel: string, event: string, payload?: unknown): Promise<{
|
|
8
|
+
seq: number;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function send(memberIds: Iterable<string>, event: string, payload?: unknown): Promise<{
|
|
11
|
+
reached: string[];
|
|
12
|
+
}>;
|
|
13
|
+
export declare function online(memberIds: Iterable<string>, options?: {
|
|
14
|
+
channel?: string;
|
|
15
|
+
}): Promise<{
|
|
16
|
+
online: string[];
|
|
17
|
+
watching: string[];
|
|
18
|
+
}>;
|
|
19
|
+
export declare function presence(channel: string): Promise<{
|
|
20
|
+
members: Present[];
|
|
21
|
+
}>;
|
|
22
|
+
//# sourceMappingURL=realtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../../client/src/realtime.ts"],"names":[],"mappings":"AA0BA,MAAM,MAAM,OAAO,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC;AAIrE,eAAO,MAAM,cAAc,QAA8C,CAAC;AAC1E,eAAO,MAAM,YAAY,QAAyB,CAAC;AAgDnD,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAIzG;AAID,wBAAsB,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAGxH;AAOD,wBAAsB,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAK/I;AAID,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,CAW/E"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { ask as chest, json, refusal } from "./api.js";
|
|
2
|
+
import { ChestError, TooLarge, Unavailable } from "./errors.js";
|
|
3
|
+
import { memberIdPattern } from "./member.js";
|
|
4
|
+
// The grammars of the Chest: a channel is segments of a-z 0-9 _ - joined by
|
|
5
|
+
// colons, 128 characters at most; an event 1 to 64 of a-z 0-9 . _ -.
|
|
6
|
+
export const channelPattern = /^[a-z0-9_-]{1,64}(?::[a-z0-9_-]{1,64})*$/u;
|
|
7
|
+
export const eventPattern = /^[a-z0-9._-]{1,64}$/u;
|
|
8
|
+
const maxChannel = 128, maxPayload = 64 << 10;
|
|
9
|
+
function checkChannel(channel) {
|
|
10
|
+
if (typeof channel !== "string" || channel.length > maxChannel || !channelPattern.test(channel))
|
|
11
|
+
throw new ChestError("invalid_channel", 400, "a channel is segments of a-z 0-9 _ - joined by colons");
|
|
12
|
+
return channel;
|
|
13
|
+
}
|
|
14
|
+
function checkEvent(event) {
|
|
15
|
+
if (typeof event !== "string" || !eventPattern.test(event))
|
|
16
|
+
throw new ChestError("invalid_event", 400, "an event is 1 to 64 of a-z 0-9 . _ -");
|
|
17
|
+
return event;
|
|
18
|
+
}
|
|
19
|
+
function checkIds(ids) {
|
|
20
|
+
const all = [...ids];
|
|
21
|
+
if (all.length < 1)
|
|
22
|
+
throw new ChestError("invalid_body", 400, "one member identifier at least");
|
|
23
|
+
if (!all.every(id => typeof id === "string" && memberIdPattern.test(id)))
|
|
24
|
+
throw new ChestError("invalid_id", 400, "invalid member identifier");
|
|
25
|
+
return all;
|
|
26
|
+
}
|
|
27
|
+
// body is a call's JSON; a payload the Chest would refuse is refused here.
|
|
28
|
+
function body(fields) {
|
|
29
|
+
const payload = JSON.stringify(fields["payload"] ?? null);
|
|
30
|
+
if (payload === undefined)
|
|
31
|
+
throw new ChestError("invalid_body", 400, "a payload is JSON");
|
|
32
|
+
if (Buffer.byteLength(payload) > maxPayload)
|
|
33
|
+
throw new TooLarge();
|
|
34
|
+
return JSON.stringify(fields);
|
|
35
|
+
}
|
|
36
|
+
const call = async (method, path, value) => {
|
|
37
|
+
const response = await chest("realtime", method, path, value === undefined ? {} : { body: value, type: "application/json" });
|
|
38
|
+
if (response.status !== 200) {
|
|
39
|
+
if (response.status < 400) {
|
|
40
|
+
await response.body?.cancel();
|
|
41
|
+
throw new Unavailable();
|
|
42
|
+
}
|
|
43
|
+
throw await refusal(response, "realtime");
|
|
44
|
+
}
|
|
45
|
+
return json(response);
|
|
46
|
+
};
|
|
47
|
+
const record = (v) => {
|
|
48
|
+
if (v === null || typeof v !== "object" || Array.isArray(v))
|
|
49
|
+
throw new Unavailable();
|
|
50
|
+
return v;
|
|
51
|
+
};
|
|
52
|
+
const ids = (v) => {
|
|
53
|
+
if (!Array.isArray(v) || !v.every(id => typeof id === "string" && memberIdPattern.test(id)))
|
|
54
|
+
throw new Unavailable();
|
|
55
|
+
return [...v];
|
|
56
|
+
};
|
|
57
|
+
// publish delivers an event to every page joined to a channel the tool
|
|
58
|
+
// declares — numbered, in order, kept a short while for a page that
|
|
59
|
+
// reconnects —: its number in the channel.
|
|
60
|
+
export async function publish(channel, event, payload) {
|
|
61
|
+
const answer = record(await call("POST", "/realtime/publish", body({ channel: checkChannel(channel), event: checkEvent(event), payload })));
|
|
62
|
+
if (!Number.isSafeInteger(answer["seq"]) || answer["seq"] < 1)
|
|
63
|
+
throw new Unavailable();
|
|
64
|
+
return { seq: answer["seq"] };
|
|
65
|
+
}
|
|
66
|
+
// send delivers an event to every page of these members, outside any
|
|
67
|
+
// channel: those it reached. The others are not online in the tool.
|
|
68
|
+
export async function send(memberIds, event, payload) {
|
|
69
|
+
const answer = record(await call("POST", "/realtime/send", body({ members: checkIds(memberIds), event: checkEvent(event), payload })));
|
|
70
|
+
return { reached: ids(answer["reached"]) };
|
|
71
|
+
}
|
|
72
|
+
// online says which of these members have a page of the tool open now,
|
|
73
|
+
// and, given a channel, which of them watch it — a page focused on it
|
|
74
|
+
// (live.focus) and in the foreground: what decides whom to notify. A chat
|
|
75
|
+
// notifies the members online but not watching the conversation, and every
|
|
76
|
+
// member not online: those watching it see the message already.
|
|
77
|
+
export async function online(memberIds, options = {}) {
|
|
78
|
+
const members = checkIds(memberIds);
|
|
79
|
+
const channel = options.channel === undefined ? undefined : checkChannel(options.channel);
|
|
80
|
+
const answer = record(await call("POST", "/realtime/online", JSON.stringify({ members, ...(channel === undefined ? {} : { channel }) })));
|
|
81
|
+
return { online: ids(answer["online"]), watching: ids(answer["watching"]) };
|
|
82
|
+
}
|
|
83
|
+
// presence is who appears in a channel now — merged across their pages —,
|
|
84
|
+
// with the state they track.
|
|
85
|
+
export async function presence(channel) {
|
|
86
|
+
const answer = record(await call("GET", "/realtime/presence?channel=" + encodeURIComponent(checkChannel(channel))));
|
|
87
|
+
const members = answer["members"];
|
|
88
|
+
if (!Array.isArray(members))
|
|
89
|
+
throw new Unavailable();
|
|
90
|
+
return {
|
|
91
|
+
members: members.map(m => {
|
|
92
|
+
const p = record(m);
|
|
93
|
+
if (typeof p["id"] !== "string" || !memberIdPattern.test(p["id"]))
|
|
94
|
+
throw new Unavailable();
|
|
95
|
+
return { id: p["id"], state: record(p["state"]) };
|
|
96
|
+
}),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=realtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime.js","sourceRoot":"","sources":["../../client/src/realtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA0B9C,4EAA4E;AAC5E,qEAAqE;AACrE,MAAM,CAAC,MAAM,cAAc,GAAG,2CAA2C,CAAC;AAC1E,MAAM,CAAC,MAAM,YAAY,GAAG,sBAAsB,CAAC;AACnD,MAAM,UAAU,GAAG,GAAG,EAAE,UAAU,GAAG,EAAE,IAAI,EAAE,CAAC;AAE9C,SAAS,YAAY,CAAC,OAAgB;IACpC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,UAAU,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,iBAAiB,EAAE,GAAG,EAAE,uDAAuD,CAAC,CAAC;IACvM,OAAO,OAAO,CAAC;AACjB,CAAC;AACD,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,eAAe,EAAE,GAAG,EAAE,sCAAsC,CAAC,CAAC;IAC/I,OAAO,KAAK,CAAC;AACf,CAAC;AACD,SAAS,QAAQ,CAAC,GAAqB;IACrC,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IACrB,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,cAAc,EAAE,GAAG,EAAE,gCAAgC,CAAC,CAAC;IAChG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,YAAY,EAAE,GAAG,EAAE,2BAA2B,CAAC,CAAC;IAC/I,OAAO,GAAG,CAAC;AACb,CAAC;AACD,2EAA2E;AAC3E,SAAS,IAAI,CAAC,MAA+B;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,CAAC;IAC1D,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,IAAI,UAAU,CAAC,cAAc,EAAE,GAAG,EAAE,mBAAmB,CAAC,CAAC;IAC1F,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,UAAU;QAAE,MAAM,IAAI,QAAQ,EAAE,CAAC;IAClE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,IAAI,GAAG,KAAK,EAAE,MAAc,EAAE,IAAY,EAAE,KAAc,EAAoB,EAAE;IACpF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC7H,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YAC1B,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;YAC9B,MAAM,IAAI,WAAW,EAAE,CAAC;QAC1B,CAAC;QACD,MAAM,MAAM,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC,CAAC;AACF,MAAM,MAAM,GAAG,CAAC,CAAU,EAA2B,EAAE;IACrD,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,WAAW,EAAE,CAAC;IACrF,OAAO,CAA4B,CAAC;AACtC,CAAC,CAAC;AACF,MAAM,GAAG,GAAG,CAAC,CAAU,EAAY,EAAE;IACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAAE,MAAM,IAAI,WAAW,EAAE,CAAC;IACrH,OAAO,CAAC,GAAG,CAAC,CAAa,CAAC;AAC5B,CAAC,CAAC;AAEF,uEAAuE;AACvE,oEAAoE;AACpE,2CAA2C;AAC3C,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAe,EAAE,KAAa,EAAE,OAAiB;IAC7E,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,mBAAmB,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5I,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAK,MAAM,CAAC,KAAK,CAAY,GAAG,CAAC;QAAE,MAAM,IAAI,WAAW,EAAE,CAAC;IACnG,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAW,EAAE,CAAC;AAC1C,CAAC;AAED,qEAAqE;AACrE,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,SAA2B,EAAE,KAAa,EAAE,OAAiB;IACtF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IACvI,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;AAC7C,CAAC;AAED,uEAAuE;AACvE,sEAAsE;AACtE,0EAA0E;AAC1E,2EAA2E;AAC3E,gEAAgE;AAChE,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,SAA2B,EAAE,OAAO,GAAyB,EAAE;IAC1F,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1F,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1I,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;AAC9E,CAAC;AAED,0EAA0E;AAC1E,6BAA6B;AAC7B,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAe;IAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,6BAA6B,GAAG,kBAAkB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACpH,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,WAAW,EAAE,CAAC;IACrD,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YACvB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACpB,IAAI,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBAAE,MAAM,IAAI,WAAW,EAAE,CAAC;YAC3F,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACpD,CAAC,CAAC;KACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { IncomingMessage } from "node:http";
|
|
2
|
+
export type SealOptions = {
|
|
3
|
+
roles?: string[];
|
|
4
|
+
context?: string;
|
|
5
|
+
};
|
|
6
|
+
export type SealItem = {
|
|
7
|
+
value: string;
|
|
8
|
+
} & SealOptions;
|
|
9
|
+
export type OpenItem = {
|
|
10
|
+
sealed: string;
|
|
11
|
+
context?: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function isSealed(text: unknown): text is string;
|
|
14
|
+
export declare function sealMany(items: SealItem[]): Promise<string[]>;
|
|
15
|
+
export declare function seal(value: string, options?: SealOptions): Promise<string>;
|
|
16
|
+
export declare function openMany(request: IncomingMessage | Request, items: OpenItem[]): Promise<(string | null)[]>;
|
|
17
|
+
export declare function open(request: IncomingMessage | Request, sealed: string, options?: {
|
|
18
|
+
context?: string;
|
|
19
|
+
}): Promise<string>;
|
|
20
|
+
//# sourceMappingURL=sealed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sealed.d.ts","sourceRoot":"","sources":["../../client/src/sealed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AA2CjD,MAAM,MAAM,WAAW,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE,MAAM,MAAM,QAAQ,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,CAAC;AACvD,MAAM,MAAM,QAAQ,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAa5D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,CAEtD;AAgDD,wBAAsB,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAKnE;AAGD,wBAAsB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAEpF;AAKD,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAiBhH;AAKD,wBAAsB,IAAI,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAWlI"}
|