wire-mesh-core 1.1.0 → 1.2.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.
@@ -16,7 +16,7 @@ function localHandshake(domains) {
16
16
  /**
17
17
  * Builds the connection-agnostic session state machine and its public MeshSession surface. dial is null for a session that can never (re)connect on its own -- acceptMeshSession's case, where the one connection it will ever have already exists by construction and reconnect therefore cannot apply (only the remote redialing, and being accepted again, produces a fresh connection). createMeshSession supplies dial as transport.connect so its own connect()/reconnect behaviour is unchanged from before this was factored out.
18
18
  */
19
- function createSessionCore(identity, clock, reconnect, dial, onPeerAdvert) {
19
+ function createSessionCore(identity, clock, reconnect, dial, onPeerAdvert, addresses = []) {
20
20
  let connection = null;
21
21
  let state = { status: "idle" };
22
22
  let handshake = { status: "pending" };
@@ -248,7 +248,7 @@ function createSessionCore(identity, clock, reconnect, dial, onPeerAdvert) {
248
248
  type: "gossip",
249
249
  peers: [{
250
250
  device: identity.deviceId,
251
- addresses: [],
251
+ addresses: [...addresses],
252
252
  "snapshot-seconds": Math.floor(clock.now() / MS_PER_SECOND)
253
253
  }]
254
254
  };
@@ -410,8 +410,8 @@ function createSessionCore(identity, clock, reconnect, dial, onPeerAdvert) {
410
410
  }
411
411
  };
412
412
  }
413
- function createMeshSession(transport, identity, clock = { now: () => Date.now() }, reconnect = null) {
414
- const { session } = createSessionCore(identity, clock, reconnect, async (address) => transport.connect(address));
413
+ function createMeshSession(transport, identity, clock = { now: () => Date.now() }, reconnect = null, addresses = []) {
414
+ const { session } = createSessionCore(identity, clock, reconnect, async (address) => transport.connect(address), void 0, addresses);
415
415
  return session;
416
416
  }
417
417
  /** Wires an already-accepted Connection up as a full MeshSession, mirroring exactly what createMeshSession's own dial path does once a connection exists (send handshake, send self-advert, negotiate, consume frames) -- the wire-mesh#45 prerequisite agent-comms needs, since its peers both listen and dial rather than only ever dialing the way web-console's own console UI does. Reconnect does not apply here: if this connection drops, only the remote redialing and being accepted again produces a new connection, and therefore a new session -- there is nothing on this side to retry. */
@@ -426,7 +426,7 @@ async function acceptMeshSession(connection, identity, localDomains, options = {
426
426
  if (peerDeviceIdResolved) return;
427
427
  peerDeviceIdResolved = true;
428
428
  resolvePeerDeviceId?.(advert.device);
429
- });
429
+ }, options.addresses);
430
430
  await wireUpConnection(connection, options.label ?? "accepted", localDomains);
