openrtc-netcode 0.1.0 → 1.0.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
@@ -11,6 +11,13 @@ and Firestore remain part of OpenRTC's control plane for identity, discovery,
11
11
  rooms, tickets, and browser signaling metadata; `openrtc-netcode` does not use
12
12
  Firestore as a state or message relay.
13
13
 
14
+ `preferredPayloadTransports` filters OpenRTC's typed application-readiness
15
+ query; it does not request promotion. When netcode creates the runtime,
16
+ `transports` and `transportPriority` are forwarded to `OpenRTC(...)` at
17
+ construction. An injected runtime must be configured by its owner. OpenRTC owns
18
+ optional transport promotion and recovery, while netcode only observes later
19
+ route events and never requests or suppresses upgrades.
20
+
14
21
  ```ts
15
22
  import { createNetcode } from 'openrtc-netcode';
16
23
 
package/dist/client.d.ts CHANGED
@@ -29,7 +29,6 @@ export declare class OpenRtcNetcodeClient implements NetcodeClientInterface {
29
29
  private readonly connectionIds;
30
30
  private readonly pendingPeerIds;
31
31
  private readonly directSendWarnings;
32
- private readonly requestedWebRtcUpgradeConnectionIds;
33
32
  private readonly introPeerIds;
34
33
  private readonly seenEnvelopeIds;
35
34
  private readonly seenEnvelopeOrder;
@@ -81,6 +80,7 @@ export declare class OpenRtcNetcodeClient implements NetcodeClientInterface {
81
80
  private sendObjectSnapshot;
82
81
  private broadcastMemberMetadata;
83
82
  private startPeerPingLoop;
83
+ private refreshPeerPayloadState;
84
84
  private stopPeerPingLoop;
85
85
  private broadcastEnvelope;
86
86
  private sendEnvelope;
@@ -101,7 +101,6 @@ export declare class OpenRtcNetcodeClient implements NetcodeClientInterface {
101
101
  private resolvePeerTransport;
102
102
  private isPeerPayloadReady;
103
103
  private resolvePayloadConnection;
104
- private requestPreferredTransportUpgrade;
105
104
  private payloadReadinessOptions;
106
105
  private refreshLobby;
107
106
  private requireRuntime;
package/dist/client.js CHANGED
@@ -40,7 +40,6 @@ export class OpenRtcNetcodeClient {
40
40
  this.connectionIds = new Set();
41
41
  this.pendingPeerIds = new Set();
42
42
  this.directSendWarnings = new Set();
43
- this.requestedWebRtcUpgradeConnectionIds = new Set();
44
43
  this.introPeerIds = new Set();
45
44
  this.seenEnvelopeIds = new Set();
46
45
  this.seenEnvelopeOrder = [];
@@ -120,7 +119,6 @@ export class OpenRtcNetcodeClient {
120
119
  this.connectionIds.clear();
121
120
  this.pendingPeerIds.clear();
122
121
  this.directSendWarnings.clear();
123
- this.requestedWebRtcUpgradeConnectionIds.clear();
124
122
  this.introPeerIds.clear();
125
123
  this.peerStatsById.clear();
126
124
  this.seenEnvelopeIds.clear();
@@ -312,13 +310,9 @@ export class OpenRtcNetcodeClient {
312
310
  if (this.fallbackChannel) {
313
311
  continue;
314
312
  }
315
- const connection = this.connectionsByPeer.get(peerId);
316
313
  this.peersById.delete(peerId);
317
314
  this.connectionsByPeer.delete(peerId);
318
315
  this.pendingPeerIds.delete(peerId);
319
- if (connection?.id) {
320
- this.requestedWebRtcUpgradeConnectionIds.delete(connection.id);
321
- }
322
316
  this.introPeerIds.delete(peerId);
323
317
  this.peerStatsById.delete(peerId);
324
318
  this.emitter.emit('peer:left', clonePeer(peer));
@@ -370,7 +364,6 @@ export class OpenRtcNetcodeClient {
370
364
  this.connectionIds.add(connectionId);
371
365
  }
372
366
  this.connectionsByPeer.set(peerId, connection);
373
- this.requestPreferredTransportUpgrade(connection);
374
367
  const payloadReady = this.isPeerPayloadReady(peerId);
375
368
  const peer = this.upsertPeer(peerId, { connected: payloadReady });
376
369
  this.updatePeerStats(peerId, {
@@ -384,13 +377,15 @@ export class OpenRtcNetcodeClient {
384
377
  connection.onMessage((message) => {
385
378
  this.handleConnectionMessage(peerId, message);
386
379
  });
380
+ connection.onUpgradeStateChange?.(() => {
381
+ this.refreshPeerPayloadState(peerId);
382
+ });
387
383
  connection.onDisconnect(() => {
388
384
  if (this.connectionsByPeer.get(peerId) === connection) {
389
385
  this.connectionsByPeer.delete(peerId);
390
386
  }
391
387
  if (connectionId) {
392
388
  this.connectionIds.delete(connectionId);
393
- this.requestedWebRtcUpgradeConnectionIds.delete(connectionId);
394
389
  }
395
390
  const disconnected = this.upsertPeer(peerId, { connected: false });
396
391
  this.updatePeerStats(peerId, {
@@ -653,29 +648,28 @@ export class OpenRtcNetcodeClient {
653
648
  return;
654
649
  }
655
650
  for (const peer of this.peersById.values()) {
656
- const payloadReady = this.isPeerPayloadReady(peer.id);
657
- if (!payloadReady) {
658
- const connection = this.connectionsByPeer.get(peer.id);
659
- if (connection) {
660
- this.requestPreferredTransportUpgrade(connection);
661
- }
662
- }
663
- if (payloadReady && !peer.connected) {
664
- const connected = this.upsertPeer(peer.id, { connected: true });
665
- this.emitter.emit('peer:connected', clonePeer(connected));
666
- void this.voiceController.handlePeerConnected(peer.id);
667
- this.queuePeerIntro(peer.id, true);
668
- }
651
+ const payloadReady = this.refreshPeerPayloadState(peer.id);
669
652
  if (payloadReady) {
670
653
  void this.sendEnvelope(peer.id, 'ping', {});
671
654
  }
672
- this.updatePeerStats(peer.id, {
673
- connected: payloadReady,
674
- transport: this.resolvePeerTransport(peer.id),
675
- });
676
655
  }
677
656
  }, PING_INTERVAL_MS);
678
657
  }
658
+ refreshPeerPayloadState(peerId) {
659
+ const payloadReady = this.isPeerPayloadReady(peerId);
660
+ const peer = this.peersById.get(peerId);
661
+ if (payloadReady && peer && !peer.connected) {
662
+ const connected = this.upsertPeer(peerId, { connected: true });
663
+ this.emitter.emit('peer:connected', clonePeer(connected));
664
+ void this.voiceController.handlePeerConnected(peerId);
665
+ this.queuePeerIntro(peerId, true);
666
+ }
667
+ this.updatePeerStats(peerId, {
668
+ connected: payloadReady,
669
+ transport: this.resolvePeerTransport(peerId),
670
+ });
671
+ return payloadReady;
672
+ }
679
673
  stopPeerPingLoop() {
680
674
  if (this.peerPingTimer) {
681
675
  clearInterval(this.peerPingTimer);
@@ -974,28 +968,11 @@ export class OpenRtcNetcodeClient {
974
968
  }
975
969
  return this.connectionsByPeer.get(peerId) ?? null;
976
970
  }
977
- requestPreferredTransportUpgrade(connection) {
978
- const preferredTransports = this.payloadReadinessOptions().preferredTransports ?? [];
979
- const wantsWebRtc = preferredTransports.some((transport) => transport === 'webrtc' || transport === 'webrtc-lan');
980
- if (!wantsWebRtc || typeof connection.requestWebRTCUpgrade !== 'function') {
981
- return;
982
- }
983
- const remotePeerId = connection.remoteNodeId ?? connection.deviceId;
984
- if (this.localPeerId && remotePeerId && this.localPeerId.localeCompare(remotePeerId) <= 0) {
985
- return;
986
- }
987
- const upgradeKey = connection.id ?? connection.remoteNodeId ?? connection.deviceId;
988
- if (upgradeKey && this.requestedWebRtcUpgradeConnectionIds.has(upgradeKey)) {
989
- return;
990
- }
991
- if (upgradeKey) {
992
- this.requestedWebRtcUpgradeConnectionIds.add(upgradeKey);
993
- }
994
- connection.requestWebRTCUpgrade('openrtc-netcode-preferred-payload');
995
- }
996
971
  payloadReadinessOptions() {
997
972
  const preferredTransports = this.options.preferredPayloadTransports
998
- ?? derivePreferredPayloadTransports(this.options.transports, this.options.transportPriority);
973
+ ?? (this.ownsRuntime
974
+ ? derivePreferredPayloadTransports(this.options.transports, this.options.transportPriority)
975
+ : []);
999
976
  if (preferredTransports.length === 0) {
1000
977
  return {};
1001
978
  }
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { OpenRTC } from 'openrtc';
2
- import type { RuntimeClient } from 'openrtc/runtime';
2
+ import type { RuntimeApplicationPayloadReadinessOptions as OpenRtcApplicationPayloadReadinessOptions, RuntimeClient } from 'openrtc/runtime';
3
3
  import type { MetadataBody, NetcodeEnvelope, ObjectRemoveBody, ObjectSnapshotBody, ObjectUpsertBody, StatePatchBody, StateSnapshotBody, UserMessageBody, VoiceSignalBody } from './protocol.js';
4
4
  type OpenrtcClientOptions = Parameters<typeof OpenRTC>[0];
5
5
  export type NetcodeRuntime = RuntimeClient;
@@ -235,16 +235,14 @@ export type RuntimeConnectionLike = {
235
235
  parallelTransport?: string | null;
236
236
  };
237
237
  getAvailableTransports?(): string[];
238
+ onUpgradeStateChange?(callback: (state: 'none' | 'upgrading' | 'upgraded' | 'failed') => void): void;
238
239
  requestWebRTCUpgrade?(reason?: string): void;
239
240
  send(message: unknown): Promise<void> | void;
240
241
  onMessage(callback: (message: unknown) => void): void | (() => void);
241
242
  onDisconnect(callback: () => void): void | (() => void);
242
243
  disconnect?(): Promise<void> | void;
243
244
  };
244
- export type RuntimeApplicationPayloadReadinessOptions = {
245
- preferredTransports?: string[];
246
- allowFallbackAfterPreferredTransportFailure?: boolean;
247
- };
245
+ export type RuntimeApplicationPayloadReadinessOptions = OpenRtcApplicationPayloadReadinessOptions;
248
246
  export type RuntimeMemberLike = {
249
247
  nodeId?: string;
250
248
  userId?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openrtc-netcode",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -42,7 +42,7 @@
42
42
  "test:watch": "vitest"
43
43
  },
44
44
  "dependencies": {
45
- "openrtc": "^0.2.0"
45
+ "openrtc": "^1.0.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/node": "^24.10.1",