@statewalker/httpeers-member 0.1.4 → 0.1.6

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
@@ -1,7 +1,58 @@
1
1
  # @statewalker/httpeers-member
2
2
 
3
- Everything a participant does: hold an identity, redeem or resume, connect,
4
- keep the link, advertise, discover, call, and serve.
3
+ ## What it is
4
+
5
+ Everything a mesh participant does: hold an identity, redeem an invitation or
6
+ resume a membership, connect to the hub, keep the link, advertise, discover,
7
+ call other members and serve its own mounts. It runs in Node and in pages; in a
8
+ page it also mounts a ServiceWorker edge, so `fetch("/peers/<peerId>/…")` from
9
+ ordinary page code reaches another member.
10
+
11
+ ## Why it exists
12
+
13
+ A Node member and a browser member do the same thing in the same order and
14
+ differ in three places: how the libp2p node is built, whether there is a
15
+ ServiceWorker edge, and whether the page can be woken from sleep. `startMember`
16
+ is the one lifecycle, and those three differences are a `MemberPlatform`
17
+ object. A page-specific copy of the lifecycle would drift from the Node one, so
18
+ there is none.
19
+
20
+ ## How to use
21
+
22
+ ```sh
23
+ pnpm add @statewalker/httpeers-member
24
+ ```
25
+
26
+ The libp2p stack is a set of **optional peer dependencies**, so the root entry
27
+ stays free of it. Install what your entry point imports:
28
+
29
+ - `./node`: `libp2p`, `@libp2p/tcp`, `@libp2p/websockets`, `@libp2p/webrtc`,
30
+ `@libp2p/circuit-relay-v2`, `@libp2p/identify`, `@chainsafe/libp2p-noise`,
31
+ `@chainsafe/libp2p-yamux`.
32
+ - `./browser`: the same minus `@libp2p/tcp`, plus `idb-keyval` and
33
+ `@statewalker/webrun-http-browser` (the ServiceWorker edge).
34
+
35
+ Under Node, `@libp2p/webrtc` needs the native `node-datachannel` module; see the
36
+ repository root README for the pnpm 10 `onlyBuiltDependencies` setting.
37
+
38
+ | Import | Gives |
39
+ |---|---|
40
+ | `.` | `startMember`, `createPeerSession`, the join blob (`encodeJoinBlob`, `decodeJoinBlob`, `joinUrl`, `invitationFromQrText`), `createGateway`, `createEdgeDispatch`, `peerRequest`, identity and mesh memory |
41
+ | `./node` | `nodePlatform` (a value: a Node member has nothing per-instance to build), `createNodeMemberNode` |
42
+ | `./browser` | `browserPlatform()`, `createSession()`, `mountEdge`, `watchPageWake`, `idbBackend`, `idbBytesBackend`, `resetBrowserState`, `UncontrolledPageError` |
43
+ | `./reset` | `resetBrowserState()` alone, with no imports, for a rescue page |
44
+
45
+ ```ts
46
+ interface MemberPlatform {
47
+ createNode(init: { privateKey?: Ed25519PrivateKey }): Promise<Libp2p>; // required
48
+ mountEdge?(init: { key: string; dispatch: FetchHandler }): Promise<MemberEdge>; // a page only
49
+ watchWake?(onWake: () => void): () => void; // a page only
50
+ }
51
+ ```
52
+
53
+ ## Examples
54
+
55
+ A Node member:
5
56
 
6
57
  ```ts
7
58
  import { startMember } from "@statewalker/httpeers-member";
@@ -9,195 +60,176 @@ import { nodePlatform } from "@statewalker/httpeers-member/node";
9
60
 
10
61
  const member = await startMember({
11
62
  key: "peers",
12
- mounts, // what this peer serves
13
- rules, // the mesh's policy
63
+ mounts, // what this peer serves
64
+ rules, // the mesh's RuleSet
14
65
  config: { relayAddrs, hubPeerId },
15
66
  platform: nodePlatform,
16
- invitationId, // omit to resume an existing membership
67
+ invitationId, // omit to resume an existing membership
17
68
  });
18
69
 
19
70
  await member.fetch(new Request(`http://local/peers/${otherPeer}/hello`));
