Skip to content

Commit ecafaf4

Browse files
committed
await new Peer()
1 parent 9a0c9ef commit ecafaf4

File tree

3 files changed

+134
-53
lines changed

3 files changed

+134
-53
lines changed

e2e/peer/id-taken.await.html

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title></title>
7+
<link rel="stylesheet" href="../style.css" />
8+
</head>
9+
<body>
10+
<h1>ID-TAKEN</h1>
11+
<div id="messages"></div>
12+
<div id="error-message"></div>
13+
<script src="/dist/peerjs.js"></script>
14+
<script type="module">
15+
/**
16+
* @type {typeof import("../..").Peer}
17+
*/
18+
const Peer = window.peerjs.Peer;
19+
20+
const messages = document.getElementById("messages");
21+
const errorMessage = document.getElementById("error-message");
22+
23+
// Peer A should be created without an error
24+
try {
25+
const peerA = await new Peer();
26+
// Create 10 new `Peer`s that will try to steel A's id
27+
let peers_try_to_take = Array.from({ length: 10 }, async (_, i) => {
28+
try {
29+
await new Peer(peerA.id);
30+
throw `Peer ${i} failed! Connection got established.`;
31+
} catch (error) {
32+
if (error.type === "unavailable-id") {
33+
return `ID already taken. (${i})`;
34+
} else {
35+
throw error;
36+
}
37+
}
38+
});
39+
await Promise.all(peers_try_to_take);
40+
messages.textContent = "No ID takeover";
41+
} catch (error) {
42+
errorMessage.textContent += JSON.stringify(error);
43+
}
44+
</script>
45+
</body>
46+
</html>

e2e/peer/peer.spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,10 @@ describe("Peer", () => {
1818
expect(await P.errorMessage.getText()).toBe("");
1919
});
2020
});
21+
describe("Peer:async", () => {
22+
it("should emit an error, when the ID is already taken", async () => {
23+
await P.open("id-taken.await");
24+
await P.waitForMessage("No ID takeover");
25+
expect(await P.errorMessage.getText()).toBe("");
26+
});
27+
});

lib/peer.ts