431
431
  return {
432
432
  ...session,
@@ -85,7 +85,9 @@ export interface MeshSession {
85
85
  sendManageRequest: (command: ManageCommand, scope: Readonly<CapabilityScope>, targetDevice?: DeviceId, token?: CapabilityToken) => Promise<ManageOutcome>;
86
86
  close: () => Promise<void>;
87
87
  }
88
- export declare function createMeshSession(transport: Readonly<Transport>, identity: Readonly<IdentityPort>, clock?: Readonly<Clock>, reconnect?: ReconnectPolicy | null): MeshSession;
88
+ export declare function createMeshSession(transport: Readonly<Transport>, identity: Readonly<IdentityPort>, clock?: Readonly<Clock>, reconnect?: ReconnectPolicy | null,
89
+ /** This node's own directly-reachable "host:port" candidates (wire-mesh#38), advertised in this session's self-advert so other peers can attempt a direct connection instead of always falling back to a relay. Omit (or pass none) for a caller with nothing to offer, e.g. a browser client. */
90
+ addresses?: readonly string[]): MeshSession;
89
91
  /** A MeshSession built over a connection that already exists (a Transport's own listen() handed it to onConnection), extended with the one thing a dial-side session can't offer: the device-id of the specific peer at the other end. Unlike createMeshSession, which may end up talking to a relay gossiping about many devices at once, an accepted connection is the agent-comms case -- exactly two peers, directly connected -- so "the peer" is well-defined here in a way it structurally isn't for the dial side. */
90
92
  export interface AcceptedMeshSession extends MeshSession {
91
93
  /** Resolves with the device-id carried by the first peer-advert this connection's remote sends -- the same self-advertisement mechanism createMeshSession's own directory already relies on for every peer, just narrowed to "the one peer this specific connection is with" rather than accumulated into a directory of possibly many. There is no transport-level authentication behind this yet (see wire-mesh#45's own createTlsTransport item): it is only as trustworthy as the remote's own gossip, exactly the same trust level the dial-side directory already has for every entry in it. */
@@ -95,6 +97,8 @@ export interface AcceptedMeshSessionOptions {
95
97
  /** A caller-chosen label for this connection, used only for ConnectionState's own address field -- the Connection/Transport ports expose no remote-address concept an accepted connection could report on its own (see wire-mesh#45). Defaults to a fixed placeholder since most callers have nothing more specific to offer; a transport adapter that does know the remote's address should pass it here. */
96
98
  label?: string;
97
99
  clock?: Readonly<Clock>;
100
+ /** This node's own directly-reachable "host:port" candidates (wire-mesh#38), advertised in this session's self-advert. Omit (or pass none) for a caller with nothing to offer. */
101
+ addresses?: readonly string[];
98
102
  }
99
103
  /** Wires an already-accepted Connection up as a full MeshSession, mirroring exactly what createMeshSession's own dial path does once a connection exists (send handshake, send self-advert, negotiate, consume frames) -- the wire-mesh#45 prerequisite agent-comms needs, since its peers both listen and dial rather than only ever dialing the way web-console's own console UI does. Reconnect does not apply here: if this connection drops, only the remote redialing and being accepted again produces a new connection, and therefore a new session -- there is nothing on this side to retry. */
100
104
  export declare function acceptMeshSession(connection: Readonly<Connection>, identity: Readonly<IdentityPort>, localDomains: readonly string[], options?: Readonly<AcceptedMeshSessionOptions>): Promise<AcceptedMeshSession>;
@@ -85,7 +85,9 @@ export interface MeshSession {
85
85
  sendManageRequest: (command: ManageCommand, scope: Readonly<CapabilityScope>, targetDevice?: DeviceId, token?: CapabilityToken) => Promise<ManageOutcome>;
86
86
  close: () => Promise<void>;
87
87
  }
88
- export declare function createMeshSession(transport: Readonly<Transport>, identity: Readonly<IdentityPort>, clock?: Readonly<Clock>, reconnect?: ReconnectPolicy | null): MeshSession;
88
+ export declare function createMeshSession(transport: Readonly<Transport>, identity: Readonly<IdentityPort>, clock?: Readonly<Clock>, reconnect?: ReconnectPolicy | null,
89
+ /** This node's own directly-reachable "host:port" candidates (wire-mesh#38), advertised in this session's self-advert so other peers can attempt a direct connection instead of always falling back to a relay. Omit (or pass none) for a caller with nothing to offer, e.g. a browser client. */
90
+ addresses?: readonly string[]): MeshSession;
89
91
  /** A MeshSession built over a connection that already exists (a Transport's own listen() handed it to onConnection), extended with the one thing a dial-side session can't offer: the device-id of the specific peer at the other end. Unlike createMeshSession, which may end up talking to a relay gossiping about many devices at once, an accepted connection is the agent-comms case -- exactly two peers, directly connected -- so "the peer" is well-defined here in a way it structurally isn't for the dial side. */
90
92
  export interface AcceptedMeshSession extends MeshSession {
91
93
  /** Resolves with the device-id carried by the first peer-advert this connection's remote sends -- the same self-advertisement mechanism createMeshSession's own directory already relies on for every peer, just narrowed to "the one peer this specific connection is with" rather than accumulated into a directory of possibly many. There is no transport-level authentication behind this yet (see wire-mesh#45's own createTlsTransport item): it is only as trustworthy as the remote's own gossip, exactly the same trust level the dial-side directory already has for every entry in it. */
@@ -95,6 +97,8 @@ export interface AcceptedMeshSessionOptions {
95
97
  /** A caller-chosen label for this connection, used only for ConnectionState's own address field -- the Connection/Transport ports expose no remote-address concept an accepted connection could report on its own (see wire-mesh#45). Defaults to a fixed placeholder since most callers have nothing more specific to offer; a transport adapter that does know the remote's address should pass it here. */
96
98
  label?: string;
97
99
  clock?: Readonly<Clock>;
100
+ /** This node's own directly-reachable "host:port" candidates (wire-mesh#38), advertised in this session's self-advert. Omit (or pass none) for a caller with nothing to offer. */
101
+ addresses?: readonly string[];
98
102
  }
99
103
  /** Wires an already-accepted Connection up as a full MeshSession, mirroring exactly what createMeshSession's own dial path does once a connection exists (send handshake, send self-advert, negotiate, consume frames) -- the wire-mesh#45 prerequisite agent-comms needs, since its peers both listen and dial rather than only ever dialing the way web-console's own console UI does. Reconnect does not apply here: if this connection drops, only the remote redialing and being accepted again produces a new connection, and therefore a new session -- there is nothing on this side to retry. */
100
104
  export declare function acceptMeshSession(connection: Readonly<Connection>, identity: Readonly<IdentityPort>, localDomains: readonly string[], options?: Readonly<AcceptedMeshSessionOptions>): Promise<AcceptedMeshSession>;
@@ -15,7 +15,7 @@ function localHandshake(domains) {
15
15
  /**
16
16
  * Builds the connection-agnostic session state machine and its public MeshSession surface. dial is null for a session that can never (re)connect on its own -- acceptMeshSession's case, where the one connection it will ever have already exists by construction and reconnect therefore cannot apply (only the remote redialing, and being accepted again, produces a fresh connection). createMeshSession supplies dial as transport.connect so its own connect()/reconnect behaviour is unchanged from before this was factored out.
17
17
  */
18
- function createSessionCore(identity, clock, reconnect, dial, onPeerAdvert) {
18
+ function createSessionCore(identity, clock, reconnect, dial, onPeerAdvert, addresses = []) {
19
19
  let connection = null;
20
20
  let state = { status: "idle" };
21
21
  let handshake = { status: "pending" };
@@ -247,7 +247,7 @@ function createSessionCore(identity, clock, reconnect, dial, onPeerAdvert) {
247
247
  type: "gossip",
248
248
  peers: [{
249
249
  device: identity.deviceId,
250
- addresses: [],
250
+ addresses: [...addresses],
251
251
  "snapshot-seconds": Math.floor(clock.now() / MS_PER_SECOND)
252
252
  }]
253
253
  };
@@ -409,8 +409,8 @@ function createSessionCore(identity, clock, reconnect, dial, onPeerAdvert) {
409
409
  }
410
410
  };
411
411
  }
412
- function createMeshSession(transport, identity, clock = { now: () => Date.now() }, reconnect = null) {
413
- const { session } = createSessionCore(identity, clock, reconnect, async (address) => transport.connect(address));
412
+ function createMeshSession(transport, identity, clock = { now: () => Date.now() }, reconnect = null, addresses = []) {
413
+ const { session } = createSessionCore(identity, clock, reconnect, async (address) => transport.connect(address), void 0, addresses);
414
414
  return session;
415
415
  }
416
416
  /** Wires an already-accepted Connection up as a full MeshSession, mirroring exactly what createMeshSession's own dial path does once a connection exists (send handshake, send self-advert, negotiate, consume frames) -- the wire-mesh#45 prerequisite agent-comms needs, since its peers both listen and dial rather than only ever dialing the way web-console's own console UI does. Reconnect does not apply here: if this connection drops, only the remote redialing and being accepted again produces a new connection, and therefore a new session -- there is nothing on this side to retry. */
@@ -425,7 +425,7 @@ async function acceptMeshSession(connection, identity, localDomains, options = {
425
425
  if (peerDeviceIdResolved) return;
426
426
  peerDeviceIdResolved = true;
427
427
  resolvePeerDeviceId?.(advert.device);
428
- });
428
+ }, options.addresses);
429
429
  await wireUpConnection(connection, options.label ?? "accepted", localDomains);
430
430
  return {
431
431
  ...session,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wire-mesh-core",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "packageManager": "pnpm@10.33.0",
6
6
  "repository": {