dropspace 0.0.0-stage → 0.1.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.
Files changed (63) hide show
  1. package/README.md +17 -2
  2. package/dist/automerge/index.d.ts +103 -0
  3. package/dist/automerge/index.d.ts.map +1 -0
  4. package/dist/automerge/index.js +394 -0
  5. package/dist/automerge/index.js.map +1 -0
  6. package/dist/client/channel.d.ts +131 -0
  7. package/dist/client/channel.d.ts.map +1 -0
  8. package/dist/client/channel.js +566 -0
  9. package/dist/client/channel.js.map +1 -0
  10. package/dist/client/client.d.ts +310 -0
  11. package/dist/client/client.d.ts.map +1 -0
  12. package/dist/client/client.js +1176 -0
  13. package/dist/client/client.js.map +1 -0
  14. package/dist/client/events.d.ts +14 -0
  15. package/dist/client/events.d.ts.map +1 -0
  16. package/dist/client/events.js +71 -0
  17. package/dist/client/events.js.map +1 -0
  18. package/dist/client/identity.d.ts +89 -0
  19. package/dist/client/identity.d.ts.map +1 -0
  20. package/dist/client/identity.js +274 -0
  21. package/dist/client/identity.js.map +1 -0
  22. package/dist/client/index.d.ts +8 -0
  23. package/dist/client/index.d.ts.map +1 -0
  24. package/dist/client/index.js +8 -0
  25. package/dist/client/index.js.map +1 -0
  26. package/dist/client/peer-connection.d.ts +182 -0
  27. package/dist/client/peer-connection.d.ts.map +1 -0
  28. package/dist/client/peer-connection.js +593 -0
  29. package/dist/client/peer-connection.js.map +1 -0
  30. package/dist/client/peer-selection.d.ts +70 -0
  31. package/dist/client/peer-selection.d.ts.map +1 -0
  32. package/dist/client/peer-selection.js +193 -0
  33. package/dist/client/peer-selection.js.map +1 -0
  34. package/dist/client/storage.d.ts +118 -0
  35. package/dist/client/storage.d.ts.map +1 -0
  36. package/dist/client/storage.js +463 -0
  37. package/dist/client/storage.js.map +1 -0
  38. package/dist/files/index.d.ts +136 -0
  39. package/dist/files/index.d.ts.map +1 -0
  40. package/dist/files/index.js +701 -0
  41. package/dist/files/index.js.map +1 -0
  42. package/dist/files/sha256.d.ts +24 -0
  43. package/dist/files/sha256.d.ts.map +1 -0
  44. package/dist/files/sha256.js +133 -0
  45. package/dist/files/sha256.js.map +1 -0
  46. package/dist/index.d.ts +4 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +4 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/protocol/envelope.d.ts +61 -0
  51. package/dist/protocol/envelope.d.ts.map +1 -0
  52. package/dist/protocol/envelope.js +260 -0
  53. package/dist/protocol/envelope.js.map +1 -0
  54. package/dist/protocol/framing.d.ts +56 -0
  55. package/dist/protocol/framing.d.ts.map +1 -0
  56. package/dist/protocol/framing.js +93 -0
  57. package/dist/protocol/framing.js.map +1 -0
  58. package/dist/protocol/index.d.ts +3 -0
  59. package/dist/protocol/index.d.ts.map +1 -0
  60. package/dist/protocol/index.js +3 -0
  61. package/dist/protocol/index.js.map +1 -0
  62. package/fixtures/envelopes.json +132 -0
  63. package/package.json +43 -4
