@muhkoo/connect 0.10.4-alpha.0 → 0.10.5-alpha.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/browser/index.js +26 -15
- package/dist/browser/index.js.map +1 -1
- package/dist/connect.d.ts +17 -6
- package/dist/server/index.js +26 -15
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/connect.d.ts
CHANGED
|
@@ -4379,6 +4379,10 @@ declare class SpaceNamespace {
|
|
|
4379
4379
|
private spaceCache?;
|
|
4380
4380
|
/** Spaces built this session, by id — used to route offline send replays. */
|
|
4381
4381
|
private readonly openSpaces;
|
|
4382
|
+
/** Unique id for THIS device/session — the P2P peer identity. A user's own
|
|
4383
|
+
* devices share a member id, so the mesh MUST distinguish them by this or a
|
|
4384
|
+
* device treats its siblings' signals as its own echo and never connects. */
|
|
4385
|
+
private readonly deviceId;
|
|
4382
4386
|
constructor(deps: SpaceNamespaceDeps);
|
|
4383
4387
|
/**
|
|
4384
4388
|
* Create a new space: generate its keypair (public key = id), register
|
|
@@ -5392,15 +5396,20 @@ declare class PeerExchange implements PeerBlockSource {
|
|
|
5392
5396
|
* to Space membership. The sender (`from`) is server-stamped and can't be
|
|
5393
5397
|
* spoofed; the payload is opaque to the server.
|
|
5394
5398
|
*
|
|
5395
|
-
*
|
|
5396
|
-
*
|
|
5397
|
-
*
|
|
5398
|
-
*
|
|
5399
|
+
* Peers are identified by a unique **peer id** (per device/connection), carried
|
|
5400
|
+
* in the envelope's `from`/`to` — NOT by the server-stamped member id. This is
|
|
5401
|
+
* essential: one user's own devices share a member id, so the server's `from`
|
|
5402
|
+
* can't tell them apart (and would make each treat the others' signals as its
|
|
5403
|
+
* own echo). We therefore route entirely on the envelope peer ids and broadcast
|
|
5404
|
+
* to the whole Space, filtering client-side. The server `from` still guarantees
|
|
5405
|
+
* the sender is an authenticated Space member.
|
|
5399
5406
|
*/
|
|
5400
5407
|
declare const P2P_SUBJECT = "__p2p__";
|
|
5401
5408
|
type SignalKind = "hello" | "bye" | "offer" | "answer" | "ice";
|
|
5402
5409
|
interface SignalEnvelope {
|
|
5403
|
-
/**
|
|
5410
|
+
/** Sender's unique PEER id (per device/connection). */
|
|
5411
|
+
from: string;
|
|
5412
|
+
/** Target peer id, or `"*"` to broadcast (discovery / departure). */
|
|
5404
5413
|
to: string;
|
|
5405
5414
|
kind: SignalKind;
|
|
5406
5415
|
data?: unknown;
|
|
@@ -5424,7 +5433,9 @@ declare class SpaceSignaler {
|
|
|
5424
5433
|
broadcast(kind: SignalKind, data?: unknown): void;
|
|
5425
5434
|
/**
|
|
5426
5435
|
* Subscribe to inbound signals addressed to us (or broadcast). Skips our own
|
|
5427
|
-
* echoes. Returns an unsubscribe function.
|
|
5436
|
+
* echoes. Returns an unsubscribe function. Routing is entirely by the envelope
|
|
5437
|
+
* peer id (`env.from`/`env.to`), so a user's own devices — which share the
|
|
5438
|
+
* server-stamped `e.from` — are correctly distinguished.
|
|
5428
5439
|
*/
|
|
5429
5440
|
onSignal(cb: (from: string, kind: SignalKind, data: unknown) => void): () => void;
|
|
5430
5441
|
}
|
package/dist/server/index.js
CHANGED
|
@@ -2976,7 +2976,7 @@ function base64UrlDecode(s) {
|
|
|
2976
2976
|
* expect (and isn't serving a stale cached bundle). Keep this in sync with
|
|
2977
2977
|
* `package.json` `version`.
|
|
2978
2978
|
*/
|
|
2979
|
-
const VERSION = "0.10.
|
|
2979
|
+
const VERSION = "0.10.5-alpha.0";
|
|
2980
2980
|
|
|
2981
2981
|
/**
|
|
2982
2982
|
* `HttpClient` — the one place the unified {@link Client} talks to the
|
|
@@ -8470,10 +8470,13 @@ class PeerExchange {
|
|
|
8470
8470
|
* to Space membership. The sender (`from`) is server-stamped and can't be
|
|
8471
8471
|
* spoofed; the payload is opaque to the server.
|
|
8472
8472
|
*
|
|
8473
|
-
*
|
|
8474
|
-
*
|
|
8475
|
-
*
|
|
8476
|
-
*
|
|
8473
|
+
* Peers are identified by a unique **peer id** (per device/connection), carried
|
|
8474
|
+
* in the envelope's `from`/`to` — NOT by the server-stamped member id. This is
|
|
8475
|
+
* essential: one user's own devices share a member id, so the server's `from`
|
|
8476
|
+
* can't tell them apart (and would make each treat the others' signals as its
|
|
8477
|
+
* own echo). We therefore route entirely on the envelope peer ids and broadcast
|
|
8478
|
+
* to the whole Space, filtering client-side. The server `from` still guarantees
|
|
8479
|
+
* the sender is an authenticated Space member.
|
|
8477
8480
|
*/
|
|
8478
8481
|
const P2P_SUBJECT = "__p2p__";
|
|
8479
8482
|
class SpaceSignaler {
|
|
@@ -8485,11 +8488,11 @@ class SpaceSignaler {
|
|
|
8485
8488
|
}
|
|
8486
8489
|
/** Send a signal to one peer (or `"*"`). */
|
|
8487
8490
|
send(to, kind, data) {
|
|
8488
|
-
const env = { to, kind, data };
|
|
8489
|
-
//
|
|
8490
|
-
//
|
|
8491
|
-
//
|
|
8492
|
-
this.space.sendEphemeral(P2P_SUBJECT, env
|
|
8491
|
+
const env = { from: this.myId, to, kind, data };
|
|
8492
|
+
// Always broadcast to the Space: the server can't unicast to a specific
|
|
8493
|
+
// DEVICE (a user's devices share a member id), so we route client-side on
|
|
8494
|
+
// the envelope peer id. Signaling frames are tiny.
|
|
8495
|
+
this.space.sendEphemeral(P2P_SUBJECT, env);
|
|
8493
8496
|
}
|
|
8494
8497
|
/** Announce/withdraw P2P availability to all Space members. */
|
|
8495
8498
|
broadcast(kind, data) {
|
|
@@ -8497,18 +8500,22 @@ class SpaceSignaler {
|
|
|
8497
8500
|
}
|
|
8498
8501
|
/**
|
|
8499
8502
|
* Subscribe to inbound signals addressed to us (or broadcast). Skips our own
|
|
8500
|
-
* echoes. Returns an unsubscribe function.
|
|
8503
|
+
* echoes. Returns an unsubscribe function. Routing is entirely by the envelope
|
|
8504
|
+
* peer id (`env.from`/`env.to`), so a user's own devices — which share the
|
|
8505
|
+
* server-stamped `e.from` — are correctly distinguished.
|
|
8501
8506
|
*/
|
|
8502
8507
|
onSignal(cb) {
|
|
8503
8508
|
return this.space.onEphemeral((e) => {
|
|
8504
|
-
if (e.subject !== P2P_SUBJECT
|
|
8509
|
+
if (e.subject !== P2P_SUBJECT)
|
|
8505
8510
|
return;
|
|
8506
8511
|
const env = e.data;
|
|
8507
|
-
if (!env || typeof env.kind !== "string")
|
|
8512
|
+
if (!env || typeof env.kind !== "string" || typeof env.from !== "string")
|
|
8508
8513
|
return;
|
|
8514
|
+
if (env.from === this.myId)
|
|
8515
|
+
return; // our own device's echo
|
|
8509
8516
|
if (env.to !== this.myId && env.to !== "*")
|
|
8510
8517
|
return;
|
|
8511
|
-
cb(
|
|
8518
|
+
cb(env.from, env.kind, env.data);
|
|
8512
8519
|
});
|
|
8513
8520
|
}
|
|
8514
8521
|
}
|
|
@@ -9285,6 +9292,10 @@ class SpaceNamespace {
|
|
|
9285
9292
|
spaceCache;
|
|
9286
9293
|
/** Spaces built this session, by id — used to route offline send replays. */
|
|
9287
9294
|
openSpaces = new Map();
|
|
9295
|
+
/** Unique id for THIS device/session — the P2P peer identity. A user's own
|
|
9296
|
+
* devices share a member id, so the mesh MUST distinguish them by this or a
|
|
9297
|
+
* device treats its siblings' signals as its own echo and never connects. */
|
|
9298
|
+
deviceId = `peer-${globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2)}`;
|
|
9288
9299
|
constructor(deps) {
|
|
9289
9300
|
this.deps = deps;
|
|
9290
9301
|
if (deps.offline?.enabled) {
|
|
@@ -9483,7 +9494,7 @@ class SpaceNamespace {
|
|
|
9483
9494
|
if (this.deps.p2p?.enabled && isP2pCapable()) {
|
|
9484
9495
|
space.attachPeerNetwork(new PeerNetwork({
|
|
9485
9496
|
space,
|
|
9486
|
-
myId:
|
|
9497
|
+
myId: this.deviceId, // per-device peer id, NOT the shared member id
|
|
9487
9498
|
workerFactory: this.deps.p2p.workerFactory,
|
|
9488
9499
|
iceServers: this.deps.p2p.iceServers,
|
|
9489
9500
|
maxPeers: this.deps.p2p.maxPeers,
|