Skip to content

Commit 0c96603

Browse files
committed
fix(typings): much stronger event typings for DataConnection,MediaConnection
1 parent 666dcd9 commit 0c96603

File tree

8 files changed

+78
-72
lines changed

8 files changed

+78
-72
lines changed

lib/baseconnection.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1-
import { EventEmitter } from "eventemitter3";
1+
import { EventEmitter, ValidEventTypes } from "eventemitter3";
22
import { Peer } from "./peer";
33
import { ServerMessage } from "./servermessage";
44
import { ConnectionType } from "./enums";
55

6-
export abstract class BaseConnection extends EventEmitter {
6+
export type BaseConnectionEvents = {
7+
/**
8+
* Emitted when either you or the remote peer closes the connection.
9+
*/
10+
close: () => void;
11+
error: (error: Error) => void;
12+
iceStateChanged: (state: RTCIceConnectionState) => void;
13+
};
14+
15+
export abstract class BaseConnection<
16+
T extends ValidEventTypes,
17+
> extends EventEmitter<T & BaseConnectionEvents> {
718
protected _open = false;
819

920
readonly metadata: any;

lib/dataconnection.ts

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
11
import { util } from "./util";
22
import logger from "./logger";
33
import { Negotiator } from "./negotiator";
4-
import {
5-
ConnectionType,
6-
ConnectionEventType,
7-
SerializationType,
8-
ServerMessageType,
9-
} from "./enums";
4+
import { ConnectionType, SerializationType, ServerMessageType } from "./enums";
105
import { Peer } from "./peer";
116
import { BaseConnection } from "./baseconnection";
127
import { ServerMessage } from "./servermessage";
138
import { EncodingQueue } from "./encodingQueue";
149
import type { DataConnection as IDataConnection } from "./dataconnection";
1510

11+
type DataConnectionEvents = {
12+
/**
13+
* Emitted when data is received from the remote peer.
14+
*/
15+
data: (data: unknown) => void;
16+
/**
17+
* Emitted when the connection is established and ready-to-use.
18+
*/
19+
open: () => void;
20+
};
21+
1622
/**
1723
* Wraps a DataChannel between two Peers.
1824
*/
19-
export class DataConnection extends BaseConnection implements IDataConnection {
25+
export class DataConnection
26+
extends BaseConnection<DataConnectionEvents>
27+
implements IDataConnection
28+
{
2029
private static readonly ID_PREFIX = "dc_";
2130
private static readonly MAX_BUFFERED_AMOUNT = 8 * 1024 * 1024;
2231

23-
private _negotiator: Negotiator;
32+
private _negotiator: Negotiator<DataConnectionEvents, DataConnection>;
2433
readonly label: string;
2534
readonly serialization: SerializationType;
2635
readonly reliable: boolean;
@@ -98,7 +107,7 @@ export class DataConnection extends BaseConnection implements IDataConnection {
98107
this.dataChannel.onopen = () => {
99108
logger.log(`DC#${this.connectionId} dc connection success`);
100109
this._open = true;
101-
this.emit(ConnectionEventType.Open);
110+
this.emit("open");
102111
};
103112

104113
this.dataChannel.onmessage = (e) => {
@@ -131,7 +140,7 @@ export class DataConnection extends BaseConnection implements IDataConnection {
131140
// Datatype should never be blob
132141
util.blobToArrayBuffer(data as Blob, (ab) => {
133142
const unpackedData = util.unpack(ab);
134-
this.emit(ConnectionEventType.Data, unpackedData);
143+
this.emit("data", unpackedData);
135144
});
136145
return;
137146
} else if (datatype === ArrayBuffer) {
@@ -152,7 +161,7 @@ export class DataConnection extends BaseConnection implements IDataConnection {
152161
return;
153162
}
154163

155-
super.emit(ConnectionEventType.Data, deserializedData);
164+
super.emit("data", deserializedData);
156165
}
157166

158167
private _handleChunk(data: {
@@ -222,14 +231,14 @@ export class DataConnection extends BaseConnection implements IDataConnection {
222231

223232
this._open = false;
224233

225-
super.emit(ConnectionEventType.Close);
234+
super.emit("close");
226235
}
227236

228237
/** Allows user to send data. */
229238
send(data: any, chunked?: boolean): void {
230239
if (!this.open) {
231240
super.emit(
232-
ConnectionEventType.Error,
241+
"error",
233242
new Error(
234243
"Connection is not open. You should listen for the `open` event before sending messages.",
235244
),

lib/enums.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,8 @@
1-
export enum ConnectionEventType {
2-
Open = "open",
3-
Stream = "stream",
4-
Data = "data",
5-
Close = "close",
6-
Error = "error",
7-
IceStateChanged = "iceStateChanged",
8-
}
9-
101
export enum ConnectionType {
112
Data = "data",
123
Media = "media",
134
}
145

15-
export type PeerEventType =
16-
| "open"
17-
| "close"
18-
| "connection"
19-
| "call"
20-
| "disconnected"
21-
| "error";
22-
236
export enum PeerErrorType {
247
BrowserIncompatible = "browser-incompatible",
258
Disconnected = "disconnected",

lib/exports.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ export type { DataConnection } from "./dataconnection";
1212
export type { MediaConnection } from "./mediaconnection";
1313
export type { LogLevel } from "./logger";
1414
export type {
15-
ConnectionEventType,
1615
ConnectionType,
17-
PeerEventType,
1816
PeerErrorType,
1917
SerializationType,
2018
SocketEventType,

lib/mediaconnection.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
11
import { util } from "./util";
22
import logger from "./logger";
33
import { Negotiator } from "./negotiator";
4-
import {
5-
ConnectionType,
6-
ConnectionEventType,
7-
ServerMessageType,
8-
} from "./enums";
4+
import { ConnectionType, ServerMessageType } from "./enums";
95
import { Peer } from "./peer";
106
import { BaseConnection } from "./baseconnection";
117
import { ServerMessage } from "./servermessage";
128
import type { AnswerOption } from "./optionInterfaces";
139

10+
type MediaConnectionEvents = {
11+
/**
12+
* Emitted when a connection to the PeerServer is established.
13+
*/
14+
stream: (stream: MediaStream) => void;
15+
};
16+
1417
/**
1518
* Wraps the streaming interface between two Peers.
1619
*/
17-
export class MediaConnection extends BaseConnection {
20+
export class MediaConnection extends BaseConnection<MediaConnectionEvents> {
1821
private static readonly ID_PREFIX = "mc_";
1922

20-
private _negotiator: Negotiator;
23+
private _negotiator: Negotiator<MediaConnectionEvents, MediaConnection>;
2124
private _localStream: MediaStream;
2225
private _remoteStream: MediaStream;
2326

@@ -54,7 +57,7 @@ export class MediaConnection extends BaseConnection {
5457
logger.log("Receiving stream", remoteStream);
5558

5659
this._remoteStream = remoteStream;
57-
super.emit(ConnectionEventType.Stream, remoteStream); // Should we call this `open`?
60+
super.emit("stream", remoteStream); // Should we call this `open`?
5861
}
5962

6063
handleMessage(message: ServerMessage): void {
@@ -134,6 +137,6 @@ export class MediaConnection extends BaseConnection {
134137

135138
this._open = false;
136139

137-
super.emit(ConnectionEventType.Close);
140+
super.emit("close");
138141
}
139142
}

lib/negotiator.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,18 @@ import { util } from "./util";
22
import logger from "./logger";
33
import { MediaConnection } from "./mediaconnection";
44
import { DataConnection } from "./dataconnection";
5-
import {
6-
ConnectionType,
7-
PeerErrorType,
8-
ConnectionEventType,
9-
ServerMessageType,
10-
} from "./enums";
11-
import { BaseConnection } from "./baseconnection";
5+
import { ConnectionType, PeerErrorType, ServerMessageType } from "./enums";
6+
import { BaseConnection, BaseConnectionEvents } from "./baseconnection";
7+
import { ValidEventTypes } from "eventemitter3";
128

139
/**
1410
* Manages all negotiations between Peers.
1511
*/
16-
export class Negotiator {
17-
constructor(readonly connection: BaseConnection) {}
12+
export class Negotiator<
13+
A extends ValidEventTypes,
14+
T extends BaseConnection<A | BaseConnectionEvents>,
15+
> {
16+
constructor(readonly connection: T) {}
1817

1918
/** Returns a PeerConnection object set up correctly (for data, media). */
2019
startConnection(options: any) {
@@ -30,7 +29,7 @@ export class Negotiator {
3029
// What do we need to do now?
3130
if (options.originator) {
3231
if (this.connection.type === ConnectionType.Data) {
33-
const dataConnection = <DataConnection>this.connection;
32+
const dataConnection = <DataConnection>(<unknown>this.connection);
3433

3534
const config: RTCDataChannelInit = { ordered: !!options.reliable };
3635

@@ -93,7 +92,7 @@ export class Negotiator {
9392
"iceConnectionState is failed, closing connections to " + peerId,
9493
);
9594
this.connection.emit(
96-
ConnectionEventType.Error,
95+
"error",
9796
new Error("Negotiation of connection to " + peerId + " failed."),
9897
);
9998
this.connection.close();
@@ -103,7 +102,7 @@ export class Negotiator {
103102
"iceConnectionState is closed, closing connections to " + peerId,
104103
);
105104
this.connection.emit(
106-
ConnectionEventType.Error,
105+
"error",
107106
new Error("Connection to " + peerId + " closed."),
108107
);
109108
this.connection.close();
@@ -120,7 +119,7 @@ export class Negotiator {
120119
}
121120

122121
this.connection.emit(
123-
ConnectionEventType.IceStateChanged,
122+
"iceStateChanged",
124123
peerConnection.iceConnectionState,
125124
);
126125
};
@@ -179,7 +178,7 @@ export class Negotiator {
179178
let dataChannelNotClosed = false;
180179

181180
if (this.connection.type === ConnectionType.Data) {
182-
const dataConnection = <DataConnection>this.connection;
181+
const dataConnection = <DataConnection>(<unknown>this.connection);
183182
const dataChannel = dataConnection.dataChannel;
184183

185184
if (dataChannel) {
@@ -230,7 +229,7 @@ export class Negotiator {
230229
};
231230

232231
if (this.connection.type === ConnectionType.Data) {
233-
const dataConnection = <DataConnection>this.connection;
232+
const dataConnection = <DataConnection>(<unknown>this.connection);
234233

235234
payload = {
236235
...payload,

lib/peer.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
SocketEventType,
1111
ServerMessageType,
1212
} from "./enums";
13-
import { BaseConnection } from "./baseconnection";
1413
import { ServerMessage } from "./servermessage";
1514
import { API } from "./api";
1615
import type {
@@ -76,7 +75,10 @@ export class Peer extends EventEmitter<PeerEvents> {
7675
private _destroyed = false; // Connections have been killed
7776
private _disconnected = false; // Connection to PeerServer killed but P2P connections still active
7877
private _open = false; // Sockets and such are not yet open.
79-
private readonly _connections: Map<string, BaseConnection[]> = new Map(); // All connections for this peer.
78+
private readonly _connections: Map<
79+
string,
80+
(DataConnection | MediaConnection)[]
81+
> = new Map(); // All connections for this peer.
8082
private readonly _lostMessages: Map<string, ServerMessage[]> = new Map(); // src => [list of messages]
8183
/**
8284
* The brokering ID of this peer
@@ -471,7 +473,10 @@ export class Peer extends EventEmitter<PeerEvents> {
471473
}
472474

473475
/** Add a data/media connection to this peer. */
474-
private _addConnection(peerId: string, connection: BaseConnection): void {
476+
private _addConnection(
477+
peerId: string,
478+
connection: MediaConnection | DataConnection,
479+
): void {
475480
logger.log(
476481
`add connection ${connection.type}:${connection.connectionId} to peerId:${peerId}`,
477482
);
@@ -483,7 +488,7 @@ export class Peer extends EventEmitter<PeerEvents> {
483488
}
484489

485490
//TODO should be private
486-
_removeConnection(connection: BaseConnection): void {
491+
_removeConnection(connection: DataConnection | MediaConnection): void {
487492
const connections = this._connections.get(connection.peer);
488493

489494
if (connections) {
@@ -499,7 +504,10 @@ export class Peer extends EventEmitter<PeerEvents> {
499504
}
500505

501506
/** Retrieve a data/media connection for this peer. */
502-
getConnection(peerId: string, connectionId: string): null | BaseConnection {
507+
getConnection(
508+
peerId: string,
509+
connectionId: string,
510+
): null | DataConnection | MediaConnection {
503511
const connections = this._connections.get(peerId);
504512
if (!connections) {
505513
return null;

test/peer.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@ import "./setup";
22
import { expect } from "chai";
33
import { Peer } from "../lib/peer";
44
import { Server } from "mock-socket";
5-
import {
6-
ConnectionType,
7-
ServerMessageType,
8-
PeerErrorType,
9-
PeerEventType,
10-
} from "../lib/enums";
5+
import { ConnectionType, ServerMessageType } from "../lib/enums";
116

127
const createMockServer = (): Server => {
138
const fakeURL = "ws://localhost:8080/peerjs?key=peerjs&id=1&token=testToken";
@@ -202,10 +197,10 @@ describe("Peer", function () {
202197

203198
const peer1 = new Peer({ port: 8080, host: "localhost" });
204199

205-
peer1.once(PeerEventType.Error, (error) => {
206-
expect(error.type).to.be.eq(PeerErrorType.ServerError);
200+
peer1.once("error", (_error) => {
201+
// expect(error.type).to.be.eq(PeerErrorType.ServerError);
207202

208-
peer1.once(PeerEventType.Close, () => {
203+
peer1.once("close", () => {
209204
expect(peer1.disconnected).to.be.true;
210205
expect(peer1.destroyed).to.be.true;
211206
expect(peer1.open).to.be.false;

0 commit comments

Comments
 (0)