@peerkit/transport-libp2p-react-native 0.1.0-alpha.13
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 +155 -0
- package/dist/datachannel-early-message-polyfill.d.ts +23 -0
- package/dist/datachannel-early-message-polyfill.d.ts.map +1 -0
- package/dist/datachannel-early-message-polyfill.js +131 -0
- package/dist/datachannel-early-message-polyfill.js.map +1 -0
- package/dist/event-target-polyfill.d.ts +40 -0
- package/dist/event-target-polyfill.d.ts.map +1 -0
- package/dist/event-target-polyfill.js +192 -0
- package/dist/event-target-polyfill.js.map +1 -0
- package/dist/factories.d.ts +68 -0
- package/dist/factories.d.ts.map +1 -0
- package/dist/factories.js +73 -0
- package/dist/factories.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/polyfills.d.ts +41 -0
- package/dist/polyfills.d.ts.map +1 -0
- package/dist/polyfills.js +67 -0
- package/dist/polyfills.js.map +1 -0
- package/dist/quick-crypto-noise.d.ts +35 -0
- package/dist/quick-crypto-noise.d.ts.map +1 -0
- package/dist/quick-crypto-noise.js +105 -0
- package/dist/quick-crypto-noise.js.map +1 -0
- package/dist/text-codec-polyfill.d.ts +25 -0
- package/dist/text-codec-polyfill.d.ts.map +1 -0
- package/dist/text-codec-polyfill.js +79 -0
- package/dist/text-codec-polyfill.js.map +1 -0
- package/dist/webrtc-certificate-polyfill.d.ts +37 -0
- package/dist/webrtc-certificate-polyfill.d.ts.map +1 -0
- package/dist/webrtc-certificate-polyfill.js +53 -0
- package/dist/webrtc-certificate-polyfill.js.map +1 -0
- package/dist/websocket-buffered-amount-polyfill.d.ts +21 -0
- package/dist/websocket-buffered-amount-polyfill.d.ts.map +1 -0
- package/dist/websocket-buffered-amount-polyfill.js +41 -0
- package/dist/websocket-buffered-amount-polyfill.js.map +1 -0
- package/package.json +78 -0
- package/src/datachannel-early-message-polyfill.ts +176 -0
- package/src/event-target-polyfill.ts +268 -0
- package/src/factories.ts +116 -0
- package/src/index.ts +10 -0
- package/src/polyfills.ts +72 -0
- package/src/quick-crypto-noise.ts +130 -0
- package/src/rn-modules.d.ts +100 -0
- package/src/text-codec-polyfill.ts +118 -0
- package/src/webrtc-certificate-polyfill.ts +60 -0
- package/src/websocket-buffered-amount-polyfill.ts +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# @peerkit/transport-libp2p-react-native
|
|
2
|
+
|
|
3
|
+
React Native implementation of the peerkit transport layer. Wires
|
|
4
|
+
`@peerkit/transport-libp2p-core` to a libp2p stack configured for mobile:
|
|
5
|
+
WebSockets (outbound), WebRTC, and circuit-relay-v2 client.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @peerkit/transport-libp2p-react-native
|
|
11
|
+
npm install react-native-get-random-values react-native-quick-crypto react-native-webrtc
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The three `react-native-*` peer dependencies provide native modules and must
|
|
15
|
+
be linked via the standard React Native autolinking flow (iOS: `pod install`,
|
|
16
|
+
Android: Gradle sync).
|
|
17
|
+
|
|
18
|
+
## Polyfills
|
|
19
|
+
|
|
20
|
+
libp2p depends on Node built-ins (`crypto`, `stream`, `buffer`, `events`,
|
|
21
|
+
`process`) and on the Web Crypto / WebRTC globals. Hermes provides none of
|
|
22
|
+
those out of the box (Hermes is Meta's JavaScript engine for React
|
|
23
|
+
Native). The package ships a single side-effect entry that
|
|
24
|
+
installs everything in the right order.
|
|
25
|
+
|
|
26
|
+
Add **as the very first import** of the app entry (typically `index.js` or
|
|
27
|
+
`App.tsx`):
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
import "@peerkit/transport-libp2p-react-native/polyfills";
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The polyfill module:
|
|
34
|
+
|
|
35
|
+
1. Patches `globalThis.crypto.getRandomValues` via
|
|
36
|
+
`react-native-get-random-values`. Must run first — peer-id generation and
|
|
37
|
+
noise key generation reach for RNG during module init.
|
|
38
|
+
2. Installs `react-native-quick-crypto`, providing a JSI-backed
|
|
39
|
+
`globalThis.crypto.subtle`.
|
|
40
|
+
3. Registers `react-native-webrtc` globals (`RTCPeerConnection`,
|
|
41
|
+
`RTCSessionDescription`, etc.) consumed by `@libp2p/webrtc`.
|
|
42
|
+
4. Assigns `globalThis.Buffer` and `globalThis.process` from the `buffer` and
|
|
43
|
+
`process` shims so libp2p code that touches these as globals (rather than
|
|
44
|
+
ES module imports) works.
|
|
45
|
+
5. Installs the WHATWG `Event` / `EventTarget` / `CustomEvent` globals that
|
|
46
|
+
Hermes lacks but `@libp2p/interface` extends at module init.
|
|
47
|
+
6. Installs UTF-8 `TextEncoder` / `TextDecoder` globals that Hermes lacks but
|
|
48
|
+
`uint8arrays` constructs at module init.
|
|
49
|
+
|
|
50
|
+
## Metro config
|
|
51
|
+
|
|
52
|
+
Metro (React Native's JavaScript bundler) must rewrite Node-style bare
|
|
53
|
+
imports to their React Native shims. Add
|
|
54
|
+
the following to `metro.config.js`:
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
const { getDefaultConfig } = require("@react-native/metro-config");
|
|
58
|
+
|
|
59
|
+
const config = getDefaultConfig(__dirname);
|
|
60
|
+
|
|
61
|
+
config.resolver.extraNodeModules = {
|
|
62
|
+
...config.resolver.extraNodeModules,
|
|
63
|
+
crypto: require.resolve("react-native-quick-crypto"),
|
|
64
|
+
stream: require.resolve("readable-stream"),
|
|
65
|
+
buffer: require.resolve("buffer"),
|
|
66
|
+
events: require.resolve("events"),
|
|
67
|
+
process: require.resolve("process"),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// libp2p 3.x publishes a `browser` conditional export that is broken under
|
|
71
|
+
// Metro's package-exports resolver — see <https://github.com/libp2p/js-libp2p/issues/2969>.
|
|
72
|
+
// Enabling the resolver is required for several libp2p subpackages to
|
|
73
|
+
// resolve at all; per-package overrides may be needed if a specific module
|
|
74
|
+
// fails to bundle.
|
|
75
|
+
config.resolver.unstable_enablePackageExports = true;
|
|
76
|
+
|
|
77
|
+
module.exports = config;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Babel config
|
|
81
|
+
|
|
82
|
+
Compile public class fields with spec `[[Define]]` semantics by setting the
|
|
83
|
+
`setPublicClassFields: false` assumption:
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
module.exports = {
|
|
87
|
+
presets: ["babel-preset-expo"], // or "module:@react-native/babel-preset"
|
|
88
|
+
assumptions: {
|
|
89
|
+
setPublicClassFields: false,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
This is **required**, not optional. `babel-preset-expo` defaults to loose
|
|
95
|
+
(`[[Set]]`) class fields, which compile an uninitialized field declaration to
|
|
96
|
+
`this.field = void 0`. React Native's webapis define read-only prototype
|
|
97
|
+
constants — notably `Event.prototype.NONE` (and `CAPTURING_PHASE` /
|
|
98
|
+
`AT_TARGET` / `BUBBLING_PHASE`) via `Object.defineProperty` without
|
|
99
|
+
`writable: true`. The matching `this.NONE = void 0` walks the prototype chain
|
|
100
|
+
and throws `Cannot assign to read-only property 'NONE'` the moment libp2p or
|
|
101
|
+
WebRTC construct an `Event`. The `[[Define]]` assumption drops the bare
|
|
102
|
+
declaration, so the read-only constant is never assigned.
|
|
103
|
+
|
|
104
|
+
Do **not** add `["@babel/plugin-transform-private-methods", { loose: true }]`:
|
|
105
|
+
its loose option sets the opposite assumption (`setPublicClassFields: true`)
|
|
106
|
+
and reintroduces the crash. libp2p's private fields (`#field`) are transformed
|
|
107
|
+
by the preset without it.
|
|
108
|
+
|
|
109
|
+
## Usage
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import "@peerkit/transport-libp2p-react-native/polyfills";
|
|
113
|
+
import { createNode } from "@peerkit/transport-libp2p-react-native";
|
|
114
|
+
|
|
115
|
+
const transport = await createNode({
|
|
116
|
+
networkAccessBytes: new Uint8Array([
|
|
117
|
+
/* network access bytes */
|
|
118
|
+
]),
|
|
119
|
+
bootstrapRelays: ["/dns4/relay.example.com/tcp/443/wss/p2p/12D3Koo..."],
|
|
120
|
+
// Optional: defaults to ["/p2p-circuit", "/webrtc"].
|
|
121
|
+
addrs: ["/p2p-circuit", "/webrtc"],
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`createNode` returns a `TransportLibp2p` instance from
|
|
126
|
+
`@peerkit/transport-libp2p-core`. Refer to that package's documentation for
|
|
127
|
+
the public API (`onAccessConnect`, `onAgentsConnect`, `onMessageConnect`,
|
|
128
|
+
`sendAgents`, `sendMessage`, etc.).
|
|
129
|
+
|
|
130
|
+
## Noise crypto
|
|
131
|
+
|
|
132
|
+
`createNode` wires Noise with a JSI-backed `ICryptoInterface` over
|
|
133
|
+
`react-native-quick-crypto`. SHA-256, HKDF and ChaCha20-Poly1305 run as
|
|
134
|
+
native code; X25519 stays on the pure-JS Noise default because
|
|
135
|
+
`ICryptoInterface` is synchronous and quick-crypto's X25519 surface is not.
|
|
136
|
+
|
|
137
|
+
The adapter is also exported standalone for consumers who want to wire it
|
|
138
|
+
into their own libp2p stack:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import { quickCryptoNoise } from "@peerkit/transport-libp2p-react-native/quick-crypto-noise";
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Runtime scope
|
|
145
|
+
|
|
146
|
+
Importing the package's main entry pulls `react-native-quick-crypto` at
|
|
147
|
+
module load time. The package is therefore intended exclusively for React
|
|
148
|
+
Native bundles — do not import it from Node test code. Type-only imports
|
|
149
|
+
(`import type { ... }`) remain safe in any TypeScript context.
|
|
150
|
+
|
|
151
|
+
## Known limitations
|
|
152
|
+
|
|
153
|
+
- No background operation. iOS suspends the JS runtime when the app is
|
|
154
|
+
backgrounded; Android Doze mode throttles. Foreground-only without
|
|
155
|
+
additional OS-specific work.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Buffers the earliest message(s) arriving on a freshly opened inbound
|
|
3
|
+
* (in-band) datachannel and replays them once the JS `RTCDataChannel` object
|
|
4
|
+
* and its listener exist.
|
|
5
|
+
*
|
|
6
|
+
* On `react-native-webrtc`, the channel-open announcement and inbound message
|
|
7
|
+
* events can reach JS out of order during connection setup: a message for a
|
|
8
|
+
* newly opened inbound channel may arrive before the corresponding
|
|
9
|
+
* `RTCDataChannel` object is created, leaving no listener to receive it. This
|
|
10
|
+
* polyfill captures such early messages by `reactTag` and delivers them when
|
|
11
|
+
* the listener is attached.
|
|
12
|
+
*
|
|
13
|
+
* Pre-negotiated channels (`createDataChannel` with `negotiated: true, id: 0`
|
|
14
|
+
* on both ends) are unaffected: their JS object and listener exist before any
|
|
15
|
+
* data arrives.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Install the early-message recovery. Idempotent, and a no-op when the WebRTC
|
|
19
|
+
* native module or the global `RTCPeerConnection` is absent (`registerGlobals()`
|
|
20
|
+
* has not run, or under tests).
|
|
21
|
+
*/
|
|
22
|
+
export declare function installDataChannelEarlyMessagePolyfill(): void;
|
|
23
|
+
//# sourceMappingURL=datachannel-early-message-polyfill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"datachannel-early-message-polyfill.d.ts","sourceRoot":"","sources":["../src/datachannel-early-message-polyfill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAuEH;;;;GAIG;AACH,wBAAgB,sCAAsC,IAAI,IAAI,CAoF7D"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Buffers the earliest message(s) arriving on a freshly opened inbound
|
|
3
|
+
* (in-band) datachannel and replays them once the JS `RTCDataChannel` object
|
|
4
|
+
* and its listener exist.
|
|
5
|
+
*
|
|
6
|
+
* On `react-native-webrtc`, the channel-open announcement and inbound message
|
|
7
|
+
* events can reach JS out of order during connection setup: a message for a
|
|
8
|
+
* newly opened inbound channel may arrive before the corresponding
|
|
9
|
+
* `RTCDataChannel` object is created, leaving no listener to receive it. This
|
|
10
|
+
* polyfill captures such early messages by `reactTag` and delivers them when
|
|
11
|
+
* the listener is attached.
|
|
12
|
+
*
|
|
13
|
+
* Pre-negotiated channels (`createDataChannel` with `negotiated: true, id: 0`
|
|
14
|
+
* on both ends) are unaffected: their JS object and listener exist before any
|
|
15
|
+
* data arrives.
|
|
16
|
+
*/
|
|
17
|
+
import { Buffer } from "buffer";
|
|
18
|
+
import { NativeEventEmitter, NativeModules } from "react-native";
|
|
19
|
+
const PROBE_CHANNEL_LABEL = "peerkit-early-message-probe";
|
|
20
|
+
const INSTALLED_FLAG = "__peerkitDataChannelEarlyMessagePatched";
|
|
21
|
+
/**
|
|
22
|
+
* Decode a base64 datachannel payload to an exactly sized `ArrayBuffer`,
|
|
23
|
+
* matching how `react-native-webrtc` surfaces binary messages
|
|
24
|
+
* (`event.data.byteLength` must equal the message length).
|
|
25
|
+
*/
|
|
26
|
+
function base64ToArrayBuffer(base64) {
|
|
27
|
+
const view = Buffer.from(base64, "base64");
|
|
28
|
+
return view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Capture the shared `RTCDataChannel` prototype. The class is not exported, so a
|
|
32
|
+
* throwaway peer connection mints a probe channel and its prototype is read off
|
|
33
|
+
* the instance. Returns `null` if a peer connection cannot be created.
|
|
34
|
+
*/
|
|
35
|
+
function captureDataChannelPrototype(RTCPeerConnectionCtor) {
|
|
36
|
+
let probeConnection;
|
|
37
|
+
try {
|
|
38
|
+
probeConnection = new RTCPeerConnectionCtor();
|
|
39
|
+
const channel = probeConnection.createDataChannel(PROBE_CHANNEL_LABEL);
|
|
40
|
+
return Object.getPrototypeOf(channel);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
probeConnection?.close();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Install the early-message recovery. Idempotent, and a no-op when the WebRTC
|
|
51
|
+
* native module or the global `RTCPeerConnection` is absent (`registerGlobals()`
|
|
52
|
+
* has not run, or under tests).
|
|
53
|
+
*/
|
|
54
|
+
export function installDataChannelEarlyMessagePolyfill() {
|
|
55
|
+
const webRtcModule = NativeModules.WebRTCModule;
|
|
56
|
+
const scope = globalThis;
|
|
57
|
+
const RTCPeerConnectionCtor = scope.RTCPeerConnection;
|
|
58
|
+
if (webRtcModule == null || RTCPeerConnectionCtor == null) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const prototype = captureDataChannelPrototype(RTCPeerConnectionCtor);
|
|
62
|
+
if (prototype == null || prototype[INSTALLED_FLAG] === true) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, "onmessage");
|
|
66
|
+
if (descriptor?.get == null || descriptor.set == null) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Early messages buffered per datachannel reactTag, awaiting a consumer.
|
|
70
|
+
const buffered = new Map();
|
|
71
|
+
// reactTags whose consumer has attached. Their live messages are delivered by
|
|
72
|
+
// react-native-webrtc's own path, so the duplicate seen here is ignored.
|
|
73
|
+
const consumed = new Set();
|
|
74
|
+
const emitter = new NativeEventEmitter(webRtcModule);
|
|
75
|
+
emitter.addListener("dataChannelReceiveMessage", (raw) => {
|
|
76
|
+
const event = raw;
|
|
77
|
+
// libp2p only sends binary frames; ignore everything else.
|
|
78
|
+
if (event.type !== "binary" || consumed.has(event.reactTag)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const payload = base64ToArrayBuffer(event.data);
|
|
82
|
+
const existing = buffered.get(event.reactTag);
|
|
83
|
+
if (existing) {
|
|
84
|
+
existing.push(payload);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
buffered.set(event.reactTag, [payload]);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
emitter.addListener("dataChannelStateChanged", (raw) => {
|
|
91
|
+
const event = raw;
|
|
92
|
+
if (event.state === "closed") {
|
|
93
|
+
buffered.delete(event.reactTag);
|
|
94
|
+
consumed.delete(event.reactTag);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
const originalGet = descriptor.get;
|
|
98
|
+
const originalSet = descriptor.set;
|
|
99
|
+
Object.defineProperty(prototype, "onmessage", {
|
|
100
|
+
configurable: true,
|
|
101
|
+
enumerable: descriptor.enumerable ?? false,
|
|
102
|
+
get() {
|
|
103
|
+
return originalGet.call(this);
|
|
104
|
+
},
|
|
105
|
+
set(handler) {
|
|
106
|
+
originalSet.call(this, handler);
|
|
107
|
+
if (handler == null) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const reactTag = this._reactTag;
|
|
111
|
+
// From now on react-native-webrtc delivers live messages to this handler;
|
|
112
|
+
// mark the channel so the duplicate copies seen here are dropped.
|
|
113
|
+
consumed.add(reactTag);
|
|
114
|
+
const pending = buffered.get(reactTag);
|
|
115
|
+
if (pending == null) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
buffered.delete(reactTag);
|
|
119
|
+
for (const data of pending) {
|
|
120
|
+
handler({ data });
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
Object.defineProperty(prototype, INSTALLED_FLAG, {
|
|
125
|
+
value: true,
|
|
126
|
+
enumerable: false,
|
|
127
|
+
writable: false,
|
|
128
|
+
configurable: true,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=datachannel-early-message-polyfill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"datachannel-early-message-polyfill.js","sourceRoot":"","sources":["../src/datachannel-early-message-polyfill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A self-contained WHATWG `Event` / `EventTarget` / `CustomEvent` polyfill for
|
|
3
|
+
* the React Native Hermes engine.
|
|
4
|
+
*
|
|
5
|
+
* React Native's `setUpDOM` polyfills a handful of DOM globals (`DOMRect`,
|
|
6
|
+
* `Node`, `Element`, ...) but **not** the event classes, and Hermes ships none
|
|
7
|
+
* of them. libp2p depends on all three at module-evaluation time:
|
|
8
|
+
*
|
|
9
|
+
* - `@libp2p/interface` declares `class StreamMessageEvent extends Event`.
|
|
10
|
+
* - `main-event`'s `TypedEventEmitter extends EventTarget` and dispatches
|
|
11
|
+
* `new CustomEvent(type, { detail })`.
|
|
12
|
+
*
|
|
13
|
+
* Without these globals the bundle red-screens with
|
|
14
|
+
* `Property 'Event' doesn't exist` before any application code runs.
|
|
15
|
+
*
|
|
16
|
+
* This is a hand-rolled implementation rather than a dependency on
|
|
17
|
+
* `event-target-shim` on purpose: the shim's type definitions expose `Event`
|
|
18
|
+
* only as an interface (not a constructor value), and its dispatcher wraps
|
|
19
|
+
* foreign event objects in a copy — which breaks the `instanceof` checks and
|
|
20
|
+
* subclass fields (e.g. `StreamMessageEvent.data`) that libp2p relies on.
|
|
21
|
+
* Owning both `Event` and `EventTarget` here guarantees the exact event
|
|
22
|
+
* instance is delivered to every listener.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Install `Event`, `EventTarget`, and `CustomEvent` on the global scope,
|
|
26
|
+
* overwriting any implementation the runtime already provides.
|
|
27
|
+
*
|
|
28
|
+
* The overwrite is deliberate, not defensive. React Native's own global `Event`
|
|
29
|
+
* exposes read-only/non-configurable members (`type`, the phase constants) that
|
|
30
|
+
* libp2p's event subclasses redeclare as class fields, which throws at
|
|
31
|
+
* construction on Hermes. {@link PolyfillEvent} declares them as writable,
|
|
32
|
+
* configurable fields, so the three globals are replaced outright (not `??=`d)
|
|
33
|
+
* to guarantee a single, subclass-safe hierarchy for libp2p's `instanceof`
|
|
34
|
+
* checks and `EventTarget` dispatch.
|
|
35
|
+
*
|
|
36
|
+
* Runs once from the polyfills entry, before any libp2p module evaluates. Safe
|
|
37
|
+
* to call more than once.
|
|
38
|
+
*/
|
|
39
|
+
export declare function installEventTargetPolyfill(): void;
|
|
40
|
+
//# sourceMappingURL=event-target-polyfill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-target-polyfill.d.ts","sourceRoot":"","sources":["../src/event-target-polyfill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AA6NH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CASjD"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A self-contained WHATWG `Event` / `EventTarget` / `CustomEvent` polyfill for
|
|
3
|
+
* the React Native Hermes engine.
|
|
4
|
+
*
|
|
5
|
+
* React Native's `setUpDOM` polyfills a handful of DOM globals (`DOMRect`,
|
|
6
|
+
* `Node`, `Element`, ...) but **not** the event classes, and Hermes ships none
|
|
7
|
+
* of them. libp2p depends on all three at module-evaluation time:
|
|
8
|
+
*
|
|
9
|
+
* - `@libp2p/interface` declares `class StreamMessageEvent extends Event`.
|
|
10
|
+
* - `main-event`'s `TypedEventEmitter extends EventTarget` and dispatches
|
|
11
|
+
* `new CustomEvent(type, { detail })`.
|
|
12
|
+
*
|
|
13
|
+
* Without these globals the bundle red-screens with
|
|
14
|
+
* `Property 'Event' doesn't exist` before any application code runs.
|
|
15
|
+
*
|
|
16
|
+
* This is a hand-rolled implementation rather than a dependency on
|
|
17
|
+
* `event-target-shim` on purpose: the shim's type definitions expose `Event`
|
|
18
|
+
* only as an interface (not a constructor value), and its dispatcher wraps
|
|
19
|
+
* foreign event objects in a copy — which breaks the `instanceof` checks and
|
|
20
|
+
* subclass fields (e.g. `StreamMessageEvent.data`) that libp2p relies on.
|
|
21
|
+
* Owning both `Event` and `EventTarget` here guarantees the exact event
|
|
22
|
+
* instance is delivered to every listener.
|
|
23
|
+
*/
|
|
24
|
+
function normalizeAddOptions(options) {
|
|
25
|
+
if (typeof options === "boolean") {
|
|
26
|
+
return { capture: options };
|
|
27
|
+
}
|
|
28
|
+
return options ?? {};
|
|
29
|
+
}
|
|
30
|
+
/** WHATWG `Event`. */
|
|
31
|
+
class PolyfillEvent {
|
|
32
|
+
static NONE = 0;
|
|
33
|
+
static CAPTURING_PHASE = 1;
|
|
34
|
+
static AT_TARGET = 2;
|
|
35
|
+
static BUBBLING_PHASE = 3;
|
|
36
|
+
type;
|
|
37
|
+
bubbles;
|
|
38
|
+
cancelable;
|
|
39
|
+
composed;
|
|
40
|
+
timeStamp = 0;
|
|
41
|
+
isTrusted = false;
|
|
42
|
+
eventPhase = PolyfillEvent.NONE;
|
|
43
|
+
targetInternal = null;
|
|
44
|
+
currentTargetInternal = null;
|
|
45
|
+
defaultPreventedInternal = false;
|
|
46
|
+
propagationStopped = false;
|
|
47
|
+
immediatePropagationStopped = false;
|
|
48
|
+
constructor(type, eventInitDict) {
|
|
49
|
+
this.type = type;
|
|
50
|
+
this.bubbles = eventInitDict?.bubbles ?? false;
|
|
51
|
+
this.cancelable = eventInitDict?.cancelable ?? false;
|
|
52
|
+
this.composed = eventInitDict?.composed ?? false;
|
|
53
|
+
}
|
|
54
|
+
get target() {
|
|
55
|
+
return this.targetInternal;
|
|
56
|
+
}
|
|
57
|
+
get srcElement() {
|
|
58
|
+
return this.targetInternal;
|
|
59
|
+
}
|
|
60
|
+
get currentTarget() {
|
|
61
|
+
return this.currentTargetInternal;
|
|
62
|
+
}
|
|
63
|
+
get defaultPrevented() {
|
|
64
|
+
return this.defaultPreventedInternal;
|
|
65
|
+
}
|
|
66
|
+
preventDefault() {
|
|
67
|
+
if (this.cancelable) {
|
|
68
|
+
this.defaultPreventedInternal = true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
stopPropagation() {
|
|
72
|
+
this.propagationStopped = true;
|
|
73
|
+
}
|
|
74
|
+
stopImmediatePropagation() {
|
|
75
|
+
this.propagationStopped = true;
|
|
76
|
+
this.immediatePropagationStopped = true;
|
|
77
|
+
}
|
|
78
|
+
composedPath() {
|
|
79
|
+
return this.currentTargetInternal == null
|
|
80
|
+
? []
|
|
81
|
+
: [this.currentTargetInternal];
|
|
82
|
+
}
|
|
83
|
+
// The following methods are polyfill-internal: `PolyfillEventTarget` uses them
|
|
84
|
+
// to drive dispatch state across the class boundary (TypeScript `private`
|
|
85
|
+
// members are not reachable from another class).
|
|
86
|
+
/** @internal */
|
|
87
|
+
beginDispatch(target) {
|
|
88
|
+
this.targetInternal = target;
|
|
89
|
+
this.currentTargetInternal = target;
|
|
90
|
+
}
|
|
91
|
+
/** @internal */
|
|
92
|
+
endDispatch() {
|
|
93
|
+
this.currentTargetInternal = null;
|
|
94
|
+
}
|
|
95
|
+
/** @internal */
|
|
96
|
+
get immediatePropagationWasStopped() {
|
|
97
|
+
return this.immediatePropagationStopped;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/** WHATWG `CustomEvent`. */
|
|
101
|
+
class PolyfillCustomEvent extends PolyfillEvent {
|
|
102
|
+
detail;
|
|
103
|
+
constructor(type, eventInitDict) {
|
|
104
|
+
super(type, eventInitDict);
|
|
105
|
+
this.detail = eventInitDict?.detail ?? null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/** WHATWG `EventTarget`. */
|
|
109
|
+
class PolyfillEventTarget {
|
|
110
|
+
listenerMap = new Map();
|
|
111
|
+
addEventListener(type, callback, options) {
|
|
112
|
+
if (callback == null) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const opts = normalizeAddOptions(options);
|
|
116
|
+
const signal = opts.signal;
|
|
117
|
+
if (signal?.aborted === true) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const list = this.listenerMap.get(type) ?? [];
|
|
121
|
+
// Per spec a (callback, capture) pair is registered at most once.
|
|
122
|
+
if (list.some((entry) => entry.callback === callback)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
list.push({ callback, once: opts.once ?? false });
|
|
126
|
+
this.listenerMap.set(type, list);
|
|
127
|
+
if (signal != null) {
|
|
128
|
+
signal.addEventListener("abort", () => {
|
|
129
|
+
this.removeEventListener(type, callback);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
removeEventListener(type, callback, _options) {
|
|
134
|
+
if (callback == null) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const list = this.listenerMap.get(type);
|
|
138
|
+
if (list == null) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const index = list.findIndex((entry) => entry.callback === callback);
|
|
142
|
+
if (index >= 0) {
|
|
143
|
+
list.splice(index, 1);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
dispatchEvent(event) {
|
|
147
|
+
event.beginDispatch(this);
|
|
148
|
+
// Snapshot the list: a listener may add or remove listeners mid-dispatch.
|
|
149
|
+
const list = this.listenerMap.get(event.type);
|
|
150
|
+
if (list != null) {
|
|
151
|
+
for (const entry of [...list]) {
|
|
152
|
+
if (entry.once) {
|
|
153
|
+
this.removeEventListener(event.type, entry.callback);
|
|
154
|
+
}
|
|
155
|
+
const { callback } = entry;
|
|
156
|
+
if (typeof callback === "function") {
|
|
157
|
+
callback(event);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
callback.handleEvent(event);
|
|
161
|
+
}
|
|
162
|
+
if (event.immediatePropagationWasStopped) {
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
event.endDispatch();
|
|
168
|
+
return !event.defaultPrevented;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Install `Event`, `EventTarget`, and `CustomEvent` on the global scope,
|
|
173
|
+
* overwriting any implementation the runtime already provides.
|
|
174
|
+
*
|
|
175
|
+
* The overwrite is deliberate, not defensive. React Native's own global `Event`
|
|
176
|
+
* exposes read-only/non-configurable members (`type`, the phase constants) that
|
|
177
|
+
* libp2p's event subclasses redeclare as class fields, which throws at
|
|
178
|
+
* construction on Hermes. {@link PolyfillEvent} declares them as writable,
|
|
179
|
+
* configurable fields, so the three globals are replaced outright (not `??=`d)
|
|
180
|
+
* to guarantee a single, subclass-safe hierarchy for libp2p's `instanceof`
|
|
181
|
+
* checks and `EventTarget` dispatch.
|
|
182
|
+
*
|
|
183
|
+
* Runs once from the polyfills entry, before any libp2p module evaluates. Safe
|
|
184
|
+
* to call more than once.
|
|
185
|
+
*/
|
|
186
|
+
export function installEventTargetPolyfill() {
|
|
187
|
+
const eventScope = globalThis;
|
|
188
|
+
eventScope.Event = PolyfillEvent;
|
|
189
|
+
eventScope.EventTarget = PolyfillEventTarget;
|
|
190
|
+
eventScope.CustomEvent = PolyfillCustomEvent;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=event-target-polyfill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-target-polyfill.js","sourceRoot":"","sources":["../src/event-target-polyfill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AA0CH,SAAS,mBAAmB,CAC1B,OAA2C;IAE3C,IAAI,OAAO,OAAO,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IAC9B,CAAC;IACD,OAAO,OAAO,IAAI,EAAE,CAAC;AACvB,CAAC;AAED,sBAAsB;AACtB,MAAM,aAAa;IACjB,MAAM,CAAU,IAAI,GAAG,CAAC,CAAC;IACzB,MAAM,CAAU,eAAe,GAAG,CAAC,CAAC;IACpC,MAAM,CAAU,SAAS,GAAG,CAAC,CAAC;IAC9B,MAAM,CAAU,cAAc,GAAG,CAAC,CAAC;IAE1B,IAAI,CAAS;IACb,OAAO,CAAU;IACjB,UAAU,CAAU;IACpB,QAAQ,CAAU;IAClB,SAAS,GAAG,CAAC,CAAC;IACd,SAAS,GAAG,KAAK,CAAC;IAClB,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC;IAEjC,cAAc,GAA+B,IAAI,CAAC;IAClD,qBAAqB,GAA+B,IAAI,CAAC;IACzD,wBAAwB,GAAG,KAAK,CAAC;IACjC,kBAAkB,GAAG,KAAK,CAAC;IAC3B,2BAA2B,GAAG,KAAK,CAAC;IAE5C,YAAY,IAAY,EAAE,aAA6B;QACrD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,aAAa,EAAE,OAAO,IAAI,KAAK,CAAC;QAC/C,IAAI,CAAC,UAAU,GAAG,aAAa,EAAE,UAAU,IAAI,KAAK,CAAC;QACrD,IAAI,CAAC,QAAQ,GAAG,aAAa,EAAE,QAAQ,IAAI,KAAK,CAAC;IACnD,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,qBAAqB,CAAC;IACpC,CAAC;IAED,IAAI,gBAAgB;QAClB,OAAO,IAAI,CAAC,wBAAwB,CAAC;IACvC,CAAC;IAED,cAAc;QACZ,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAC;QACvC,CAAC;IACH,CAAC;IAED,eAAe;QACb,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;IACjC,CAAC;IAED,wBAAwB;QACtB,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,2BAA2B,GAAG,IAAI,CAAC;IAC1C,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,qBAAqB,IAAI,IAAI;YACvC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACnC,CAAC;IAED,+EAA+E;IAC/E,0EAA0E;IAC1E,iDAAiD;IAEjD,gBAAgB;IAChB,aAAa,CAAC,MAA2B;QACvC,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC;QAC7B,IAAI,CAAC,qBAAqB,GAAG,MAAM,CAAC;IACtC,CAAC;IAED,gBAAgB;IAChB,WAAW;QACT,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC;IACpC,CAAC;IAED,gBAAgB;IAChB,IAAI,8BAA8B;QAChC,OAAO,IAAI,CAAC,2BAA2B,CAAC;IAC1C,CAAC;;AAGH,4BAA4B;AAC5B,MAAM,mBAAiC,SAAQ,aAAa;IACjD,MAAM,CAAW;IAE1B,YAAY,IAAY,EAAE,aAAsC;QAC9D,KAAK,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,aAAa,EAAE,MAAM,IAAI,IAAI,CAAC;IAC9C,CAAC;CACF;AAED,4BAA4B;AAC5B,MAAM,mBAAmB;IACN,WAAW,GAAG,IAAI,GAAG,EAAgC,CAAC;IAEvE,gBAAgB,CACd,IAAY,EACZ,QAAsC,EACtC,OAA2C;QAE3C,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC9C,kEAAkE;QAClE,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,EAAE,CAAC;YACtD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACjC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;gBACpC,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC3C,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,mBAAmB,CACjB,IAAY,EACZ,QAAsC,EACtC,QAAyC;QAEzC,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QACrE,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,aAAa,CAAC,KAAoB;QAChC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAC1B,0EAA0E;QAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;YACjB,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;gBAC9B,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;oBACf,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACvD,CAAC;gBACD,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;gBAC3B,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;oBACnC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAClB,CAAC;qBAAM,CAAC;oBACN,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBAC9B,CAAC;gBACD,IAAI,KAAK,CAAC,8BAA8B,EAAE,CAAC;oBACzC,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QACD,KAAK,CAAC,WAAW,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC;IACjC,CAAC;CACF;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,0BAA0B;IACxC,MAAM,UAAU,GAAG,UAIlB,CAAC;IACF,UAAU,CAAC,KAAK,GAAG,aAAa,CAAC;IACjC,UAAU,CAAC,WAAW,GAAG,mBAAmB,CAAC;IAC7C,UAAU,CAAC,WAAW,GAAG,mBAAmB,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ConnectionGater } from "@libp2p/interface";
|
|
2
|
+
import type { NodeAddress, RelayDialAddress } from "@peerkit/api";
|
|
3
|
+
import { TransportLibp2p, type NodeOptions } from "@peerkit/transport-libp2p-core";
|
|
4
|
+
/**
|
|
5
|
+
* Default libp2p listen addresses for a React Native peerkit node.
|
|
6
|
+
*
|
|
7
|
+
* Mobile peers cannot accept inbound direct TCP/UDP (CGNAT, no listen socket
|
|
8
|
+
* survives backgrounding on iOS / Android), so reachability is always
|
|
9
|
+
* relay-mediated: `/p2p-circuit` advertises a reservation on a connected
|
|
10
|
+
* relay, `/webrtc` advertises that the peer can be upgraded to a direct
|
|
11
|
+
* WebRTC connection through the relay-coordinated SDP exchange.
|
|
12
|
+
*/
|
|
13
|
+
export declare const defaultNodeListenAddrs: NodeAddress[];
|
|
14
|
+
/**
|
|
15
|
+
* React Native-specific options accepted by {@link createNode}, on top of the
|
|
16
|
+
* platform-agnostic {@link NodeOptions}.
|
|
17
|
+
*/
|
|
18
|
+
export interface CreateNodeOptions extends NodeOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Listening addresses.
|
|
21
|
+
*
|
|
22
|
+
* Defaults to {@link defaultNodeListenAddrs}.
|
|
23
|
+
*/
|
|
24
|
+
addrs?: string[];
|
|
25
|
+
/**
|
|
26
|
+
* Relay multiaddrs to dial at startup. Required on mobile — without an
|
|
27
|
+
* active relay reservation the peer is unreachable. The transport invokes
|
|
28
|
+
* {@link NodeOptions.connectedToRelayCallback} once the dialable circuit
|
|
29
|
+
* address has been received.
|
|
30
|
+
*/
|
|
31
|
+
bootstrapRelays?: RelayDialAddress[];
|
|
32
|
+
/**
|
|
33
|
+
* List of ICE server URLs needed for establishing direct connections.
|
|
34
|
+
*/
|
|
35
|
+
iceServerUrls?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Overrides libp2p's connection gater.
|
|
38
|
+
*
|
|
39
|
+
* On React Native libp2p applies its browser gater, which refuses to dial
|
|
40
|
+
* private/LAN addresses. A production deployment behind a public relay never
|
|
41
|
+
* hits this, but development and demo setups that target a LAN relay or LAN
|
|
42
|
+
* peers must supply a gater that permits those dials
|
|
43
|
+
* (e.g. `{ denyDialMultiaddr: async () => false }`).
|
|
44
|
+
*
|
|
45
|
+
* Left undefined, libp2p keeps its secure-by-default browser gater.
|
|
46
|
+
*/
|
|
47
|
+
connectionGater?: ConnectionGater;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Build a React Native peerkit transport. Configures libp2p with WebRTC +
|
|
51
|
+
* WebRTC Direct + circuit-relay-v2 client + noise + yamux + identify.
|
|
52
|
+
*
|
|
53
|
+
* Noise is wired with `quickCryptoNoise`, the JSI-backed `ICryptoInterface`
|
|
54
|
+
* from `./quick-crypto-noise`, so SHA-256, HKDF, and ChaCha20-Poly1305 are
|
|
55
|
+
* offloaded to `react-native-quick-crypto`. X25519 stays on pure JS because
|
|
56
|
+
* `ICryptoInterface` is synchronous and quick-crypto's X25519 surface is not.
|
|
57
|
+
*
|
|
58
|
+
* Crypto primitives, RNG and the WebRTC globals come from runtime polyfills
|
|
59
|
+
* — the consumer must import `@peerkit/transport-libp2p-react-native/polyfills`
|
|
60
|
+
* once from the app entry before this factory runs.
|
|
61
|
+
*
|
|
62
|
+
* Handles all three peerkit protocols (access, agents, messages). DCUtR is
|
|
63
|
+
* deliberately not registered: mobile cannot listen on TCP/QUIC, so there is
|
|
64
|
+
* no relayed connection that can be upgraded by hole-punching; WebRTC ICE
|
|
65
|
+
* provides the only viable direct-connection path on mobile.
|
|
66
|
+
*/
|
|
67
|
+
export declare function createNode(options: CreateNodeOptions): Promise<TransportLibp2p>;
|
|
68
|
+
//# sourceMappingURL=factories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factories.d.ts","sourceRoot":"","sources":["../src/factories.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EACL,eAAe,EACf,KAAK,WAAW,EACjB,MAAM,gCAAgC,CAAC;AAIxC;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,EAG/C,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACrC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;;;;;OAUG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,4BAiC1D"}
|