Lines changed: 81 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,76 @@ export type PeerEvents = {
120120
*/
121121
error: (error: PeerError) => void;
122122
};
123+
124+
export interface IPeer {
125+
/**
126+
* The brokering ID of this peer
127+
*
128+
* If no ID was specified in {@apilink Peer | the constructor},
129+
* this will be `undefined` until the {@apilink PeerEvents | `open`} event is emitted.
130+
*/
131+
get id(): string;
132+
get open(): boolean;
133+
/**
134+
* A hash of all connections associated with this peer, keyed by the remote peer's ID.
135+
* @deprecated
136+
* Return type will change from Object to Map<string,[]>
137+
*/
138+
get connections(): Object;
139+
/**
140+
* true if this peer and all of its connections can no longer be used.
141+
*/
142+
get destroyed(): boolean;
143+
/**
144+
* Connects to the remote peer specified by id and returns a data connection.
145+
* @param peer The brokering ID of the remote peer (their {@apilink Peer.id}).
146+
* @param options for specifying details about Peer Connection
147+
*/
148+
connect(peer: string, options: PeerConnectOption): DataConnection;
149+
/**
150+
* Calls the remote peer specified by id and returns a media connection.
151+
* @param peer The brokering ID of the remote peer (their peer.id).
152+
* @param stream The caller's media stream
153+
* @param options Metadata associated with the connection, passed in by whoever initiated the connection.
154+
*/
155+
call(peer: string, stream: MediaStream, options: CallOption): MediaConnection;
156+
/** Retrieve a data/media connection for this peer. */
157+
getConnection(
158+
peerId: string,
159+
connectionId: string,
160+
): null | DataConnection | MediaConnection;
161+
/**
162+
* Destroys the Peer: closes all active connections as well as the connection
163+
* to the server.
164+
*
165+
* :::caution
166+
* This cannot be undone; the respective peer object will no longer be able
167+
* to create or receive any connections, its ID will be forfeited on the server,
168+
* and all of its data and media connections will be closed.
169+
* :::
170+
*/
171+
destroy(): void;
172+
/**
173+
* Disconnects the Peer's connection to the PeerServer. Does not close any
174+
* active connections.
175+
* Warning: The peer can no longer create or accept connections after being
176+
* disconnected. It also cannot reconnect to the server.
177+
*/
178+
disconnect(): void;
179+
/** Attempts to reconnect with the same ID.
180+
*
181+
* Only {@apilink Peer.disconnect | disconnected peers} can be reconnected.
182+
* Destroyed peers cannot be reconnected.
183+
* If the connection fails (as an example, if the peer's old ID is now taken),
184+
* the peer's existing connections will not close, but any associated errors events will fire.
185+
*/
186+
reconnect(): void;
187+
}
188+
123189
/**
124190
* A peer who can initiate connections with other peers.
125191
*/
126-
export class Peer extends EventEmitter<PeerEvents> {
192+
export class Peer extends EventEmitter<PeerEvents> implements IPeer {
127193
private static readonly DEFAULT_KEY = "peerjs";
128194

129195
private readonly _serializers: SerializerMapping = {
@@ -150,12 +216,11 @@ export class Peer extends EventEmitter<PeerEvents> {
150216
(DataConnection | MediaConnection)[]
151217
> = new Map(); // All connections for this peer.
152218
private readonly _lostMessages: Map<string, ServerMessage[]> = new Map(); // src => [list of messages]
153-
/**
154-
* The brokering ID of this peer
155-
*
156-
* If no ID was specified in {@apilink Peer | the constructor},
157-
* this will be `undefined` until the {@apilink PeerEvents | `open`} event is emitted.
158-
*/
219+
private then: (
220+
onfulfilled?: (value: IPeer) => any,
221+
onrejected?: (reason: PeerError) => any,
222+
) => void;
223+
159224
get id() {
160225
return this._id;
161226
}
@@ -175,11 +240,6 @@ export class Peer extends EventEmitter<PeerEvents> {
175240
return this._socket;
176241
}
177242

178-
/**
179-
* A hash of all connections associated with this peer, keyed by the remote peer's ID.
180-
* @deprecated
181-
* Return type will change from Object to Map<string,[]>
182-
*/
183243
get connections(): Object {
184244
const plainConnections = Object.create(null);
185245

@@ -190,15 +250,9 @@ export class Peer extends EventEmitter<PeerEvents> {
190250
return plainConnections;
191251
}
192252

193-
/**
194-
* true if this peer and all of its connections can no longer be used.
195-
*/
196253
get destroyed() {
197254
return this._destroyed;
198255
}
199-
/**
200-
* false if there is an active connection to the PeerServer.
201-
*/
202256
get disconnected() {
203257
return this._disconnected;
204258
}
@@ -226,6 +280,15 @@ export class Peer extends EventEmitter<PeerEvents> {
226280
constructor(id?: string | PeerOptions, options?: PeerOptions) {
227281
super();
228282

283+
this.then = (
284+
onfulfilled?: (value: IPeer) => any,
285+
onrejected?: (reason: PeerError) => any,
286+
) => {
287+
delete this.then;
288+
this.once("open", () => onfulfilled?.(this));
289+
this.once("error", onrejected);
290+
};
291+
229292
let userId: string | undefined;
230293

231294
// Deal with overloading
@@ -495,11 +558,6 @@ export class Peer extends EventEmitter<PeerEvents> {
495558
return [];
496559
}
497560

498-
/**
499-
* Connects to the remote peer specified by id and returns a data connection.
500-
* @param peer The brokering ID of the remote peer (their {@apilink Peer.id}).
501-
* @param options for specifying details about Peer Connection
502-
*/
503561
connect(peer: string, options: PeerConnectOption): DataConnection {
504562
options = {
505563
serialization: "default",
@@ -528,12 +586,6 @@ export class Peer extends EventEmitter<PeerEvents> {
528586
return dataConnection;
529587
}
530588

531-
/**
532-
* Calls the remote peer specified by id and returns a media connection.
533-
* @param peer The brokering ID of the remote peer (their peer.id).
534-
* @param stream The caller's media stream
535-
* @param options Metadata associated with the connection, passed in by whoever initiated the connection.
536-
*/
537589
call(
538590
peer: string,
539591
stream: MediaStream,
@@ -598,7 +650,6 @@ export class Peer extends EventEmitter<PeerEvents> {
598650
this._lostMessages.delete(connection.connectionId);
599651
}
600652

601-
/** Retrieve a data/media connection for this peer. */
602653
getConnection(
603654
peerId: string,
604655
connectionId: string,
@@ -647,16 +698,6 @@ export class Peer extends EventEmitter<PeerEvents> {
647698
this.emit("error", new PeerError(type, err));
648699
}
649700

650-
/**
651-
* Destroys the Peer: closes all active connections as well as the connection
652-
* to the server.
653-
*
654-
* :::caution
655-
* This cannot be undone; the respective peer object will no longer be able
656-
* to create or receive any connections, its ID will be forfeited on the server,
657-
* and all of its data and media connections will be closed.
658-
* :::
659-
*/
660701
destroy(): void {
661702
if (this.destroyed) {
662703
return;
@@ -693,12 +734,6 @@ export class Peer extends EventEmitter<PeerEvents> {
693734
}
694735
}
695736

696-
/**
697-
* Disconnects the Peer's connection to the PeerServer. Does not close any
698-
* active connections.
699-
* Warning: The peer can no longer create or accept connections after being
700-
* disconnected. It also cannot reconnect to the server.
701-
*/
702737
disconnect(): void {
703738
if (this.disconnected) {
704739
return;
@@ -719,13 +754,6 @@ export class Peer extends EventEmitter<PeerEvents> {
719754
this.emit("disconnected", currentId);
720755
}
721756

722-
/** Attempts to reconnect with the same ID.
723-
*
724-
* Only {@apilink Peer.disconnect | disconnected peers} can be reconnected.
725-
* Destroyed peers cannot be reconnected.
726-
* If the connection fails (as an example, if the peer's old ID is now taken),
727-
* the peer's existing connections will not close, but any associated errors events will fire.
728-
*/
729757
reconnect(): void {
730758
if (this.disconnected && !this.destroyed) {
731759
logger.log(

0 commit comments

Comments
 (0)