@meshwhisper/sdk 0.1.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.
Files changed (163) hide show
  1. package/README.md +138 -0
  2. package/dist/browser/index.d.ts +4 -0
  3. package/dist/browser/index.d.ts.map +1 -0
  4. package/dist/browser/index.js +19 -0
  5. package/dist/browser/index.js.map +1 -0
  6. package/dist/chaff/index.d.ts +91 -0
  7. package/dist/chaff/index.d.ts.map +1 -0
  8. package/dist/chaff/index.js +268 -0
  9. package/dist/chaff/index.js.map +1 -0
  10. package/dist/cluster/index.d.ts +159 -0
  11. package/dist/cluster/index.d.ts.map +1 -0
  12. package/dist/cluster/index.js +393 -0
  13. package/dist/cluster/index.js.map +1 -0
  14. package/dist/compliance/index.d.ts +129 -0
  15. package/dist/compliance/index.d.ts.map +1 -0
  16. package/dist/compliance/index.js +315 -0
  17. package/dist/compliance/index.js.map +1 -0
  18. package/dist/crypto/index.d.ts +65 -0
  19. package/dist/crypto/index.d.ts.map +1 -0
  20. package/dist/crypto/index.js +146 -0
  21. package/dist/crypto/index.js.map +1 -0
  22. package/dist/group/index.d.ts +155 -0
  23. package/dist/group/index.d.ts.map +1 -0
  24. package/dist/group/index.js +560 -0
  25. package/dist/group/index.js.map +1 -0
  26. package/dist/index.d.ts +7 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +11 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/namespace/index.d.ts +155 -0
  31. package/dist/namespace/index.d.ts.map +1 -0
  32. package/dist/namespace/index.js +278 -0
  33. package/dist/namespace/index.js.map +1 -0
  34. package/dist/node/index.d.ts +4 -0
  35. package/dist/node/index.d.ts.map +1 -0
  36. package/dist/node/index.js +19 -0
  37. package/dist/node/index.js.map +1 -0
  38. package/dist/packet/index.d.ts +63 -0
  39. package/dist/packet/index.d.ts.map +1 -0
  40. package/dist/packet/index.js +244 -0
  41. package/dist/packet/index.js.map +1 -0
  42. package/dist/permissions/index.d.ts +107 -0
  43. package/dist/permissions/index.d.ts.map +1 -0
  44. package/dist/permissions/index.js +282 -0
  45. package/dist/permissions/index.js.map +1 -0
  46. package/dist/persistence/idb-storage.d.ts +27 -0
  47. package/dist/persistence/idb-storage.d.ts.map +1 -0
  48. package/dist/persistence/idb-storage.js +75 -0
  49. package/dist/persistence/idb-storage.js.map +1 -0
  50. package/dist/persistence/index.d.ts +4 -0
  51. package/dist/persistence/index.d.ts.map +1 -0
  52. package/dist/persistence/index.js +3 -0
  53. package/dist/persistence/index.js.map +1 -0
  54. package/dist/persistence/node-storage.d.ts +33 -0
  55. package/dist/persistence/node-storage.d.ts.map +1 -0
  56. package/dist/persistence/node-storage.js +90 -0
  57. package/dist/persistence/node-storage.js.map +1 -0
  58. package/dist/persistence/serialization.d.ts +4 -0
  59. package/dist/persistence/serialization.d.ts.map +1 -0
  60. package/dist/persistence/serialization.js +49 -0
  61. package/dist/persistence/serialization.js.map +1 -0
  62. package/dist/persistence/types.d.ts +29 -0
  63. package/dist/persistence/types.d.ts.map +1 -0
  64. package/dist/persistence/types.js +5 -0
  65. package/dist/persistence/types.js.map +1 -0
  66. package/dist/ratchet/index.d.ts +80 -0
  67. package/dist/ratchet/index.d.ts.map +1 -0
  68. package/dist/ratchet/index.js +259 -0
  69. package/dist/ratchet/index.js.map +1 -0
  70. package/dist/reciprocity/index.d.ts +109 -0
  71. package/dist/reciprocity/index.d.ts.map +1 -0
  72. package/dist/reciprocity/index.js +311 -0
  73. package/dist/reciprocity/index.js.map +1 -0
  74. package/dist/relay/index.d.ts +87 -0
  75. package/dist/relay/index.d.ts.map +1 -0
  76. package/dist/relay/index.js +286 -0
  77. package/dist/relay/index.js.map +1 -0
  78. package/dist/routing/index.d.ts +136 -0
  79. package/dist/routing/index.d.ts.map +1 -0
  80. package/dist/routing/index.js +478 -0
  81. package/dist/routing/index.js.map +1 -0
  82. package/dist/sdk/index.d.ts +322 -0
  83. package/dist/sdk/index.d.ts.map +1 -0
  84. package/dist/sdk/index.js +1530 -0
  85. package/dist/sdk/index.js.map +1 -0
  86. package/dist/sybil/index.d.ts +123 -0
  87. package/dist/sybil/index.d.ts.map +1 -0
  88. package/dist/sybil/index.js +491 -0
  89. package/dist/sybil/index.js.map +1 -0
  90. package/dist/transport/browser/index.d.ts +34 -0
  91. package/dist/transport/browser/index.d.ts.map +1 -0
  92. package/dist/transport/browser/index.js +176 -0
  93. package/dist/transport/browser/index.js.map +1 -0
  94. package/dist/transport/local/index.d.ts +57 -0
  95. package/dist/transport/local/index.d.ts.map +1 -0
  96. package/dist/transport/local/index.js +442 -0
  97. package/dist/transport/local/index.js.map +1 -0
  98. package/dist/transport/negotiator/index.d.ts +79 -0
  99. package/dist/transport/negotiator/index.d.ts.map +1 -0
  100. package/dist/transport/negotiator/index.js +289 -0
  101. package/dist/transport/negotiator/index.js.map +1 -0
  102. package/dist/transport/node/index.d.ts +56 -0
  103. package/dist/transport/node/index.d.ts.map +1 -0
  104. package/dist/transport/node/index.js +209 -0
  105. package/dist/transport/node/index.js.map +1 -0
  106. package/dist/transport/noop/index.d.ts +11 -0
  107. package/dist/transport/noop/index.d.ts.map +1 -0
  108. package/dist/transport/noop/index.js +20 -0
  109. package/dist/transport/noop/index.js.map +1 -0
  110. package/dist/transport/p2p/index.d.ts +109 -0
  111. package/dist/transport/p2p/index.d.ts.map +1 -0
  112. package/dist/transport/p2p/index.js +237 -0
  113. package/dist/transport/p2p/index.js.map +1 -0
  114. package/dist/transport/websocket/index.d.ts +89 -0
  115. package/dist/transport/websocket/index.d.ts.map +1 -0
  116. package/dist/transport/websocket/index.js +498 -0
  117. package/dist/transport/websocket/index.js.map +1 -0
  118. package/dist/transport/websocket/serialize.d.ts +5 -0
  119. package/dist/transport/websocket/serialize.d.ts.map +1 -0
  120. package/dist/transport/websocket/serialize.js +55 -0
  121. package/dist/transport/websocket/serialize.js.map +1 -0
  122. package/dist/types.d.ts +215 -0
  123. package/dist/types.d.ts.map +1 -0
  124. package/dist/types.js +15 -0
  125. package/dist/types.js.map +1 -0
  126. package/dist/x3dh/index.d.ts +120 -0
  127. package/dist/x3dh/index.d.ts.map +1 -0
  128. package/dist/x3dh/index.js +290 -0
  129. package/dist/x3dh/index.js.map +1 -0
  130. package/package.json +59 -0
  131. package/src/browser/index.ts +19 -0
  132. package/src/chaff/index.ts +340 -0
  133. package/src/cluster/index.ts +482 -0
  134. package/src/compliance/index.ts +407 -0
  135. package/src/crypto/index.ts +193 -0
  136. package/src/group/index.ts +719 -0
  137. package/src/index.ts +87 -0
  138. package/src/lz4js.d.ts +58 -0
  139. package/src/namespace/index.ts +336 -0
  140. package/src/node/index.ts +19 -0
  141. package/src/packet/index.ts +326 -0
  142. package/src/permissions/index.ts +405 -0
  143. package/src/persistence/idb-storage.ts +83 -0
  144. package/src/persistence/index.ts +3 -0
  145. package/src/persistence/node-storage.ts +96 -0
  146. package/src/persistence/serialization.ts +75 -0
  147. package/src/persistence/types.ts +33 -0
  148. package/src/ratchet/index.ts +363 -0
  149. package/src/reciprocity/index.ts +371 -0
  150. package/src/relay/index.ts +382 -0
  151. package/src/routing/index.ts +577 -0
  152. package/src/sdk/index.ts +1994 -0
  153. package/src/sybil/index.ts +661 -0
  154. package/src/transport/browser/index.ts +201 -0
  155. package/src/transport/local/index.ts +540 -0
  156. package/src/transport/negotiator/index.ts +397 -0
  157. package/src/transport/node/index.ts +234 -0
  158. package/src/transport/noop/index.ts +22 -0
  159. package/src/transport/p2p/index.ts +345 -0
  160. package/src/transport/websocket/index.ts +660 -0
  161. package/src/transport/websocket/serialize.ts +68 -0
  162. package/src/types.ts +275 -0
  163. package/src/x3dh/index.ts +388 -0