@@ -0,0 +1,566 @@
1
+ import { encodeWireFrame, decodeWireFrame, encodeJsonPayload, decodeJsonPayload, WireFrameType, DEFAULT_MAX_FRAME_PAYLOAD_BYTES, } from "../protocol/index.js";
2
+ import { TypedEventEmitter } from "./events.js";
3
+ export class MessagingError extends Error {
4
+ code;
5
+ constructor(message, code) {
6
+ super(message);
7
+ this.code = code;
8
+ this.name = "MessagingError";
9
+ }
10
+ }
11
+ let msgCounter = 0;
12
+ function nextMessageId(prefix = "msg") {
13
+ msgCounter = (msgCounter + 1) % 1_000_000_000;
14
+ return `${prefix}_${Date.now().toString(36)}_${msgCounter.toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
15
+ }
16
+ /**
17
+ * Reliable binary-first framing, chunking, backpressure queue, and optional application ACK engine
18
+ * over an underlying `RTCDataChannel` (Section 13).
19
+ *
20
+ * Important Transport Note:
21
+ * Even an ordered, reliable `RTCDataChannel` only guarantees SCTP in-order delivery within a single
22
+ * active transport association. Across reconnects or new `RTCPeerConnection` instances, in-flight
23
+ * SCTP packets can be lost or re-sent. Enable `ack: "received" | "persisted" | "processed"` when
24
+ * application-level delivery confirmation and deduplication across retries are required.
25
+ */
26
+ export class PeerChannelMultiplexer {
27
+ options;
28
+ events = new TypedEventEmitter();
29
+ dataChannel = null;
30
+ maxFramePayloadBytes;
31
+ highWaterMark;
32
+ lowWaterMark;
33
+ maxQueueFrames;
34
+ maxQueueBytes;
35
+ dedupWindowMs;
36
+ maxDedupEntries;
37
+ sendQueue = [];
38
+ queuedBytes = 0;
39
+ isFlushing = false;
40
+ backpressurePaused = false;
41
+ closed = false;
42
+ pendingAcks = new Map();
43
+ seenMessageIds = new Map();
44
+ partialAssemblies = new Map();
45
+ boundOnMessage;
46
+ boundOnBufferedAmountLow;
47
+ boundOnClose;
48
+ constructor(options) {
49
+ this.options = options;
50
+ this.maxFramePayloadBytes =
51
+ options.maxFramePayloadBytes ?? DEFAULT_MAX_FRAME_PAYLOAD_BYTES;
52
+ this.highWaterMark = options.bufferedAmountHighWaterMark ?? 256 * 1024; // 256 KiB
53
+ this.lowWaterMark = options.bufferedAmountLowWaterMark ?? 64 * 1024; // 64 KiB
54
+ this.maxQueueFrames = options.maxSendQueueFrames ?? 2048;
55
+ this.maxQueueBytes = options.maxSendQueueBytes ?? 16 * 1024 * 1024; // 16 MiB
56
+ this.dedupWindowMs = options.dedupWindowMs ?? 120_000;
57
+ this.maxDedupEntries = options.maxDedupEntries ?? 4096;
58
+ this.boundOnMessage = (ev) => this.handleIncomingRaw(ev.data);
59
+ this.boundOnBufferedAmountLow = () => {
60
+ this.backpressurePaused = false;
61
+ this.events.emit("backpressureChange", {
62
+ bufferedAmount: this.dataChannel?.bufferedAmount ?? 0,
63
+ queuedBytes: this.queuedBytes,
64
+ paused: false,
65
+ });
66
+ void this.flushQueue();
67
+ };
68
+ this.boundOnClose = () => {
69
+ this.rejectQueuedFrames(new MessagingError("DataChannel closed while frames were queued", "CHANNEL_CLOSED"));
70
+ this.events.emit("close", undefined);
71
+ };
72
+ }
73
+ attachDataChannel(dc) {
74
+ this.detachDataChannel();
75
+ this.closed = false;
76
+ this.dataChannel = dc;
77
+ if ("binaryType" in dc) {
78
+ dc.binaryType = "arraybuffer";
79
+ }
80
+ dc.bufferedAmountLowThreshold = this.lowWaterMark;
81
+ dc.addEventListener("message", this.boundOnMessage);
82
+ dc.addEventListener("bufferedamountlow", this.boundOnBufferedAmountLow);
83
+ dc.addEventListener("close", this.boundOnClose);
84
+ if (dc.readyState === "open") {
85
+ void this.flushQueue();
86
+ }
87
+ }
88
+ detachDataChannel() {
89
+ if (!this.dataChannel)
90
+ return;
91
+ this.dataChannel.removeEventListener("message", this.boundOnMessage);
92
+ this.dataChannel.removeEventListener("bufferedamountlow", this.boundOnBufferedAmountLow);
93
+ this.dataChannel.removeEventListener("close", this.boundOnClose);
94
+ this.dataChannel = null;
95
+ }
96
+ getQueueMetrics() {
97
+ return {
98
+ queuedFrames: this.sendQueue.length,
99
+ queuedBytes: this.queuedBytes,
100
+ bufferedAmount: this.dataChannel?.bufferedAmount ?? 0,
101
+ };
102
+ }
103
+ async sendBinary(payload, options = {}) {
104
+ return this.sendInternal(WireFrameType.MESSAGE_BINARY, payload, options);
105
+ }
106
+ async sendJson(value, options = {}) {
107
+ const bytes = encodeJsonPayload(value);
108
+ return this.sendInternal(WireFrameType.MESSAGE_JSON, bytes, options);
109
+ }
110
+ async sendRawWireFrame(frameType, header, payload = new Uint8Array(0), signal) {
111
+ const encoded = encodeWireFrame(frameType, header, payload);
112
+ await this.enqueueEncodedFrame(encoded, signal);
113
+ }
114
+ async sendInternal(frameType, payload, options) {
115
+ if (this.closed) {
116
+ throw new MessagingError("Channel multiplexer is closed", "CHANNEL_CLOSED");
117
+ }
118
+ if (options.signal?.aborted) {
119
+ throw new MessagingError("Message send aborted before start", "ABORTED");
120
+ }
121
+ const messageId = options.messageId ?? nextMessageId("msg");
122
+ const channel = options.channel ?? "default";
123
+ const ackMode = options.ack ? options.ack : undefined;
124
+ const maxRetries = options.maxRetries ?? (ackMode ? 2 : 0);
125
+ const ackTimeoutMs = options.ackTimeoutMs ?? options.timeoutMs ?? 5000;
126
+ const totalChunks = Math.max(1, Math.ceil(payload.byteLength / this.maxFramePayloadBytes));
127
+ const sendAllChunksOnce = async () => {
128
+ for (let i = 0; i < totalChunks; i++) {
129
+ if (options.signal?.aborted) {
130
+ throw new MessagingError("Message send aborted during chunking", "ABORTED");
131
+ }
132
+ const start = i * this.maxFramePayloadBytes;
133
+ const end = Math.min(payload.byteLength, start + this.maxFramePayloadBytes);
134
+ const slice = payload.subarray(start, end);
135
+ const header = {
136
+ messageId,
137
+ channel,
138
+ timestamp: Date.now(),
139
+ chunkIndex: i,
140
+ totalChunks,
141
+ totalByteLength: payload.byteLength,
142
+ ackRequired: Boolean(ackMode) && i === totalChunks - 1,
143
+ ackMode,
144
+ meta: options.meta,
145
+ };
146
+ let frameBytes = encodeWireFrame(frameType, header, slice);
147
+ if (options.viaHubDeviceId) {
148
+ // Wrap inside HUB_RELAY envelope
149
+ const relayHeader = {
150
+ messageId: `${messageId}_chunk_${i}`,
151
+ channel: "hub_relay",
152
+ timestamp: Date.now(),
153
+ sourceDeviceId: this.options.localDeviceId,
154
+ targetDeviceId: this.options.peerDeviceId,
155
+ spaceId: options.spaceId,
156
+ hopCount: 0,
157
+ maxHops: options.maxHops ?? 2,
158
+ };
159
+ frameBytes = encodeWireFrame(WireFrameType.HUB_RELAY, relayHeader, frameBytes);
160
+ }
161
+ await this.enqueueEncodedFrame(frameBytes, options.signal, options.timeoutMs);
162
+ }
163
+ };
164
+ if (!ackMode) {
165
+ await sendAllChunksOnce();
166
+ return { messageId };
167
+ }
168
+ let attempt = 0;
169
+ while (true) {
170
+ attempt++;
171
+ const ackPromise = this.waitForAck(messageId, ackMode, ackTimeoutMs, options.signal);
172
+ try {
173
+ await sendAllChunksOnce();
174
+ const confirmed = await ackPromise;
175
+ return { messageId, ackSemantics: confirmed };
176
+ }
177
+ catch (err) {
178
+ if (options.signal?.aborted) {
179
+ throw new MessagingError("Send aborted while awaiting ACK", "ABORTED");
180
+ }
181
+ if (attempt > maxRetries) {
182
+ throw err;
183
+ }
184
+ }
185
+ }
186
+ }
187
+ waitForAck(messageId, expectedSemantics, timeoutMs, signal) {
188
+ return new Promise((resolve, reject) => {
189
+ const existing = this.pendingAcks.get(messageId);
190
+ if (existing) {
191
+ clearTimeout(existing.timer);
192
+ }
193
+ let onAbort;
194
+ const cleanup = () => {
195
+ if (onAbort && signal) {
196
+ signal.removeEventListener("abort", onAbort);
197
+ }
198
+ };
199
+ const timer = setTimeout(() => {
200
+ this.pendingAcks.delete(messageId);
201
+ cleanup();
202
+ reject(new MessagingError(`Timed out waiting ${timeoutMs}ms for '${expectedSemantics}' ACK on message '${messageId}'`, "ACK_TIMEOUT"));
203
+ }, timeoutMs);
204
+ if (signal) {
205
+ onAbort = () => {
206
+ clearTimeout(timer);
207
+ this.pendingAcks.delete(messageId);
208
+ reject(new MessagingError("ACK wait aborted by AbortSignal", "ABORTED"));
209
+ };
210
+ signal.addEventListener("abort", onAbort, { once: true });
211
+ }
212
+ this.pendingAcks.set(messageId, {
213
+ messageId,
214
+ expectedSemantics,
215
+ resolve: (sem) => {
216
+ cleanup();
217
+ resolve(sem);
218
+ },
219
+ reject: (err) => {
220
+ cleanup();
221
+ reject(err);
222
+ },
223
+ timer,
224
+ });
225
+ });
226
+ }
227
+ enqueueEncodedFrame(bytes, signal, timeoutMs) {
228
+ if (this.closed) {
229
+ return Promise.reject(new MessagingError("Cannot send frame on closed multiplexer", "CHANNEL_CLOSED"));
230
+ }
231
+ if (signal?.aborted) {
232
+ return Promise.reject(new MessagingError("Frame send aborted", "ABORTED"));
233
+ }
234
+ if (this.sendQueue.length >= this.maxQueueFrames ||
235
+ this.queuedBytes + bytes.byteLength > this.maxQueueBytes) {
236
+ return Promise.reject(new MessagingError(`Send queue limit exceeded (${this.sendQueue.length} frames, ${this.queuedBytes} bytes)`, "QUEUE_OVERFLOW"));
237
+ }
238
+ return new Promise((resolve, reject) => {
239
+ let timeoutHandle;
240
+ const item = {
241
+ bytes,
242
+ resolve: () => {
243
+ if (timeoutHandle)
244
+ clearTimeout(timeoutHandle);
245
+ if (item.onAbort && signal) {
246
+ signal.removeEventListener("abort", item.onAbort);
247
+ }
248
+ resolve();
249
+ },
250
+ reject: (err) => {
251
+ if (timeoutHandle)
252
+ clearTimeout(timeoutHandle);
253
+ if (item.onAbort && signal) {
254
+ signal.removeEventListener("abort", item.onAbort);
255
+ }
256
+ reject(err);
257
+ },
258
+ signal,
259
+ };
260
+ if (signal) {
261
+ item.onAbort = () => {
262
+ const idx = this.sendQueue.indexOf(item);
263
+ if (idx !== -1) {
264
+ this.sendQueue.splice(idx, 1);
265
+ this.queuedBytes = Math.max(0, this.queuedBytes - bytes.byteLength);
266
+ }
267
+ item.reject(new MessagingError("Frame aborted while in send queue", "ABORTED"));
268
+ };
269
+ signal.addEventListener("abort", item.onAbort, { once: true });
270
+ }
271
+ if (timeoutMs && timeoutMs > 0) {
272
+ timeoutHandle = setTimeout(() => {
273
+ const idx = this.sendQueue.indexOf(item);
274
+ if (idx !== -1) {
275
+ this.sendQueue.splice(idx, 1);
276
+ this.queuedBytes = Math.max(0, this.queuedBytes - bytes.byteLength);
277
+ }
278
+ item.reject(new MessagingError(`Frame send timed out after ${timeoutMs}ms`, "TIMEOUT"));
279
+ }, timeoutMs);
280
+ }
281
+ this.sendQueue.push(item);
282
+ this.queuedBytes += bytes.byteLength;
283
+ void this.flushQueue();
284
+ });
285
+ }
286
+ async flushQueue() {
287
+ if (this.isFlushing || this.closed)
288
+ return;
289
+ if (!this.dataChannel || this.dataChannel.readyState !== "open")
290
+ return;
291
+ this.isFlushing = true;
292
+ try {
293
+ while (this.sendQueue.length > 0 && this.dataChannel && this.dataChannel.readyState === "open") {
294
+ if (this.dataChannel.bufferedAmount >= this.highWaterMark) {
295
+ this.backpressurePaused = true;
296
+ this.events.emit("backpressureChange", {
297
+ bufferedAmount: this.dataChannel.bufferedAmount,
298
+ queuedBytes: this.queuedBytes,
299
+ paused: true,
300
+ });
301
+ // Wait until bufferedAmount drops below highWaterMark (either via bufferedamountlow event or micro-poll fallback)
302
+ await this.waitForBufferDrain();
303
+ if (!this.dataChannel || this.dataChannel.readyState !== "open") {
304
+ break;
305
+ }
306
+ }
307
+ const next = this.sendQueue.shift();
308
+ if (!next)
309
+ break;
310
+ this.queuedBytes = Math.max(0, this.queuedBytes - next.bytes.byteLength);
311
+ if (next.signal?.aborted) {
312
+ next.reject(new MessagingError("Frame aborted before send", "ABORTED"));
313
+ continue;
314
+ }
315
+ try {
316
+ this.dataChannel.send(next.bytes);
317
+ next.resolve();
318
+ }
319
+ catch (err) {
320
+ next.reject(err instanceof Error
321
+ ? err
322
+ : new MessagingError(String(err), "CHANNEL_CLOSED"));
323
+ break;
324
+ }
325
+ }
326
+ }
327
+ finally {
328
+ this.isFlushing = false;
329
+ }
330
+ }
331
+ waitForBufferDrain() {
332
+ return new Promise((resolve) => {
333
+ if (!this.dataChannel || this.dataChannel.bufferedAmount <= this.lowWaterMark) {
334
+ this.backpressurePaused = false;
335
+ resolve();
336
+ return;
337
+ }
338
+ let resolved = false;
339
+ const done = () => {
340
+ if (resolved)
341
+ return;
342
+ resolved = true;
343
+ clearInterval(pollTimer);
344
+ this.dataChannel?.removeEventListener("bufferedamountlow", onLow);
345
+ this.backpressurePaused = false;
346
+ resolve();
347
+ };
348
+ const onLow = () => done();
349
+ this.dataChannel.addEventListener("bufferedamountlow", onLow);
350
+ const pollTimer = setInterval(() => {
351
+ if (!this.dataChannel ||
352
+ this.dataChannel.readyState !== "open" ||
353
+ this.dataChannel.bufferedAmount <= this.lowWaterMark) {
354
+ done();
355
+ }
356
+ }, 15);
357
+ });
358
+ }
359
+ handleIncomingRaw(rawData) {
360
+ let decoded;
361
+ try {
362
+ decoded = decodeWireFrame(rawData);
363
+ }
364
+ catch (err) {
365
+ this.events.emit("error", err instanceof Error ? err : new Error("Failed to decode wire frame"));
366
+ return;
367
+ }
368
+ this.options.onRawFrame?.(decoded);
369
+ switch (decoded.frameType) {
370
+ case WireFrameType.CONTROL_JSON: {
371
+ this.handleControlFrame(decoded);
372
+ break;
373
+ }
374
+ case WireFrameType.TRANSFER_CONTROL:
375
+ case WireFrameType.TRANSFER_CHUNK: {
376
+ this.events.emit("transferFrame", decoded);
377
+ break;
378
+ }
379
+ case WireFrameType.CRDT_SYNC: {
380
+ this.events.emit("crdtFrame", decoded);
381
+ break;
382
+ }
383
+ case WireFrameType.HUB_RELAY: {
384
+ this.events.emit("hubRelayFrame", decoded);
385
+ break;
386
+ }
387
+ case WireFrameType.MESSAGE_BINARY:
388
+ case WireFrameType.MESSAGE_JSON: {
389
+ this.handleApplicationFrame(decoded);
390
+ break;
391
+ }
392
+ }
393
+ }
394
+ handleControlFrame(frame) {
395
+ try {
396
+ const ctrl = decodeJsonPayload(frame.payload);
397
+ if (ctrl.type === "ack" && ctrl.ackForMessageId) {
398
+ const pending = this.pendingAcks.get(ctrl.ackForMessageId);
399
+ if (pending) {
400
+ const sem = ctrl.semantics ?? "received";
401
+ // Resolve if semantics satisfy expected level
402
+ if (pending.expectedSemantics === "received" ||
403
+ pending.expectedSemantics === sem ||
404
+ sem === "processed") {
405
+ clearTimeout(pending.timer);
406
+ this.pendingAcks.delete(ctrl.ackForMessageId);
407
+ pending.resolve(sem);
408
+ }
409
+ }
410
+ }
411
+ }
412
+ catch {
413
+ // Ignore malformed control payload
414
+ }
415
+ }
416
+ handleApplicationFrame(frame, routedViaHub) {
417
+ const { header, payload, frameType } = frame;
418
+ const totalChunks = header.totalChunks ?? 1;
419
+ const chunkIndex = header.chunkIndex ?? 0;
420
+ if (totalChunks <= 1) {
421
+ this.deliverReassembledMessage(frameType, header, payload, routedViaHub);
422
+ return;
423
+ }
424
+ let assembly = this.partialAssemblies.get(header.messageId);
425
+ if (!assembly) {
426
+ assembly = {
427
+ frameType,
428
+ header,
429
+ totalChunks,
430
+ chunks: new Map(),
431
+ receivedBytes: 0,
432
+ createdAt: Date.now(),
433
+ };
434
+ this.partialAssemblies.set(header.messageId, assembly);
435
+ }
436
+ if (!assembly.chunks.has(chunkIndex)) {
437
+ const copy = new Uint8Array(payload.byteLength);
438
+ copy.set(payload);
439
+ assembly.chunks.set(chunkIndex, copy);
440
+ assembly.receivedBytes += copy.byteLength;
441
+ }
442
+ if (header.ackRequired) {
443
+ assembly.header = header;
444
+ }
445
+ if (assembly.chunks.size === totalChunks) {
446
+ this.partialAssemblies.delete(header.messageId);
447
+ const fullBuffer = new Uint8Array(assembly.receivedBytes);
448
+ let offset = 0;
449
+ for (let i = 0; i < totalChunks; i++) {
450
+ const part = assembly.chunks.get(i);
451
+ if (!part)
452
+ return;
453
+ fullBuffer.set(part, offset);
454
+ offset += part.byteLength;
455
+ }
456
+ this.deliverReassembledMessage(assembly.frameType, assembly.header, fullBuffer, routedViaHub);
457
+ }
458
+ }
459
+ deliverHubUnwrappedFrame(innerFrame, hubDeviceId) {
460
+ if (innerFrame.frameType === WireFrameType.MESSAGE_BINARY ||
461
+ innerFrame.frameType === WireFrameType.MESSAGE_JSON) {
462
+ this.handleApplicationFrame(innerFrame, hubDeviceId);
463
+ }
464
+ else if (innerFrame.frameType === WireFrameType.TRANSFER_CONTROL ||
465
+ innerFrame.frameType === WireFrameType.TRANSFER_CHUNK) {
466
+ this.events.emit("transferFrame", innerFrame);
467
+ }
468
+ else if (innerFrame.frameType === WireFrameType.CRDT_SYNC) {
469
+ this.events.emit("crdtFrame", innerFrame);
470
+ }
471
+ else if (innerFrame.frameType === WireFrameType.CONTROL_JSON) {
472
+ this.handleControlFrame(innerFrame);
473
+ }
474
+ }
475
+ deliverReassembledMessage(frameType, header, fullPayload, routedViaHub) {
476
+ const now = Date.now();
477
+ this.pruneDeduplicationMap(now);
478
+ const sendAck = async (semantics = "received") => {
479
+ if (!header.ackRequired)
480
+ return;
481
+ const ackPayload = encodeJsonPayload({
482
+ type: "ack",
483
+ ackForMessageId: header.messageId,
484
+ semantics,
485
+ });
486
+ const ackHeader = {
487
+ messageId: nextMessageId("ack"),
488
+ channel: header.channel,
489
+ timestamp: Date.now(),
490
+ correlationId: header.messageId,
491
+ };
492
+ try {
493
+ await this.sendRawWireFrame(WireFrameType.CONTROL_JSON, ackHeader, ackPayload);
494
+ }
495
+ catch {
496
+ // Best-effort ACK reply
497
+ }
498
+ };
499
+ // Deduplicate by messageId within window
500
+ const seenAt = this.seenMessageIds.get(header.messageId);
501
+ if (seenAt !== undefined && now - seenAt < this.dedupWindowMs) {
502
+ // Still send ACK if peer retried because previous ACK was lost
503
+ if (header.ackRequired) {
504
+ void sendAck(header.ackMode ?? "received");
505
+ }
506
+ return;
507
+ }
508
+ this.seenMessageIds.set(header.messageId, now);
509
+ // Automatically send "received" ACK immediately if requested mode is "received"
510
+ if (header.ackRequired && (!header.ackMode || header.ackMode === "received")) {
511
+ void sendAck("received");
512
+ }
513
+ let parsedJson;
514
+ if (frameType === WireFrameType.MESSAGE_JSON) {
515
+ try {
516
+ parsedJson = decodeJsonPayload(fullPayload);
517
+ }
518
+ catch {
519
+ parsedJson = undefined;
520
+ }
521
+ }
522
+ this.events.emit("message", {
523
+ peerDeviceId: header.sourceDeviceId ?? this.options.peerDeviceId,
524
+ channel: header.channel,
525
+ messageId: header.messageId,
526
+ frameType,
527
+ header,
528
+ binary: fullPayload,
529
+ json: parsedJson,
530
+ routedViaHub,
531
+ acknowledge: sendAck,
532
+ });
533
+ }
534
+ pruneDeduplicationMap(now) {
535
+ if (this.seenMessageIds.size <= this.maxDedupEntries)
536
+ return;
537
+ for (const [id, ts] of this.seenMessageIds.entries()) {
538
+ if (now - ts >= this.dedupWindowMs || this.seenMessageIds.size > this.maxDedupEntries) {
539
+ this.seenMessageIds.delete(id);
540
+ }
541
+ }
542
+ }
543
+ rejectQueuedFrames(err) {
544
+ while (this.sendQueue.length > 0) {
545
+ const item = this.sendQueue.shift();
546
+ item.reject(err);
547
+ }
548
+ this.queuedBytes = 0;
549
+ }
550
+ close() {
551
+ if (this.closed)
552
+ return;
553
+ this.closed = true;
554
+ this.detachDataChannel();
555
+ this.rejectQueuedFrames(new MessagingError("PeerChannelMultiplexer closed", "CHANNEL_CLOSED"));
556
+ for (const pending of this.pendingAcks.values()) {
557
+ clearTimeout(pending.timer);
558
+ pending.reject(new MessagingError("Channel closed while awaiting ACK", "CHANNEL_CLOSED"));
559
+ }
560
+ this.pendingAcks.clear();
561
+ this.partialAssemblies.clear();
562
+ this.seenMessageIds.clear();
563
+ this.events.removeAllListeners();
564
+ }
565
+ }
566
+ //# sourceMappingURL=channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/client/channel.ts"],"names":[],"mappings":"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"}