@afterrealism/dendri-client 2.3.7 → 2.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/LICENSE +202 -21
- package/README.md +65 -72
- package/dist/{chunk-MJW5M75V.js → chunk-3CE674DE.js} +267 -24
- package/dist/chunk-3CE674DE.js.map +1 -0
- package/dist/dendri.browser.global.js +233 -18
- package/dist/dendri.browser.global.js.map +1 -1
- package/dist/dendri.cjs +266 -22
- package/dist/dendri.cjs.map +1 -1
- package/dist/dendri.d.cts +13 -4
- package/dist/dendri.d.ts +13 -4
- package/dist/dendri.js +3 -3
- package/dist/dendri.js.map +1 -1
- package/dist/dendri.min.global.js +13 -13
- package/dist/dendri.min.global.js.map +1 -1
- package/dist/serializer.msgpack.cjs +3 -3
- package/dist/serializer.msgpack.cjs.map +1 -1
- package/dist/serializer.msgpack.d.cts +31 -4
- package/dist/serializer.msgpack.d.ts +31 -4
- package/dist/serializer.msgpack.js +2 -2
- package/dist/serializer.msgpack.js.map +1 -1
- package/dist/{store-RTivRmUW.d.cts → store-C3Nwl62R.d.cts} +38 -5
- package/dist/{store-RTivRmUW.d.ts → store-C3Nwl62R.d.ts} +38 -5
- package/dist/store.cjs +256 -21
- package/dist/store.cjs.map +1 -1
- package/dist/store.d.cts +1 -1
- package/dist/store.d.ts +1 -1
- package/dist/store.js +1 -1
- package/package.json +8 -2
- package/dist/chunk-MJW5M75V.js.map +0 -1
|
@@ -3529,7 +3529,7 @@ var Util = class extends BinaryPackChunker {
|
|
|
3529
3529
|
var util = new Util();
|
|
3530
3530
|
|
|
3531
3531
|
// src/api.ts
|
|
3532
|
-
var version = "2.
|
|
3532
|
+
var version = "2.5.0";
|
|
3533
3533
|
var API = class _API {
|
|
3534
3534
|
constructor(_options) {
|
|
3535
3535
|
this._options = _options;
|
|
@@ -3542,6 +3542,7 @@ var API = class _API {
|
|
|
3542
3542
|
const url = new URL(`${protocol}://${host}:${port}${path}${key}/${method}`);
|
|
3543
3543
|
url.searchParams.set("ts", `${Date.now()}${Math.random()}`);
|
|
3544
3544
|
url.searchParams.set("version", version);
|
|
3545
|
+
if (this._options.apiKey) url.searchParams.set("api_key", this._options.apiKey);
|
|
3545
3546
|
const controller = new AbortController();
|
|
3546
3547
|
const timeoutId = setTimeout(() => controller.abort(), _API.FETCH_TIMEOUT);
|
|
3547
3548
|
return fetch(url.href, {
|
|
@@ -3566,15 +3567,16 @@ var API = class _API {
|
|
|
3566
3567
|
throw new Error(`Could not get an ID from the server.${pathError}`);
|
|
3567
3568
|
}
|
|
3568
3569
|
}
|
|
3569
|
-
/** Fetch TURN credentials from the signaling server's
|
|
3570
|
+
/** Fetch TURN credentials from the signaling server's turn-credentials endpoint. */
|
|
3570
3571
|
async getTurnCredentials() {
|
|
3571
3572
|
const protocol = this._options.secure ? "https" : "http";
|
|
3572
|
-
const { host, port } = this._options;
|
|
3573
|
-
const url = `${protocol}://${host}:${port}/turn
|
|
3573
|
+
const { host, port, path, key } = this._options;
|
|
3574
|
+
const url = new URL(`${protocol}://${host}:${port}${path}${key}/turn-credentials`);
|
|
3575
|
+
if (this._options.apiKey) url.searchParams.set("api_key", this._options.apiKey);
|
|
3574
3576
|
try {
|
|
3575
3577
|
const controller = new AbortController();
|
|
3576
3578
|
const timeoutId = setTimeout(() => controller.abort(), _API.FETCH_TIMEOUT);
|
|
3577
|
-
const response = await fetch(url, {
|
|
3579
|
+
const response = await fetch(url.href, {
|
|
3578
3580
|
referrerPolicy: this._options.referrerPolicy,
|
|
3579
3581
|
signal: controller.signal
|
|
3580
3582
|
}).finally(() => clearTimeout(timeoutId));
|
|
@@ -3679,6 +3681,9 @@ var ServerMessageType = /* @__PURE__ */ ((ServerMessageType2) => {
|
|
|
3679
3681
|
ServerMessageType2["HostMigrate"] = "HOST-MIGRATE";
|
|
3680
3682
|
ServerMessageType2["PresenceUpdate"] = "PRESENCE-UPDATE";
|
|
3681
3683
|
ServerMessageType2["KeyExchange"] = "KEY-EXCHANGE";
|
|
3684
|
+
ServerMessageType2["ConnectRequest"] = "CONNECT-REQUEST";
|
|
3685
|
+
ServerMessageType2["DcutrConnect"] = "DCUTR-CONNECT";
|
|
3686
|
+
ServerMessageType2["DcutrSync"] = "DCUTR-SYNC";
|
|
3682
3687
|
return ServerMessageType2;
|
|
3683
3688
|
})(ServerMessageType || {});
|
|
3684
3689
|
var TransportMode = /* @__PURE__ */ ((TransportMode2) => {
|
|
@@ -3704,6 +3709,11 @@ var ConnectionQuality = /* @__PURE__ */ ((ConnectionQuality2) => {
|
|
|
3704
3709
|
ConnectionQuality2["Unknown"] = "unknown";
|
|
3705
3710
|
return ConnectionQuality2;
|
|
3706
3711
|
})(ConnectionQuality || {});
|
|
3712
|
+
var TopicClass = /* @__PURE__ */ ((TopicClass2) => {
|
|
3713
|
+
TopicClass2["Persistent"] = "persistent";
|
|
3714
|
+
TopicClass2["Ephemeral"] = "ephemeral";
|
|
3715
|
+
return TopicClass2;
|
|
3716
|
+
})(TopicClass || {});
|
|
3707
3717
|
|
|
3708
3718
|
// src/dendriError.ts
|
|
3709
3719
|
var import_eventemitter3 = __toESM(require_eventemitter3(), 1);
|
|
@@ -3792,6 +3802,7 @@ var Negotiator = class {
|
|
|
3792
3802
|
}
|
|
3793
3803
|
connection;
|
|
3794
3804
|
_pendingCandidates = [];
|
|
3805
|
+
_iceCandidateFilter = null;
|
|
3795
3806
|
/** Returns a PeerConnection object set up correctly (for data, media). */
|
|
3796
3807
|
startConnection(options) {
|
|
3797
3808
|
const peerConnection = this._startPeerConnection();
|
|
@@ -3814,6 +3825,13 @@ var Negotiator = class {
|
|
|
3814
3825
|
_startPeerConnection() {
|
|
3815
3826
|
logger_default.log("Creating RTCPeerConnection.");
|
|
3816
3827
|
const peerConnection = new RTCPeerConnection(this.connection.provider?.options.config);
|
|
3828
|
+
if (this.connection.provider?.options.ipPolicy === "public") {
|
|
3829
|
+
const isPublicCandidate = (c) => {
|
|
3830
|
+
const sdp2 = c.candidate ?? "";
|
|
3831
|
+
return !sdp2.includes("typ host");
|
|
3832
|
+
};
|
|
3833
|
+
this._iceCandidateFilter = isPublicCandidate;
|
|
3834
|
+
}
|
|
3817
3835
|
this._setupListeners(peerConnection);
|
|
3818
3836
|
return peerConnection;
|
|
3819
3837
|
}
|
|
@@ -3826,6 +3844,9 @@ var Negotiator = class {
|
|
|
3826
3844
|
logger_default.log("Listening for ICE candidates.");
|
|
3827
3845
|
peerConnection.onicecandidate = (evt) => {
|
|
3828
3846
|
if (!evt.candidate?.candidate) return;
|
|
3847
|
+
if (this._iceCandidateFilter && !this._iceCandidateFilter(evt.candidate)) {
|
|
3848
|
+
return;
|
|
3849
|
+
}
|
|
3829
3850
|
logger_default.log(`Received ICE candidates for ${peerId}:`, evt.candidate);
|
|
3830
3851
|
provider.socket.send({
|
|
3831
3852
|
type: "CANDIDATE" /* Candidate */,
|
|
@@ -4164,6 +4185,7 @@ var DataConnection = class _DataConnection extends BaseConnection {
|
|
|
4164
4185
|
this.dataChannel.onopen = () => {
|
|
4165
4186
|
logger_default.log(`DC#${this.connectionId} dc connection success`);
|
|
4166
4187
|
this._open = true;
|
|
4188
|
+
this._applyAdaptiveBuffer(dc);
|
|
4167
4189
|
this.emit("open");
|
|
4168
4190
|
};
|
|
4169
4191
|
this.dataChannel.onclose = () => {
|
|
@@ -4171,6 +4193,24 @@ var DataConnection = class _DataConnection extends BaseConnection {
|
|
|
4171
4193
|
this.close();
|
|
4172
4194
|
};
|
|
4173
4195
|
}
|
|
4196
|
+
_applyAdaptiveBuffer(dc) {
|
|
4197
|
+
const pc = this.peerConnection;
|
|
4198
|
+
if (!pc || typeof pc.getStats !== "function") return;
|
|
4199
|
+
pc.getStats().then((stats) => {
|
|
4200
|
+
let rtt = null;
|
|
4201
|
+
stats.forEach((report) => {
|
|
4202
|
+
if (report.type === "candidate-pair" && report.state === "succeeded" && report.currentRoundTripTime) {
|
|
4203
|
+
rtt = report.currentRoundTripTime * 1e3;
|
|
4204
|
+
}
|
|
4205
|
+
});
|
|
4206
|
+
if (rtt !== null) {
|
|
4207
|
+
const bdp = 12.5 * 1024 * 1024 * (rtt / 1e3);
|
|
4208
|
+
const optimal = Math.max(1 * 1024 * 1024, Math.min(32 * 1024 * 1024, Math.ceil(bdp)));
|
|
4209
|
+
dc.bufferedAmountLowThreshold = optimal;
|
|
4210
|
+
}
|
|
4211
|
+
}).catch(() => {
|
|
4212
|
+
});
|
|
4213
|
+
}
|
|
4174
4214
|
/**
|
|
4175
4215
|
* Exposed functionality for users.
|
|
4176
4216
|
*/
|
|
@@ -4705,7 +4745,17 @@ var HybridConnection = class extends import_eventemitter32.EventEmitter {
|
|
|
4705
4745
|
if (this._closed) {
|
|
4706
4746
|
return;
|
|
4707
4747
|
}
|
|
4708
|
-
|
|
4748
|
+
logger_default.log(
|
|
4749
|
+
`HybridConnection: start peer=${this.peer} iceTimeout=${this._options.iceTimeout ?? 1e4}ms encryptRelay=${this._encryptRelay}`
|
|
4750
|
+
);
|
|
4751
|
+
if (typeof this._provider?.on !== "function") {
|
|
4752
|
+
this._attemptWebRTC();
|
|
4753
|
+
return;
|
|
4754
|
+
}
|
|
4755
|
+
this._tryConnectionReversal().then((direct) => {
|
|
4756
|
+
if (direct) return;
|
|
4757
|
+
this._attemptWebRTC();
|
|
4758
|
+
});
|
|
4709
4759
|
}
|
|
4710
4760
|
/** Send data through the best available transport, optionally tagged with a topic. */
|
|
4711
4761
|
send(data, options) {
|
|
@@ -4995,10 +5045,16 @@ var HybridConnection = class extends import_eventemitter32.EventEmitter {
|
|
|
4995
5045
|
this._dataConnection = dc;
|
|
4996
5046
|
this._iceTimer = setTimeout(() => {
|
|
4997
5047
|
if (this._mode !== "webrtc" /* WebRTC */) {
|
|
5048
|
+
logger_default.warn(
|
|
5049
|
+
`HybridConnection: ICE timeout after ${iceTimeout}ms for ${this.peer}, falling back to relay`
|
|
5050
|
+
);
|
|
4998
5051
|
this._fallbackToRelay();
|
|
4999
5052
|
}
|
|
5000
5053
|
}, iceTimeout);
|
|
5001
5054
|
this._dataConnection.on("open", () => {
|
|
5055
|
+
logger_default.log(
|
|
5056
|
+
`HybridConnection: WebRTC opened to ${this.peer} (attempt ${this._upgradeAttempts + 1})`
|
|
5057
|
+
);
|
|
5002
5058
|
this._clearIceTimer();
|
|
5003
5059
|
this._clearUpgradeTimer();
|
|
5004
5060
|
this._upgradeAttempts = 0;
|
|
@@ -5039,6 +5095,7 @@ var HybridConnection = class extends import_eventemitter32.EventEmitter {
|
|
|
5039
5095
|
/** Update the transport mode and emit if changed. */
|
|
5040
5096
|
_setMode(mode) {
|
|
5041
5097
|
if (this._mode !== mode) {
|
|
5098
|
+
logger_default.log(`HybridConnection: transport ${this._mode} -> ${mode} for ${this.peer}`);
|
|
5042
5099
|
this._mode = mode;
|
|
5043
5100
|
this.emit("transportChanged", mode);
|
|
5044
5101
|
}
|
|
@@ -5079,6 +5136,117 @@ var HybridConnection = class extends import_eventemitter32.EventEmitter {
|
|
|
5079
5136
|
this._attemptWebRTC();
|
|
5080
5137
|
}, interval);
|
|
5081
5138
|
}
|
|
5139
|
+
async _tryConnectionReversal() {
|
|
5140
|
+
if (typeof this._provider?.on !== "function") return false;
|
|
5141
|
+
try {
|
|
5142
|
+
const resp = await new Promise((resolve, reject) => {
|
|
5143
|
+
const timer = setTimeout(() => reject(new Error("timeout")), 3e3);
|
|
5144
|
+
const handler = (data) => {
|
|
5145
|
+
clearTimeout(timer);
|
|
5146
|
+
this._provider.off("CONNECT-REQUEST" /* ConnectRequest */, handler);
|
|
5147
|
+
resolve(data);
|
|
5148
|
+
};
|
|
5149
|
+
this._provider.on("CONNECT-REQUEST" /* ConnectRequest */, handler);
|
|
5150
|
+
this._provider.socket.send({
|
|
5151
|
+
type: "CONNECT-REQUEST" /* ConnectRequest */,
|
|
5152
|
+
payload: { peer: this.peer }
|
|
5153
|
+
});
|
|
5154
|
+
});
|
|
5155
|
+
const addr = resp?.address;
|
|
5156
|
+
if (!addr) return false;
|
|
5157
|
+
const pc = new RTCPeerConnection(this._provider.options.config);
|
|
5158
|
+
const dc = pc.createDataChannel("probe", { id: 0 });
|
|
5159
|
+
await new Promise((resolve, reject) => {
|
|
5160
|
+
const timer = setTimeout(() => {
|
|
5161
|
+
pc.close();
|
|
5162
|
+
reject(new Error("direct-dial-timeout"));
|
|
5163
|
+
}, 2500);
|
|
5164
|
+
dc.onopen = () => {
|
|
5165
|
+
clearTimeout(timer);
|
|
5166
|
+
resolve();
|
|
5167
|
+
};
|
|
5168
|
+
dc.onerror = () => {
|
|
5169
|
+
clearTimeout(timer);
|
|
5170
|
+
pc.close();
|
|
5171
|
+
reject(new Error("dc-error"));
|
|
5172
|
+
};
|
|
5173
|
+
});
|
|
5174
|
+
this._dataConnection = void 0;
|
|
5175
|
+
this._setMode("webrtc" /* WebRTC */);
|
|
5176
|
+
pc.close();
|
|
5177
|
+
return true;
|
|
5178
|
+
} catch {
|
|
5179
|
+
return false;
|
|
5180
|
+
}
|
|
5181
|
+
}
|
|
5182
|
+
async _gatherSrflxCandidates() {
|
|
5183
|
+
const pc = new RTCPeerConnection({ iceServers: this._provider.options.config?.iceServers });
|
|
5184
|
+
pc.createDataChannel("probe");
|
|
5185
|
+
const offer = await pc.createOffer();
|
|
5186
|
+
await pc.setLocalDescription(offer);
|
|
5187
|
+
const candidates = [];
|
|
5188
|
+
await new Promise((resolve) => {
|
|
5189
|
+
const timer = setTimeout(resolve, 2e3);
|
|
5190
|
+
pc.onicecandidate = (evt) => {
|
|
5191
|
+
if (!evt.candidate) {
|
|
5192
|
+
clearTimeout(timer);
|
|
5193
|
+
resolve();
|
|
5194
|
+
return;
|
|
5195
|
+
}
|
|
5196
|
+
if (!evt.candidate.candidate.includes("typ host")) {
|
|
5197
|
+
candidates.push(evt.candidate.candidate);
|
|
5198
|
+
}
|
|
5199
|
+
};
|
|
5200
|
+
});
|
|
5201
|
+
pc.close();
|
|
5202
|
+
return candidates;
|
|
5203
|
+
}
|
|
5204
|
+
async _dcutrHolePunch() {
|
|
5205
|
+
try {
|
|
5206
|
+
const localAddrs = await this._gatherSrflxCandidates();
|
|
5207
|
+
const t0 = performance.now();
|
|
5208
|
+
const peerAddrs = await new Promise((resolve, reject) => {
|
|
5209
|
+
const timer = setTimeout(() => reject(new Error("dcutr-timeout")), 8e3);
|
|
5210
|
+
const handler = (data) => {
|
|
5211
|
+
clearTimeout(timer);
|
|
5212
|
+
this._provider.off("DCUTR-CONNECT" /* DcutrConnect */, handler);
|
|
5213
|
+
resolve(data?.addresses ?? []);
|
|
5214
|
+
};
|
|
5215
|
+
this._provider.on("DCUTR-CONNECT" /* DcutrConnect */, handler);
|
|
5216
|
+
this._provider.socket.send({
|
|
5217
|
+
type: "DCUTR-CONNECT" /* DcutrConnect */,
|
|
5218
|
+
payload: { addresses: localAddrs }
|
|
5219
|
+
});
|
|
5220
|
+
});
|
|
5221
|
+
const relayRtt = performance.now() - t0;
|
|
5222
|
+
this._provider.socket.send({ type: "DCUTR-SYNC" /* DcutrSync */, payload: {} });
|
|
5223
|
+
await new Promise((r) => setTimeout(r, relayRtt / 2));
|
|
5224
|
+
for (let i = 0; i < Math.min(peerAddrs.length, 4); i++) {
|
|
5225
|
+
try {
|
|
5226
|
+
const pc = new RTCPeerConnection(this._provider.options.config);
|
|
5227
|
+
await new Promise((resolve, reject) => {
|
|
5228
|
+
const timer = setTimeout(() => {
|
|
5229
|
+
pc.close();
|
|
5230
|
+
reject(new Error("dc-dial-timeout"));
|
|
5231
|
+
}, 5e3);
|
|
5232
|
+
const dc = pc.createDataChannel("dcutr");
|
|
5233
|
+
dc.onopen = () => {
|
|
5234
|
+
clearTimeout(timer);
|
|
5235
|
+
resolve();
|
|
5236
|
+
};
|
|
5237
|
+
});
|
|
5238
|
+
this._dataConnection = void 0;
|
|
5239
|
+
this._setMode("webrtc" /* WebRTC */);
|
|
5240
|
+
pc.close();
|
|
5241
|
+
return true;
|
|
5242
|
+
} catch {
|
|
5243
|
+
}
|
|
5244
|
+
}
|
|
5245
|
+
return false;
|
|
5246
|
+
} catch {
|
|
5247
|
+
return false;
|
|
5248
|
+
}
|
|
5249
|
+
}
|
|
5082
5250
|
};
|
|
5083
5251
|
|
|
5084
5252
|
// src/mediaconnection.ts
|
|
@@ -5235,17 +5403,29 @@ var PollingTransport = class _PollingTransport extends SignalingTransport {
|
|
|
5235
5403
|
_heartbeatTimer;
|
|
5236
5404
|
_lastSeq = 0;
|
|
5237
5405
|
_baseUrl;
|
|
5406
|
+
_key;
|
|
5407
|
+
_jwt;
|
|
5408
|
+
_apiKey;
|
|
5238
5409
|
_pingInterval;
|
|
5239
5410
|
_abortController;
|
|
5240
5411
|
/** Backoff schedule base delays in milliseconds. */
|
|
5241
5412
|
static BACKOFF_SCHEDULE = [0, 1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
|
|
5242
5413
|
/** Random jitter range in milliseconds (applied as +/-). */
|
|
5243
5414
|
static BACKOFF_JITTER = 500;
|
|
5244
|
-
constructor(secure, host, port, path,
|
|
5415
|
+
constructor(secure, host, port, path, key, pingInterval = 5e3, jwt, apiKey) {
|
|
5245
5416
|
super();
|
|
5246
5417
|
const protocol = secure ? "https://" : "http://";
|
|
5247
5418
|
this._baseUrl = `${protocol + host}:${port}${path}`;
|
|
5248
5419
|
this._pingInterval = pingInterval;
|
|
5420
|
+
this._key = key;
|
|
5421
|
+
this._jwt = jwt;
|
|
5422
|
+
this._apiKey = apiKey;
|
|
5423
|
+
}
|
|
5424
|
+
/** Append the shared auth params (key, jwt, api_key) so every HTTP call authenticates like the WS transport. */
|
|
5425
|
+
_applyAuthParams(params) {
|
|
5426
|
+
params.set("key", this._key);
|
|
5427
|
+
if (this._jwt) params.set("jwt", this._jwt);
|
|
5428
|
+
if (this._apiKey) params.set("api_key", this._apiKey);
|
|
5249
5429
|
}
|
|
5250
5430
|
get reconnectAttempt() {
|
|
5251
5431
|
return this._reconnectAttempt;
|
|
@@ -5273,6 +5453,7 @@ var PollingTransport = class _PollingTransport extends SignalingTransport {
|
|
|
5273
5453
|
id: this._id,
|
|
5274
5454
|
token: this._token
|
|
5275
5455
|
});
|
|
5456
|
+
this._applyAuthParams(params);
|
|
5276
5457
|
if (this._lastSeq > 0) params.set("last_seq", String(this._lastSeq));
|
|
5277
5458
|
const response = await fetch(`${this._baseUrl}http/poll?${params}`, {
|
|
5278
5459
|
signal: this._abortController.signal
|
|
@@ -5311,6 +5492,7 @@ var PollingTransport = class _PollingTransport extends SignalingTransport {
|
|
|
5311
5492
|
id: this._id,
|
|
5312
5493
|
token: this._token
|
|
5313
5494
|
});
|
|
5495
|
+
this._applyAuthParams(params);
|
|
5314
5496
|
try {
|
|
5315
5497
|
await fetch(`${this._baseUrl}http/send?${params}`, {
|
|
5316
5498
|
method: "POST",
|
|
@@ -5375,13 +5557,16 @@ var PollingTransport = class _PollingTransport extends SignalingTransport {
|
|
|
5375
5557
|
};
|
|
5376
5558
|
|
|
5377
5559
|
// src/socket.ts
|
|
5378
|
-
var version2 = "2.
|
|
5560
|
+
var version2 = "2.5.0";
|
|
5379
5561
|
var Socket = class _Socket extends SignalingTransport {
|
|
5380
|
-
constructor(secure, host, port, path, key, pingInterval = 5e3, jwt) {
|
|
5562
|
+
constructor(secure, host, port, path, key, pingInterval = 5e3, jwt, apiKey) {
|
|
5381
5563
|
super();
|
|
5382
5564
|
this.pingInterval = pingInterval;
|
|
5383
5565
|
const wsProtocol = secure ? "wss://" : "ws://";
|
|
5384
5566
|
this._baseUrl = `${wsProtocol + host}:${port}${path}dendri?key=${key}`;
|
|
5567
|
+
if (apiKey) {
|
|
5568
|
+
this._baseUrl += `&api_key=${encodeURIComponent(apiKey)}`;
|
|
5569
|
+
}
|
|
5385
5570
|
this._jwt = jwt;
|
|
5386
5571
|
}
|
|
5387
5572
|
pingInterval;
|
|
@@ -5417,7 +5602,7 @@ var Socket = class _Socket extends SignalingTransport {
|
|
|
5417
5602
|
if (this._jwt) {
|
|
5418
5603
|
wsUrl += `&jwt=${encodeURIComponent(this._jwt)}`;
|
|
5419
5604
|
}
|
|
5420
|
-
if (
|
|
5605
|
+
if (this._socket || !this._disconnected) {
|
|
5421
5606
|
return;
|
|
5422
5607
|
}
|
|
5423
5608
|
this._socket = new WebSocket(`${wsUrl}&version=${version2}`);
|
|
@@ -5687,18 +5872,28 @@ var SSETransport = class _SSETransport extends SignalingTransport {
|
|
|
5687
5872
|
_heartbeatTimer;
|
|
5688
5873
|
_lastSeq = 0;
|
|
5689
5874
|
_baseUrl;
|
|
5875
|
+
_key;
|
|
5690
5876
|
_jwt;
|
|
5877
|
+
_apiKey;
|
|
5691
5878
|
_pingInterval;
|
|
5692
5879
|
/** Backoff schedule base delays in milliseconds. */
|
|
5693
5880
|
static BACKOFF_SCHEDULE = [0, 1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
|
|
5694
5881
|
/** Random jitter range in milliseconds (applied as +/-). */
|
|
5695
5882
|
static BACKOFF_JITTER = 500;
|
|
5696
|
-
constructor(secure, host, port, path,
|
|
5883
|
+
constructor(secure, host, port, path, key, pingInterval = 5e3, jwt, apiKey) {
|
|
5697
5884
|
super();
|
|
5698
5885
|
const protocol = secure ? "https://" : "http://";
|
|
5699
5886
|
this._baseUrl = `${protocol + host}:${port}${path}`;
|
|
5700
5887
|
this._pingInterval = pingInterval;
|
|
5888
|
+
this._key = key;
|
|
5701
5889
|
this._jwt = jwt;
|
|
5890
|
+
this._apiKey = apiKey;
|
|
5891
|
+
}
|
|
5892
|
+
/** Append the shared auth params (key, jwt, api_key) so every HTTP call authenticates like the WS transport. */
|
|
5893
|
+
_applyAuthParams(params) {
|
|
5894
|
+
params.set("key", this._key);
|
|
5895
|
+
if (this._jwt) params.set("jwt", this._jwt);
|
|
5896
|
+
if (this._apiKey) params.set("api_key", this._apiKey);
|
|
5702
5897
|
}
|
|
5703
5898
|
get reconnectAttempt() {
|
|
5704
5899
|
return this._reconnectAttempt;
|
|
@@ -5716,10 +5911,9 @@ var SSETransport = class _SSETransport extends SignalingTransport {
|
|
|
5716
5911
|
if (this._disconnected) return;
|
|
5717
5912
|
const params = new URLSearchParams({
|
|
5718
5913
|
id: this._id,
|
|
5719
|
-
token: this._token
|
|
5720
|
-
key: "dendri"
|
|
5914
|
+
token: this._token
|
|
5721
5915
|
});
|
|
5722
|
-
|
|
5916
|
+
this._applyAuthParams(params);
|
|
5723
5917
|
if (this._lastSeq > 0) params.set("last_seq", String(this._lastSeq));
|
|
5724
5918
|
const url = `${this._baseUrl}http/sse?${params}`;
|
|
5725
5919
|
try {
|
|
@@ -5793,6 +5987,7 @@ var SSETransport = class _SSETransport extends SignalingTransport {
|
|
|
5793
5987
|
id: this._id,
|
|
5794
5988
|
token: this._token
|
|
5795
5989
|
});
|
|
5990
|
+
this._applyAuthParams(params);
|
|
5796
5991
|
try {
|
|
5797
5992
|
await fetch(`${this._baseUrl}http/send?${params}`, {
|
|
5798
5993
|
method: "POST",
|
|
@@ -5865,6 +6060,28 @@ var SSETransport = class _SSETransport extends SignalingTransport {
|
|
|
5865
6060
|
};
|
|
5866
6061
|
|
|
5867
6062
|
// src/dendri.ts
|
|
6063
|
+
function parseServerUrl(url) {
|
|
6064
|
+
let parsed;
|
|
6065
|
+
try {
|
|
6066
|
+
parsed = new URL(url);
|
|
6067
|
+
} catch {
|
|
6068
|
+
throw new Error(
|
|
6069
|
+
`Invalid Dendri "url" option: "${url}". Expected a full URL like "wss://signal.example.com".`
|
|
6070
|
+
);
|
|
6071
|
+
}
|
|
6072
|
+
const secure = parsed.protocol === "wss:" || parsed.protocol === "https:";
|
|
6073
|
+
if (!secure && parsed.protocol !== "ws:" && parsed.protocol !== "http:") {
|
|
6074
|
+
throw new Error(
|
|
6075
|
+
`Invalid Dendri "url" protocol: "${parsed.protocol}". Use wss://, ws://, https://, or http://.`
|
|
6076
|
+
);
|
|
6077
|
+
}
|
|
6078
|
+
return {
|
|
6079
|
+
host: parsed.hostname,
|
|
6080
|
+
port: parsed.port ? Number(parsed.port) : secure ? 443 : 80,
|
|
6081
|
+
secure,
|
|
6082
|
+
path: parsed.pathname || "/"
|
|
6083
|
+
};
|
|
6084
|
+
}
|
|
5868
6085
|
var Dendri = class _Dendri extends EventEmitterWithError {
|
|
5869
6086
|
static DEFAULT_KEY = "dendri";
|
|
5870
6087
|
_serializers = {
|
|
@@ -5955,6 +6172,9 @@ var Dendri = class _Dendri extends EventEmitterWithError {
|
|
|
5955
6172
|
} else if (id) {
|
|
5956
6173
|
userId = id.toString();
|
|
5957
6174
|
}
|
|
6175
|
+
if (providedOptions?.url) {
|
|
6176
|
+
providedOptions = { ...parseServerUrl(providedOptions.url), ...providedOptions };
|
|
6177
|
+
}
|
|
5958
6178
|
const normalizedOptions = {
|
|
5959
6179
|
debug: 0,
|
|
5960
6180
|
// 1: Errors, 2: Warnings, 3: All logs
|
|
@@ -6008,7 +6228,7 @@ var Dendri = class _Dendri extends EventEmitterWithError {
|
|
|
6008
6228
|
return;
|
|
6009
6229
|
}
|
|
6010
6230
|
}
|
|
6011
|
-
if (
|
|
6231
|
+
if (userId && !util.validateId(userId)) {
|
|
6012
6232
|
this._delayedAbort("invalid-id" /* InvalidID */, `ID "${userId}" is invalid`);
|
|
6013
6233
|
return;
|
|
6014
6234
|
}
|
|
@@ -6073,7 +6293,8 @@ var Dendri = class _Dendri extends EventEmitterWithError {
|
|
|
6073
6293
|
this._options.path,
|
|
6074
6294
|
this._options.key,
|
|
6075
6295
|
this._options.pingInterval,
|
|
6076
|
-
this._options.jwt
|
|
6296
|
+
this._options.jwt,
|
|
6297
|
+
this._options.apiKey
|
|
6077
6298
|
) : transport === "polling" ? new PollingTransport(
|
|
6078
6299
|
this._options.secure ?? false,
|
|
6079
6300
|
this._options.host,
|
|
@@ -6081,7 +6302,8 @@ var Dendri = class _Dendri extends EventEmitterWithError {
|
|
|
6081
6302
|
this._options.path,
|
|
6082
6303
|
this._options.key,
|
|
6083
6304
|
this._options.pingInterval,
|
|
6084
|
-
this._options.jwt
|
|
6305
|
+
this._options.jwt,
|
|
6306
|
+
this._options.apiKey
|
|
6085
6307
|
) : new Socket(
|
|
6086
6308
|
this._options.secure ?? false,
|
|
6087
6309
|
this._options.host,
|
|
@@ -6089,7 +6311,8 @@ var Dendri = class _Dendri extends EventEmitterWithError {
|
|
|
6089
6311
|
this._options.path,
|
|
6090
6312
|
this._options.key,
|
|
6091
6313
|
this._options.pingInterval,
|
|
6092
|
-
this._options.jwt
|
|
6314
|
+
this._options.jwt,
|
|
6315
|
+
this._options.apiKey
|
|
6093
6316
|
);
|
|
6094
6317
|
socket.on("message" /* Message */, (data) => {
|
|
6095
6318
|
this._handleMessage(data);
|
|
@@ -6930,7 +7153,13 @@ var Room = class extends import_eventemitter35.EventEmitter {
|
|
|
6930
7153
|
sentViaWebRTC = true;
|
|
6931
7154
|
}
|
|
6932
7155
|
}
|
|
6933
|
-
if (
|
|
7156
|
+
if (this._dendriOptions?.enableRelay && this._peer?.socket) {
|
|
7157
|
+
this._peer.socket.send({
|
|
7158
|
+
type: "DATA" /* Data */,
|
|
7159
|
+
room: this._roomId,
|
|
7160
|
+
payload: wire
|
|
7161
|
+
});
|
|
7162
|
+
} else if (!sentViaWebRTC && this._peer?.socket) {
|
|
6934
7163
|
this._peer.socket.send({
|
|
6935
7164
|
type: "DATA" /* Data */,
|
|
6936
7165
|
room: this._roomId,
|
|
@@ -6964,7 +7193,13 @@ var Room = class extends import_eventemitter35.EventEmitter {
|
|
|
6964
7193
|
sentViaWebRTC = true;
|
|
6965
7194
|
}
|
|
6966
7195
|
}
|
|
6967
|
-
if (
|
|
7196
|
+
if (this._dendriOptions?.enableRelay && this._peer?.socket) {
|
|
7197
|
+
this._peer.socket.send({
|
|
7198
|
+
type: "DATA" /* Data */,
|
|
7199
|
+
room: this._roomId,
|
|
7200
|
+
payload: wire
|
|
7201
|
+
});
|
|
7202
|
+
} else if (!sentViaWebRTC && this._peer?.socket) {
|
|
6968
7203
|
this._peer.socket.send({
|
|
6969
7204
|
type: "DATA" /* Data */,
|
|
6970
7205
|
room: this._roomId,
|
|
@@ -7155,8 +7390,8 @@ var Room = class extends import_eventemitter35.EventEmitter {
|
|
|
7155
7390
|
const remotePeerId = conn.peer;
|
|
7156
7391
|
this._connections.set(remotePeerId, conn);
|
|
7157
7392
|
this._knownPeers.add(remotePeerId);
|
|
7393
|
+
this.emit("peerJoined", remotePeerId);
|
|
7158
7394
|
conn.on("open", () => {
|
|
7159
|
-
this.emit("peerJoined", remotePeerId);
|
|
7160
7395
|
for (const [peerId, c] of this._connections) {
|
|
7161
7396
|
if (peerId !== remotePeerId && c.open) {
|
|
7162
7397
|
c.send({ __room: { type: "peer-joined", peerId: remotePeerId } });
|
|
@@ -7478,6 +7713,14 @@ var Room = class extends import_eventemitter35.EventEmitter {
|
|
|
7478
7713
|
const conn = this._connections.get(peerId);
|
|
7479
7714
|
if (conn?.open) {
|
|
7480
7715
|
conn.send(data);
|
|
7716
|
+
if (this._dendriOptions?.enableRelay && this._peer?.socket) {
|
|
7717
|
+
this._peer.socket.send({
|
|
7718
|
+
type: "DATA" /* Data */,
|
|
7719
|
+
dst: peerId,
|
|
7720
|
+
room: this._roomId,
|
|
7721
|
+
payload: data
|
|
7722
|
+
});
|
|
7723
|
+
}
|
|
7481
7724
|
return;
|
|
7482
7725
|
}
|
|
7483
7726
|
if (!this._isHost && this._hostId) {
|
|
@@ -7780,6 +8023,6 @@ function createDendriStore(input) {
|
|
|
7780
8023
|
};
|
|
7781
8024
|
}
|
|
7782
8025
|
|
|
7783
|
-
export { AckManager, BaseConnectionErrorType, BufferedConnection, ConnectionQuality, ConnectionState, ConnectionType, DataConnection, DataConnectionErrorType, Dendri, DendriError, DendriErrorType, HybridConnection, PollingTransport, PresenceManager, RelayEncryption, Room, RpcError, RpcErrorCode, RpcManager, SSETransport, SerializationType, ServerMessageType, SignalingTransport, SocketEventType, TopicManager, TransportMode, createDendriStore, electNewHost, isRpcRequest, isRpcResponse, isTopicEnvelope, logger_default, util };
|
|
7784
|
-
//# sourceMappingURL=chunk-
|
|
7785
|
-
//# sourceMappingURL=chunk-
|
|
8026
|
+
export { AckManager, BaseConnectionErrorType, BufferedConnection, ConnectionQuality, ConnectionState, ConnectionType, DataConnection, DataConnectionErrorType, Dendri, DendriError, DendriErrorType, HybridConnection, PollingTransport, PresenceManager, RelayEncryption, Room, RpcError, RpcErrorCode, RpcManager, SSETransport, SerializationType, ServerMessageType, SignalingTransport, SocketEventType, TopicClass, TopicManager, TransportMode, createDendriStore, electNewHost, isRpcRequest, isRpcResponse, isTopicEnvelope, logger_default, util };
|
|
8027
|
+
//# sourceMappingURL=chunk-3CE674DE.js.map
|
|
8028
|
+
//# sourceMappingURL=chunk-3CE674DE.js.map
|