@@ -0,0 +1,209 @@
1
+ // ============================================================
2
+ // MeshWhisper SDK — Node Transport
3
+ // Connects the SDK to a MeshWhisper Node (relay + directory).
4
+ // All traffic flows through the Node WebSocket endpoint; the
5
+ // Node routes packets by destination hash and buffers blobs
6
+ // for offline recipients.
7
+ // ============================================================
8
+ import { WebSocket } from 'ws';
9
+ import { serializePacket, deserializePacket, HEADER_SIZE, } from '../websocket/serialize.js';
10
+ // ---- Constants ----
11
+ /** Foundation-hosted relay nodes. Used when node config is "mesh". */
12
+ export const FOUNDATION_RELAY_NODES = [
13
+ 'wss://relay.meshwhisper.io', // TODO: deploy actual Foundation nodes
14
+ ];
15
+ const RECONNECT_BASE_MS = 1_000;
16
+ const RECONNECT_MAX_MS = 30_000;
17
+ // ---- NodeTransport ----
18
+ /**
19
+ * Transport that connects to a MeshWhisper Node for relay and
20
+ * store-and-forward delivery.
21
+ *
22
+ * Sends a `hello` control message on connect to register the device's
23
+ * current destination hashes. The Node then routes incoming packets
24
+ * to the registered hashes and delivers any queued blobs.
25
+ *
26
+ * All outbound packets are forwarded to the Node regardless of the
27
+ * `destination` argument — the packet's destHash header field is what
28
+ * the Node uses for routing.
29
+ */
30
+ export class NodeTransport {
31
+ nodeUrl;
32
+ getDestHashes;
33
+ pushConfig;
34
+ type = 'internet';
35
+ ws = null;
36
+ receiveCallbacks = [];
37
+ running = false;
38
+ reconnectAttempt = 0;
39
+ reconnectTimer = null;
40
+ /**
41
+ * @param nodeUrl - The WebSocket URL of the Node, or "mesh" for Foundation nodes.
42
+ * @param getDestHashes - Callback returning the device's current dest hashes
43
+ * as hex strings. Called on every (re)connect so the Node always has
44
+ * up-to-date hashes.
45
+ * @param pushConfig - Optional push token to register with the Node so it can
46
+ * wake the device via APNs/FCM when a message arrives while offline.
47
+ */
48
+ constructor(nodeUrl, getDestHashes, pushConfig) {
49
+ this.nodeUrl = nodeUrl;
50
+ this.getDestHashes = getDestHashes;
51
+ this.pushConfig = pushConfig;
52
+ }
53
+ // ---- Transport interface ----
54
+ async start() {
55
+ this.running = true;
56
+ await this.connect();
57
+ }
58
+ async stop() {
59
+ this.running = false;
60
+ if (this.reconnectTimer) {
61
+ clearTimeout(this.reconnectTimer);
62
+ this.reconnectTimer = null;
63
+ }
64
+ if (this.ws) {
65
+ this.ws.close(1000, 'shutdown');
66
+ this.ws = null;
67
+ }
68
+ }
69
+ async isAvailable() {
70
+ return this.ws?.readyState === WebSocket.OPEN;
71
+ }
72
+ async send(packet, _destination) {
73
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
74
+ throw new Error('NodeTransport: not connected to Node');
75
+ }
76
+ const binary = serializePacket(packet);
77
+ return new Promise((resolve, reject) => {
78
+ this.ws.send(binary, { binary: true }, (err) => {
79
+ if (err)
80
+ reject(new Error(`NodeTransport send failed: ${err.message}`));
81
+ else
82
+ resolve();
83
+ });
84
+ });
85
+ }
86
+ onReceive(callback) {
87
+ this.receiveCallbacks.push(callback);
88
+ }
89
+ // ---- Connection management ----
90
+ resolveUrl() {
91
+ if (this.nodeUrl === 'mesh') {
92
+ return FOUNDATION_RELAY_NODES[0];
93
+ }
94
+ return this.nodeUrl;
95
+ }
96
+ connect() {
97
+ const url = this.resolveUrl();
98
+ return new Promise((resolve, reject) => {
99
+ let resolved = false;
100
+ const ws = new WebSocket(url);
101
+ ws.binaryType = 'arraybuffer';
102
+ ws.on('open', () => {
103
+ this.ws = ws;
104
+ this.reconnectAttempt = 0;
105
+ resolved = true;
106
+ // Register dest hashes (and optional push token) with the Node
107
+ ws.send(JSON.stringify(this.buildHello()));
108
+ resolve();
109
+ });
110
+ ws.on('message', (raw) => {
111
+ this.handleMessage(raw);
112
+ });
113
+ ws.on('close', () => {
114
+ this.ws = null;
115
+ if (this.running)
116
+ this.scheduleReconnect();
117
+ });
118
+ ws.on('error', (err) => {
119
+ if (!resolved) {
120
+ resolved = true;
121
+ reject(new Error(`NodeTransport: failed to connect to ${url}: ${err.message}`));
122
+ }
123
+ });
124
+ });
125
+ }
126
+ scheduleReconnect() {
127
+ if (!this.running)
128
+ return;
129
+ const delay = Math.min(RECONNECT_BASE_MS * Math.pow(2, this.reconnectAttempt), RECONNECT_MAX_MS);
130
+ this.reconnectAttempt++;
131
+ this.reconnectTimer = setTimeout(async () => {
132
+ if (!this.running)
133
+ return;
134
+ try {
135
+ await this.connect();
136
+ }
137
+ catch {
138
+ this.scheduleReconnect();
139
+ }
140
+ }, delay);
141
+ }
142
+ // ---- Message handling ----
143
+ handleMessage(raw) {
144
+ // Binary messages are relay packets
145
+ if (raw instanceof ArrayBuffer && raw.byteLength >= HEADER_SIZE) {
146
+ try {
147
+ const packet = deserializePacket(new Uint8Array(raw));
148
+ const source = this.resolveUrl();
149
+ for (const cb of this.receiveCallbacks) {
150
+ try {
151
+ cb(packet, source);
152
+ }
153
+ catch { /* swallow */ }
154
+ }
155
+ }
156
+ catch {
157
+ // Malformed packet — discard
158
+ }
159
+ return;
160
+ }
161
+ // JSON messages from the Node (informational; no action needed in v1)
162
+ if (typeof raw === 'string' || raw instanceof Buffer) {
163
+ try {
164
+ JSON.parse(raw.toString());
165
+ // Reserved for future Node→client control messages
166
+ }
167
+ catch { /* not JSON */ }
168
+ }
169
+ }
170
+ // ---- Dest hash refresh ----
171
+ /**
172
+ * Re-registers the device's destination hashes with the Node.
173
+ * Call this when the epoch hour rolls over and hashes rotate.
174
+ */
175
+ refreshDestHashes() {
176
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN)
177
+ return;
178
+ this.ws.send(JSON.stringify(this.buildHello()));
179
+ }
180
+ /**
181
+ * Update the push token (e.g. after APNs/FCM issues a new token).
182
+ * Re-registers with the Node immediately if connected.
183
+ */
184
+ setPushConfig(pushConfig) {
185
+ this.pushConfig = pushConfig;
186
+ this.refreshDestHashes();
187
+ }
188
+ // ---- Private helpers ----
189
+ buildHello() {
190
+ const msg = {
191
+ type: 'hello',
192
+ destHashes: this.getDestHashes(),
193
+ };
194
+ if (this.pushConfig) {
195
+ msg['pushPlatform'] = this.pushConfig.platform;
196
+ if (this.pushConfig.platform === 'webpush') {
197
+ msg['pushSubscription'] = JSON.stringify(this.pushConfig.subscription);
198
+ }
199
+ else {
200
+ msg['pushToken'] = this.pushConfig.token;
201
+ if (this.pushConfig.platform === 'apns' && this.pushConfig.topic) {
202
+ msg['pushTopic'] = this.pushConfig.topic;
203
+ }
204
+ }
205
+ }
206
+ return msg;
207
+ }
208
+ }
209
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/transport/node/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Transport, Packet, BearerType } from '../../types.js';
2
+ export declare class NoOpTransport implements Transport {
3
+ readonly type: BearerType;
4
+ constructor(type: BearerType);
5
+ start(): Promise<void>;
6
+ stop(): Promise<void>;
7
+ isAvailable(): Promise<boolean>;
8
+ send(_packet: Packet, _destination: string): Promise<void>;
9
+ onReceive(_callback: (packet: Packet, source: string) => void): void;
10
+ }
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/transport/noop/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEpE,qBAAa,aAAc,YAAW,SAAS;IACjC,QAAQ,CAAC,IAAI,EAAE,UAAU;gBAAhB,IAAI,EAAE,UAAU;IAE/B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IACtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IACrB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAE/B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,SAAS,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;CACrE"}
@@ -0,0 +1,20 @@
1
+ // ============================================================
2
+ // MeshWhisper SDK — No-Op Transport
3
+ // Satisfies the Transport interface but does nothing.
4
+ // Used as a placeholder for transports that are unavailable
5
+ // in the current environment (e.g. LocalTransport in a browser).
6
+ // ============================================================
7
+ export class NoOpTransport {
8
+ type;
9
+ constructor(type) {
10
+ this.type = type;
11
+ }
12
+ async start() { }
13
+ async stop() { }
14
+ async isAvailable() { return false; }
15
+ async send(_packet, _destination) {
16
+ throw new Error(`NoOpTransport(${this.type}): not available in this environment`);
17
+ }
18
+ onReceive(_callback) { }
19
+ }
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/transport/noop/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,oCAAoC;AACpC,sDAAsD;AACtD,4DAA4D;AAC5D,iEAAiE;AACjE,+DAA+D;AAI/D,MAAM,OAAO,aAAa;IACH;IAArB,YAAqB,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEzC,KAAK,CAAC,KAAK,KAAmB,CAAC;IAC/B,KAAK,CAAC,IAAI,KAAmB,CAAC;IAC9B,KAAK,CAAC,WAAW,KAAuB,OAAO,KAAK,CAAC,CAAC,CAAC;IAEvD,KAAK,CAAC,IAAI,CAAC,OAAe,EAAE,YAAoB;QAC9C,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,CAAC,IAAI,sCAAsC,CAAC,CAAC;IACpF,CAAC;IAED,SAAS,CAAC,SAAmD,IAAS,CAAC;CACxE"}
@@ -0,0 +1,109 @@
1
+ import type { Packet, Transport } from '../../types.js';
2
+ /**
3
+ * Metadata about a discovered P2P peer.
4
+ * Provided by the native layer during discovery.
5
+ */
6
+ export interface PeerInfo {
7
+ /** Human-readable name for the peer device. */
8
+ displayName: string;
9
+ /** The service identifier under which this peer was discovered. */
10
+ serviceId: string;
11
+ /** Advertised capabilities (e.g. "relay", "store-forward"). */
12
+ capabilities: string[];
13
+ }
14
+ /**
15
+ * Abstract interface that native platform code (Swift / Kotlin)
16
+ * must implement to provide P2P connectivity to the TypeScript SDK.
17
+ *
18
+ * - iOS: backed by Apple Multipeer Connectivity Framework
19
+ * (BLE discovery + Wi-Fi Direct data transfer).
20
+ * - Android: backed by Google Nearby Connections API
21
+ * (Bluetooth + Wi-Fi).
22
+ *
23
+ * All methods are designed to be thin wrappers around the native
24
+ * APIs so the bridge implementation stays minimal.
25
+ */
26
+ export interface PlatformP2PBridge {
27
+ /** Begin advertising this device for the given service. */
28
+ startAdvertising(serviceId: string): Promise<void>;
29
+ /** Begin scanning for peers advertising the given service. */
30
+ startDiscovery(serviceId: string): Promise<void>;
31
+ /** Stop advertising. */
32
+ stopAdvertising(): Promise<void>;
33
+ /** Stop discovery scanning. */
34
+ stopDiscovery(): Promise<void>;
35
+ /** Send raw bytes to a connected peer. */
36
+ sendData(peerId: string, data: Uint8Array): Promise<void>;
37
+ /** Register a callback invoked when a new peer is discovered. */
38
+ onPeerDiscovered(callback: (peerId: string, info: PeerInfo) => void): void;
39
+ /** Register a callback invoked when a previously discovered peer is lost. */
40
+ onPeerLost(callback: (peerId: string) => void): void;
41
+ /** Register a callback invoked when data is received from a peer. */
42
+ onDataReceived(callback: (peerId: string, data: Uint8Array) => void): void;
43
+ /** Returns the IDs of all currently connected peers. */
44
+ getConnectedPeers(): string[];
45
+ /**
46
+ * Returns true if the underlying native P2P framework is
47
+ * available on this device / OS version.
48
+ */
49
+ isSupported(): boolean;
50
+ }
51
+ /**
52
+ * Registers a platform-specific P2P bridge implementation.
53
+ *
54
+ * Called by native code (via JSI on React Native, or similar
55
+ * interop layers) to inject the real Multipeer / Nearby
56
+ * Connections wrapper at runtime.
57
+ *
58
+ * @param bridge - The native bridge implementation.
59
+ */
60
+ export declare function registerPlatformBridge(bridge: PlatformP2PBridge): void;
61
+ /**
62
+ * Generates a platform-appropriate service identifier from an
63
+ * application namespace string.
64
+ *
65
+ * Both Apple Multipeer Connectivity and Android NSD impose
66
+ * restrictions on service type identifiers (length, allowed
67
+ * characters). This function produces a short, deterministic,
68
+ * lowercase-alphanumeric ID derived from the namespace.
69
+ *
70
+ * @param namespace - The application namespace (e.g. "com.example.chat").
71
+ * @returns A service ID string safe for both iOS and Android.
72
+ */
73
+ export declare function generateServiceId(namespace: string): string;
74
+ /**
75
+ * PlatformP2PTransport adapts a PlatformP2PBridge into the
76
+ * SDK's Transport interface.
77
+ *
78
+ * When a native bridge has been registered via
79
+ * `registerPlatformBridge()`, this transport serializes Packets
80
+ * to wire bytes, sends them through the bridge, and
81
+ * deserializes incoming bytes back into Packets for the mesh
82
+ * router.
83
+ *
84
+ * When no bridge is registered, the transport reports itself
85
+ * as unavailable and all operations are safe no-ops.
86
+ */
87
+ export declare class PlatformP2PTransport implements Transport {
88
+ readonly type: "platform_p2p";
89
+ private readonly serviceId;
90
+ private receiveCallback;
91
+ private running;
92
+ /**
93
+ * @param namespace - Application namespace used to derive
94
+ * the P2P service identifier.
95
+ */
96
+ constructor(namespace: string);
97
+ /**
98
+ * Returns the bridge currently in use. Reads from the
99
+ * module-level registry so that bridges registered after
100
+ * construction are picked up automatically.
101
+ */
102
+ private get bridge();
103
+ isAvailable(): Promise<boolean>;
104
+ start(): Promise<void>;
105
+ stop(): Promise<void>;
106
+ send(packet: Packet, destination: string): Promise<void>;
107
+ onReceive(callback: (packet: Packet, source: string) => void): void;
108
+ }
109
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/transport/p2p/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAe,MAAM,gBAAgB,CAAC;AAIrE;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnD,8DAA8D;IAC9D,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD,wBAAwB;IACxB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjC,+BAA+B;IAC/B,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/B,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1D,iEAAiE;IACjE,gBAAgB,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,IAAI,GAAG,IAAI,CAAC;IAE3E,6EAA6E;IAC7E,UAAU,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAErD,qEAAqE;IACrE,cAAc,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAC;IAE3E,wDAAwD;IACxD,iBAAiB,IAAI,MAAM,EAAE,CAAC;IAE9B;;;OAGG;IACH,WAAW,IAAI,OAAO,CAAC;CACxB;AA4ID;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAEtE;AAOD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAY3D;AAID;;;;;;;;;;;;GAYG;AACH,qBAAa,oBAAqB,YAAW,SAAS;IACpD,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAU;IAExC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,eAAe,CAA2D;IAClF,OAAO,CAAC,OAAO,CAAS;IAExB;;;OAGG;gBACS,SAAS,EAAE,MAAM;IAI7B;;;;OAIG;IACH,OAAO,KAAK,MAAM,GAEjB;IAIK,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQrB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9D,SAAS,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;CAGpE"}
@@ -0,0 +1,237 @@
1
+ // ============================================================
2
+ // MeshWhisper SDK — Platform P2P Transport
3
+ // Abstract bridge for native P2P (Apple Multipeer Connectivity,
4
+ // Google Nearby Connections) with TypeScript-side Transport
5
+ // wrapper. Native SDKs implement PlatformP2PBridge; this module
6
+ // provides the Transport adapter and a no-op fallback for
7
+ // environments where native P2P is unavailable.
8
+ // ============================================================
9
+ // ---- Packet Serialization ----
10
+ /**
11
+ * Minimum header size in bytes:
12
+ * version (1) + flags (1) + destHash (8) + senderEphemeralId (16)
13
+ * + ttl (1) + payloadLength (4) = 31
14
+ */
15
+ const HEADER_SIZE = 31;
16
+ /**
17
+ * Serializes a Packet into a compact binary format for transmission
18
+ * over the native P2P bridge.
19
+ *
20
+ * Wire format (big-endian):
21
+ * [0] u8 version
22
+ * [1] u8 flags
23
+ * [2..9] 8B destHash
24
+ * [10..25] 16B senderEphemeralId
25
+ * [26] u8 ttl
26
+ * [27..30] u32 payloadLength
27
+ * [31..] var encryptedPayload
28
+ */
29
+ function serializePacket(packet) {
30
+ const totalLength = HEADER_SIZE + packet.encryptedPayload.length;
31
+ const buffer = new Uint8Array(totalLength);
32
+ const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
33
+ let offset = 0;
34
+ // version (u8)
35
+ view.setUint8(offset, packet.version);
36
+ offset += 1;
37
+ // flags (u8)
38
+ view.setUint8(offset, packet.flags);
39
+ offset += 1;
40
+ // destHash (8 bytes)
41
+ buffer.set(packet.destHash, offset);
42
+ offset += 8;
43
+ // senderEphemeralId (16 bytes)
44
+ buffer.set(packet.senderEphemeralId, offset);
45
+ offset += 16;
46
+ // ttl (u8)
47
+ view.setUint8(offset, packet.ttl);
48
+ offset += 1;
49
+ // payloadLength (u32 big-endian)
50
+ view.setUint32(offset, packet.payloadLength, false);
51
+ offset += 4;
52
+ // encryptedPayload
53
+ buffer.set(packet.encryptedPayload, offset);
54
+ return buffer;
55
+ }
56
+ /**
57
+ * Deserializes a Uint8Array back into a Packet.
58
+ * Throws if the data is too short or the payload length mismatches.
59
+ */
60
+ function deserializePacket(data) {
61
+ if (data.length < HEADER_SIZE) {
62
+ throw new Error(`P2P: packet too short (${data.length} bytes, need at least ${HEADER_SIZE})`);
63
+ }
64
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
65
+ let offset = 0;
66
+ const version = view.getUint8(offset);
67
+ offset += 1;
68
+ const flags = view.getUint8(offset);
69
+ offset += 1;
70
+ const destHash = data.slice(offset, offset + 8);
71
+ offset += 8;
72
+ const senderEphemeralId = data.slice(offset, offset + 16);
73
+ offset += 16;
74
+ const ttl = view.getUint8(offset);
75
+ offset += 1;
76
+ const payloadLength = view.getUint32(offset, false);
77
+ offset += 4;
78
+ const encryptedPayload = data.slice(offset, offset + payloadLength);
79
+ if (encryptedPayload.length !== payloadLength) {
80
+ throw new Error(`P2P: payload length mismatch (header says ${payloadLength}, got ${encryptedPayload.length})`);
81
+ }
82
+ return {
83
+ version,
84
+ flags,
85
+ destHash,
86
+ senderEphemeralId,
87
+ ttl,
88
+ payloadLength,
89
+ encryptedPayload,
90
+ };
91
+ }
92
+ // ---- No-Op Bridge ----
93
+ /**
94
+ * Default bridge used when no native implementation is registered.
95
+ * All methods are safe no-ops. isSupported() returns false so the
96
+ * transport layer knows to skip this bearer.
97
+ */
98
+ class NoOpBridge {
99
+ async startAdvertising(_serviceId) { }
100
+ async startDiscovery(_serviceId) { }
101
+ async stopAdvertising() { }
102
+ async stopDiscovery() { }
103
+ async sendData(_peerId, _data) { }
104
+ onPeerDiscovered(_callback) { }
105
+ onPeerLost(_callback) { }
106
+ onDataReceived(_callback) { }
107
+ getConnectedPeers() {
108
+ return [];
109
+ }
110
+ isSupported() {
111
+ return false;
112
+ }
113
+ }
114
+ // ---- Bridge Registry ----
115
+ /** The currently registered bridge (defaults to NoOpBridge). */
116
+ let activeBridge = new NoOpBridge();
117
+ /**
118
+ * Registers a platform-specific P2P bridge implementation.
119
+ *
120
+ * Called by native code (via JSI on React Native, or similar
121
+ * interop layers) to inject the real Multipeer / Nearby
122
+ * Connections wrapper at runtime.
123
+ *
124
+ * @param bridge - The native bridge implementation.
125
+ */
126
+ export function registerPlatformBridge(bridge) {
127
+ activeBridge = bridge;
128
+ }
129
+ // ---- Service ID Generation ----
130
+ /** Max length for Bonjour / NSD service types. */
131
+ const MAX_SERVICE_ID_LENGTH = 15;
132
+ /**
133
+ * Generates a platform-appropriate service identifier from an
134
+ * application namespace string.
135
+ *
136
+ * Both Apple Multipeer Connectivity and Android NSD impose
137
+ * restrictions on service type identifiers (length, allowed
138
+ * characters). This function produces a short, deterministic,
139
+ * lowercase-alphanumeric ID derived from the namespace.
140
+ *
141
+ * @param namespace - The application namespace (e.g. "com.example.chat").
142
+ * @returns A service ID string safe for both iOS and Android.
143
+ */
144
+ export function generateServiceId(namespace) {
145
+ // Simple FNV-1a 32-bit hash for determinism without heavy deps.
146
+ let h = 0x811c9dc5;
147
+ for (let i = 0; i < namespace.length; i++) {
148
+ h ^= namespace.charCodeAt(i);
149
+ h = Math.imul(h, 0x01000193);
150
+ }
151
+ // Unsigned conversion then base-36 for compact alphanumeric output.
152
+ const hashStr = (h >>> 0).toString(36);
153
+ // Prefix with "mw-" (MeshWhisper) for readability, truncate to limit.
154
+ const serviceId = `mw-${hashStr}`;
155
+ return serviceId.slice(0, MAX_SERVICE_ID_LENGTH);
156
+ }
157
+ // ---- Transport Implementation ----
158
+ /**
159
+ * PlatformP2PTransport adapts a PlatformP2PBridge into the
160
+ * SDK's Transport interface.
161
+ *
162
+ * When a native bridge has been registered via
163
+ * `registerPlatformBridge()`, this transport serializes Packets
164
+ * to wire bytes, sends them through the bridge, and
165
+ * deserializes incoming bytes back into Packets for the mesh
166
+ * router.
167
+ *
168
+ * When no bridge is registered, the transport reports itself
169
+ * as unavailable and all operations are safe no-ops.
170
+ */
171
+ export class PlatformP2PTransport {
172
+ type = 'platform_p2p';
173
+ serviceId;
174
+ receiveCallback = null;
175
+ running = false;
176
+ /**
177
+ * @param namespace - Application namespace used to derive
178
+ * the P2P service identifier.
179
+ */
180
+ constructor(namespace) {
181
+ this.serviceId = generateServiceId(namespace);
182
+ }
183
+ /**
184
+ * Returns the bridge currently in use. Reads from the
185
+ * module-level registry so that bridges registered after
186
+ * construction are picked up automatically.
187
+ */
188
+ get bridge() {
189
+ return activeBridge;
190
+ }
191
+ // ---- Transport interface ----
192
+ async isAvailable() {
193
+ return this.bridge.isSupported();
194
+ }
195
+ async start() {
196
+ if (this.running)
197
+ return;
198
+ if (!this.bridge.isSupported()) {
199
+ // Silently skip — the transport negotiator will use
200
+ // the next bearer in priority order.
201
+ return;
202
+ }
203
+ // Wire up data reception.
204
+ this.bridge.onDataReceived((peerId, data) => {
205
+ if (!this.receiveCallback)
206
+ return;
207
+ try {
208
+ const packet = deserializePacket(data);
209
+ this.receiveCallback(packet, peerId);
210
+ }
211
+ catch {
212
+ // Malformed packet — drop silently. A production build
213
+ // may want to emit a diagnostic event here.
214
+ }
215
+ });
216
+ await this.bridge.startAdvertising(this.serviceId);
217
+ await this.bridge.startDiscovery(this.serviceId);
218
+ this.running = true;
219
+ }
220
+ async stop() {
221
+ if (!this.running)
222
+ return;
223
+ await this.bridge.stopAdvertising();
224
+ await this.bridge.stopDiscovery();
225
+ this.running = false;
226
+ }
227
+ async send(packet, destination) {
228
+ if (!this.running || !this.bridge.isSupported())
229
+ return;
230
+ const data = serializePacket(packet);
231
+ await this.bridge.sendData(destination, data);
232
+ }
233
+ onReceive(callback) {
234
+ this.receiveCallback = callback;
235
+ }
236
+ }
237
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/transport/p2p/index.ts"],"names":[],"mappings":"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"}