71
+ member.hubLink(); // "direct" | "relay"
20
72
  ```
21
73
 
22
- ## One lifecycle, and a platform object with three methods
74
+ A page, with the operator controls a join widget drives:
23
75
 
24
- The prototype had **two** lifecycles — a 644-line `startBrowserPeer` and a Node
25
- equivalent — that agreed on every step and diverged on three. `startMember` is
26
- both of them, with the three differences injected:
76
+ ```ts
77
+ import { createSession } from "@statewalker/httpeers-member/browser";
78
+
79
+ const session = createSession({
80
+ key: "peers",
81
+ mounts,
82
+ rules,
83
+ onChange: (state) => render(state),
84
+ });
85
+ await session.start(); // resumes, or waits for an invitation
86
+ await session.join(pastedText); // a join blob, a bare invitation id, or a join URL
87
+ // later: session.disconnect(), session.reconnect(), session.resetIdentity()
88
+ ```
89
+
90
+ The mesh as plain HTTP, for a client that knows nothing about peers:
27
91
 
28
92
  ```ts
29
- interface MemberPlatform {
30
- createNode(init): Promise<Libp2p>; // required
31
- mountEdge?(init): Promise<MemberEdge>; // a page only
32
- watchWake?(onWake): () => void; // a page only
33
- }
93
+ import { createGateway } from "@statewalker/httpeers-member";
94
+
95
+ const gateway = createGateway({ source: member, basePath: "", edgeKey: "peers" });
96
+ // gateway is a FetchHandler serving /{peerId}/{path}
34
97
  ```
35
98
 
36
- That is the extraction's central claim, so `browser/peer-runtime.ts` was
37
- deliberately **not ported**: porting it would have walked the duplication back
38
- in through the front door. There is no browser peer runtime in this package,
39
- only `browserPlatform()`.
99
+ A rescue page that returns the origin to a first visit:
40
100
 
41
- | Import | Holds |
42
- |---|---|
43
- | `.` | `startMember`, the session, the join blob, the gateway, the edge dispatch, identity, mesh memory |
44
- | `./node` | `nodePlatform` — a value, because a Node member has nothing per-instance to build |
45
- | `./browser` | `browserPlatform()`, `createSession()`, `mountEdge`, `watchPageWake`, the IndexedDB backends |
101
+ ```ts
102
+ import { resetBrowserState } from "@statewalker/httpeers-member/reset";
103
+
104
+ const { serviceWorkers, databases } = await resetBrowserState();
105
+ location.reload();
106
+ ```
46
107
 
47
- ## `MemberHandle.fetch` IS the edge, on both platforms
108
+ ## Internals
109
+
110
+ ### `MemberHandle.fetch` is the edge on both platforms
48
111
 
49
112
  A Node caller writes `member.fetch(...)`; a page writes
50
- `fetch(`${baseUrl}${peer}/x`)` and the ServiceWorker hands it to the same
51
- handler. `baseUrl` is the browser-only extra, which is why it is optional.
113
+ `fetch(`${baseUrl}${peer}/x`)` and the ServiceWorker hands the request to the
114
+ same handler. `baseUrl` is the browser-only extra.
52
115
 
53
- **The edge is a local ingress and strips the proven-peer header.** A page
54
- builds the requests that enter its own edge, so a header there is a claim, not
55
- a fact. `createEdgeDispatch` used to branch on "does this already have a
56
- binding" to mean "it arrived from the network" — safe while that binding was a
57
- WeakMap no page could write, and a forgery hole the moment it became a header.
58
- The branch is gone: a network request never reaches the edge, because
59
- `serveTransport` dispatches to `peer.dispatch` directly.
116
+ **The edge is a local ingress and strips the proven-peer header.** A page builds
117
+ the requests that enter its own edge, so a header there is a claim, not a fact.
118
+ A request from the network never reaches the edge: the transport dispatches it
119
+ to `peer.dispatch` directly.
60
120
 
61
121
  **A member must be told it may route its own traffic.** The edge hands
62
- `/{peerId}/{path}` to the peer's router, and that router refuses to forward
63
- unless asked — relaying is its own capability, deny by default. `startMember`
64
- passes `forwardLocalOnly` (from `httpeers-core`), which allows what originated
65
- at this edge and refuses anything that arrived from the network. Omitting it
66
- does not fail to compile; it fails at runtime with `403 this peer does not
67
- relay for you`, from the **caller's own** router. That was a real defect here,
68
- found by standing up a live mesh.
69
-
70
- ## `mountEdge` never waits for a controller that cannot come
71
-
72
- The edge is `webrun-http-browser`'s `SwHttpAdapter` (`^0.5.0`). A **hard
73
- reload** (Ctrl+Shift+R; Firefox's `location.reload(true)`) loads the page
74
- bypassing its ServiceWorker, while that worker is already active and claimed its
75
- clients long ago — so no `controllerchange` ever comes. Up to 0.4 `start()`
76
- then waited forever, and llm-chat's `mesh.html` shipped sitting at "Joining…
77
- (mounting-edge)" for good after one.
78
-
79
- Since 0.5 the library recovers it, and `mountEdge` relies on that:
80
-
81
- - uncontrolled under an active worker → `start()` sends a `CLAIM` request, the
82
- stock `sw-worker` (every app's `/sw.js`) answers with `clients.claim()`, and
83
- the page is taken over **in place, without a reload**;
84
- - a worker that does not answer `CLAIM` (an older `/sw.js` still installed in a
85
- returning visitor's browser, or a custom `serviceWorkerUrl`) → after the
86
- bound, **one reload** (`reloadIfUncontrolled`, kept as the last resort; the
87
- library guards it with a `sessionStorage` marker, so it cannot loop);
88
- - still uncontrolled after that, or no usable `sessionStorage` → throw
89
- `UncontrolledPageError` ("close the tab and reopen it").
90
-
91
- Every wait is bounded (`controlTimeoutMs`, default `DEFAULT_CONTROL_TIMEOUT_MS`
92
- = 30 s, passed to the adapter as its `timeout`); a worker that never activates
93
- or never answers fails with an `Error` that says what to do. `edge-control.ts`
94
- maps the library's `ServiceWorkerControlError` onto those errors, matching on
95
- `name`/`reason` rather than `instanceof`. `tests/edge-control.test.ts` pins the
96
- mapping; `httpeers-browser-conformance`'s `pnpm run test:reload` runs first
97
- visit, reload, a hard reload (asserting it recovers with no extra navigation) and
98
- a second tab, then — against a worker that ignores `CLAIM` — the fallback reload
99
- and a spent guard, in real Chromium and Firefox.
100
-
101
- ## Direct or relay: how a member reaches its hub
102
-
103
- `MemberHandle.hubLink()` is `"direct"` or `"relay"`, decided once per join.
104
- **Direct** is a WebRTC upgrade to the hub plus a reservation on it, which is
105
- what lets other members reach this one. **Relay** is a kept, limited circuit
106
- through the public relay: the member calls the hub over it and nothing else
107
- can reach the member. A member lands in relay mode when
108
-
109
- - the WebRTC upgrade fails (a hub in Docker on a bridge network), or
110
- - the upgrade works but the hub **refuses the reservation for want of capacity**
111
- (`RESERVATION_REFUSED`, `RESOURCE_LIMIT_EXCEEDED`) or does not answer. The
112
- WebRTC link is then closed and the member continues exactly as in the first
113
- case. `MemberHandle.hubLinkNote` says why, and the session shows it as the
114
- live phase's note (the join widget: `Connected (relay)` plus the reason).
115
-
116
- Before this, a full reservation store on the hub failed the whole join while a
117
- relay-mode member worked. Any other refusal — `PERMISSION_DENIED` from a hub
118
- that has just accepted this peer, a hub with no relay service — still fails the
119
- join: those are faults to report, not conditions to route around
122
+ `/{peerId}/{path}` to the peer's router, which refuses to forward by default.
123
+ `startMember` passes `forwardLocalOnly` from `@statewalker/httpeers-core`, which
124
+ forwards what originated at this edge and nothing from the network. A router
125
+ without it answers `403 {"error":"this peer does not relay for you"}` from the
126
+ caller's **own** router.
127
+
128
+ ### `mountEdge` never waits for a controller that cannot come
129
+
130
+ The edge is `SwHttpAdapter` from `@statewalker/webrun-http-browser`. A hard
131
+ reload (Ctrl+Shift+R) loads the page past its ServiceWorker while that worker is
132
+ already active, so no `controllerchange` event ever fires. `mountEdge` handles
133
+ each case:
134
+
135
+ - uncontrolled under an active worker: the adapter sends a `CLAIM` request, the
136
+ stock worker (`/sw.js`, `DEFAULT_SERVICE_WORKER_URL`) answers with
137
+ `clients.claim()`, and the page is taken over in place, without a reload;
138
+ - a worker that does not answer `CLAIM` (an older `/sw.js`, or a custom
139
+ `serviceWorkerUrl`): after the bound, **one** reload, guarded by a
140
+ `sessionStorage` marker so it cannot loop;
141
+ - still uncontrolled after that, or no usable `sessionStorage`: it throws
142
+ `UncontrolledPageError` — "This page isn't controlled by its ServiceWorker, so
143
+ the mesh cannot be reached through it — close the tab and reopen it."
144
+
145
+ Every wait is bounded by `controlTimeoutMs` (default
146
+ `DEFAULT_CONTROL_TIMEOUT_MS`, 30 s). The library's `ServiceWorkerControlError`
147
+ is matched by `name` and `reason`, not `instanceof`, because every bundle of the
148
+ adapter carries its own copy of the class. `tests/edge-control.test.ts` pins the
149
+ mapping; `httpeers-browser-conformance` runs the reload cases in real Chromium
150
+ and Firefox.
151
+
152
+ ### Direct or relay: how a member reaches its hub
153
+
154
+ `member.hubLink()` is decided once per join:
155
+
156
+ - **direct** — a WebRTC upgrade to the hub plus a reservation on it, which lets
157
+ other members reach this one;
158
+ - **relay** — a kept, limited circuit through the public relay. The member
159
+ calls the hub over it, and nothing can reach the member.
160
+
161
+ A member falls back to relay when the WebRTC upgrade fails (for example, a hub
162
+ in Docker on a bridge network) or when the hub refuses the reservation for lack
163
+ of capacity (`RESERVATION_REFUSED`, `RESOURCE_LIMIT_EXCEEDED`) or does not
164
+ answer. `member.hubLinkNote` says why, and the join widget shows
165
+ `Connected (relay)` with that note. Any other refusal — `PERMISSION_DENIED`
166
+ from a hub that has just accepted this peer, a hub with no relay service —
167
+ fails the join, because it is a fault rather than a condition to route around
120
168
  (`fallsBackToRelay` in `start-member.ts`). Relay mode does not retry the
121
169
  upgrade; a reconnect decides again.
122
170
 
123
- ## `createGateway` — the mesh as ordinary HTTP
124
-
125
- ```ts
126
- const gateway = createGateway({ source: member, basePath: "", edgeKey: "peers" });
127
- ```
128
-
129
- A `FetchHandler` dispatching `/{peerId}/{path}`, so a client with no peer
130
- object, no token and no knowledge of libp2p can `fetch()` a mesh resource.
131
- `GatewaySource` is structurally a subset of `MemberHandle`, so **a member is
132
- one** — no adapter.
133
-
134
- ## Joining: a blob, a bare id, and one rule that must not bend
171
+ ### Which mesh an invitation joins
135
172
 
136
173
  | What someone supplies | Which mesh |
137
174
  |---|---|
138
- | a join **blob** (`eyJ…`) | the one the blob names — a hub page's |
139
- | a **bare invitation id** | the one the deployment's `httpeers.json` names |
175
+ | a join **blob** (`eyJ…`) | the one the blob names |
176
+ | a **bare invitation id** | the one the deployment's `/httpeers.json` names |
140
177
  | nothing (a resume) | the one this origin remembers, else the deployment's |
141
178
 
142
- Only a **resume** consults the remembered mesh. A bare id still means the
143
- deployment's, because that is the contract a Node-hub invitation travels under;
144
- reversing it would silently point those joins at whatever mesh the page last
145
- saw. `tests/session.test.ts` pins all three.
179
+ Only a resume consults the remembered mesh. A bare id always means the
180
+ deployment's mesh; otherwise it would silently point at whatever mesh the page
181
+ last saw. `tests/session.test.ts` pins all three.
146
182
 
147
- `invitationFromQrText` lives here rather than in `@statewalker/httpeers-qr`,
148
- because it is entirely about the join format — a QR package that knew it could
149
- not be used for anything else. It is a **predicate, never a parser**: it cannot
150
- throw, because a live scanner that died on a malformed URL would die on the
151
- first poster.
183
+ `invitationFromQrText` lives here, not in `@statewalker/httpeers-qr`, because
184
+ it is entirely about the join format. It is a predicate, never a parser: a live
185
+ scanner must not die on the first malformed QR code it sees.
152
186
 
153
- ## The session, and why it is isomorphic
187
+ ### The session is isomorphic, so it is tested without a browser
154
188
 
155
189
  `createPeerSession` holds the four operator controls — join, disconnect,
156
- reconnect, reset identity — and the state a page renders. It has **no DOM and
157
- no browser imports**, so all fifteen of its branches are tested under Node with
158
- no browser, no relay and no ServiceWorker.
190
+ reconnect, reset identity — and the state a page renders. It has no DOM and no
191
+ browser imports, so all its branches run under Node with no relay and no
192
+ ServiceWorker. The browser defaults live in `./browser`'s `createSession`.
193
+
194
+ **Disconnect is not leaving.** `disconnect()` drops presence and keeps
195
+ membership, so `reconnect()` needs no new invitation. `resetIdentity()` forgets
196
+ the identity and is the destructive one.
159
197
 
160
- That is load-bearing rather than tidy: `browserPlatform` reaches
161
- `@libp2p/webrtc`, whose Node build loads a native module, so a browser default
162
- inside the session would have made importing it a browser-only act. The
163
- defaults live in `./browser`'s `createSession` instead.
198
+ ### The two "cannot resume" states say which one happened
164
199
 
165
- **Disconnect is not leaving.** `stop()` drops presence and keeps membership, so
166
- reconnecting needs no new invitation. `resetIdentity` is the destructive one,
167
- named separately and documented with what it costs.
200
+ A page with no saved identity has never joined. A page whose identity the hub
201
+ does not recognise was revoked, or is talking to a reset hub. When a resume
202
+ fails and the deployment names a different hub, the session adds: "This
203
+ deployment's httpeers.json now names a different hub (…), which is a different
204
+ mesh -- so a membership in the old one cannot carry over."
168
205
 
169
- ## The two "cannot resume" states are different, and say so
206
+ ### `./reset` imports nothing
170
207
 
171
- A page with no saved identity has never joined; a page whose identity the hub
172
- does not recognise has had its membership revoked, or is talking to a hub that
173
- was reset. Both would otherwise render as "please paste an invitation", and an
174
- operator could not tell which had happened. When a resume fails *and* the
175
- deployment now names a different hub, the session says so — that is almost
176
- always a re-run of `pnpm bootstrap`, and saying it is the difference between a
177
- two-minute fix and an hour.
208
+ A rescue page has to work when the app does not start, so `./reset` has no
209
+ imports at all. `resetBrowserState()` unregisters every ServiceWorker on the
210
+ origin, deletes its IndexedDB databases and clears `localStorage` and
211
+ `sessionStorage`. It never throws, and reports what it removed. Reload the page
212
+ afterwards: `unregister()` does not evict a worker already controlling the
213
+ page.
178
214
 
179
- ## Isomorphism, measured by reachability
215
+ ### The root never reaches a platform module
180
216
 
181
217
  `tests/boundary.test.ts` walks the import closure of `index.ts` and fails if it
182
218
  reaches `node:`, `@libp2p/tcp`, `@libp2p/webrtc`, `idb-keyval`, a ServiceWorker
183
- adapter or a DOM-only global. It does **not** exempt filenames: `edge.ts` and
184
- `page-wake.ts` are browser-only by construction and simply are not reachable
185
- from the root, which the test asserts explicitly. Verified non-vacuous by
186
- re-exporting `mountEdge` from `index.ts` and watching three named tests fail.
187
-
188
- ## Tests
189
-
190
- **116.** `tests/edge-control.test.ts` pins the error `mountEdge` throws when
191
- its ServiceWorker cannot take control. `tests/reservation-fallback.test.ts` pins which refused reservations
192
- drop a join to relay mode and which fail it. `tests/consumer.test.ts` compiles a real dependent against all three
193
- entry points under three tsconfig shapes — the `NodeNext` row is the only one
194
- that honours the `exports` map, and for a subpath there is no legacy `types`
195
- field to fall back to.
196
-
197
- A member is also exercised for real in `@statewalker/httpeers-conformance`:
198
- two live members redeem invitations from a live hub over a relay, call each
199
- other, and the far side reports back a subject read out of a verified Biscuit
200
- that matches the peer its handshake proved. `member-relay-fallback.test.ts` and
201
- `member-reservation-fallback.test.ts` there run the two ways into relay mode
202
- against a live hub: an upgrade that fails, and a hub whose reservation store is
203
- full.
219
+ adapter or a DOM-only global. It does not exempt filenames: browser-only files
220
+ are simply unreachable from the root.
221
+
222
+ ### Dependencies
223
+
224
+ `@statewalker/httpeers-core`, `@statewalker/httpeers-access` and
225
+ `@statewalker/httpeers-libp2p`, a few `@libp2p/*` helpers for keys and
226
+ addresses, plus the optional peers above. `tests/consumer.test.ts` compiles a
227
+ real dependent against all entry points under three tsconfig shapes; the
228
+ `NodeNext` one is what checks the `exports` map.
229
+
230
+ Tests: `pnpm --filter @statewalker/httpeers-member test`. Live members redeem
231
+ invitations and call each other over a relay in `httpeers-conformance`.
232
+
233
+ ## License
234
+
235
+ MIT
package/dist/join.js CHANGED
@@ -16,7 +16,7 @@
16
16
  */
