@fairfox/polly 0.56.0 → 0.57.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.
@@ -21,7 +21,7 @@ export type { EncryptedEnvelope, SealedBytes, } from "./shared/lib/encryption";
21
21
  export { decrypt, decryptOrThrow, EncryptionError, encrypt, generateDocumentKey, KEY_BYTES as ENCRYPTION_KEY_BYTES, NONCE_BYTES as ENCRYPTION_NONCE_BYTES, TAG_BYTES as ENCRYPTION_TAG_BYTES, } from "./shared/lib/encryption";
22
22
  export type { KeyringStorage } from "./shared/lib/keyring-storage";
23
23
  export { deserialiseKeyring, memoryKeyringStorage, serialiseKeyring, } from "./shared/lib/keyring-storage";
24
- export type { CreateMeshClientOptions, MeshClient } from "./shared/lib/mesh-client";
24
+ export type { CreateMeshClientOptions, MeshClient, MeshClientHandleSnapshot, MeshClientPeerStateSnapshot, } from "./shared/lib/mesh-client";
25
25
  export { createMeshClient } from "./shared/lib/mesh-client";
26
26
  export type { MeshKeyring, MeshNetworkAdapterOptions, } from "./shared/lib/mesh-network-adapter";
27
27
  export { DEFAULT_MESH_KEY_ID, MeshNetworkAdapter, } from "./shared/lib/mesh-network-adapter";
