@afterrealism/dendri-client 2.4.0 → 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/README.md CHANGED
@@ -10,30 +10,26 @@ npm install @afterrealism/dendri-client
10
10
 
11
11
  ## Connect To Your Server
12
12
 
13
- Dendri is self-host-first. You must provide the signaling server that your app should use:
13
+ Pass the signaling server your app should use as a single URL:
14
14
 
15
15
  ```ts
16
16
  import { Dendri } from "@afterrealism/dendri-client";
17
17
 
18
18
  const peer = new Dendri({
19
- host: "signal.example.com",
20
- port: 443,
21
- secure: true,
22
- path: "/",
19
+ url: "wss://signal.example.com",
20
+ apiKey: "your-api-key", // only needed for hosted / multi-tenant deployments
23
21
  });
24
22
  ```
25
23
 
24
+ `url` is shorthand for `host`/`port`/`secure`/`path` — pass those individually if you
25
+ prefer; explicitly passed fields win over url-derived ones.
26
+
26
27
  You can also pass an explicit peer id as the first argument: `new Dendri("my-peer-id", { ... })`.
27
28
 
28
29
  Local development usually looks like:
29
30
 
30
31
  ```ts
31
- const peer = new Dendri({
32
- host: "localhost",
33
- port: 9876,
34
- secure: false,
35
- path: "/",
36
- });
32
+ const peer = new Dendri({ url: "ws://localhost:9876" });
37
33
  ```
38
34
 
39
35
  ## Quick Start
