@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 +187 -155
- package/dist/join.js +4 -4
- package/package.json +9 -5
- package/src/join.ts +4 -4
package/README.md
CHANGED
|
@@ -1,7 +1,58 @@
|
|
|
1
1
|
# @statewalker/httpeers-member
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
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,
|
|
13
|
-
rules,
|
|
63
|
+
mounts, // what this peer serves
|
|
64
|
+
rules, // the mesh's RuleSet
|
|
14
65
|
config: { relayAddrs, hubPeerId },
|
|
15
66
|
platform: nodePlatform,
|
|
16
|
-
invitationId,
|
|
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
|
-
|
|
74
|
+
A page, with the operator controls a join widget drives:
|
|
23
75
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
101
|
+
```ts
|
|
102
|
+
import { resetBrowserState } from "@statewalker/httpeers-member/reset";
|
|
103
|
+
|
|
104
|
+
const { serviceWorkers, databases } = await resetBrowserState();
|
|
105
|
+
location.reload();
|
|
106
|
+
```
|
|
46
107
|
|
|
47
|
-
##
|
|
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
|
|
51
|
-
handler. `baseUrl` is the browser-only extra
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
- uncontrolled
|
|
82
|
-
|
|
83
|
-
the
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
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
|
|
139
|
-
| a **bare invitation id** | the one the deployment's
|
|
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
|
|
143
|
-
deployment's
|
|
144
|
-
|
|
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
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
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
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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
|
-
|
|
206
|
+
### `./reset` imports nothing
|
|
170
207
|
|
|
171
|
-
A page
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
-
|
|
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
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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+
|
|
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.
|
|
47
|
-
"@statewalker/httpeers-
|
|
48
|
-
"@statewalker/httpeers-
|
|
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
|
|
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
|
|
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
|
|
141
|
+
if (advertised.length > 0) await dialWebRTC(node, advertised);
|
|
142
142
|
else await preDialPeer(node, relayAddr, peerId);
|
|
143
143
|
};
|
|
144
144
|
}
|