17
17
  import { peerIdFromString } from "@libp2p/peer-id";
18
18
  import { multiaddr } from "@multiformats/multiaddr";
19
- import { hubRoute, reachHub } from "@statewalker/httpeers-libp2p";
19
+ import { dialWebRTC, hubRoute, reachHub } from "@statewalker/httpeers-libp2p";
20
20
  import { peerRequest } from "./peer-request.js";
21
21
  /**
22
22
  * Dial `${relayAddr}/p2p-circuit/webrtc/p2p/${peerId}` explicitly, BEFORE
@@ -36,7 +36,7 @@ import { peerRequest } from "./peer-request.js";
36
36
  */
37
37
  export async function preDialPeer(node, relayAddr, peerId) {
38
38
  const target = multiaddr(`${relayAddr}/p2p-circuit/webrtc/p2p/${peerId}`);
39
- await node.dial(target);
39
+ await dialWebRTC(node, target);
40
40
  }
41
41
  /**
42
42
  * "Make sure this peer can be called" -- the function
@@ -95,7 +95,7 @@ export function createRouteEnsurer(init) {
95
95
  if (node.getConnections(target).some((conn) => conn.limits == null))
96
96
  return;
97
97
  if (init.hubPeerId != null && init.hubPeerId !== selfPeerId) {
98
- await node.dial(multiaddr(hubRoute(init.hubPeerId, peerId)));
98
+ await dialWebRTC(node, multiaddr(hubRoute(init.hubPeerId, peerId)));
99
99
  return;
100
100
  }
101
101
  const advertised = (init.meshView()?.members.find((m) => m.peerId === peerId)?.addrs ?? [])
@@ -106,7 +106,7 @@ export function createRouteEnsurer(init) {
106
106
  // full dial timeout for each unreachable interface address the provider
107
107
  // reported (a browser peer behind a relay routinely reports several).
108
108
  if (advertised.length > 0)
109
- await node.dial(advertised);
109
+ await dialWebRTC(node, advertised);
110
110
  else
111
111
  await preDialPeer(node, relayAddr, peerId);
112
112
  };
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "@statewalker/httpeers-member",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "description": "Everything a participant does: hold an identity, redeem or resume, connect, keep the link, advertise, discover, call, and serve.",
6
+ "bugs": {
7
+ "url": "https://github.com/statewalker/httpeers/issues"
8
+ },
9
+ "homepage": "https://github.com/statewalker/httpeers/tree/main/packages/httpeers-member#readme",
6
10
  "license": "MIT",
7
11
  "repository": {
8
12
  "type": "git",
9
- "url": "git+ssh://git@github.com/statewalker/httpeers.git",
13
+ "url": "git+https://github.com/statewalker/httpeers.git",
10
14
  "directory": "packages/httpeers-member"
11
15
  },
12
16
  "main": "./dist/index.js",
@@ -43,9 +47,9 @@
43
47
  "@libp2p/interface": "^3.3.0",
44
48
  "@libp2p/peer-id": "^6.0.15",
45
49
  "@multiformats/multiaddr": "^13.0.3",
46
- "@statewalker/httpeers-access": "^0.1.3",
47
- "@statewalker/httpeers-libp2p": "^0.1.3",
48
- "@statewalker/httpeers-core": "^0.1.2"
50
+ "@statewalker/httpeers-access": "^0.1.4",
51
+ "@statewalker/httpeers-core": "^0.1.3",
52
+ "@statewalker/httpeers-libp2p": "^0.1.5"
49
53
  },
50
54
  "peerDependencies": {
51
55
  "@chainsafe/libp2p-noise": "^17.0.0",
package/src/join.ts CHANGED
@@ -21,7 +21,7 @@ import { multiaddr } from "@multiformats/multiaddr";
21
21
  import type { ChangeEntry, RevocationCache, RuleSet } from "@statewalker/httpeers-access";
22
22
  import type { MeshView, PeerIdStr } from "@statewalker/httpeers-core";
23
23
  import type { Peer } from "@statewalker/httpeers-libp2p";
24
- import { hubRoute, reachHub } from "@statewalker/httpeers-libp2p";
24
+ import { dialWebRTC, hubRoute, reachHub } from "@statewalker/httpeers-libp2p";
25
25
  import { peerRequest } from "./peer-request.js";
26
26
 
27
27
  /**
@@ -46,7 +46,7 @@ export async function preDialPeer(
46
46
  peerId: PeerIdStr,
47
47
  ): Promise<void> {
48
48
  const target = multiaddr(`${relayAddr}/p2p-circuit/webrtc/p2p/${peerId}`);
49
- await node.dial(target);
49
+ await dialWebRTC(node, target);
50
50
  }
51
51
 
52
52
  export interface RouteEnsurerInit {
@@ -126,7 +126,7 @@ export function createRouteEnsurer(init: RouteEnsurerInit): (peerId: PeerIdStr)
126
126
  if (node.getConnections(target).some((conn) => conn.limits == null)) return;
127
127
 
128
128
  if (init.hubPeerId != null && init.hubPeerId !== selfPeerId) {
129
- await node.dial(multiaddr(hubRoute(init.hubPeerId, peerId)));
129
+ await dialWebRTC(node, multiaddr(hubRoute(init.hubPeerId, peerId)));
130
130
  return;
131
131
  }
132
132
 
@@ -138,7 +138,7 @@ export function createRouteEnsurer(init: RouteEnsurerInit): (peerId: PeerIdStr)
138
138
  // addresses of a single peer itself, and a sequential loop would pay the
139
139
  // full dial timeout for each unreachable interface address the provider
140
140
  // reported (a browser peer behind a relay routinely reports several).
141
- if (advertised.length > 0) await node.dial(advertised);
141
+ if (advertised.length > 0) await dialWebRTC(node, advertised);
142
142
  else await preDialPeer(node, relayAddr, peerId);
143
143
  };
144
144
  }