@adeeliore/p2p-core 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 (83) hide show
  1. package/API_REFERENCE.md +164 -0
  2. package/CHANGELOG.md +13 -0
  3. package/LICENSE +12 -0
  4. package/README.md +164 -0
  5. package/dist/errors.d.ts +16 -0
  6. package/dist/errors.d.ts.map +1 -0
  7. package/dist/errors.js +13 -0
  8. package/dist/index.d.ts +13 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +22 -0
  11. package/dist/rtc/PeerConnectionManager.d.ts +34 -0
  12. package/dist/rtc/PeerConnectionManager.d.ts.map +1 -0
  13. package/dist/rtc/PeerConnectionManager.js +231 -0
  14. package/dist/rtc/constants.d.ts +15 -0
  15. package/dist/rtc/constants.d.ts.map +1 -0
  16. package/dist/rtc/constants.js +65 -0
  17. package/dist/rtc/defaults.d.ts +13 -0
  18. package/dist/rtc/defaults.d.ts.map +1 -0
  19. package/dist/rtc/defaults.js +15 -0
  20. package/dist/rtc/index.d.ts +6 -0
  21. package/dist/rtc/index.d.ts.map +1 -0
  22. package/dist/rtc/index.js +21 -0
  23. package/dist/rtc/native.d.ts +11 -0
  24. package/dist/rtc/native.d.ts.map +1 -0
  25. package/dist/rtc/native.js +31 -0
  26. package/dist/rtc/options.d.ts +6 -0
  27. package/dist/rtc/options.d.ts.map +1 -0
  28. package/dist/rtc/options.js +22 -0
  29. package/dist/rtc/payloadParsers.d.ts +4 -0
  30. package/dist/rtc/payloadParsers.d.ts.map +1 -0
  31. package/dist/rtc/payloadParsers.js +33 -0
  32. package/dist/rtc/runtime.d.ts +22 -0
  33. package/dist/rtc/runtime.d.ts.map +1 -0
  34. package/dist/rtc/runtime.js +25 -0
  35. package/dist/rtc/types.d.ts +56 -0
  36. package/dist/rtc/types.d.ts.map +1 -0
  37. package/dist/rtc/types.js +2 -0
  38. package/dist/session/P2PSession.d.ts +10 -0
  39. package/dist/session/P2PSession.d.ts.map +1 -0
  40. package/dist/session/P2PSession.js +285 -0
  41. package/dist/session/constants.d.ts +4 -0
  42. package/dist/session/constants.d.ts.map +1 -0
  43. package/dist/session/constants.js +6 -0
  44. package/dist/session/index.d.ts +3 -0
  45. package/dist/session/index.d.ts.map +1 -0
  46. package/dist/session/index.js +18 -0
  47. package/dist/session/runtimeSupport.d.ts +36 -0
  48. package/dist/session/runtimeSupport.d.ts.map +1 -0
  49. package/dist/session/runtimeSupport.js +144 -0
  50. package/dist/session/serverMessageHandlers.d.ts +21 -0
  51. package/dist/session/serverMessageHandlers.d.ts.map +1 -0
  52. package/dist/session/serverMessageHandlers.js +30 -0
  53. package/dist/session/types.d.ts +195 -0
  54. package/dist/session/types.d.ts.map +1 -0
  55. package/dist/session/types.js +2 -0
  56. package/dist/signaling/SignalingClient.d.ts +39 -0
  57. package/dist/signaling/SignalingClient.d.ts.map +1 -0
  58. package/dist/signaling/SignalingClient.js +130 -0
  59. package/dist/signaling/constants.d.ts +14 -0
  60. package/dist/signaling/constants.d.ts.map +1 -0
  61. package/dist/signaling/constants.js +20 -0
  62. package/dist/signaling/index.d.ts +5 -0
  63. package/dist/signaling/index.d.ts.map +1 -0
  64. package/dist/signaling/index.js +20 -0
  65. package/dist/signaling/provider.d.ts +56 -0
  66. package/dist/signaling/provider.d.ts.map +1 -0
  67. package/dist/signaling/provider.js +87 -0
  68. package/dist/signaling/types.d.ts +62 -0
  69. package/dist/signaling/types.d.ts.map +1 -0
  70. package/dist/signaling/types.js +2 -0
  71. package/dist/sync/constants.d.ts +10 -0
  72. package/dist/sync/constants.d.ts.map +1 -0
  73. package/dist/sync/constants.js +12 -0
  74. package/dist/sync/engine.d.ts +13 -0
  75. package/dist/sync/engine.d.ts.map +1 -0
  76. package/dist/sync/engine.js +137 -0
  77. package/dist/sync/index.d.ts +4 -0
  78. package/dist/sync/index.d.ts.map +1 -0
  79. package/dist/sync/index.js +19 -0
  80. package/dist/sync/types.d.ts +61 -0
  81. package/dist/sync/types.d.ts.map +1 -0
  82. package/dist/sync/types.js +2 -0
  83. package/package.json +46 -0
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PeerConnectionManager = void 0;
4
+ const constants_1 = require("./constants");
5
+ const native_1 = require("./native");
6
+ const options_1 = require("./options");
7
+ const payloadParsers_1 = require("./payloadParsers");
8
+ class PeerConnectionManager {
9
+ constructor(options) {
10
+ var _a, _b;
11
+ this.peers = new Map();
12
+ this.signalEmitter = options.signalEmitter;
13
+ this.events = (_a = options.events) !== null && _a !== void 0 ? _a : {};
14
+ this.rtcConfig = (_b = options.rtcConfig) !== null && _b !== void 0 ? _b : constants_1.WEBRTC_DEFAULT_CONFIG;
15
+ this.heartbeatConfig = (0, options_1.normalizeHeartbeatConfig)(options.heartbeat);
16
+ this.reconnectConfig = (0, options_1.normalizeReconnectConfig)(options.reconnect);
17
+ }
18
+ async createOffer(peerId) {
19
+ const context = this.getOrCreatePeerContext(peerId);
20
+ context.isInitiator = true;
21
+ if (!context.dataChannel) {
22
+ this.attachDataChannel(peerId, context, context.peerConnection.createDataChannel(constants_1.DATA_CHANNEL_LABEL));
23
+ }
24
+ const offer = await context.peerConnection.createOffer();
25
+ await context.peerConnection.setLocalDescription(offer);
26
+ this.signalEmitter.emit(peerId, 'offer', {
27
+ type: offer.type,
28
+ sdp: offer.sdp,
29
+ });
30
+ }
31
+ async handleRemoteOffer(peerId, payload) {
32
+ const context = this.getOrCreatePeerContext(peerId);
33
+ context.isInitiator = false;
34
+ const offer = (0, payloadParsers_1.parseSessionDescriptionPayload)(payload, 'offer');
35
+ await context.peerConnection.setRemoteDescription((0, native_1.createSessionDescription)(offer));
36
+ const answer = await context.peerConnection.createAnswer();
37
+ await context.peerConnection.setLocalDescription(answer);
38
+ this.signalEmitter.emit(peerId, 'answer', {
39
+ type: answer.type,
40
+ sdp: answer.sdp,
41
+ });
42
+ }
43
+ async handleRemoteAnswer(peerId, payload) {
44
+ const context = this.getOrCreatePeerContext(peerId);
45
+ const answer = (0, payloadParsers_1.parseSessionDescriptionPayload)(payload, 'answer');
46
+ await context.peerConnection.setRemoteDescription((0, native_1.createSessionDescription)(answer));
47
+ }
48
+ async handleRemoteIce(peerId, payload) {
49
+ const context = this.getOrCreatePeerContext(peerId);
50
+ const candidate = (0, payloadParsers_1.parseIceCandidatePayload)(payload);
51
+ await context.peerConnection.addIceCandidate((0, native_1.createIceCandidate)(candidate));
52
+ }
53
+ sendData(peerId, message) {
54
+ const context = this.peers.get(peerId);
55
+ if (!context || !context.dataChannel) {
56
+ throw new Error(`DataChannel for peer ${peerId} is not ready`);
57
+ }
58
+ if (context.dataChannel.readyState !== 'open') {
59
+ throw new Error(`DataChannel for peer ${peerId} is not open`);
60
+ }
61
+ context.dataChannel.send(message);
62
+ }
63
+ closePeer(peerId) {
64
+ var _a;
65
+ const context = this.peers.get(peerId);
66
+ if (!context) {
67
+ return;
68
+ }
69
+ try {
70
+ this.stopReconnect(context);
71
+ this.stopHeartbeat(context);
72
+ (_a = context.dataChannel) === null || _a === void 0 ? void 0 : _a.close();
73
+ }
74
+ finally {
75
+ context.peerConnection.close();
76
+ this.peers.delete(peerId);
77
+ }
78
+ }
79
+ closeAll() {
80
+ const peerIds = [...this.peers.keys()];
81
+ peerIds.forEach((peerId) => this.closePeer(peerId));
82
+ }
83
+ getOrCreatePeerContext(peerId) {
84
+ const existing = this.peers.get(peerId);
85
+ if (existing) {
86
+ return existing;
87
+ }
88
+ const peerConnection = (0, native_1.createPeerConnection)(this.rtcConfig);
89
+ const context = {
90
+ peerConnection,
91
+ dataChannel: null,
92
+ heartbeatTimer: null,
93
+ lastSeenAt: Date.now(),
94
+ isInitiator: false,
95
+ reconnectAttempts: 0,
96
+ reconnectTimer: null,
97
+ };
98
+ const peerEventBindings = peerConnection;
99
+ peerEventBindings.onicecandidate = (event) => {
100
+ const candidate = event.candidate;
101
+ if (!candidate) {
102
+ return;
103
+ }
104
+ this.signalEmitter.emit(peerId, 'ice', {
105
+ candidate: candidate.candidate,
106
+ sdpMid: candidate.sdpMid,
107
+ sdpMLineIndex: candidate.sdpMLineIndex,
108
+ });
109
+ };
110
+ peerEventBindings.oniceconnectionstatechange = () => {
111
+ var _a, _b;
112
+ const state = peerConnection.iceConnectionState;
113
+ (_b = (_a = this.events).onIceConnectionStateChange) === null || _b === void 0 ? void 0 : _b.call(_a, peerId, state);
114
+ this.handleIceStateChange(peerId, context, state);
115
+ };
116
+ peerEventBindings.ondatachannel = (event) => {
117
+ const channel = event.channel;
118
+ if (channel) {
119
+ this.attachDataChannel(peerId, context, channel);
120
+ }
121
+ };
122
+ this.peers.set(peerId, context);
123
+ return context;
124
+ }
125
+ attachDataChannel(peerId, context, channel) {
126
+ context.dataChannel = channel;
127
+ const dataChannelBindings = channel;
128
+ dataChannelBindings.onopen = () => {
129
+ var _a, _b;
130
+ context.lastSeenAt = Date.now();
131
+ this.startHeartbeat(peerId, context);
132
+ (_b = (_a = this.events).onDataChannelOpen) === null || _b === void 0 ? void 0 : _b.call(_a, peerId);
133
+ };
134
+ dataChannelBindings.onclose = () => {
135
+ var _a, _b;
136
+ this.stopHeartbeat(context);
137
+ (_b = (_a = this.events).onDataChannelClosed) === null || _b === void 0 ? void 0 : _b.call(_a, peerId);
138
+ };
139
+ dataChannelBindings.onmessage = (event) => {
140
+ var _a, _b;
141
+ const data = event.data;
142
+ if (typeof data === 'string') {
143
+ if (this.handleHeartbeatMessage(context, data)) {
144
+ return;
145
+ }
146
+ (_b = (_a = this.events).onDataChannelMessage) === null || _b === void 0 ? void 0 : _b.call(_a, peerId, data);
147
+ }
148
+ };
149
+ }
150
+ startHeartbeat(peerId, context) {
151
+ if (context.heartbeatTimer) {
152
+ return;
153
+ }
154
+ context.heartbeatTimer = setInterval(() => {
155
+ if (!context.dataChannel || context.dataChannel.readyState !== 'open') {
156
+ return;
157
+ }
158
+ const now = Date.now();
159
+ if (now - context.lastSeenAt > this.heartbeatConfig.timeoutMs) {
160
+ this.closePeer(peerId);
161
+ return;
162
+ }
163
+ context.dataChannel.send(this.heartbeatConfig.pingMessage);
164
+ }, this.heartbeatConfig.intervalMs);
165
+ }
166
+ stopHeartbeat(context) {
167
+ if (context.heartbeatTimer) {
168
+ clearInterval(context.heartbeatTimer);
169
+ context.heartbeatTimer = null;
170
+ }
171
+ }
172
+ handleIceStateChange(peerId, context, state) {
173
+ if (!this.reconnectConfig.enabled) {
174
+ return;
175
+ }
176
+ if (state === 'connected' || state === 'completed') {
177
+ context.reconnectAttempts = 0;
178
+ this.stopReconnect(context);
179
+ return;
180
+ }
181
+ if (state === 'failed' || state === 'disconnected') {
182
+ this.scheduleReconnect(peerId, context);
183
+ }
184
+ }
185
+ scheduleReconnect(peerId, context) {
186
+ if (context.reconnectTimer) {
187
+ return;
188
+ }
189
+ if (context.reconnectAttempts >= this.reconnectConfig.maxAttempts) {
190
+ return;
191
+ }
192
+ const delay = this.reconnectConfig.baseDelayMs * (context.reconnectAttempts + 1);
193
+ context.reconnectAttempts += 1;
194
+ context.reconnectTimer = setTimeout(() => {
195
+ context.reconnectTimer = null;
196
+ if (!context.isInitiator) {
197
+ return;
198
+ }
199
+ try {
200
+ context.peerConnection.restartIce();
201
+ }
202
+ catch {
203
+ // ignore restartIce errors
204
+ }
205
+ void this.createOffer(peerId).catch(() => {
206
+ // fail silently; next ice state change will retry
207
+ });
208
+ }, delay);
209
+ }
210
+ stopReconnect(context) {
211
+ if (context.reconnectTimer) {
212
+ clearTimeout(context.reconnectTimer);
213
+ context.reconnectTimer = null;
214
+ }
215
+ }
216
+ handleHeartbeatMessage(context, message) {
217
+ if (message === this.heartbeatConfig.pingMessage) {
218
+ context.lastSeenAt = Date.now();
219
+ if (context.dataChannel && context.dataChannel.readyState === 'open') {
220
+ context.dataChannel.send(this.heartbeatConfig.pongMessage);
221
+ }
222
+ return true;
223
+ }
224
+ if (message === this.heartbeatConfig.pongMessage) {
225
+ context.lastSeenAt = Date.now();
226
+ return true;
227
+ }
228
+ return false;
229
+ }
230
+ }
231
+ exports.PeerConnectionManager = PeerConnectionManager;
@@ -0,0 +1,15 @@
1
+ import { WebRtcConfiguration } from './types';
2
+ import { DATA_CHANNEL_LABEL, HEARTBEAT_DEFAULTS, RECONNECT_DEFAULTS } from './defaults';
3
+ export declare const WEBRTC_DEFAULT_CONFIG: WebRtcConfiguration;
4
+ export declare const WEBRTC_CONFIG_DIAGNOSTICS: {
5
+ platform: "ios" | "android" | "windows" | "macos" | "web";
6
+ iceTransportPolicy: "all" | "relay";
7
+ sharedTurnConfigured: boolean;
8
+ sharedTurnRelayOnly: boolean;
9
+ localEmulatorTurnEnabled: boolean;
10
+ localEmulatorTurnActive: boolean;
11
+ localEmulatorTurnHost: string;
12
+ localEmulatorTurnRelayOnly: boolean;
13
+ };
14
+ export { DATA_CHANNEL_LABEL, HEARTBEAT_DEFAULTS, RECONNECT_DEFAULTS, };
15
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/rtc/constants.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EACH,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EACrB,MAAM,YAAY,CAAC;AAuDpB,eAAO,MAAM,qBAAqB,EAAE,mBAGnC,CAAC;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;;CASrC,CAAC;AACF,OAAO,EACH,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACrB,CAAC"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var _a, _b, _c, _d, _e;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.RECONNECT_DEFAULTS = exports.HEARTBEAT_DEFAULTS = exports.DATA_CHANNEL_LABEL = exports.WEBRTC_CONFIG_DIAGNOSTICS = exports.WEBRTC_DEFAULT_CONFIG = void 0;
5
+ const react_native_1 = require("react-native");
6
+ const defaults_1 = require("./defaults");
7
+ Object.defineProperty(exports, "DATA_CHANNEL_LABEL", { enumerable: true, get: function () { return defaults_1.DATA_CHANNEL_LABEL; } });
8
+ Object.defineProperty(exports, "HEARTBEAT_DEFAULTS", { enumerable: true, get: function () { return defaults_1.HEARTBEAT_DEFAULTS; } });
9
+ Object.defineProperty(exports, "RECONNECT_DEFAULTS", { enumerable: true, get: function () { return defaults_1.RECONNECT_DEFAULTS; } });
10
+ const STUN_SERVERS = [{ urls: 'stun:stun.l.google.com:19302' }];
11
+ const LOCAL_EMULATOR_TURN_ENABLED = process.env.EXPO_PUBLIC_LOCAL_EMULATOR_TURN_ENABLED === 'true';
12
+ const LOCAL_EMULATOR_TURN_USERNAME = ((_a = process.env.EXPO_PUBLIC_LOCAL_EMULATOR_TURN_USERNAME) === null || _a === void 0 ? void 0 : _a.trim()) || 'testuser';
13
+ const LOCAL_EMULATOR_TURN_CREDENTIAL = ((_b = process.env.EXPO_PUBLIC_LOCAL_EMULATOR_TURN_CREDENTIAL) === null || _b === void 0 ? void 0 : _b.trim()) || 'testpass';
14
+ const LOCAL_EMULATOR_TURN_PORT = Number(process.env.EXPO_PUBLIC_LOCAL_EMULATOR_TURN_PORT || '3478');
15
+ const LOCAL_EMULATOR_TURN_HOST = ((_c = process.env.EXPO_PUBLIC_LOCAL_EMULATOR_TURN_HOST) === null || _c === void 0 ? void 0 : _c.trim()) || '10.0.2.2';
16
+ const LOCAL_EMULATOR_RELAY_ONLY = process.env.EXPO_PUBLIC_LOCAL_EMULATOR_RELAY_ONLY === 'true';
17
+ function parseTurnUrls(value) {
18
+ return (value || '')
19
+ .split(',')
20
+ .map((item) => item.trim())
21
+ .filter(Boolean);
22
+ }
23
+ const SHARED_TURN_URLS = parseTurnUrls(process.env.EXPO_PUBLIC_SHARED_TURN_URLS);
24
+ const SHARED_TURN_USERNAME = ((_d = process.env.EXPO_PUBLIC_SHARED_TURN_USERNAME) === null || _d === void 0 ? void 0 : _d.trim()) || '';
25
+ const SHARED_TURN_CREDENTIAL = ((_e = process.env.EXPO_PUBLIC_SHARED_TURN_CREDENTIAL) === null || _e === void 0 ? void 0 : _e.trim()) || '';
26
+ const SHARED_TURN_RELAY_ONLY = process.env.EXPO_PUBLIC_SHARED_TURN_RELAY_ONLY === 'true';
27
+ const LOCAL_EMULATOR_TURN_ACTIVE = LOCAL_EMULATOR_TURN_ENABLED && react_native_1.Platform.OS === 'android';
28
+ function buildSharedTurnServers() {
29
+ if (SHARED_TURN_URLS.length === 0 || !SHARED_TURN_USERNAME || !SHARED_TURN_CREDENTIAL) {
30
+ return [];
31
+ }
32
+ return [
33
+ {
34
+ urls: SHARED_TURN_URLS.length === 1 ? SHARED_TURN_URLS[0] : SHARED_TURN_URLS,
35
+ username: SHARED_TURN_USERNAME,
36
+ credential: SHARED_TURN_CREDENTIAL,
37
+ },
38
+ ];
39
+ }
40
+ function buildIceServers() {
41
+ const iceServers = [...STUN_SERVERS, ...buildSharedTurnServers()];
42
+ if (LOCAL_EMULATOR_TURN_ACTIVE) {
43
+ iceServers.push({
44
+ urls: `turn:${LOCAL_EMULATOR_TURN_HOST}:${LOCAL_EMULATOR_TURN_PORT}?transport=tcp`,
45
+ username: LOCAL_EMULATOR_TURN_USERNAME,
46
+ credential: LOCAL_EMULATOR_TURN_CREDENTIAL,
47
+ });
48
+ }
49
+ return iceServers;
50
+ }
51
+ const ICE_TRANSPORT_POLICY = (SHARED_TURN_RELAY_ONLY || (LOCAL_EMULATOR_RELAY_ONLY && LOCAL_EMULATOR_TURN_ACTIVE)) ? 'relay' : 'all';
52
+ exports.WEBRTC_DEFAULT_CONFIG = {
53
+ iceServers: buildIceServers(),
54
+ iceTransportPolicy: ICE_TRANSPORT_POLICY,
55
+ };
56
+ exports.WEBRTC_CONFIG_DIAGNOSTICS = {
57
+ platform: react_native_1.Platform.OS,
58
+ iceTransportPolicy: ICE_TRANSPORT_POLICY,
59
+ sharedTurnConfigured: SHARED_TURN_URLS.length > 0 && Boolean(SHARED_TURN_USERNAME && SHARED_TURN_CREDENTIAL),
60
+ sharedTurnRelayOnly: SHARED_TURN_RELAY_ONLY,
61
+ localEmulatorTurnEnabled: LOCAL_EMULATOR_TURN_ENABLED,
62
+ localEmulatorTurnActive: LOCAL_EMULATOR_TURN_ACTIVE,
63
+ localEmulatorTurnHost: LOCAL_EMULATOR_TURN_HOST,
64
+ localEmulatorTurnRelayOnly: LOCAL_EMULATOR_RELAY_ONLY,
65
+ };
@@ -0,0 +1,13 @@
1
+ export declare const DATA_CHANNEL_LABEL = "p2p-core-data";
2
+ export declare const HEARTBEAT_DEFAULTS: {
3
+ readonly intervalMs: 15000;
4
+ readonly timeoutMs: 45000;
5
+ readonly pingMessage: "__ping__";
6
+ readonly pongMessage: "__pong__";
7
+ };
8
+ export declare const RECONNECT_DEFAULTS: {
9
+ readonly enabled: true;
10
+ readonly maxAttempts: 5;
11
+ readonly baseDelayMs: 1500;
12
+ };
13
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/rtc/defaults.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAElD,eAAO,MAAM,kBAAkB;;;;;CAKrB,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;CAIrB,CAAC"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RECONNECT_DEFAULTS = exports.HEARTBEAT_DEFAULTS = exports.DATA_CHANNEL_LABEL = void 0;
4
+ exports.DATA_CHANNEL_LABEL = 'p2p-core-data';
5
+ exports.HEARTBEAT_DEFAULTS = {
6
+ intervalMs: 15000,
7
+ timeoutMs: 45000,
8
+ pingMessage: '__ping__',
9
+ pongMessage: '__pong__',
10
+ };
11
+ exports.RECONNECT_DEFAULTS = {
12
+ enabled: true,
13
+ maxAttempts: 5,
14
+ baseDelayMs: 1500,
15
+ };
@@ -0,0 +1,6 @@
1
+ export * from './constants';
2
+ export * from './options';
3
+ export * from './PeerConnectionManager';
4
+ export * from './runtime';
5
+ export * from './types';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rtc/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,yBAAyB,CAAC;AACxC,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./constants"), exports);
18
+ __exportStar(require("./options"), exports);
19
+ __exportStar(require("./PeerConnectionManager"), exports);
20
+ __exportStar(require("./runtime"), exports);
21
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,11 @@
1
+ import { RTCIceCandidate, RTCPeerConnection, RTCSessionDescription } from 'react-native-webrtc';
2
+ import { RtcIceCandidateInit } from './types';
3
+ export declare function initializeWebRtcRuntime(): void;
4
+ export declare function createPeerConnection(configuration: object): RTCPeerConnection;
5
+ export declare function createSessionDescription(init: {
6
+ sdp: string;
7
+ type: string | null;
8
+ }): RTCSessionDescription;
9
+ export declare function createIceCandidate(init: RtcIceCandidateInit): RTCIceCandidate;
10
+ export declare function isWebRtcNativeAvailable(): boolean;
11
+ //# sourceMappingURL=native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../src/rtc/native.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EAExB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAI9C,wBAAgB,uBAAuB,IAAI,IAAI,CAO9C;AAED,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,iBAAiB,CAG7E;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,qBAAqB,CAE1G;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,GAAG,eAAe,CAE7E;AAED,wBAAgB,uBAAuB,IAAI,OAAO,CAMjD"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initializeWebRtcRuntime = initializeWebRtcRuntime;
4
+ exports.createPeerConnection = createPeerConnection;
5
+ exports.createSessionDescription = createSessionDescription;
6
+ exports.createIceCandidate = createIceCandidate;
7
+ exports.isWebRtcNativeAvailable = isWebRtcNativeAvailable;
8
+ const react_native_webrtc_1 = require("react-native-webrtc");
9
+ let initialized = false;
10
+ function initializeWebRtcRuntime() {
11
+ if (initialized) {
12
+ return;
13
+ }
14
+ (0, react_native_webrtc_1.registerGlobals)();
15
+ initialized = true;
16
+ }
17
+ function createPeerConnection(configuration) {
18
+ initializeWebRtcRuntime();
19
+ return new react_native_webrtc_1.RTCPeerConnection(configuration);
20
+ }
21
+ function createSessionDescription(init) {
22
+ return new react_native_webrtc_1.RTCSessionDescription(init);
23
+ }
24
+ function createIceCandidate(init) {
25
+ return new react_native_webrtc_1.RTCIceCandidate(init);
26
+ }
27
+ function isWebRtcNativeAvailable() {
28
+ return (typeof react_native_webrtc_1.RTCPeerConnection === 'function' &&
29
+ typeof react_native_webrtc_1.RTCSessionDescription === 'function' &&
30
+ typeof react_native_webrtc_1.RTCIceCandidate === 'function');
31
+ }
@@ -0,0 +1,6 @@
1
+ import { WebRtcHeartbeatConfig, WebRtcReconnectConfig } from './types';
2
+ export type NormalizedWebRtcHeartbeatConfig = Required<WebRtcHeartbeatConfig>;
3
+ export type NormalizedWebRtcReconnectConfig = Required<WebRtcReconnectConfig>;
4
+ export declare function normalizeHeartbeatConfig(heartbeat?: WebRtcHeartbeatConfig): NormalizedWebRtcHeartbeatConfig;
5
+ export declare function normalizeReconnectConfig(reconnect?: WebRtcReconnectConfig): NormalizedWebRtcReconnectConfig;
6
+ //# sourceMappingURL=options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/rtc/options.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,qBAAqB,EACrB,qBAAqB,EACxB,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,+BAA+B,GAAG,QAAQ,CAAC,qBAAqB,CAAC,CAAC;AAC9E,MAAM,MAAM,+BAA+B,GAAG,QAAQ,CAAC,qBAAqB,CAAC,CAAC;AAE9E,wBAAgB,wBAAwB,CACpC,SAAS,CAAC,EAAE,qBAAqB,GAClC,+BAA+B,CAOjC;AAED,wBAAgB,wBAAwB,CACpC,SAAS,CAAC,EAAE,qBAAqB,GAClC,+BAA+B,CAMjC"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeHeartbeatConfig = normalizeHeartbeatConfig;
4
+ exports.normalizeReconnectConfig = normalizeReconnectConfig;
5
+ const defaults_1 = require("./defaults");
6
+ function normalizeHeartbeatConfig(heartbeat) {
7
+ var _a, _b, _c, _d;
8
+ return {
9
+ intervalMs: (_a = heartbeat === null || heartbeat === void 0 ? void 0 : heartbeat.intervalMs) !== null && _a !== void 0 ? _a : defaults_1.HEARTBEAT_DEFAULTS.intervalMs,
10
+ timeoutMs: (_b = heartbeat === null || heartbeat === void 0 ? void 0 : heartbeat.timeoutMs) !== null && _b !== void 0 ? _b : defaults_1.HEARTBEAT_DEFAULTS.timeoutMs,
11
+ pingMessage: (_c = heartbeat === null || heartbeat === void 0 ? void 0 : heartbeat.pingMessage) !== null && _c !== void 0 ? _c : defaults_1.HEARTBEAT_DEFAULTS.pingMessage,
12
+ pongMessage: (_d = heartbeat === null || heartbeat === void 0 ? void 0 : heartbeat.pongMessage) !== null && _d !== void 0 ? _d : defaults_1.HEARTBEAT_DEFAULTS.pongMessage,
13
+ };
14
+ }
15
+ function normalizeReconnectConfig(reconnect) {
16
+ var _a, _b, _c;
17
+ return {
18
+ enabled: (_a = reconnect === null || reconnect === void 0 ? void 0 : reconnect.enabled) !== null && _a !== void 0 ? _a : defaults_1.RECONNECT_DEFAULTS.enabled,
19
+ maxAttempts: (_b = reconnect === null || reconnect === void 0 ? void 0 : reconnect.maxAttempts) !== null && _b !== void 0 ? _b : defaults_1.RECONNECT_DEFAULTS.maxAttempts,
20
+ baseDelayMs: (_c = reconnect === null || reconnect === void 0 ? void 0 : reconnect.baseDelayMs) !== null && _c !== void 0 ? _c : defaults_1.RECONNECT_DEFAULTS.baseDelayMs,
21
+ };
22
+ }
@@ -0,0 +1,4 @@
1
+ import { RtcIceCandidateInit, SessionDescriptionPayload } from './types';
2
+ export declare function parseSessionDescriptionPayload(payload: unknown, expectedType: 'offer' | 'answer'): SessionDescriptionPayload;
3
+ export declare function parseIceCandidatePayload(payload: unknown): RtcIceCandidateInit;
4
+ //# sourceMappingURL=payloadParsers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payloadParsers.d.ts","sourceRoot":"","sources":["../../src/rtc/payloadParsers.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,mBAAmB,EACnB,yBAAyB,EAC5B,MAAM,SAAS,CAAC;AAEjB,wBAAgB,8BAA8B,CAC1C,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,OAAO,GAAG,QAAQ,GACjC,yBAAyB,CAc3B;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,mBAAmB,CAgB9E"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseSessionDescriptionPayload = parseSessionDescriptionPayload;
4
+ exports.parseIceCandidatePayload = parseIceCandidatePayload;
5
+ function parseSessionDescriptionPayload(payload, expectedType) {
6
+ if (!payload || typeof payload !== 'object') {
7
+ throw new Error(`Invalid ${expectedType} payload: object expected`);
8
+ }
9
+ const candidate = payload;
10
+ if (candidate.type !== expectedType || typeof candidate.sdp !== 'string') {
11
+ throw new Error(`Invalid ${expectedType} payload: type/sdp mismatch`);
12
+ }
13
+ return {
14
+ type: candidate.type,
15
+ sdp: candidate.sdp,
16
+ };
17
+ }
18
+ function parseIceCandidatePayload(payload) {
19
+ var _a, _b, _c;
20
+ if (!payload || typeof payload !== 'object') {
21
+ throw new Error('Invalid ICE payload: object expected');
22
+ }
23
+ const candidate = payload;
24
+ if (typeof candidate.candidate !== 'string') {
25
+ throw new Error('Invalid ICE payload: candidate is required');
26
+ }
27
+ return {
28
+ candidate: candidate.candidate,
29
+ sdpMid: (_a = candidate.sdpMid) !== null && _a !== void 0 ? _a : undefined,
30
+ sdpMLineIndex: (_b = candidate.sdpMLineIndex) !== null && _b !== void 0 ? _b : undefined,
31
+ usernameFragment: (_c = candidate.usernameFragment) !== null && _c !== void 0 ? _c : undefined,
32
+ };
33
+ }
@@ -0,0 +1,22 @@
1
+ import { PeerConnectionManager } from './PeerConnectionManager';
2
+ import { WebRtcConfiguration, WebRtcEvents, WebRtcHeartbeatConfig, WebRtcReconnectConfig, WebRtcSignalEmitter } from './types';
3
+ interface CreateWebRtcManagerOptions {
4
+ signalEmitter: WebRtcSignalEmitter;
5
+ events?: WebRtcEvents;
6
+ rtcConfig?: WebRtcConfiguration;
7
+ heartbeat?: WebRtcHeartbeatConfig;
8
+ reconnect?: WebRtcReconnectConfig;
9
+ }
10
+ /**
11
+ * Creates a low-level WebRTC peer manager.
12
+ *
13
+ * This is intended for advanced consumers building their own session runtime.
14
+ * Most apps should use `createP2PSession()` instead.
15
+ */
16
+ export declare function createWebRtcPeerManager(options: CreateWebRtcManagerOptions): PeerConnectionManager;
17
+ /**
18
+ * Returns whether the native `react-native-webrtc` runtime is available.
19
+ */
20
+ export declare function isWebRtcRuntimeAvailable(): boolean;
21
+ export {};
22
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/rtc/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EACH,mBAAmB,EACnB,YAAY,EACZ,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACtB,MAAM,SAAS,CAAC;AAEjB,UAAU,0BAA0B;IAChC,aAAa,EAAE,mBAAmB,CAAC;IACnC,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,SAAS,CAAC,EAAE,qBAAqB,CAAC;CACrC;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,0BAA0B,GAAG,qBAAqB,CASlG;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAElD"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createWebRtcPeerManager = createWebRtcPeerManager;
4
+ exports.isWebRtcRuntimeAvailable = isWebRtcRuntimeAvailable;
5
+ const PeerConnectionManager_1 = require("./PeerConnectionManager");
6
+ const native_1 = require("./native");
7
+ /**
8
+ * Creates a low-level WebRTC peer manager.
9
+ *
10
+ * This is intended for advanced consumers building their own session runtime.
11
+ * Most apps should use `createP2PSession()` instead.
12
+ */
13
+ function createWebRtcPeerManager(options) {
14
+ if (!(0, native_1.isWebRtcNativeAvailable)()) {
15
+ throw new Error('WebRTC runtime is not available. Check react-native-webrtc installation and native build setup.');
16
+ }
17
+ (0, native_1.initializeWebRtcRuntime)();
18
+ return new PeerConnectionManager_1.PeerConnectionManager(options);
19
+ }
20
+ /**
21
+ * Returns whether the native `react-native-webrtc` runtime is available.
22
+ */
23
+ function isWebRtcRuntimeAvailable() {
24
+ return (0, native_1.isWebRtcNativeAvailable)();
25
+ }
@@ -0,0 +1,56 @@
1
+ export type WebRtcSignalType = 'offer' | 'answer' | 'ice';
2
+ export type IceConnectionState = 'new' | 'checking' | 'connected' | 'completed' | 'failed' | 'disconnected' | 'closed';
3
+ export interface WebRtcConfiguration {
4
+ iceServers?: Array<{
5
+ urls?: string | string[];
6
+ username?: string;
7
+ credential?: string;
8
+ }>;
9
+ iceTransportPolicy?: 'all' | 'relay';
10
+ }
11
+ export interface SessionDescriptionPayload {
12
+ type: 'offer' | 'answer';
13
+ sdp: string;
14
+ }
15
+ export interface IceCandidatePayload {
16
+ candidate: string;
17
+ sdpMid?: string | null;
18
+ sdpMLineIndex?: number | null;
19
+ usernameFragment?: string | null;
20
+ }
21
+ export interface RtcIceCandidateInit {
22
+ candidate: string;
23
+ sdpMid?: string | null;
24
+ sdpMLineIndex?: number | null;
25
+ usernameFragment?: string | null;
26
+ }
27
+ export interface WebRtcSignalEmitter {
28
+ emit: (targetPeerId: string, type: WebRtcSignalType, payload: unknown) => void;
29
+ }
30
+ export interface WebRtcEvents {
31
+ onDataChannelOpen?: (peerId: string) => void;
32
+ onDataChannelClosed?: (peerId: string) => void;
33
+ onDataChannelMessage?: (peerId: string, message: string) => void;
34
+ onIceConnectionStateChange?: (peerId: string, state: IceConnectionState) => void;
35
+ }
36
+ export interface WebRtcPeerManager {
37
+ createOffer: (peerId: string) => Promise<void>;
38
+ handleRemoteOffer: (peerId: string, payload: unknown) => Promise<void>;
39
+ handleRemoteAnswer: (peerId: string, payload: unknown) => Promise<void>;
40
+ handleRemoteIce: (peerId: string, payload: unknown) => Promise<void>;
41
+ sendData: (peerId: string, message: string) => void;
42
+ closePeer: (peerId: string) => void;
43
+ closeAll: () => void;
44
+ }
45
+ export interface WebRtcHeartbeatConfig {
46
+ intervalMs?: number;
47
+ timeoutMs?: number;
48
+ pingMessage?: string;
49
+ pongMessage?: string;
50
+ }
51
+ export interface WebRtcReconnectConfig {
52
+ enabled?: boolean;
53
+ maxAttempts?: number;
54
+ baseDelayMs?: number;
55
+ }
56
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/rtc/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,10 @@
1
+ import { P2PSession, P2PSessionOptions } from './types';
2
+ /**
3
+ * Creates a high-level reusable P2P session runtime.
4
+ *
5
+ * The returned session owns signaling, WebRTC orchestration and peer lifecycle,
6
+ * while the consuming app stays responsible for message encoding, decoding and
7
+ * domain-specific synchronization.
8
+ */
9
+ export declare function createP2PSession(options: P2PSessionOptions): P2PSession;
10
+ //# sourceMappingURL=P2PSession.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"P2PSession.d.ts","sourceRoot":"","sources":["../../src/session/P2PSession.ts"],"names":[],"mappings":"AAKA,OAAO,EACH,UAAU,EAEV,iBAAiB,EAGpB,MAAM,SAAS,CAAC;AAkWjB;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAEvE"}