@solarpunkltd/swarm-chat-js 7.1.0 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -8
- package/dist/chat.d.ts +8 -1
- package/dist/follower.d.ts +53 -10
- package/dist/history.d.ts +20 -6
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +278 -119
- package/dist/message/index.d.ts +1 -0
- package/dist/message/note.d.ts +38 -0
- package/dist/message.cjs +1 -1
- package/dist/message.js +139 -95
- package/dist/notes.d.ts +88 -0
- package/dist/pacer.d.ts +31 -0
- package/dist/swarm.d.ts +8 -1
- package/package.json +10 -12
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ChatMessageError as e,
|
|
2
|
-
import { Bee as
|
|
1
|
+
import { ChatMessageError as e, DEFAULT_NOTE_HEARTBEAT_MS as t, DEFAULT_NOTE_SLOT_MS as n, MAX_ENTRY_BYTES as r, MAX_MESSAGE_BYTES as i, MAX_NAME_CHARACTERS as a, MAX_NOTE_BYTES as o, MAX_TEXT_CHARACTERS as s, MAX_TOPIC_CHARACTERS as c, MESSAGE_VERSION as l, MessageType as u, NOTE_VERSION as d, chatMessageSchema as f, checkChatMessage as p, countCharacters as m, createChatMessage as h, encodeChatMessage as g, encodeSlotNote as _, feedEntrySchema as ee, hasValidSignature as te, historyFileSchema as ne, historyLinkSchema as v, historyRowSchema as y, newMessageId as b, noteAddress as x, noteIdentifier as S, noteIdentifierText as re, noteSlotEnd as C, noteSlotOf as w, parseChatMessage as T, parseFeedEntry as E, parseHistoryFile as D, parseSlotNote as O, signedBytes as k, slotNoteSchema as A } from "./message.js";
|
|
2
|
+
import { Bee as j, BeeResponseError as M, Identifier as ie, PrivateKey as N, Topic as P } from "@ethersphere/bee-js";
|
|
3
3
|
//#region src/events.ts
|
|
4
|
-
var
|
|
4
|
+
var F = {
|
|
5
5
|
LOADING_INIT: "loadingInit",
|
|
6
6
|
LOADING_PREVIOUS_MESSAGES: "loadingPreviousMessages",
|
|
7
7
|
MESSAGE_RECEIVED: "messageReceived",
|
|
@@ -13,13 +13,13 @@ var O = {
|
|
|
13
13
|
MESSAGE_SKIPPED: "messageSkipped",
|
|
14
14
|
ERROR: "error"
|
|
15
15
|
};
|
|
16
|
-
function
|
|
17
|
-
return
|
|
16
|
+
function I(e) {
|
|
17
|
+
return R(e, -1, e.ts);
|
|
18
18
|
}
|
|
19
|
-
function
|
|
20
|
-
return
|
|
19
|
+
function L(e) {
|
|
20
|
+
return R(e.msg, e.seq, e.at);
|
|
21
21
|
}
|
|
22
|
-
function
|
|
22
|
+
function R(e, t, n) {
|
|
23
23
|
return {
|
|
24
24
|
id: e.id,
|
|
25
25
|
type: e.type,
|
|
@@ -34,7 +34,7 @@ function j(e, t, n) {
|
|
|
34
34
|
sentAt: e.ts
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
-
var
|
|
37
|
+
var z = class {
|
|
38
38
|
constructor() {
|
|
39
39
|
this.listeners = /* @__PURE__ */ new Map(), this.on = (e, t) => {
|
|
40
40
|
this.listeners.set(e, [...this.listeners.get(e) ?? [], t]);
|
|
@@ -51,66 +51,92 @@ var M = class {
|
|
|
51
51
|
console.error(`a listener for ${e} threw`, t);
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
},
|
|
54
|
+
}, B = 2e4, V = class {
|
|
55
|
+
constructor(e, t) {
|
|
56
|
+
this.spacingMs = e, this.now = t, this.missedAt = /* @__PURE__ */ new Map();
|
|
57
|
+
}
|
|
58
|
+
readableAt(e, t = this.now()) {
|
|
59
|
+
let n = this.missedAt.get(e);
|
|
60
|
+
return n === void 0 || this.expired(n, t) ? -Infinity : n + this.spacingMs;
|
|
61
|
+
}
|
|
62
|
+
mayRead(e, t = this.now()) {
|
|
63
|
+
return t >= this.readableAt(e, t);
|
|
64
|
+
}
|
|
65
|
+
missed(e, t = this.now()) {
|
|
66
|
+
for (let [e, n] of this.missedAt) this.expired(n, t) && this.missedAt.delete(e);
|
|
67
|
+
this.missedAt.set(e, t);
|
|
68
|
+
}
|
|
69
|
+
found(e) {
|
|
70
|
+
this.missedAt.delete(e);
|
|
71
|
+
}
|
|
72
|
+
clear() {
|
|
73
|
+
this.missedAt.clear();
|
|
74
|
+
}
|
|
75
|
+
expired(e, t) {
|
|
76
|
+
return e > t || t - e >= this.spacingMs;
|
|
77
|
+
}
|
|
78
|
+
}, H = class extends Error {
|
|
55
79
|
constructor(e) {
|
|
56
80
|
super("the feed head lookup did not answer in time", e), this.name = "HeadLookupTimeoutError";
|
|
57
81
|
}
|
|
58
|
-
},
|
|
82
|
+
}, U = class extends Error {
|
|
59
83
|
constructor(e, t) {
|
|
60
84
|
super(`feed slot ${e} was served but could not be read`, t), this.index = e, this.name = "UnreadableSlotError";
|
|
61
85
|
}
|
|
62
86
|
};
|
|
63
|
-
function
|
|
64
|
-
return e instanceof
|
|
87
|
+
function W(e) {
|
|
88
|
+
return e instanceof M && (e.status === 404 || e.status === 500);
|
|
65
89
|
}
|
|
66
|
-
async function
|
|
90
|
+
async function G(e, t) {
|
|
67
91
|
try {
|
|
68
92
|
return await t();
|
|
69
93
|
} catch (t) {
|
|
70
|
-
if (
|
|
71
|
-
throw t instanceof
|
|
94
|
+
if (W(t)) return null;
|
|
95
|
+
throw t instanceof M ? t : new U(e, { cause: t });
|
|
72
96
|
}
|
|
73
97
|
}
|
|
74
|
-
function
|
|
75
|
-
let
|
|
98
|
+
function K(e, t, r, i, a = n) {
|
|
99
|
+
let o = P.fromString(r), s = (n) => e.feed.makeReader(o, t, q(n));
|
|
76
100
|
return {
|
|
77
|
-
|
|
101
|
+
readNote: (n) => G(n, async () => (await e.soc.makeReader(t, q(i.slotReadMs)).download(S(r, a, n))).payload.toUint8Array()),
|
|
102
|
+
readSlot: (e) => G(e, async () => (await s(i.slotReadMs).downloadPayload({ index: e })).payload.toUint8Array()),
|
|
78
103
|
async readHead() {
|
|
79
|
-
let n =
|
|
104
|
+
let n = q(i.feedReadMs);
|
|
80
105
|
try {
|
|
81
|
-
let { payload: r, feedIndex:
|
|
106
|
+
let { payload: r, feedIndex: i } = await e.feed.makeReader(o, t, n).downloadPayload();
|
|
82
107
|
return {
|
|
83
|
-
index: Number(
|
|
108
|
+
index: Number(i.toBigInt()),
|
|
84
109
|
payload: r.toUint8Array()
|
|
85
110
|
};
|
|
86
111
|
} catch (e) {
|
|
87
|
-
if (
|
|
88
|
-
throw n.signal?.aborted ? new
|
|
112
|
+
if (W(e)) return null;
|
|
113
|
+
throw n.signal?.aborted ? new H({ cause: e }) : e;
|
|
89
114
|
}
|
|
90
115
|
},
|
|
91
116
|
async readFile(t) {
|
|
92
|
-
return (await e.data.download(t, void 0,
|
|
117
|
+
return (await e.data.download(t, void 0, q(i.feedReadMs))).toUint8Array();
|
|
93
118
|
}
|
|
94
119
|
};
|
|
95
120
|
}
|
|
96
|
-
function
|
|
121
|
+
function q(e) {
|
|
97
122
|
return { signal: AbortSignal.timeout(e) };
|
|
98
123
|
}
|
|
99
|
-
var
|
|
100
|
-
function
|
|
101
|
-
let a = new
|
|
124
|
+
var ae = "0123456789abcdef".repeat(4);
|
|
125
|
+
function J(e, t, n, r, i) {
|
|
126
|
+
let a = new N(n), o = ie.fromString(r);
|
|
102
127
|
return async (n) => {
|
|
103
|
-
await e.messaging.gsocSend(t, a, o, n, { deferred: !1 },
|
|
128
|
+
await e.messaging.gsocSend(t, a, o, n, { deferred: !1 }, q(i.writeMs));
|
|
104
129
|
};
|
|
105
130
|
}
|
|
106
131
|
//#endregion
|
|
107
132
|
//#region src/follower.ts
|
|
108
|
-
var
|
|
133
|
+
var Y = {
|
|
109
134
|
LIVE: "live",
|
|
110
135
|
RECONNECTING: "reconnecting",
|
|
111
136
|
STALLED: "stalled"
|
|
112
|
-
},
|
|
137
|
+
}, oe = {
|
|
113
138
|
pollIntervalMs: 1e3,
|
|
139
|
+
missingReadSpacingMs: B,
|
|
114
140
|
maxSlotsPerPoll: 16,
|
|
115
141
|
unservedPollsBeforeProbe: 3,
|
|
116
142
|
unreadablePollsBeforeFailure: 3,
|
|
@@ -128,16 +154,16 @@ var V = {
|
|
|
128
154
|
stallAfterMs: 8e3,
|
|
129
155
|
random: Math.random,
|
|
130
156
|
now: Date.now
|
|
131
|
-
},
|
|
157
|
+
}, X = class extends Error {
|
|
132
158
|
constructor(e) {
|
|
133
159
|
super(`the gateway keeps answering feed slot ${e} with something that is not a chunk`), this.index = e, this.name = "UnreadableGatewayError";
|
|
134
160
|
}
|
|
135
|
-
},
|
|
136
|
-
constructor(e, t, n, r = {}) {
|
|
137
|
-
this.source = e, this.topic = t, this.events = n, this.next = 0, this.unservedPolls = 0, this.nextProbeAt = 0, this.unreadablePolls = 0, this.gatewayFailures = 0, this.missed = /* @__PURE__ */ new Map(), this.timer = null, this.generation = 0, this.running = !1, this.status = null, this.settings = {
|
|
138
|
-
...
|
|
161
|
+
}, se = class {
|
|
162
|
+
constructor(e, t, n, r = {}, i = null) {
|
|
163
|
+
this.source = e, this.topic = t, this.events = n, this.notes = i, this.next = 0, this.ceiling = null, this.nextNoteSlot = 0, this.lastNoteFoundAt = 0, this.unservedPolls = 0, this.nextProbeAt = 0, this.unreadablePolls = 0, this.gatewayFailures = 0, this.missed = /* @__PURE__ */ new Map(), this.timer = null, this.generation = 0, this.running = !1, this.status = null, this.settings = {
|
|
164
|
+
...oe,
|
|
139
165
|
...r
|
|
140
|
-
};
|
|
166
|
+
}, this.pacer = new V(this.settings.missingReadSpacingMs, this.settings.now);
|
|
141
167
|
}
|
|
142
168
|
get nextIndex() {
|
|
143
169
|
return this.next;
|
|
@@ -145,8 +171,11 @@ var V = {
|
|
|
145
171
|
get missedIndices() {
|
|
146
172
|
return [...this.missed.keys()];
|
|
147
173
|
}
|
|
148
|
-
|
|
149
|
-
|
|
174
|
+
get ledByNotes() {
|
|
175
|
+
return this.ceiling !== null;
|
|
176
|
+
}
|
|
177
|
+
start(e, t = null) {
|
|
178
|
+
this.stop(), this.next = e, this.ceiling = t?.newest ?? null, this.nextNoteSlot = t?.nextNoteSlot ?? (this.notes ? this.notes.lastReadableSlot() + 1 : 0), this.lastNoteFoundAt = this.settings.now(), this.resetRefusals(), this.unreadablePolls = 0, this.gatewayFailures = 0, this.missed.clear(), this.pacer.clear(), this.status = null, this.running = !0, this.schedule(0);
|
|
150
179
|
}
|
|
151
180
|
stop() {
|
|
152
181
|
this.running = !1, this.generation++, this.timer &&= (clearTimeout(this.timer), null);
|
|
@@ -160,7 +189,7 @@ var V = {
|
|
|
160
189
|
async poll(e) {
|
|
161
190
|
let t = 0, n = !1;
|
|
162
191
|
try {
|
|
163
|
-
t = await this.walk(e), await this.readMissed(e);
|
|
192
|
+
this.notes !== null && await this.readDueNotes(this.notes, e), t = await this.walk(e), await this.readMissed(e);
|
|
164
193
|
} catch (t) {
|
|
165
194
|
n = !0, e === this.generation && this.gatewayFailed(t);
|
|
166
195
|
}
|
|
@@ -169,28 +198,58 @@ var V = {
|
|
|
169
198
|
this.schedule(this.backoffMs());
|
|
170
199
|
return;
|
|
171
200
|
}
|
|
172
|
-
this.gatewayAnswered(), this.schedule(t >= this.settings.maxSlotsPerPoll ? 0 : this.
|
|
201
|
+
this.gatewayAnswered(), this.schedule(t >= this.settings.maxSlotsPerPoll ? 0 : this.untilNextRead());
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
untilNextRead() {
|
|
205
|
+
let e = this.settings.now(), t = (t) => {
|
|
206
|
+
let n = this.pacer.readableAt(t);
|
|
207
|
+
return n > e ? n : e + this.settings.pollIntervalMs;
|
|
208
|
+
}, n = [...this.missed.keys()].map(t);
|
|
209
|
+
return this.notes !== null && n.push(this.notes.readableAt(this.nextNoteSlot)), this.ceiling === null && n.push(t(this.next)), Math.max(0, Math.min(...n) - e);
|
|
210
|
+
}
|
|
211
|
+
async readDueNotes(e, t) {
|
|
212
|
+
let n = this.settings.now(), r = e.lastReadableSlot(n);
|
|
213
|
+
if (r < this.nextNoteSlot) return;
|
|
214
|
+
let i = Math.max(this.nextNoteSlot, r - e.lookBackSlots + 1), a = await e.scan(r, i);
|
|
215
|
+
if (t === this.generation) {
|
|
216
|
+
if (this.nextNoteSlot = r + 1, a) {
|
|
217
|
+
this.lastNoteFoundAt = n, this.ceiling = Math.max(this.ceiling ?? -1, a.note.newest, this.next - 1);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
n - this.lastNoteFoundAt >= e.silenceMs && (this.lastNoteFoundAt = n, e.clock.distrust(), this.nextNoteSlot = Math.min(this.nextNoteSlot, e.lastReadableSlot(n) + 1));
|
|
173
221
|
}
|
|
174
222
|
}
|
|
175
223
|
async read(e) {
|
|
224
|
+
let t;
|
|
176
225
|
try {
|
|
177
|
-
|
|
226
|
+
t = await this.source.readSlot(e);
|
|
178
227
|
} catch (e) {
|
|
179
|
-
if (e instanceof
|
|
228
|
+
if (e instanceof U) return "unreadable";
|
|
180
229
|
throw e;
|
|
181
230
|
}
|
|
231
|
+
return t === null ? this.pacer.missed(e) : this.pacer.found(e), t;
|
|
232
|
+
}
|
|
233
|
+
async readUnnamed(e) {
|
|
234
|
+
return this.pacer.mayRead(e) ? this.read(e) : "held";
|
|
182
235
|
}
|
|
183
236
|
async walk(e) {
|
|
184
237
|
for (let t = 0; t < this.settings.maxSlotsPerPoll; t++) {
|
|
185
|
-
let n = this.next
|
|
186
|
-
if (
|
|
238
|
+
let n = this.next;
|
|
239
|
+
if (this.ceiling !== null && n > this.ceiling) return t;
|
|
240
|
+
let r = this.ceiling === null ? await this.readUnnamed(n) : await this.read(n);
|
|
241
|
+
if (e !== this.generation || r === "held") return t;
|
|
242
|
+
if (this.ceiling !== null && (r === null || r === "unreadable")) {
|
|
243
|
+
this.remember(n), this.next = n + 1;
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
187
246
|
if (r === null || r === "unreadable") {
|
|
188
247
|
if (t === 0) {
|
|
189
248
|
if (this.unservedPolls++, this.unreadablePolls = r === "unreadable" ? this.unreadablePolls + 1 : 0, this.shouldProbe() && await this.probePast(n, e)) {
|
|
190
249
|
this.unreadablePolls = 0;
|
|
191
250
|
continue;
|
|
192
251
|
}
|
|
193
|
-
if (this.unreadablePolls >= this.settings.unreadablePollsBeforeFailure) throw new
|
|
252
|
+
if (this.unreadablePolls >= this.settings.unreadablePollsBeforeFailure) throw new X(n);
|
|
194
253
|
}
|
|
195
254
|
return t;
|
|
196
255
|
}
|
|
@@ -200,8 +259,8 @@ var V = {
|
|
|
200
259
|
}
|
|
201
260
|
shouldProbe() {
|
|
202
261
|
if (this.unservedPolls !== this.nextProbeAt) return !1;
|
|
203
|
-
let { probeIntervalCapMs: e, pollIntervalMs: t } = this.settings,
|
|
204
|
-
return this.nextProbeAt += Math.min(this.nextProbeAt,
|
|
262
|
+
let { probeIntervalCapMs: e, pollIntervalMs: t, missingReadSpacingMs: n } = this.settings, r = Math.max(1, Math.ceil(e / Math.max(t, n)));
|
|
263
|
+
return this.nextProbeAt += Math.min(this.nextProbeAt, r), !0;
|
|
205
264
|
}
|
|
206
265
|
resetRefusals() {
|
|
207
266
|
this.unservedPolls = 0, this.nextProbeAt = this.settings.unservedPollsBeforeProbe;
|
|
@@ -209,17 +268,17 @@ var V = {
|
|
|
209
268
|
async probePast(e, t) {
|
|
210
269
|
let n = /* @__PURE__ */ new Set([e]);
|
|
211
270
|
for (let r of this.settings.probeDistances) {
|
|
212
|
-
let i = e + r, a = await this.
|
|
271
|
+
let i = e + r, a = await this.readUnnamed(i);
|
|
213
272
|
if (t !== this.generation) return !1;
|
|
214
|
-
if (a === null || a === "unreadable") {
|
|
273
|
+
if (a === null || a === "unreadable" || a === "held") {
|
|
215
274
|
n.add(i);
|
|
216
275
|
continue;
|
|
217
276
|
}
|
|
218
277
|
this.resetRefusals(), this.remember(e);
|
|
219
278
|
for (let r = e + 1; r < i; r++) {
|
|
220
|
-
let e = n.has(r) ? null : await this.
|
|
279
|
+
let e = n.has(r) ? null : await this.readUnnamed(r);
|
|
221
280
|
if (t !== this.generation) return !1;
|
|
222
|
-
e === null || e === "unreadable" ? this.remember(r) : this.accept(r, e);
|
|
281
|
+
e === null || e === "unreadable" || e === "held" ? this.remember(r) : this.accept(r, e);
|
|
223
282
|
}
|
|
224
283
|
return this.next = i + 1, this.accept(i, a), !0;
|
|
225
284
|
}
|
|
@@ -237,7 +296,7 @@ var V = {
|
|
|
237
296
|
async readMissed(e) {
|
|
238
297
|
let t = this.settings.now();
|
|
239
298
|
for (let [e, n] of this.missed) t - n >= this.settings.missedExpiryMs && (this.missed.delete(e), this.events.skipped(e, "unreachable", "not served within the time a stepped-past slot is kept"));
|
|
240
|
-
let n = [...this.missed.keys()].slice(0, this.settings.missedReadsPerPoll);
|
|
299
|
+
let n = [...this.missed.keys()].filter((e) => this.pacer.mayRead(e, t)).slice(0, this.settings.missedReadsPerPoll);
|
|
241
300
|
for (let t of n) {
|
|
242
301
|
let n = await this.read(t);
|
|
243
302
|
if (e !== this.generation) return;
|
|
@@ -246,16 +305,16 @@ var V = {
|
|
|
246
305
|
}
|
|
247
306
|
}
|
|
248
307
|
accept(e, t) {
|
|
249
|
-
let n =
|
|
250
|
-
n.ok ? this.events.entry(n.value) : this.events.skipped(e, n.reason, n.detail);
|
|
308
|
+
let n = E(t, e, this.topic);
|
|
309
|
+
n.ok ? (this.notes?.clock.observe(n.value.at, this.settings.now()), this.events.entry(n.value)) : this.events.skipped(e, n.reason, n.detail);
|
|
251
310
|
}
|
|
252
311
|
gatewayFailed(e) {
|
|
253
|
-
this.gatewayFailures++, this.setStatus(
|
|
312
|
+
this.gatewayFailures++, this.setStatus(Y.RECONNECTING), this.events.error(e);
|
|
254
313
|
}
|
|
255
314
|
gatewayAnswered() {
|
|
256
315
|
this.gatewayFailures = 0;
|
|
257
316
|
let e = this.settings.now(), t = [...this.missed.values()].some((t) => e - t >= this.settings.stallAfterMs);
|
|
258
|
-
this.setStatus(t ?
|
|
317
|
+
this.setStatus(t ? Y.STALLED : Y.LIVE);
|
|
259
318
|
}
|
|
260
319
|
backoffMs() {
|
|
261
320
|
let { pollIntervalMs: e, backoffCapMs: t, random: n } = this.settings, r = Math.min(t, e * 2 ** this.gatewayFailures);
|
|
@@ -264,36 +323,52 @@ var V = {
|
|
|
264
323
|
setStatus(e) {
|
|
265
324
|
e !== this.status && (this.status = e, this.events.status(e));
|
|
266
325
|
}
|
|
267
|
-
},
|
|
268
|
-
constructor(e, t, n) {
|
|
269
|
-
this.source = e, this.topic = t, this.events = n, this.older = null, this.loading = null;
|
|
326
|
+
}, ce = 16, le = class {
|
|
327
|
+
constructor(e, t, n, r = null) {
|
|
328
|
+
this.source = e, this.topic = t, this.events = n, this.notes = r, this.older = null, this.loading = null;
|
|
270
329
|
}
|
|
271
330
|
async open() {
|
|
272
331
|
this.older = null;
|
|
273
|
-
let e = await this.
|
|
274
|
-
if (e
|
|
332
|
+
let e = await this.newestNote();
|
|
333
|
+
if (e !== null) return this.openAt(e.newest, e);
|
|
334
|
+
let t = await this.readHead();
|
|
335
|
+
return t === null ? {
|
|
275
336
|
startAt: 0,
|
|
276
|
-
rows: []
|
|
337
|
+
rows: [],
|
|
338
|
+
notes: null
|
|
339
|
+
} : this.openAt(t.index, null, t.payload);
|
|
340
|
+
}
|
|
341
|
+
async newestNote() {
|
|
342
|
+
if (this.notes === null) return null;
|
|
343
|
+
let e = this.notes.lastReadableSlot(), t = await this.notes.scan(e, e - this.notes.lookBackSlots + 1);
|
|
344
|
+
return t === null ? null : {
|
|
345
|
+
newest: t.note.newest,
|
|
346
|
+
nextNoteSlot: e + 1
|
|
277
347
|
};
|
|
278
|
-
|
|
279
|
-
|
|
348
|
+
}
|
|
349
|
+
async openAt(e, t, n) {
|
|
350
|
+
let r = e < 0 ? null : await this.newestLink(e, n);
|
|
351
|
+
if (r === null) return {
|
|
280
352
|
startAt: 0,
|
|
281
|
-
rows: []
|
|
353
|
+
rows: [],
|
|
354
|
+
notes: t
|
|
282
355
|
};
|
|
283
|
-
let
|
|
284
|
-
return
|
|
356
|
+
let i = await this.readFile(r);
|
|
357
|
+
return i === "refused" ? {
|
|
285
358
|
startAt: 0,
|
|
286
|
-
rows: []
|
|
359
|
+
rows: [],
|
|
360
|
+
notes: t
|
|
287
361
|
} : {
|
|
288
|
-
startAt:
|
|
289
|
-
rows:
|
|
362
|
+
startAt: r.toSeq + 1,
|
|
363
|
+
rows: i ?? [],
|
|
364
|
+
notes: t
|
|
290
365
|
};
|
|
291
366
|
}
|
|
292
367
|
async readHead() {
|
|
293
368
|
try {
|
|
294
369
|
return await this.source.readHead();
|
|
295
370
|
} catch (e) {
|
|
296
|
-
if (e instanceof
|
|
371
|
+
if (e instanceof H) return this.events.error(e), null;
|
|
297
372
|
throw e;
|
|
298
373
|
}
|
|
299
374
|
}
|
|
@@ -308,27 +383,30 @@ var V = {
|
|
|
308
383
|
async loadOlderOnce() {
|
|
309
384
|
let e = this.older;
|
|
310
385
|
if (e === null) return [];
|
|
311
|
-
let t = await this.source.readFile(e.ref), n =
|
|
386
|
+
let t = await this.source.readFile(e.ref), n = D(t, this.topic, e);
|
|
312
387
|
if (!n.ok) throw this.older = null, Error(`history file ${e.ref} refused (${n.reason}): ${n.detail}`);
|
|
313
388
|
return this.report(n.value.skipped), this.older = n.value.prev, n.value.rows;
|
|
314
389
|
}
|
|
315
390
|
async newestLink(e, t) {
|
|
316
|
-
let n =
|
|
317
|
-
if (
|
|
318
|
-
|
|
391
|
+
let n = t === void 0 ? e : e - 1;
|
|
392
|
+
if (t !== void 0) {
|
|
393
|
+
let n = E(t, e, this.topic);
|
|
394
|
+
if (n.ok) return n.value.history;
|
|
395
|
+
}
|
|
396
|
+
for (let t = n; t >= Math.max(0, e - ce); t--) {
|
|
319
397
|
let e = await this.source.readSlot(t).catch((e) => {
|
|
320
|
-
if (e instanceof
|
|
398
|
+
if (e instanceof U) return null;
|
|
321
399
|
throw e;
|
|
322
400
|
});
|
|
323
401
|
if (e === null) continue;
|
|
324
|
-
let n =
|
|
402
|
+
let n = E(e, t, this.topic);
|
|
325
403
|
if (n.ok) return n.value.history;
|
|
326
404
|
}
|
|
327
405
|
return null;
|
|
328
406
|
}
|
|
329
407
|
async readFile(e) {
|
|
330
408
|
try {
|
|
331
|
-
let t =
|
|
409
|
+
let t = D(await this.source.readFile(e.ref), this.topic, e);
|
|
332
410
|
return t.ok ? (this.report(t.value.skipped), this.older = t.value.prev, t.value.rows) : (this.events.error(/* @__PURE__ */ Error(`history file ${e.ref} refused (${t.reason}): ${t.detail}`)), "refused");
|
|
333
411
|
} catch (t) {
|
|
334
412
|
return this.events.error(t), this.older = e, null;
|
|
@@ -337,20 +415,94 @@ var V = {
|
|
|
337
415
|
report(e) {
|
|
338
416
|
e > 0 && this.events.skipped(e);
|
|
339
417
|
}
|
|
340
|
-
},
|
|
418
|
+
}, ue = {
|
|
419
|
+
slotMs: n,
|
|
420
|
+
heartbeatMs: t,
|
|
421
|
+
marginMs: 1e3,
|
|
422
|
+
scanBatch: 4,
|
|
423
|
+
clockLimitMs: 3e5,
|
|
424
|
+
missingReadSpacingMs: B
|
|
425
|
+
};
|
|
426
|
+
function Z(e) {
|
|
427
|
+
return typeof e.readNote == "function";
|
|
428
|
+
}
|
|
429
|
+
var de = class {
|
|
430
|
+
constructor(e) {
|
|
431
|
+
this.limitMs = e, this.aheadAtMost = Infinity, this.trusted = !0;
|
|
432
|
+
}
|
|
433
|
+
observe(e, t) {
|
|
434
|
+
this.aheadAtMost = Math.min(this.aheadAtMost, t - e);
|
|
435
|
+
}
|
|
436
|
+
distrust() {
|
|
437
|
+
this.trusted = !1;
|
|
438
|
+
}
|
|
439
|
+
get isTrusted() {
|
|
440
|
+
return this.trusted;
|
|
441
|
+
}
|
|
442
|
+
get ms() {
|
|
443
|
+
let e = Number.isFinite(this.aheadAtMost), t = this.trusted || !e ? Math.min(0, this.aheadAtMost) : this.aheadAtMost;
|
|
444
|
+
return Math.max(-this.limitMs, Math.min(this.limitMs, t));
|
|
445
|
+
}
|
|
446
|
+
}, fe = class {
|
|
447
|
+
constructor(e, t, n) {
|
|
448
|
+
this.source = e, this.now = n, this.counts = {
|
|
449
|
+
found: 0,
|
|
450
|
+
empty: 0
|
|
451
|
+
}, this.settings = {
|
|
452
|
+
...ue,
|
|
453
|
+
...t
|
|
454
|
+
}, this.clock = new de(this.settings.clockLimitMs), this.pacer = new V(this.settings.missingReadSpacingMs, n);
|
|
455
|
+
}
|
|
456
|
+
lastReadableSlot(e = this.now()) {
|
|
457
|
+
return w(e - this.settings.marginMs - this.clock.ms, this.settings.slotMs) - 1;
|
|
458
|
+
}
|
|
459
|
+
readableAt(e) {
|
|
460
|
+
return C(e, this.settings.slotMs) + this.settings.marginMs + this.clock.ms;
|
|
461
|
+
}
|
|
462
|
+
get lookBackSlots() {
|
|
463
|
+
return Math.ceil(this.settings.heartbeatMs / this.settings.slotMs) + 2;
|
|
464
|
+
}
|
|
465
|
+
get silenceMs() {
|
|
466
|
+
return this.settings.heartbeatMs + 2 * this.settings.slotMs + this.settings.marginMs;
|
|
467
|
+
}
|
|
468
|
+
async read(e) {
|
|
469
|
+
if (!this.pacer.mayRead(e)) return null;
|
|
470
|
+
let t;
|
|
471
|
+
try {
|
|
472
|
+
t = await this.source.readNote(e), t === null && this.pacer.missed(e);
|
|
473
|
+
} catch (e) {
|
|
474
|
+
if (!(e instanceof U)) throw e;
|
|
475
|
+
t = null;
|
|
476
|
+
}
|
|
477
|
+
let n = t === null ? null : O(t);
|
|
478
|
+
return n === null ? (this.counts.empty++, null) : (this.counts.found++, this.clock.observe(n.writtenAt, this.now()), n);
|
|
479
|
+
}
|
|
480
|
+
async scan(e, t) {
|
|
481
|
+
for (let n = e; n >= t; n -= this.settings.scanBatch) {
|
|
482
|
+
let e = [];
|
|
483
|
+
for (let r = n; r > n - this.settings.scanBatch && r >= t; r--) e.push(r);
|
|
484
|
+
let r = await Promise.all(e.map((e) => this.read(e))), i = r.findIndex((e) => e !== null);
|
|
485
|
+
if (i >= 0) return {
|
|
486
|
+
slot: e[i],
|
|
487
|
+
note: r[i]
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
return null;
|
|
491
|
+
}
|
|
492
|
+
}, Q = {
|
|
341
493
|
resendAfterMs: 1e4,
|
|
342
494
|
maxResends: 5,
|
|
343
495
|
reactionWindowMs: 1e3,
|
|
344
496
|
isLive: () => !0
|
|
345
|
-
},
|
|
346
|
-
constructor(e, t, n, r, i =
|
|
497
|
+
}, pe = class {
|
|
498
|
+
constructor(e, t, n, r, i = Q) {
|
|
347
499
|
this.key = e, this.name = t, this.write = n, this.events = r, this.settings = i, this.outgoing = /* @__PURE__ */ new Map(), this.reactions = /* @__PURE__ */ new Map(), this.stopped = !1;
|
|
348
500
|
}
|
|
349
501
|
get address() {
|
|
350
502
|
return this.key.publicKey().address().toHex();
|
|
351
503
|
}
|
|
352
504
|
send(e) {
|
|
353
|
-
let { message: t, bytes: n } =
|
|
505
|
+
let { message: t, bytes: n } = h(this.key, {
|
|
354
506
|
...e,
|
|
355
507
|
name: this.name
|
|
356
508
|
}), r = {
|
|
@@ -378,7 +530,7 @@ var V = {
|
|
|
378
530
|
let i = this.reactions.get(r);
|
|
379
531
|
this.reactions.delete(r), i && i.taps % 2 == 1 && !this.stopped && this.send({
|
|
380
532
|
topic: e,
|
|
381
|
-
type:
|
|
533
|
+
type: u.REACTION,
|
|
382
534
|
target: t,
|
|
383
535
|
text: n
|
|
384
536
|
});
|
|
@@ -429,49 +581,56 @@ var V = {
|
|
|
429
581
|
clearTimer(e) {
|
|
430
582
|
e.timer &&= (clearTimeout(e.timer), null);
|
|
431
583
|
}
|
|
432
|
-
},
|
|
584
|
+
}, me = [
|
|
433
585
|
1e3,
|
|
434
586
|
2e3,
|
|
435
587
|
4e3,
|
|
436
588
|
8e3
|
|
437
|
-
],
|
|
438
|
-
function
|
|
589
|
+
], he = 3;
|
|
590
|
+
function $(e) {
|
|
439
591
|
return (e.startsWith("0x") ? e.slice(2) : e).toLowerCase();
|
|
440
592
|
}
|
|
441
|
-
var
|
|
593
|
+
var ge = class {
|
|
442
594
|
constructor(e, t = {}) {
|
|
443
|
-
this.emitter = new
|
|
595
|
+
this.emitter = new z(), this.seen = /* @__PURE__ */ new Set(), this.status = null, this.generation = 0, this.running = !1, this.starting = null, this.openTimer = null, this.wakeOpen = null;
|
|
444
596
|
let { user: n, infra: r } = e;
|
|
445
|
-
this.key = new
|
|
446
|
-
...
|
|
447
|
-
isLive: () => this.status ===
|
|
597
|
+
this.key = new N($(n.privateKey)), this.topic = r.chatTopic, this.nickname = n.nickname, this.openRetryMs = t.openRetryMs ?? me, this.senderSettings = {
|
|
598
|
+
...Q,
|
|
599
|
+
isLive: () => this.status === Y.LIVE,
|
|
448
600
|
...t.sender
|
|
449
601
|
};
|
|
450
602
|
let i = {
|
|
451
603
|
slotReadMs: r.socReadTimeout ?? 5e3,
|
|
452
604
|
feedReadMs: r.feedReadTimeout ?? 15e3,
|
|
453
605
|
writeMs: r.gsocWriteTimeout ?? 1e4
|
|
606
|
+
}, a = {
|
|
607
|
+
...r.noteSlotMs === void 0 ? {} : { slotMs: r.noteSlotMs },
|
|
608
|
+
...r.noteHeartbeatMs === void 0 ? {} : { heartbeatMs: r.noteHeartbeatMs },
|
|
609
|
+
...t.notes
|
|
454
610
|
};
|
|
455
|
-
this.source = t.source ??
|
|
611
|
+
this.source = t.source ?? K(new j(r.beeUrl), $(r.chatAddress), r.chatTopic, i, a.slotMs), this.write = t.write ?? J(new j(r.writeUrl ?? r.beeUrl), r.stamp ? $(r.stamp) : ae, $(r.gsocResourceId), r.gsocTopic, i);
|
|
612
|
+
let o = t.follower?.now ?? (() => Date.now()), s = {
|
|
613
|
+
pollIntervalMs: r.pollingInterval ?? 1e3,
|
|
614
|
+
...t.follower,
|
|
615
|
+
now: o
|
|
616
|
+
}, c = this.source;
|
|
617
|
+
this.notes = Z(c) ? new fe(c, a, o) : null, this.follower = new se(this.source, this.topic, {
|
|
456
618
|
entry: (e) => this.show(e),
|
|
457
|
-
skipped: (e, t, n) => this.emitter.emit(
|
|
619
|
+
skipped: (e, t, n) => this.emitter.emit(F.MESSAGE_SKIPPED, {
|
|
458
620
|
index: e,
|
|
459
621
|
reason: t,
|
|
460
622
|
detail: n
|
|
461
623
|
}),
|
|
462
624
|
status: (e) => this.setStatus(e),
|
|
463
|
-
error: (e) => this.emitter.emit(
|
|
464
|
-
}, {
|
|
465
|
-
|
|
466
|
-
...t.follower
|
|
467
|
-
}), this.history = new K(this.source, this.topic, {
|
|
468
|
-
skipped: (e) => this.emitter.emit(O.MESSAGE_SKIPPED, {
|
|
625
|
+
error: (e) => this.emitter.emit(F.ERROR, e)
|
|
626
|
+
}, s, this.notes), this.history = new le(this.source, this.topic, {
|
|
627
|
+
skipped: (e) => this.emitter.emit(F.MESSAGE_SKIPPED, {
|
|
469
628
|
index: -1,
|
|
470
629
|
reason: "history-row",
|
|
471
630
|
detail: `${e} rows of a history file`
|
|
472
631
|
}),
|
|
473
|
-
error: (e) => this.emitter.emit(
|
|
474
|
-
}), this.sender = this.makeSender();
|
|
632
|
+
error: (e) => this.emitter.emit(F.ERROR, e)
|
|
633
|
+
}, this.notes), this.sender = this.makeSender();
|
|
475
634
|
}
|
|
476
635
|
getEmitter() {
|
|
477
636
|
return this.emitter;
|
|
@@ -494,11 +653,11 @@ var Q = class {
|
|
|
494
653
|
this.running = !1, this.generation++, this.openTimer &&= (clearTimeout(this.openTimer), null), this.wakeOpen?.(), this.follower.stop(), this.sender.stop();
|
|
495
654
|
}
|
|
496
655
|
async sendMessage(e, t, n) {
|
|
497
|
-
if (t ===
|
|
656
|
+
if (t === u.REACTION) {
|
|
498
657
|
if (!n) throw Error("a reaction names the message it reacts to");
|
|
499
658
|
return this.sender.react(this.topic, n, e), null;
|
|
500
659
|
}
|
|
501
|
-
return
|
|
660
|
+
return I(this.sender.send({
|
|
502
661
|
topic: this.topic,
|
|
503
662
|
type: t,
|
|
504
663
|
target: n ?? "",
|
|
@@ -509,12 +668,12 @@ var Q = class {
|
|
|
509
668
|
return this.sender.retry(typeof e == "string" ? e : e.id);
|
|
510
669
|
}
|
|
511
670
|
async fetchPreviousMessages() {
|
|
512
|
-
this.emitter.emit(
|
|
671
|
+
this.emitter.emit(F.LOADING_PREVIOUS_MESSAGES, !0);
|
|
513
672
|
try {
|
|
514
673
|
let e = this.generation, t = await this.history.loadOlder();
|
|
515
674
|
return e === this.generation ? this.showRows(t) : [];
|
|
516
675
|
} finally {
|
|
517
|
-
this.emitter.emit(
|
|
676
|
+
this.emitter.emit(F.LOADING_PREVIOUS_MESSAGES, !1);
|
|
518
677
|
}
|
|
519
678
|
}
|
|
520
679
|
hasPreviousMessages() {
|
|
@@ -524,16 +683,16 @@ var Q = class {
|
|
|
524
683
|
return [...e].sort((e, t) => e.index >= 0 && t.index >= 0 ? e.index - t.index : e.index >= 0 || t.index >= 0 ? e.index >= 0 ? -1 : 1 : e.timestamp - t.timestamp);
|
|
525
684
|
}
|
|
526
685
|
async open(e) {
|
|
527
|
-
this.emitter.emit(
|
|
686
|
+
this.emitter.emit(F.LOADING_INIT, !0);
|
|
528
687
|
let t = 0;
|
|
529
688
|
for (; e === this.generation;) try {
|
|
530
689
|
let t = await this.history.open();
|
|
531
690
|
if (e !== this.generation) return;
|
|
532
|
-
this.showRows(t.rows), this.follower.start(t.startAt), this.emitter.emit(
|
|
691
|
+
this.showRows(t.rows), this.follower.start(t.startAt, t.notes), this.emitter.emit(F.LOADING_INIT, !1);
|
|
533
692
|
return;
|
|
534
693
|
} catch (n) {
|
|
535
694
|
if (e !== this.generation) return;
|
|
536
|
-
t++, this.emitter.emit(
|
|
695
|
+
t++, this.emitter.emit(F.ERROR, n), this.setStatus(Y.RECONNECTING), t === he && this.emitter.emit(F.CRITICAL_ERROR, n), await this.waitToOpen(this.openRetryMs[Math.min(t, this.openRetryMs.length) - 1] ?? 8e3);
|
|
537
696
|
}
|
|
538
697
|
}
|
|
539
698
|
waitToOpen(e) {
|
|
@@ -546,31 +705,31 @@ var Q = class {
|
|
|
546
705
|
});
|
|
547
706
|
}
|
|
548
707
|
makeSender() {
|
|
549
|
-
return new
|
|
550
|
-
pending: (e) => this.emitter.emit(
|
|
551
|
-
written: (e) => this.emitter.emit(
|
|
708
|
+
return new pe(this.key, this.nickname, this.write, {
|
|
709
|
+
pending: (e) => this.emitter.emit(F.MESSAGE_REQUEST_INITIATED, I(e)),
|
|
710
|
+
written: (e) => this.emitter.emit(F.MESSAGE_REQUEST_UPLOADED, I(e)),
|
|
552
711
|
failed: (e, t) => {
|
|
553
|
-
this.emitter.emit(
|
|
712
|
+
this.emitter.emit(F.ERROR, t), this.emitter.emit(F.MESSAGE_REQUEST_ERROR, I(e));
|
|
554
713
|
},
|
|
555
714
|
confirmed: () => {}
|
|
556
715
|
}, this.senderSettings);
|
|
557
716
|
}
|
|
558
717
|
show(e) {
|
|
559
|
-
this.seen.has(e.seq) || (this.seen.add(e.seq), this.sender.confirm(e.msg), this.emitter.emit(
|
|
718
|
+
this.seen.has(e.seq) || (this.seen.add(e.seq), this.sender.confirm(e.msg), this.emitter.emit(F.MESSAGE_RECEIVED, L(e)));
|
|
560
719
|
}
|
|
561
720
|
showRows(e) {
|
|
562
721
|
let t = [];
|
|
563
722
|
for (let n of e) {
|
|
564
723
|
if (this.seen.has(n.seq)) continue;
|
|
565
724
|
this.seen.add(n.seq), this.sender.confirm(n.msg);
|
|
566
|
-
let e =
|
|
567
|
-
t.push(e), this.emitter.emit(
|
|
725
|
+
let e = L(n);
|
|
726
|
+
t.push(e), this.emitter.emit(F.MESSAGE_RECEIVED, e);
|
|
568
727
|
}
|
|
569
728
|
return t;
|
|
570
729
|
}
|
|
571
730
|
setStatus(e) {
|
|
572
|
-
e !== this.status && (this.status = e, this.emitter.emit(
|
|
731
|
+
e !== this.status && (this.status = e, this.emitter.emit(F.STATUS, e));
|
|
573
732
|
}
|
|
574
733
|
};
|
|
575
734
|
//#endregion
|
|
576
|
-
export {
|
|
735
|
+
export { z as ChatEmitter, e as ChatMessageError, t as DEFAULT_NOTE_HEARTBEAT_MS, n as DEFAULT_NOTE_SLOT_MS, F as EVENTS, Y as FeedStatus, H as HeadLookupTimeoutError, r as MAX_ENTRY_BYTES, i as MAX_MESSAGE_BYTES, a as MAX_NAME_CHARACTERS, o as MAX_NOTE_BYTES, s as MAX_TEXT_CHARACTERS, c as MAX_TOPIC_CHARACTERS, l as MESSAGE_VERSION, u as MessageType, d as NOTE_VERSION, ge as SwarmChat, X as UnreadableGatewayError, U as UnreadableSlotError, f as chatMessageSchema, p as checkChatMessage, m as countCharacters, h as createChatMessage, g as encodeChatMessage, _ as encodeSlotNote, ee as feedEntrySchema, te as hasValidSignature, ne as historyFileSchema, v as historyLinkSchema, y as historyRowSchema, b as newMessageId, x as noteAddress, S as noteIdentifier, re as noteIdentifierText, C as noteSlotEnd, w as noteSlotOf, T as parseChatMessage, E as parseFeedEntry, D as parseHistoryFile, O as parseSlotNote, k as signedBytes, A as slotNoteSchema };
|