@@ -29,7 +29,7 @@ export type { MeshSignalingClientOptions, SignalingMessage as MeshSignalingMessa
29
29
  export { MeshSignalingClient } from "./shared/lib/mesh-signaling-client";
30
30
  export type { MeshStateOptions } from "./shared/lib/mesh-state";
31
31
  export { $meshCounter, $meshList, $meshState, $meshText, configureMeshState, resetMeshState, } from "./shared/lib/mesh-state";
32
- export type { InFlightSyncSnapshot, MeshWebRTCAdapterOptions, SlotInitiationDecision, SlotInitiationRejectionReason, SweepSnapshot, SyncHandshakeAttemptSnapshot, SyncProgressEvent, TransportSnapshot, } from "./shared/lib/mesh-webrtc-adapter";
32
+ export type { HandleSyncSnapshot, InFlightSyncSnapshot, MeshWebRTCAdapterOptions, SlotInitiationDecision, SlotInitiationRejectionReason, SweepSnapshot, SyncHandshakeAttemptSnapshot, SyncProgressEvent, TransportSnapshot, } from "./shared/lib/mesh-webrtc-adapter";
33
33
  export { DEFAULT_ICE_SERVERS, MeshWebRTCAdapter } from "./shared/lib/mesh-webrtc-adapter";
34
34
  export type { CreatePairingTokenOptions, PairingToken, } from "./shared/lib/pairing";
35
35
  export { applyPairingToken, createPairingToken, createPairingTokenWithFreshIdentity, DEFAULT_PAIRING_TTL_MS, decodePairingToken, encodePairingToken, isPairingTokenExpired, PAIRING_NONCE_BYTES, PAIRING_TOKEN_VERSION, PairingError, parsePairingToken, serialisePairingToken, } from "./shared/lib/pairing";
package/dist/src/mesh.js CHANGED
@@ -1075,12 +1075,16 @@ class MeshNetworkAdapter extends NetworkAdapter {
1075
1075
  }
1076
1076
  const signed = signEnvelope(payloadToSign, message.senderId, keyring.identity.secretKey);
1077
1077
  const signedBytes = encodeSignedEnvelope(signed);
1078
- return {
1078
+ const outer = {
1079
1079
  type: message.type,
1080
1080
  senderId: message.senderId,
1081
1081
  targetId: message.targetId,
1082
1082
  data: signedBytes
1083
1083
  };
1084
+ if ("documentId" in message && message.documentId !== undefined) {
1085
+ outer["documentId"] = message.documentId;
1086
+ }
1087
+ return outer;
1084
1088
  }
1085
1089
  tryUnwrap(message) {
1086
1090
  if (!message.data)
@@ -2033,6 +2037,10 @@ function selectActivePair(parsed) {
2033
2037
  return;
2034
2038
  }
2035
2039
  function serialiseSlotView(slot) {
2040
+ const handles = {};
2041
+ for (const [docId, snapshot] of slot.handles) {
2042
+ handles[docId] = { ...snapshot };
2043
+ }
2036
2044
  return {
2037
2045
  signalingState: slot.connection.signalingState,
2038
2046
  iceConnectionState: slot.connection.iceConnectionState,
@@ -2045,7 +2053,8 @@ function serialiseSlotView(slot) {
2045
2053
  ...slot.transport,
2046
2054
  selectedCandidatePair: slot.transport.selectedCandidatePair ? { ...slot.transport.selectedCandidatePair } : undefined
2047
2055
  } : undefined,
2048
- lastSyncHandshakeAttempt: { ...slot.lastSyncHandshakeAttempt }
2056
+ lastSyncHandshakeAttempt: { ...slot.lastSyncHandshakeAttempt },
2057
+ handles
2049
2058
  };
2050
2059
  }
2051
2060
  function emptySyncHandshakeAttempt() {
@@ -2072,6 +2081,14 @@ var DEFAULT_ICE_SERVERS = [
2072
2081
  { urls: "stun:stun.l.google.com:19302" },
2073
2082
  { urls: "stun:stun1.l.google.com:19302" }
2074
2083
  ];
2084
+ function emptyHandleSyncSnapshot() {
2085
+ return {
2086
+ lastSyncMessageOutAt: undefined,
2087
+ lastSyncMessageInAt: undefined,
2088
+ lastSyncMessageOutSize: undefined,
2089
+ lastSyncMessageOutType: undefined
2090
+ };
2091
+ }
2075
2092
 
2076
2093
  class MeshWebRTCAdapter extends NetworkAdapter2 {
2077
2094
  signaling;
@@ -2319,6 +2336,17 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
2319
2336
  if (slot.lastSyncHandshakeAttempt.firstOutboundSendAt === undefined) {
2320
2337
  slot.lastSyncHandshakeAttempt.firstOutboundSendAt = performance.now();
2321
2338
  }
2339
+ const documentId = message.documentId;
2340
+ if (typeof documentId === "string") {
2341
+ let handleEntry = slot.handles.get(documentId);
2342
+ if (!handleEntry) {
2343
+ handleEntry = emptyHandleSyncSnapshot();
2344
+ slot.handles.set(documentId, handleEntry);
2345
+ }
2346
+ handleEntry.lastSyncMessageOutAt = performance.now();
2347
+ handleEntry.lastSyncMessageOutSize = bytes.length;
2348
+ handleEntry.lastSyncMessageOutType = typeof message.type === "string" ? message.type : undefined;
2349
+ }
2322
2350
  if (slot.channel && slot.channel.readyState === "open") {
2323
2351
  this.sendBytesMaybeFragmented(slot.channel, bytes);
2324
2352
  } else {
@@ -2432,7 +2460,8 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
2432
2460
  inFlightSync: undefined,
2433
2461
  transport: undefined,
2434
2462
  lastDataChannelError: undefined,
2435
- lastSyncHandshakeAttempt: emptySyncHandshakeAttempt()
2463
+ lastSyncHandshakeAttempt: emptySyncHandshakeAttempt(),
2464
+ handles: new Map
2436
2465
  };
2437
2466
  this.slots.set(targetId, slot);
2438
2467
  this.wireConnection(targetId, connection);
@@ -2474,7 +2503,8 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
2474
2503
  inFlightSync: undefined,
2475
2504
  transport: undefined,
2476
2505
  lastDataChannelError: undefined,
2477
- lastSyncHandshakeAttempt: emptySyncHandshakeAttempt()
2506
+ lastSyncHandshakeAttempt: emptySyncHandshakeAttempt(),
2507
+ handles: new Map
2478
2508
  };
2479
2509
  this.slots.set(fromPeerId, slot);
2480
2510
  this.wireConnection(fromPeerId, connection);
@@ -2638,6 +2668,7 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
2638
2668
  }
2639
2669
  scheduleEmitMessage(fromPeerId, message, viaFragmentPath) {
2640
2670
  this.stampFirstInboundMessage(fromPeerId);
2671
+ this.stampHandleInbound(fromPeerId, message);
2641
2672
  if (!this.syncYieldEnabled) {
2642
2673
  this.emit("message", message);
2643
2674
  if (viaFragmentPath) {
@@ -2669,6 +2700,20 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
2669
2700
  return;
2670
2701
  slot.lastSyncHandshakeAttempt.firstInboundMessageAt = performance.now();
2671
2702
  }
2703
+ stampHandleInbound(fromPeerId, message) {
2704
+ const documentId = message.documentId;
2705
+ if (typeof documentId !== "string")
2706
+ return;
2707
+ const slot = this.slots.get(fromPeerId);
2708
+ if (!slot)
2709
+ return;
2710
+ let entry = slot.handles.get(documentId);
2711
+ if (!entry) {
2712
+ entry = emptyHandleSyncSnapshot();
2713
+ slot.handles.set(documentId, entry);
2714
+ }
2715
+ entry.lastSyncMessageInAt = performance.now();
2716
+ }
2672
2717
  finishInFlightSyncApply(fromPeerId) {
2673
2718
  const slot = this.slots.get(fromPeerId);
2674
2719
  if (!slot?.inFlightSync)
@@ -2810,6 +2855,54 @@ async function resolveIceServers(rtc) {
2810
2855
  }
2811
2856
  return rtc?.iceServers;
2812
2857
  }
2858
+ function buildHandleEntry(state, wire) {
2859
+ return {
2860
+ state,
2861
+ announcedToPeer: wire?.lastSyncMessageOutAt !== undefined,
2862
+ lastSyncMessageOutAt: wire?.lastSyncMessageOutAt,
2863
+ lastSyncMessageInAt: wire?.lastSyncMessageInAt,
2864
+ lastSyncMessageOutSize: wire?.lastSyncMessageOutSize,
2865
+ lastSyncMessageOutType: wire?.lastSyncMessageOutType
2866
+ };
2867
+ }
2868
+ function stringifyHandleState(handle) {
2869
+ if (handle === undefined)
2870
+ return "unknown";
2871
+ return typeof handle.state === "string" ? handle.state : String(handle.state ?? "unknown");
2872
+ }
2873
+ function enrichPeerSlot(peer, knownHandleIds, repoHandles) {
2874
+ if (!peer.slot) {
2875
+ return { ...peer, slot: undefined };
2876
+ }
2877
+ const enriched = {};
2878
+ for (const docId of knownHandleIds) {
2879
+ enriched[docId] = buildHandleEntry(stringifyHandleState(repoHandles[docId]), peer.slot.handles[docId]);
2880
+ }
2881
+ for (const docId of Object.keys(peer.slot.handles)) {
2882
+ if (enriched[docId])
2883
+ continue;
2884
+ enriched[docId] = buildHandleEntry("unknown", peer.slot.handles[docId]);
2885
+ }
2886
+ return { ...peer, slot: { ...peer.slot, handles: enriched } };
2887
+ }
2888
+ function getReevaluateDocumentShare(repo) {
2889
+ const sync = repo.synchronizer;
2890
+ const fn = sync?.reevaluateDocumentShare;
2891
+ if (typeof fn !== "function" || sync === undefined)
2892
+ return;
2893
+ return () => fn.call(sync);
2894
+ }
2895
+ function installPolly107SyncReevaluation(networkAdapter, repo) {
2896
+ const disable = typeof process !== "undefined" && process.env?.["POLLY_107_DISABLE_FIX"] === "1";
2897
+ if (disable)
2898
+ return;
2899
+ const reevaluate = getReevaluateDocumentShare(repo);
2900
+ if (!reevaluate)
2901
+ return;
2902
+ networkAdapter.on("peer-candidate", () => {
2903
+ reevaluate().catch(() => {});
2904
+ });
2905
+ }
2813
2906
  async function createMeshClient(options) {
2814
2907
  const keyringSource = await resolveKeyringSource(options.keyring);
2815
2908
  const keyring = keyringSource();
@@ -2882,6 +2975,7 @@ async function createMeshClient(options) {
2882
2975
  ...options.repoStorage !== undefined && { storage: options.repoStorage }
2883
2976
  });
2884
2977
  configureMeshState(repo);
2978
+ installPolly107SyncReevaluation(networkAdapter, repo);
2885
2979
  await signaling.connect();
2886
2980
  return {
2887
2981
  repo,
@@ -2909,7 +3003,24 @@ async function createMeshClient(options) {
2909
3003
  peers: []
2910
3004
  };
2911
3005
  }
2912
- return webrtcAdapter.getPeerStateSnapshot();
3006
+ const base = webrtcAdapter.getPeerStateSnapshot();
3007
+ const repoHandles = repo.handles;
3008
+ const knownHandleIds = Object.keys(repoHandles);
3009
+ const enrichedPeers = base.peers.map((peer) => enrichPeerSlot(peer, knownHandleIds, repoHandles));
3010
+ const out = {
3011
+ localPeerId: base.localPeerId,
3012
+ knownPeerIds: base.knownPeerIds,
3013
+ presentPeerIds: base.presentPeerIds,
3014
+ sweep: base.sweep,
3015
+ peers: enrichedPeers
3016
+ };
3017
+ return out;
3018
+ },
3019
+ reevaluateAllSync: async () => {
3020
+ const reevaluate = getReevaluateDocumentShare(repo);
3021
+ if (!reevaluate)
3022
+ return;
3023
+ await reevaluate();
2913
3024
  },
2914
3025
  refreshTransportStats: async () => {
2915
3026
  if (!webrtcAdapter)
@@ -3330,4 +3441,4 @@ export {
3330
3441
  $meshCounter
3331
3442
  };
3332
3443
 
3333
- //# debugId=27D9577FC215E14564756E2164756E21
3444
+ //# debugId=DAB92455464EE0D864756E2164756E21