@@ -65,12 +61,7 @@ Use `createDendriStore()` when integrating with UI frameworks:
65
61
  ```ts
66
62
  import { createDendriStore } from "@afterrealism/dendri-client";
67
63
 
68
- const store = createDendriStore({
69
- host: "signal.example.com",
70
- port: 443,
71
- secure: true,
72
- path: "/",
73
- });
64
+ const store = createDendriStore({ url: "wss://signal.example.com" });
74
65
 
75
66
  const unsubscribe = store.subscribe(() => {
76
67
  console.log(store.connectionState, store.peers);
@@ -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.4.0";
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, {
@@ -3570,11 +3571,12 @@ var API = class _API {
3570
3571
  async getTurnCredentials() {
3571
3572
  const protocol = this._options.secure ? "https" : "http";
3572
3573
  const { host, port, path, key } = this._options;
3573
- const url = `${protocol}://${host}:${port}${path}${key}/turn-credentials`;
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));
@@ -5401,17 +5403,29 @@ var PollingTransport = class _PollingTransport extends SignalingTransport {
5401
5403
  _heartbeatTimer;
5402
5404
  _lastSeq = 0;
5403
5405
  _baseUrl;
5406
+ _key;
5407
+ _jwt;
5408
+ _apiKey;
5404
5409
  _pingInterval;
5405
5410
  _abortController;
5406
5411
  /** Backoff schedule base delays in milliseconds. */
5407
5412
  static BACKOFF_SCHEDULE = [0, 1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
5408
5413
  /** Random jitter range in milliseconds (applied as +/-). */
5409
5414
  static BACKOFF_JITTER = 500;
5410
- constructor(secure, host, port, path, _key, pingInterval = 5e3, _jwt) {
5415
+ constructor(secure, host, port, path, key, pingInterval = 5e3, jwt, apiKey) {
5411
5416
  super();
5412
5417
  const protocol = secure ? "https://" : "http://";
5413
5418
  this._baseUrl = `${protocol + host}:${port}${path}`;
5414
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);
5415
5429
  }
5416
5430
  get reconnectAttempt() {
5417
5431
  return this._reconnectAttempt;
@@ -5439,6 +5453,7 @@ var PollingTransport = class _PollingTransport extends SignalingTransport {
5439
5453
  id: this._id,
5440
5454
  token: this._token
5441
5455
  });
5456
+ this._applyAuthParams(params);
5442
5457
  if (this._lastSeq > 0) params.set("last_seq", String(this._lastSeq));
5443
5458
  const response = await fetch(`${this._baseUrl}http/poll?${params}`, {
5444
5459
  signal: this._abortController.signal
@@ -5477,6 +5492,7 @@ var PollingTransport = class _PollingTransport extends SignalingTransport {
5477
5492
  id: this._id,
5478
5493
  token: this._token
5479
5494
  });
5495
+ this._applyAuthParams(params);
5480
5496
  try {
5481
5497
  await fetch(`${this._baseUrl}http/send?${params}`, {
5482
5498
  method: "POST",
@@ -5541,13 +5557,16 @@ var PollingTransport = class _PollingTransport extends SignalingTransport {
5541
5557
  };
5542
5558
 
5543
5559
  // src/socket.ts
5544
- var version2 = "2.4.0";
5560
+ var version2 = "2.5.0";
5545
5561
  var Socket = class _Socket extends SignalingTransport {
5546
- constructor(secure, host, port, path, key, pingInterval = 5e3, jwt) {
5562
+ constructor(secure, host, port, path, key, pingInterval = 5e3, jwt, apiKey) {
5547
5563
  super();
5548
5564
  this.pingInterval = pingInterval;
5549
5565
  const wsProtocol = secure ? "wss://" : "ws://";
5550
5566
  this._baseUrl = `${wsProtocol + host}:${port}${path}dendri?key=${key}`;
5567
+ if (apiKey) {
5568
+ this._baseUrl += `&api_key=${encodeURIComponent(apiKey)}`;
5569
+ }
5551
5570
  this._jwt = jwt;
5552
5571
  }
5553
5572
  pingInterval;
@@ -5853,18 +5872,28 @@ var SSETransport = class _SSETransport extends SignalingTransport {
5853
5872
  _heartbeatTimer;
5854
5873
  _lastSeq = 0;
5855
5874
  _baseUrl;
5875
+ _key;
5856
5876
  _jwt;
5877
+ _apiKey;
5857
5878
  _pingInterval;
5858
5879
  /** Backoff schedule base delays in milliseconds. */
5859
5880
  static BACKOFF_SCHEDULE = [0, 1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
5860
5881
  /** Random jitter range in milliseconds (applied as +/-). */
5861
5882
  static BACKOFF_JITTER = 500;
5862
- constructor(secure, host, port, path, _key, pingInterval = 5e3, jwt) {
5883
+ constructor(secure, host, port, path, key, pingInterval = 5e3, jwt, apiKey) {
5863
5884
  super();
5864
5885
  const protocol = secure ? "https://" : "http://";
5865
5886
  this._baseUrl = `${protocol + host}:${port}${path}`;
5866
5887
  this._pingInterval = pingInterval;
5888
+ this._key = key;
5867
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);
5868
5897
  }
5869
5898
  get reconnectAttempt() {
5870
5899
  return this._reconnectAttempt;
@@ -5882,10 +5911,9 @@ var SSETransport = class _SSETransport extends SignalingTransport {
5882
5911
  if (this._disconnected) return;
5883
5912
  const params = new URLSearchParams({
5884
5913
  id: this._id,
5885
- token: this._token,
5886
- key: "dendri"
5914
+ token: this._token
5887
5915
  });
5888
- if (this._jwt) params.set("jwt", this._jwt);
5916
+ this._applyAuthParams(params);
5889
5917
  if (this._lastSeq > 0) params.set("last_seq", String(this._lastSeq));
5890
5918
  const url = `${this._baseUrl}http/sse?${params}`;
5891
5919
  try {
@@ -5959,6 +5987,7 @@ var SSETransport = class _SSETransport extends SignalingTransport {
5959
5987
  id: this._id,
5960
5988
  token: this._token
5961
5989
  });
5990
+ this._applyAuthParams(params);
5962
5991
  try {
5963
5992
  await fetch(`${this._baseUrl}http/send?${params}`, {
5964
5993
  method: "POST",
@@ -6031,6 +6060,28 @@ var SSETransport = class _SSETransport extends SignalingTransport {
6031
6060
  };
6032
6061
 
6033
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
+ }
6034
6085
  var Dendri = class _Dendri extends EventEmitterWithError {
6035
6086
  static DEFAULT_KEY = "dendri";
6036
6087
  _serializers = {
@@ -6121,6 +6172,9 @@ var Dendri = class _Dendri extends EventEmitterWithError {
6121
6172
  } else if (id) {
6122
6173
  userId = id.toString();
6123
6174
  }
6175
+ if (providedOptions?.url) {
6176
+ providedOptions = { ...parseServerUrl(providedOptions.url), ...providedOptions };
6177
+ }
6124
6178
  const normalizedOptions = {
6125
6179
  debug: 0,
6126
6180
  // 1: Errors, 2: Warnings, 3: All logs
@@ -6239,7 +6293,8 @@ var Dendri = class _Dendri extends EventEmitterWithError {
6239
6293
  this._options.path,
6240
6294
  this._options.key,
6241
6295
  this._options.pingInterval,
6242
- this._options.jwt
6296
+ this._options.jwt,
6297
+ this._options.apiKey
6243
6298
  ) : transport === "polling" ? new PollingTransport(
6244
6299
  this._options.secure ?? false,
6245
6300
  this._options.host,
@@ -6247,7 +6302,8 @@ var Dendri = class _Dendri extends EventEmitterWithError {
6247
6302
  this._options.path,
6248
6303
  this._options.key,
6249
6304
  this._options.pingInterval,
6250
- this._options.jwt
6305
+ this._options.jwt,
6306
+ this._options.apiKey
6251
6307
  ) : new Socket(
6252
6308
  this._options.secure ?? false,
6253
6309
  this._options.host,
@@ -6255,7 +6311,8 @@ var Dendri = class _Dendri extends EventEmitterWithError {
6255
6311
  this._options.path,
6256
6312
  this._options.key,
6257
6313
  this._options.pingInterval,
6258
- this._options.jwt
6314
+ this._options.jwt,
6315
+ this._options.apiKey
6259
6316
  );
6260
6317
  socket.on("message" /* Message */, (data) => {
6261
6318
  this._handleMessage(data);
@@ -7967,5 +8024,5 @@ function createDendriStore(input) {
7967
8024
  }
7968
8025
 
7969
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 };
7970
- //# sourceMappingURL=chunk-MBMSG4EC.js.map
7971
- //# sourceMappingURL=chunk-MBMSG4EC.js.map
8027
+ //# sourceMappingURL=chunk-3CE674DE.js.map
8028
+ //# sourceMappingURL=chunk-3CE674DE.js.map