@fairfox/polly 0.56.0 → 0.58.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/dist/src/mesh.d.ts +3 -3
- package/dist/src/mesh.js +161 -8
- package/dist/src/mesh.js.map +7 -7
- package/dist/src/peer.js +6 -2
- package/dist/src/peer.js.map +3 -3
- package/dist/src/shared/lib/mesh-client.d.ts +119 -5
- package/dist/src/shared/lib/mesh-state.d.ts +45 -0
- package/dist/src/shared/lib/mesh-webrtc-adapter.d.ts +77 -5
- package/package.json +1 -1
package/dist/src/mesh.d.ts
CHANGED
|
@@ -21,15 +21,15 @@ 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, MeshStateModuleDiagnostics, } 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";
|
|
28
28
|
export type { MeshSignalingClientOptions, SignalingMessage as MeshSignalingMessage, } from "./shared/lib/mesh-signaling-client";
|
|
29
29
|
export { MeshSignalingClient } from "./shared/lib/mesh-signaling-client";
|
|
30
30
|
export type { MeshStateOptions } from "./shared/lib/mesh-state";
|
|
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";
|
|
31
|
+
export { $meshCounter, $meshList, $meshState, $meshText, configureMeshState, getLastConfiguredRepoPeerId, getMeshStateModuleId, isMeshStateConfigured, MESH_STATE_MODULE_ID, resetMeshState, wasMeshStateResolved, } from "./shared/lib/mesh-state";
|
|
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
|
-
|
|
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)
|
|
@@ -1760,16 +1764,37 @@ function fieldEquals(a, b) {
|
|
|
1760
1764
|
|
|
1761
1765
|
// src/shared/lib/mesh-state.ts
|
|
1762
1766
|
var defaultRepo;
|
|
1767
|
+
var MESH_STATE_MODULE_ID = `mesh-state-${typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : Math.random().toString(36).slice(2) + Date.now().toString(36)}`;
|
|
1768
|
+
function getMeshStateModuleId() {
|
|
1769
|
+
return MESH_STATE_MODULE_ID;
|
|
1770
|
+
}
|
|
1771
|
+
var lastConfiguredRepoPeerId;
|
|
1772
|
+
function getLastConfiguredRepoPeerId() {
|
|
1773
|
+
return lastConfiguredRepoPeerId;
|
|
1774
|
+
}
|
|
1763
1775
|
function configureMeshState(repo) {
|
|
1764
1776
|
defaultRepo = repo;
|
|
1777
|
+
lastConfiguredRepoPeerId = repo.peerId;
|
|
1765
1778
|
}
|
|
1766
1779
|
function resetMeshState() {
|
|
1767
1780
|
defaultRepo = undefined;
|
|
1781
|
+
lastConfiguredRepoPeerId = undefined;
|
|
1782
|
+
}
|
|
1783
|
+
function isMeshStateConfigured() {
|
|
1784
|
+
return defaultRepo !== undefined;
|
|
1785
|
+
}
|
|
1786
|
+
var meshStateEverResolved = false;
|
|
1787
|
+
function wasMeshStateResolved() {
|
|
1788
|
+
return meshStateEverResolved;
|
|
1768
1789
|
}
|
|
1769
1790
|
function resolveRepo(option) {
|
|
1791
|
+
meshStateEverResolved = true;
|
|
1770
1792
|
const repo = option ?? defaultRepo;
|
|
1771
1793
|
if (!repo) {
|
|
1772
|
-
|
|
1794
|
+
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1795
|
+
console.warn(`[polly#107 H5] $meshState resolved against unconfigured module instance ${MESH_STATE_MODULE_ID}. If createMeshClient was called elsewhere, the consumer's wrappers and the mesh client are reaching different module instances — see polly#107.`);
|
|
1796
|
+
}
|
|
1797
|
+
throw new Error(`Polly $meshState: no Repo configured (module instance ${MESH_STATE_MODULE_ID}). Call configureMeshState(repo) at startup or pass { repo } in the primitive options. If you have called configureMeshState elsewhere, the most likely cause is that the call resolved to a different module instance than this one — see polly#107.`);
|
|
1773
1798
|
}
|
|
1774
1799
|
return repo;
|
|
1775
1800
|
}
|
|
@@ -2033,6 +2058,10 @@ function selectActivePair(parsed) {
|
|
|
2033
2058
|
return;
|
|
2034
2059
|
}
|
|
2035
2060
|
function serialiseSlotView(slot) {
|
|
2061
|
+
const handles = {};
|
|
2062
|
+
for (const [docId, snapshot] of slot.handles) {
|
|
2063
|
+
handles[docId] = { ...snapshot };
|
|
2064
|
+
}
|
|
2036
2065
|
return {
|
|
2037
2066
|
signalingState: slot.connection.signalingState,
|
|
2038
2067
|
iceConnectionState: slot.connection.iceConnectionState,
|
|
@@ -2045,7 +2074,8 @@ function serialiseSlotView(slot) {
|
|
|
2045
2074
|
...slot.transport,
|
|
2046
2075
|
selectedCandidatePair: slot.transport.selectedCandidatePair ? { ...slot.transport.selectedCandidatePair } : undefined
|
|
2047
2076
|
} : undefined,
|
|
2048
|
-
lastSyncHandshakeAttempt: { ...slot.lastSyncHandshakeAttempt }
|
|
2077
|
+
lastSyncHandshakeAttempt: { ...slot.lastSyncHandshakeAttempt },
|
|
2078
|
+
handles
|
|
2049
2079
|
};
|
|
2050
2080
|
}
|
|
2051
2081
|
function emptySyncHandshakeAttempt() {
|
|
@@ -2072,6 +2102,14 @@ var DEFAULT_ICE_SERVERS = [
|
|
|
2072
2102
|
{ urls: "stun:stun.l.google.com:19302" },
|
|
2073
2103
|
{ urls: "stun:stun1.l.google.com:19302" }
|
|
2074
2104
|
];
|
|
2105
|
+
function emptyHandleSyncSnapshot() {
|
|
2106
|
+
return {
|
|
2107
|
+
lastSyncMessageOutAt: undefined,
|
|
2108
|
+
lastSyncMessageInAt: undefined,
|
|
2109
|
+
lastSyncMessageOutSize: undefined,
|
|
2110
|
+
lastSyncMessageOutType: undefined
|
|
2111
|
+
};
|
|
2112
|
+
}
|
|
2075
2113
|
|
|
2076
2114
|
class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
2077
2115
|
signaling;
|
|
@@ -2319,6 +2357,17 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2319
2357
|
if (slot.lastSyncHandshakeAttempt.firstOutboundSendAt === undefined) {
|
|
2320
2358
|
slot.lastSyncHandshakeAttempt.firstOutboundSendAt = performance.now();
|
|
2321
2359
|
}
|
|
2360
|
+
const documentId = message.documentId;
|
|
2361
|
+
if (typeof documentId === "string") {
|
|
2362
|
+
let handleEntry = slot.handles.get(documentId);
|
|
2363
|
+
if (!handleEntry) {
|
|
2364
|
+
handleEntry = emptyHandleSyncSnapshot();
|
|
2365
|
+
slot.handles.set(documentId, handleEntry);
|
|
2366
|
+
}
|
|
2367
|
+
handleEntry.lastSyncMessageOutAt = performance.now();
|
|
2368
|
+
handleEntry.lastSyncMessageOutSize = bytes.length;
|
|
2369
|
+
handleEntry.lastSyncMessageOutType = typeof message.type === "string" ? message.type : undefined;
|
|
2370
|
+
}
|
|
2322
2371
|
if (slot.channel && slot.channel.readyState === "open") {
|
|
2323
2372
|
this.sendBytesMaybeFragmented(slot.channel, bytes);
|
|
2324
2373
|
} else {
|
|
@@ -2432,7 +2481,8 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2432
2481
|
inFlightSync: undefined,
|
|
2433
2482
|
transport: undefined,
|
|
2434
2483
|
lastDataChannelError: undefined,
|
|
2435
|
-
lastSyncHandshakeAttempt: emptySyncHandshakeAttempt()
|
|
2484
|
+
lastSyncHandshakeAttempt: emptySyncHandshakeAttempt(),
|
|
2485
|
+
handles: new Map
|
|
2436
2486
|
};
|
|
2437
2487
|
this.slots.set(targetId, slot);
|
|
2438
2488
|
this.wireConnection(targetId, connection);
|
|
@@ -2474,7 +2524,8 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2474
2524
|
inFlightSync: undefined,
|
|
2475
2525
|
transport: undefined,
|
|
2476
2526
|
lastDataChannelError: undefined,
|
|
2477
|
-
lastSyncHandshakeAttempt: emptySyncHandshakeAttempt()
|
|
2527
|
+
lastSyncHandshakeAttempt: emptySyncHandshakeAttempt(),
|
|
2528
|
+
handles: new Map
|
|
2478
2529
|
};
|
|
2479
2530
|
this.slots.set(fromPeerId, slot);
|
|
2480
2531
|
this.wireConnection(fromPeerId, connection);
|
|
@@ -2638,6 +2689,7 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2638
2689
|
}
|
|
2639
2690
|
scheduleEmitMessage(fromPeerId, message, viaFragmentPath) {
|
|
2640
2691
|
this.stampFirstInboundMessage(fromPeerId);
|
|
2692
|
+
this.stampHandleInbound(fromPeerId, message);
|
|
2641
2693
|
if (!this.syncYieldEnabled) {
|
|
2642
2694
|
this.emit("message", message);
|
|
2643
2695
|
if (viaFragmentPath) {
|
|
@@ -2669,6 +2721,20 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2669
2721
|
return;
|
|
2670
2722
|
slot.lastSyncHandshakeAttempt.firstInboundMessageAt = performance.now();
|
|
2671
2723
|
}
|
|
2724
|
+
stampHandleInbound(fromPeerId, message) {
|
|
2725
|
+
const documentId = message.documentId;
|
|
2726
|
+
if (typeof documentId !== "string")
|
|
2727
|
+
return;
|
|
2728
|
+
const slot = this.slots.get(fromPeerId);
|
|
2729
|
+
if (!slot)
|
|
2730
|
+
return;
|
|
2731
|
+
let entry = slot.handles.get(documentId);
|
|
2732
|
+
if (!entry) {
|
|
2733
|
+
entry = emptyHandleSyncSnapshot();
|
|
2734
|
+
slot.handles.set(documentId, entry);
|
|
2735
|
+
}
|
|
2736
|
+
entry.lastSyncMessageInAt = performance.now();
|
|
2737
|
+
}
|
|
2672
2738
|
finishInFlightSyncApply(fromPeerId) {
|
|
2673
2739
|
const slot = this.slots.get(fromPeerId);
|
|
2674
2740
|
if (!slot?.inFlightSync)
|
|
@@ -2810,6 +2876,54 @@ async function resolveIceServers(rtc) {
|
|
|
2810
2876
|
}
|
|
2811
2877
|
return rtc?.iceServers;
|
|
2812
2878
|
}
|
|
2879
|
+
function buildHandleEntry(state, wire) {
|
|
2880
|
+
return {
|
|
2881
|
+
state,
|
|
2882
|
+
announcedToPeer: wire?.lastSyncMessageOutAt !== undefined,
|
|
2883
|
+
lastSyncMessageOutAt: wire?.lastSyncMessageOutAt,
|
|
2884
|
+
lastSyncMessageInAt: wire?.lastSyncMessageInAt,
|
|
2885
|
+
lastSyncMessageOutSize: wire?.lastSyncMessageOutSize,
|
|
2886
|
+
lastSyncMessageOutType: wire?.lastSyncMessageOutType
|
|
2887
|
+
};
|
|
2888
|
+
}
|
|
2889
|
+
function stringifyHandleState(handle) {
|
|
2890
|
+
if (handle === undefined)
|
|
2891
|
+
return "unknown";
|
|
2892
|
+
return typeof handle.state === "string" ? handle.state : String(handle.state ?? "unknown");
|
|
2893
|
+
}
|
|
2894
|
+
function enrichPeerSlot(peer, knownHandleIds, repoHandles) {
|
|
2895
|
+
if (!peer.slot) {
|
|
2896
|
+
return { ...peer, slot: undefined };
|
|
2897
|
+
}
|
|
2898
|
+
const enriched = {};
|
|
2899
|
+
for (const docId of knownHandleIds) {
|
|
2900
|
+
enriched[docId] = buildHandleEntry(stringifyHandleState(repoHandles[docId]), peer.slot.handles[docId]);
|
|
2901
|
+
}
|
|
2902
|
+
for (const docId of Object.keys(peer.slot.handles)) {
|
|
2903
|
+
if (enriched[docId])
|
|
2904
|
+
continue;
|
|
2905
|
+
enriched[docId] = buildHandleEntry("unknown", peer.slot.handles[docId]);
|
|
2906
|
+
}
|
|
2907
|
+
return { ...peer, slot: { ...peer.slot, handles: enriched } };
|
|
2908
|
+
}
|
|
2909
|
+
function getReevaluateDocumentShare(repo) {
|
|
2910
|
+
const sync = repo.synchronizer;
|
|
2911
|
+
const fn = sync?.reevaluateDocumentShare;
|
|
2912
|
+
if (typeof fn !== "function" || sync === undefined)
|
|
2913
|
+
return;
|
|
2914
|
+
return () => fn.call(sync);
|
|
2915
|
+
}
|
|
2916
|
+
function installPolly107SyncReevaluation(networkAdapter, repo) {
|
|
2917
|
+
const disable = typeof process !== "undefined" && process.env?.["POLLY_107_DISABLE_FIX"] === "1";
|
|
2918
|
+
if (disable)
|
|
2919
|
+
return;
|
|
2920
|
+
const reevaluate = getReevaluateDocumentShare(repo);
|
|
2921
|
+
if (!reevaluate)
|
|
2922
|
+
return;
|
|
2923
|
+
networkAdapter.on("peer-candidate", () => {
|
|
2924
|
+
reevaluate().catch(() => {});
|
|
2925
|
+
});
|
|
2926
|
+
}
|
|
2813
2927
|
async function createMeshClient(options) {
|
|
2814
2928
|
const keyringSource = await resolveKeyringSource(options.keyring);
|
|
2815
2929
|
const keyring = keyringSource();
|
|
@@ -2882,6 +2996,7 @@ async function createMeshClient(options) {
|
|
|
2882
2996
|
...options.repoStorage !== undefined && { storage: options.repoStorage }
|
|
2883
2997
|
});
|
|
2884
2998
|
configureMeshState(repo);
|
|
2999
|
+
installPolly107SyncReevaluation(networkAdapter, repo);
|
|
2885
3000
|
await signaling.connect();
|
|
2886
3001
|
return {
|
|
2887
3002
|
repo,
|
|
@@ -2906,10 +3021,43 @@ async function createMeshClient(options) {
|
|
|
2906
3021
|
runCount: 0,
|
|
2907
3022
|
lastRunAt: undefined
|
|
2908
3023
|
},
|
|
2909
|
-
peers: []
|
|
3024
|
+
peers: [],
|
|
3025
|
+
meshStateModule: {
|
|
3026
|
+
moduleId: getMeshStateModuleId(),
|
|
3027
|
+
configured: isMeshStateConfigured(),
|
|
3028
|
+
lastConfiguredRepoPeerId: getLastConfiguredRepoPeerId(),
|
|
3029
|
+
wasResolved: wasMeshStateResolved()
|
|
3030
|
+
},
|
|
3031
|
+
repoHandleCount: Object.keys(repo.handles).length,
|
|
3032
|
+
repoHandleIds: Object.keys(repo.handles)
|
|
2910
3033
|
};
|
|
2911
3034
|
}
|
|
2912
|
-
|
|
3035
|
+
const base = webrtcAdapter.getPeerStateSnapshot();
|
|
3036
|
+
const repoHandles = repo.handles;
|
|
3037
|
+
const knownHandleIds = Object.keys(repoHandles);
|
|
3038
|
+
const enrichedPeers = base.peers.map((peer) => enrichPeerSlot(peer, knownHandleIds, repoHandles));
|
|
3039
|
+
const out = {
|
|
3040
|
+
localPeerId: base.localPeerId,
|
|
3041
|
+
knownPeerIds: base.knownPeerIds,
|
|
3042
|
+
presentPeerIds: base.presentPeerIds,
|
|
3043
|
+
sweep: base.sweep,
|
|
3044
|
+
peers: enrichedPeers,
|
|
3045
|
+
meshStateModule: {
|
|
3046
|
+
moduleId: getMeshStateModuleId(),
|
|
3047
|
+
configured: isMeshStateConfigured(),
|
|
3048
|
+
lastConfiguredRepoPeerId: getLastConfiguredRepoPeerId(),
|
|
3049
|
+
wasResolved: wasMeshStateResolved()
|
|
3050
|
+
},
|
|
3051
|
+
repoHandleCount: knownHandleIds.length,
|
|
3052
|
+
repoHandleIds: knownHandleIds
|
|
3053
|
+
};
|
|
3054
|
+
return out;
|
|
3055
|
+
},
|
|
3056
|
+
reevaluateAllSync: async () => {
|
|
3057
|
+
const reevaluate = getReevaluateDocumentShare(repo);
|
|
3058
|
+
if (!reevaluate)
|
|
3059
|
+
return;
|
|
3060
|
+
await reevaluate();
|
|
2913
3061
|
},
|
|
2914
3062
|
refreshTransportStats: async () => {
|
|
2915
3063
|
if (!webrtcAdapter)
|
|
@@ -3271,6 +3419,7 @@ function decodeRevocation(bytes, keyring) {
|
|
|
3271
3419
|
return record;
|
|
3272
3420
|
}
|
|
3273
3421
|
export {
|
|
3422
|
+
wasMeshStateResolved,
|
|
3274
3423
|
verify,
|
|
3275
3424
|
signingKeyPairFromSecret,
|
|
3276
3425
|
sign,
|
|
@@ -3281,7 +3430,10 @@ export {
|
|
|
3281
3430
|
parsePairingToken,
|
|
3282
3431
|
memoryKeyringStorage,
|
|
3283
3432
|
isPairingTokenExpired,
|
|
3433
|
+
isMeshStateConfigured,
|
|
3284
3434
|
isBlobRef,
|
|
3435
|
+
getMeshStateModuleId,
|
|
3436
|
+
getLastConfiguredRepoPeerId,
|
|
3285
3437
|
generateSigningKeyPair,
|
|
3286
3438
|
generateDocumentKey,
|
|
3287
3439
|
encrypt,
|
|
@@ -3316,6 +3468,7 @@ export {
|
|
|
3316
3468
|
MeshSignalingClient,
|
|
3317
3469
|
MeshNetworkAdapter,
|
|
3318
3470
|
MemoryBlobCache,
|
|
3471
|
+
MESH_STATE_MODULE_ID,
|
|
3319
3472
|
IndexedDBBlobCache,
|
|
3320
3473
|
EncryptionError,
|
|
3321
3474
|
TAG_BYTES as ENCRYPTION_TAG_BYTES,
|
|
@@ -3330,4 +3483,4 @@ export {
|
|
|
3330
3483
|
$meshCounter
|
|
3331
3484
|
};
|
|
3332
3485
|
|
|
3333
|
-
//# debugId=
|
|
3486
|
+
//# debugId=23078FA0DB4C154064756E2164756E21
|