@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,285 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createP2PSession = createP2PSession;
4
+ const constants_1 = require("./constants");
5
+ const runtimeSupport_1 = require("./runtimeSupport");
6
+ const serverMessageHandlers_1 = require("./serverMessageHandlers");
7
+ const errors_1 = require("../errors");
8
+ class P2PSessionRuntime {
9
+ constructor(options) {
10
+ this.listeners = new Map();
11
+ this.signalingProvider = null;
12
+ this.peerManager = null;
13
+ this.localPeerId = null;
14
+ this.peerIds = [];
15
+ this.status = 'idle';
16
+ this.hasOpened = false;
17
+ this.initialPeerIds = new Set();
18
+ this.scheduledOfferTimers = new Set();
19
+ this.options = (0, runtimeSupport_1.normalizeSessionOptions)(options);
20
+ }
21
+ connect() {
22
+ if (this.signalingProvider) {
23
+ return;
24
+ }
25
+ const provider = (0, runtimeSupport_1.createSessionSignalingProvider)(this.options);
26
+ const providerToken = provider;
27
+ const providerHandlers = (0, runtimeSupport_1.createSessionProviderHandlers)(providerToken, () => this.signalingProvider, {
28
+ onSignalOpen: () => {
29
+ this.hasOpened = true;
30
+ this.status = 'connected';
31
+ this.emit('signalingOpen', undefined);
32
+ },
33
+ onSignalClose: (event) => {
34
+ const hadOpened = this.hasOpened;
35
+ this.clearRuntime();
36
+ this.emit('signalingClose', {
37
+ code: event.code,
38
+ reason: event.reason,
39
+ manual: false,
40
+ hadOpened,
41
+ });
42
+ },
43
+ onSignalError: (message) => {
44
+ this.status = 'error';
45
+ this.emit('signalingError', {
46
+ code: errors_1.P2P_CORE_ERROR_CODE.SIGNALING_PROVIDER_ERROR,
47
+ message,
48
+ });
49
+ },
50
+ onProtocolError: (reason, rawMessage) => {
51
+ this.emit('protocolError', {
52
+ code: errors_1.P2P_CORE_ERROR_CODE.PROTOCOL_INVALID_MESSAGE,
53
+ reason,
54
+ rawMessage,
55
+ });
56
+ },
57
+ onServerMessage: (message) => {
58
+ this.handleServerMessage(message);
59
+ },
60
+ });
61
+ try {
62
+ this.peerManager = (0, runtimeSupport_1.createPeerManager)(this.options, provider, this.emit.bind(this), this.resolvePeerJoinKind.bind(this));
63
+ }
64
+ catch (error) {
65
+ this.status = 'error';
66
+ this.emit('signalingError', (0, runtimeSupport_1.toErrorPayload)(errors_1.P2P_CORE_ERROR_CODE.PEER_MANAGER_UNAVAILABLE, error));
67
+ this.peerManager = null;
68
+ return;
69
+ }
70
+ this.signalingProvider = provider;
71
+ this.status = 'connecting';
72
+ const connectResult = provider.connect({
73
+ sessionId: this.options.sessionId,
74
+ clientId: this.options.clientId,
75
+ accessToken: this.options.accessToken,
76
+ }, providerHandlers);
77
+ if ((0, runtimeSupport_1.isPromiseLike)(connectResult)) {
78
+ void connectResult.catch((error) => {
79
+ if (this.signalingProvider !== providerToken) {
80
+ return;
81
+ }
82
+ this.status = 'error';
83
+ this.emit('signalingError', (0, runtimeSupport_1.toErrorPayload)(errors_1.P2P_CORE_ERROR_CODE.SIGNALING_CONNECT_FAILED, error));
84
+ });
85
+ }
86
+ }
87
+ disconnect(code = constants_1.SESSION_MANUAL_DISCONNECT_CODE, reason = constants_1.SESSION_MANUAL_DISCONNECT_REASON) {
88
+ const hadOpened = this.hasOpened;
89
+ const provider = this.signalingProvider;
90
+ this.clearRuntime();
91
+ provider === null || provider === void 0 ? void 0 : provider.disconnect(code, reason);
92
+ this.emit('signalingClose', {
93
+ code,
94
+ reason,
95
+ manual: true,
96
+ hadOpened,
97
+ });
98
+ }
99
+ isConnected() {
100
+ var _a;
101
+ return this.status === 'connected' && ((_a = this.signalingProvider) === null || _a === void 0 ? void 0 : _a.isConnected()) === true;
102
+ }
103
+ getState() {
104
+ return (0, runtimeSupport_1.createSessionState)(this.options.sessionId, this.localPeerId, this.peerIds, this.status);
105
+ }
106
+ getLocalPeerId() {
107
+ return this.localPeerId;
108
+ }
109
+ getPeerIds() {
110
+ return [...this.peerIds];
111
+ }
112
+ sendPing() {
113
+ if (!this.signalingProvider) {
114
+ this.emit('signalingError', {
115
+ code: errors_1.P2P_CORE_ERROR_CODE.SIGNALING_NOT_CONNECTED,
116
+ message: 'Signaling provider is not connected',
117
+ });
118
+ return false;
119
+ }
120
+ try {
121
+ this.signalingProvider.sendPing();
122
+ return true;
123
+ }
124
+ catch (error) {
125
+ this.emit('signalingError', (0, runtimeSupport_1.toErrorPayload)(errors_1.P2P_CORE_ERROR_CODE.SIGNALING_NOT_CONNECTED, error));
126
+ return false;
127
+ }
128
+ }
129
+ sendTo(peerId, message) {
130
+ if (!this.peerManager) {
131
+ this.emit('transportError', {
132
+ peerId,
133
+ code: errors_1.P2P_CORE_ERROR_CODE.PEER_MANAGER_UNAVAILABLE,
134
+ message: 'WebRTC manager not ready',
135
+ });
136
+ return false;
137
+ }
138
+ try {
139
+ this.peerManager.sendData(peerId, message);
140
+ return true;
141
+ }
142
+ catch (error) {
143
+ this.emit('transportError', {
144
+ peerId,
145
+ ...(0, runtimeSupport_1.toErrorPayload)(errors_1.P2P_CORE_ERROR_CODE.TRANSPORT_SEND_FAILED, error),
146
+ });
147
+ return false;
148
+ }
149
+ }
150
+ broadcast(message, peerIds = this.peerIds) {
151
+ let sentCount = 0;
152
+ peerIds.forEach((peerId) => {
153
+ if (this.sendTo(peerId, message)) {
154
+ sentCount += 1;
155
+ }
156
+ });
157
+ return sentCount;
158
+ }
159
+ async createOffer(peerId) {
160
+ if (!this.peerManager) {
161
+ throw (0, runtimeSupport_1.createError)(errors_1.P2P_CORE_ERROR_CODE.PEER_MANAGER_UNAVAILABLE, 'WebRTC manager not ready');
162
+ }
163
+ await this.peerManager.createOffer(peerId);
164
+ }
165
+ on(eventName, listener) {
166
+ var _a;
167
+ const listeners = (_a = this.listeners.get(eventName)) !== null && _a !== void 0 ? _a : new Set();
168
+ listeners.add(listener);
169
+ this.listeners.set(eventName, listeners);
170
+ return () => {
171
+ listeners.delete(listener);
172
+ if (listeners.size === 0) {
173
+ this.listeners.delete(eventName);
174
+ }
175
+ };
176
+ }
177
+ emit(eventName, payload) {
178
+ const listeners = this.listeners.get(eventName);
179
+ listeners === null || listeners === void 0 ? void 0 : listeners.forEach((listener) => {
180
+ listener(payload);
181
+ });
182
+ }
183
+ handleServerMessage(message) {
184
+ (0, serverMessageHandlers_1.dispatchServerMessage)(message, {
185
+ onWelcome: (welcomeMessage) => {
186
+ this.localPeerId = welcomeMessage.clientId;
187
+ this.peerIds = welcomeMessage.peers.map((peer) => peer.clientId);
188
+ this.initialPeerIds = new Set(this.peerIds);
189
+ this.emit('welcome', {
190
+ sessionId: welcomeMessage.sessionId,
191
+ clientId: welcomeMessage.clientId,
192
+ peers: [...this.peerIds],
193
+ });
194
+ if (this.options.autoCreateOffers && this.peerIds.length > 0) {
195
+ this.scheduleOffers(this.peerIds);
196
+ }
197
+ },
198
+ onPeerJoined: (joinedMessage) => {
199
+ if (!this.peerIds.includes(joinedMessage.clientId)) {
200
+ this.peerIds = [...this.peerIds, joinedMessage.clientId];
201
+ }
202
+ this.emit('peerJoined', { peerId: joinedMessage.clientId });
203
+ if (this.options.autoCreateOffers) {
204
+ this.scheduleOffers([joinedMessage.clientId]);
205
+ }
206
+ },
207
+ onPeerLeft: (leftMessage) => {
208
+ var _a;
209
+ this.peerIds = this.peerIds.filter((peerId) => peerId !== leftMessage.clientId);
210
+ this.initialPeerIds.delete(leftMessage.clientId);
211
+ (_a = this.peerManager) === null || _a === void 0 ? void 0 : _a.closePeer(leftMessage.clientId);
212
+ this.emit('peerLeft', { peerId: leftMessage.clientId });
213
+ },
214
+ onRelayMessage: (relayMessage) => {
215
+ var _a, _b, _c;
216
+ const relayOperation = relayMessage.type === 'offer'
217
+ ? (_a = this.peerManager) === null || _a === void 0 ? void 0 : _a.handleRemoteOffer(relayMessage.from, relayMessage.payload)
218
+ : relayMessage.type === 'answer'
219
+ ? (_b = this.peerManager) === null || _b === void 0 ? void 0 : _b.handleRemoteAnswer(relayMessage.from, relayMessage.payload)
220
+ : (_c = this.peerManager) === null || _c === void 0 ? void 0 : _c.handleRemoteIce(relayMessage.from, relayMessage.payload);
221
+ void (relayOperation === null || relayOperation === void 0 ? void 0 : relayOperation.catch((error) => {
222
+ this.emit('transportError', {
223
+ peerId: relayMessage.from,
224
+ ...(0, runtimeSupport_1.toErrorPayload)(errors_1.P2P_CORE_ERROR_CODE.RELAY_SEND_FAILED, error),
225
+ });
226
+ }));
227
+ },
228
+ onPong: () => {
229
+ this.emit('pong', undefined);
230
+ },
231
+ onError: (errorMessage) => {
232
+ this.emit('serverError', {
233
+ code: errorMessage.code,
234
+ message: errorMessage.message,
235
+ });
236
+ },
237
+ });
238
+ }
239
+ scheduleOffers(peerIds) {
240
+ peerIds.forEach((peerId, index) => {
241
+ const timer = setTimeout(() => {
242
+ this.scheduledOfferTimers.delete(timer);
243
+ void this.createOffer(peerId).catch((error) => {
244
+ this.emit('transportError', {
245
+ peerId,
246
+ ...(0, runtimeSupport_1.toErrorPayload)(errors_1.P2P_CORE_ERROR_CODE.RELAY_SEND_FAILED, error),
247
+ });
248
+ });
249
+ }, index * this.options.offerDelayMs);
250
+ this.scheduledOfferTimers.add(timer);
251
+ });
252
+ }
253
+ clearRuntime() {
254
+ var _a;
255
+ this.clearScheduledOffers();
256
+ (_a = this.peerManager) === null || _a === void 0 ? void 0 : _a.closeAll();
257
+ this.peerManager = null;
258
+ this.signalingProvider = null;
259
+ this.localPeerId = null;
260
+ this.peerIds = [];
261
+ this.initialPeerIds.clear();
262
+ this.hasOpened = false;
263
+ this.status = 'idle';
264
+ }
265
+ clearScheduledOffers() {
266
+ this.scheduledOfferTimers.forEach((timer) => clearTimeout(timer));
267
+ this.scheduledOfferTimers.clear();
268
+ }
269
+ resolvePeerJoinKind(peerId) {
270
+ if (this.initialPeerIds.has(peerId)) {
271
+ return 'existing';
272
+ }
273
+ return 'new';
274
+ }
275
+ }
276
+ /**
277
+ * Creates a high-level reusable P2P session runtime.
278
+ *
279
+ * The returned session owns signaling, WebRTC orchestration and peer lifecycle,
280
+ * while the consuming app stays responsible for message encoding, decoding and
281
+ * domain-specific synchronization.
282
+ */
283
+ function createP2PSession(options) {
284
+ return new P2PSessionRuntime(options);
285
+ }
@@ -0,0 +1,4 @@
1
+ export declare const SESSION_DEFAULT_OFFER_DELAY_MS = 150;
2
+ export declare const SESSION_MANUAL_DISCONNECT_CODE = 1000;
3
+ export declare const SESSION_MANUAL_DISCONNECT_REASON = "manual_disconnect";
4
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/session/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,8BAA8B,OAAO,CAAC;AACnD,eAAO,MAAM,gCAAgC,sBAAsB,CAAC"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SESSION_MANUAL_DISCONNECT_REASON = exports.SESSION_MANUAL_DISCONNECT_CODE = exports.SESSION_DEFAULT_OFFER_DELAY_MS = void 0;
4
+ exports.SESSION_DEFAULT_OFFER_DELAY_MS = 150;
5
+ exports.SESSION_MANUAL_DISCONNECT_CODE = 1000;
6
+ exports.SESSION_MANUAL_DISCONNECT_REASON = 'manual_disconnect';
@@ -0,0 +1,3 @@
1
+ export * from './P2PSession';
2
+ export * from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/session/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,18 @@
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("./P2PSession"), exports);
18
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,36 @@
1
+ import { WebRtcEvents, WebRtcPeerManager, WebRtcSignalType } from '../rtc/types';
2
+ import { SignalingProvider, SignalingProviderHandlers } from '../signaling';
3
+ import { P2PSessionEventMap, P2PSessionOptions, P2PSessionState, PeerJoinKind } from './types';
4
+ import { P2PCoreErrorCode, P2PCoreErrorPayload } from '../errors';
5
+ type EventEmitter = <TEvent extends keyof P2PSessionEventMap>(eventName: TEvent, payload: P2PSessionEventMap[TEvent]) => void;
6
+ export type NormalizedSessionOptions = Required<Pick<P2PSessionOptions, 'offerDelayMs'>> & Omit<P2PSessionOptions, 'offerDelayMs' | 'heartbeat' | 'reconnect'> & {
7
+ heartbeat: Required<NonNullable<P2PSessionOptions['heartbeat']>>;
8
+ reconnect: Required<NonNullable<P2PSessionOptions['reconnect']>>;
9
+ };
10
+ export interface RuntimeCallbacks {
11
+ onSignalOpen: () => void;
12
+ onSignalClose: (event: {
13
+ code?: number;
14
+ reason?: string;
15
+ }) => void;
16
+ onSignalError: (message: string) => void;
17
+ onProtocolError: (reason: string, rawMessage: string) => void;
18
+ onServerMessage: SignalingProviderHandlers['onMessage'];
19
+ }
20
+ export declare function normalizeSessionOptions(options: P2PSessionOptions): NormalizedSessionOptions;
21
+ export declare function createSessionSignalingProvider(options: NormalizedSessionOptions): SignalingProvider;
22
+ export declare function createSessionProviderHandlers(providerToken: SignalingProvider, getActiveProvider: () => SignalingProvider | null, callbacks: RuntimeCallbacks): SignalingProviderHandlers;
23
+ export declare function createSessionPeerEvents(emit: EventEmitter, resolvePeerJoinKind: (peerId: string) => PeerJoinKind): WebRtcEvents;
24
+ export declare function createPeerSignalEmitter(provider: SignalingProvider, emit: EventEmitter): {
25
+ emit: (target: string, type: WebRtcSignalType, payload: unknown) => void;
26
+ };
27
+ export declare function createPeerManager(options: NormalizedSessionOptions, provider: SignalingProvider, emit: EventEmitter, resolvePeerJoinKind: (peerId: string) => PeerJoinKind): WebRtcPeerManager;
28
+ export declare function createSessionState(sessionId: string, localPeerId: string | null, peerIds: string[], status: P2PSessionState['status']): P2PSessionState;
29
+ export declare function toErrorMessage(error: unknown): string;
30
+ export declare function toErrorPayload(code: P2PCoreErrorCode, error: unknown, fallbackMessage?: string): P2PCoreErrorPayload;
31
+ export declare function createError(code: P2PCoreErrorCode, message: string): Error & {
32
+ code: P2PCoreErrorCode;
33
+ };
34
+ export declare function isPromiseLike(value: void | Promise<void>): value is Promise<void>;
35
+ export {};
36
+ //# sourceMappingURL=runtimeSupport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeSupport.d.ts","sourceRoot":"","sources":["../../src/session/runtimeSupport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeSessionOptions = normalizeSessionOptions;
4
+ exports.createSessionSignalingProvider = createSessionSignalingProvider;
5
+ exports.createSessionProviderHandlers = createSessionProviderHandlers;
6
+ exports.createSessionPeerEvents = createSessionPeerEvents;
7
+ exports.createPeerSignalEmitter = createPeerSignalEmitter;
8
+ exports.createPeerManager = createPeerManager;
9
+ exports.createSessionState = createSessionState;
10
+ exports.toErrorMessage = toErrorMessage;
11
+ exports.toErrorPayload = toErrorPayload;
12
+ exports.createError = createError;
13
+ exports.isPromiseLike = isPromiseLike;
14
+ const signaling_1 = require("../signaling");
15
+ const constants_1 = require("./constants");
16
+ const errors_1 = require("../errors");
17
+ const options_1 = require("../rtc/options");
18
+ function normalizeSessionOptions(options) {
19
+ var _a;
20
+ return {
21
+ ...options,
22
+ offerDelayMs: (_a = options.offerDelayMs) !== null && _a !== void 0 ? _a : constants_1.SESSION_DEFAULT_OFFER_DELAY_MS,
23
+ heartbeat: (0, options_1.normalizeHeartbeatConfig)(options.heartbeat),
24
+ reconnect: (0, options_1.normalizeReconnectConfig)(options.reconnect),
25
+ };
26
+ }
27
+ function createSessionSignalingProvider(options) {
28
+ if (options.signalingProvider) {
29
+ return options.signalingProvider;
30
+ }
31
+ if (!options.signalBaseUrl) {
32
+ throw createError(errors_1.P2P_CORE_ERROR_CODE.SIGNALING_CONFIGURATION_REQUIRED, 'Either `signalBaseUrl` or `signalingProvider` is required');
33
+ }
34
+ return (0, signaling_1.createWebSocketSignalingProvider)({
35
+ signalBaseUrl: options.signalBaseUrl,
36
+ createSignalingClient: options.createSignalingClient,
37
+ });
38
+ }
39
+ function createSessionProviderHandlers(providerToken, getActiveProvider, callbacks) {
40
+ return {
41
+ onOpen: () => {
42
+ if (getActiveProvider() !== providerToken) {
43
+ return;
44
+ }
45
+ callbacks.onSignalOpen();
46
+ },
47
+ onClose: (event) => {
48
+ if (getActiveProvider() !== providerToken) {
49
+ return;
50
+ }
51
+ callbacks.onSignalClose(event);
52
+ },
53
+ onError: (event) => {
54
+ if (getActiveProvider() !== providerToken) {
55
+ return;
56
+ }
57
+ callbacks.onSignalError(event.message);
58
+ },
59
+ onProtocolError: callbacks.onProtocolError,
60
+ onMessage: (message) => {
61
+ var _a;
62
+ if (getActiveProvider() !== providerToken) {
63
+ return;
64
+ }
65
+ (_a = callbacks.onServerMessage) === null || _a === void 0 ? void 0 : _a.call(callbacks, message);
66
+ },
67
+ };
68
+ }
69
+ function createSessionPeerEvents(emit, resolvePeerJoinKind) {
70
+ return {
71
+ onDataChannelOpen: (peerId) => {
72
+ emit('peerDataOpen', {
73
+ peerId,
74
+ joinKind: resolvePeerJoinKind(peerId),
75
+ });
76
+ },
77
+ onDataChannelClosed: (peerId) => {
78
+ emit('peerDataClose', { peerId });
79
+ },
80
+ onDataChannelMessage: (peerId, message) => {
81
+ emit('peerMessage', { peerId, message });
82
+ },
83
+ onIceConnectionStateChange: (peerId, state) => {
84
+ emit('iceStateChange', { peerId, state });
85
+ },
86
+ };
87
+ }
88
+ function createPeerSignalEmitter(provider, emit) {
89
+ return {
90
+ emit: (target, type, payload) => {
91
+ try {
92
+ provider.sendRelay(type, target, payload);
93
+ }
94
+ catch (error) {
95
+ emit('transportError', {
96
+ peerId: target,
97
+ ...toErrorPayload(errors_1.P2P_CORE_ERROR_CODE.RELAY_SEND_FAILED, error),
98
+ });
99
+ }
100
+ },
101
+ };
102
+ }
103
+ function createPeerManager(options, provider, emit, resolvePeerJoinKind) {
104
+ const peerManagerOptions = {
105
+ signalEmitter: createPeerSignalEmitter(provider, emit),
106
+ events: createSessionPeerEvents(emit, resolvePeerJoinKind),
107
+ rtcConfig: options.rtcConfig,
108
+ heartbeat: options.heartbeat,
109
+ reconnect: options.reconnect,
110
+ };
111
+ return options.createPeerManager
112
+ ? options.createPeerManager(peerManagerOptions)
113
+ : loadDefaultPeerManagerFactory()(peerManagerOptions);
114
+ }
115
+ function createSessionState(sessionId, localPeerId, peerIds, status) {
116
+ return {
117
+ sessionId,
118
+ localPeerId,
119
+ peerIds: [...peerIds],
120
+ status,
121
+ };
122
+ }
123
+ function toErrorMessage(error) {
124
+ return error instanceof Error ? error.message : String(error);
125
+ }
126
+ function toErrorPayload(code, error, fallbackMessage) {
127
+ return {
128
+ code,
129
+ message: error instanceof Error ? error.message : fallbackMessage !== null && fallbackMessage !== void 0 ? fallbackMessage : String(error),
130
+ };
131
+ }
132
+ function createError(code, message) {
133
+ const error = new Error(message);
134
+ error.code = code;
135
+ return error;
136
+ }
137
+ function isPromiseLike(value) {
138
+ return Boolean(value && typeof value === 'object' && 'catch' in value);
139
+ }
140
+ function loadDefaultPeerManagerFactory() {
141
+ // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require
142
+ const runtime = require('../rtc/runtime');
143
+ return runtime.createWebRtcPeerManager;
144
+ }
@@ -0,0 +1,21 @@
1
+ import { IncomingServerMessage } from '../signaling';
2
+ export interface ServerMessageHandlerCallbacks {
3
+ onWelcome: (message: Extract<IncomingServerMessage, {
4
+ type: 'welcome';
5
+ }>) => void;
6
+ onPeerJoined: (message: Extract<IncomingServerMessage, {
7
+ type: 'peer-joined';
8
+ }>) => void;
9
+ onPeerLeft: (message: Extract<IncomingServerMessage, {
10
+ type: 'peer-left';
11
+ }>) => void;
12
+ onRelayMessage: (message: Extract<IncomingServerMessage, {
13
+ type: 'offer' | 'answer' | 'ice';
14
+ }>) => void;
15
+ onPong: () => void;
16
+ onError: (message: Extract<IncomingServerMessage, {
17
+ type: 'error';
18
+ }>) => void;
19
+ }
20
+ export declare function dispatchServerMessage(message: IncomingServerMessage, callbacks: ServerMessageHandlerCallbacks): void;
21
+ //# sourceMappingURL=serverMessageHandlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverMessageHandlers.d.ts","sourceRoot":"","sources":["../../src/session/serverMessageHandlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAGrD,MAAM,WAAW,6BAA6B;IAC1C,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,qBAAqB,EAAE;QAAE,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC,KAAK,IAAI,CAAC;IAClF,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,qBAAqB,EAAE;QAAE,IAAI,EAAE,aAAa,CAAA;KAAE,CAAC,KAAK,IAAI,CAAC;IACzF,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,qBAAqB,EAAE;QAAE,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC,KAAK,IAAI,CAAC;IACrF,cAAc,EAAE,CACZ,OAAO,EAAE,OAAO,CAAC,qBAAqB,EAAE;QAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;KAAE,CAAC,KAC5E,IAAI,CAAC;IACV,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,qBAAqB,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,KAAK,IAAI,CAAC;CACjF;AAED,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,qBAAqB,EAC9B,SAAS,EAAE,6BAA6B,GACzC,IAAI,CAyBN"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dispatchServerMessage = dispatchServerMessage;
4
+ const constants_1 = require("../signaling/constants");
5
+ function dispatchServerMessage(message, callbacks) {
6
+ switch (message.type) {
7
+ case constants_1.SIGNAL_TYPE.WELCOME:
8
+ callbacks.onWelcome(message);
9
+ return;
10
+ case constants_1.SIGNAL_TYPE.PEER_JOINED:
11
+ callbacks.onPeerJoined(message);
12
+ return;
13
+ case constants_1.SIGNAL_TYPE.PEER_LEFT:
14
+ callbacks.onPeerLeft(message);
15
+ return;
16
+ case constants_1.SIGNAL_TYPE.OFFER:
17
+ case constants_1.SIGNAL_TYPE.ANSWER:
18
+ case constants_1.SIGNAL_TYPE.ICE:
19
+ callbacks.onRelayMessage(message);
20
+ return;
21
+ case constants_1.SIGNAL_TYPE.PONG:
22
+ callbacks.onPong();
23
+ return;
24
+ case constants_1.SIGNAL_TYPE.ERROR:
25
+ callbacks.onError(message);
26
+ return;
27
+ default:
28
+ return;
29
+ }
30
+ }