Skip to content

Commit bee2bdb

Browse files
committed
feat: await peer.connect(...)
1 parent 2cba46d commit bee2bdb

File tree

4 files changed

+74
-3
lines changed

4 files changed

+74
-3
lines changed

e2e/peer/id-taken.await.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ <h1>ID-TAKEN</h1>
1414
<script type="application/javascript">
1515
(async () => {
1616
/**
17-
* @type {typeof import("../..").Peer}
17+
* @type {typeof import("../../lib/exports.ts").Peer}
1818
*/
1919
const Peer = window.peerjs.Peer;
2020

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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>PEER-UNAVAILABLE</h1>
11+
<div id="messages"></div>
12+
<div id="error-message"></div>
13+
<script src="/dist/peerjs.js"></script>
14+
<script type="application/javascript">
15+
(async () => {
16+
/**
17+
* @type {typeof import("../../lib/exports.ts").Peer}
18+
*/
19+
const Peer = window.peerjs.Peer;
20+
21+
const messages = document.getElementById("messages");
22+
const errors = document.getElementById("error-message");
23+
24+
const not_existing_peer = crypto
25+
.getRandomValues(new Uint8Array(16))
26+
.join("");
27+
28+
try {
29+
const peer = await new Peer();
30+
await peer.connect(not_existing_peer);
31+
} catch (error) {
32+
if (error.type === "peer-unavailable") {
33+
messages.textContent = "Success: Peer unavailable";
34+
} else {
35+
errors.textContent += JSON.stringify(error);
36+
}
37+
}
38+
})();
39+
</script>
40+
</body>
41+
</html>

e2e/peer/peer.spec.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,9 @@ describe("Peer:async", () => {
2929
await P.waitForMessage("No ID takeover");
3030
expect(await P.errorMessage.getText()).toBe("");
3131
});
32+
it("should emit an error, when the remote peer is unavailable", async () => {
33+
await P.open("peer-unavailable.async");
34+
await P.waitForMessage("Success: Peer unavailable");
35+
expect(await P.errorMessage.getText()).toBe("");
36+
});
3237
});

lib/dataconnection/DataConnection.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { BaseConnection, type BaseConnectionEvents } from "../baseconnection";
1111
import type { ServerMessage } from "../servermessage";
1212
import type { EventsWithError } from "../peerError";
1313
import { randomToken } from "../utils/randomToken";
14+
import { PeerError } from "../peerError";
1415

1516
export interface DataConnectionEvents
1617
extends EventsWithError<DataConnectionErrorType | BaseConnectionErrorType>,
@@ -25,6 +26,14 @@ export interface DataConnectionEvents
2526
open: () => void;
2627
}
2728

29+
export interface IDataConnection
30+
extends BaseConnection<DataConnectionEvents, DataConnectionErrorType> {
31+
/** Allows user to close connection. */
32+
close(options?: { flush?: boolean }): void;
33+
/** Allows user to send data. */
34+
send(data: any, chunked?: boolean): void;
35+
}
36+
2837
/**
2938
* Wraps a DataChannel between two Peers.
3039
*/
@@ -38,6 +47,10 @@ export abstract class DataConnection extends BaseConnection<
3847
private _negotiator: Negotiator<DataConnectionEvents, this>;
3948
abstract readonly serialization: string;
4049
readonly reliable: boolean;
50+
private then: (
51+
onfulfilled?: (value: IDataConnection) => any,
52+
onrejected?: (reason: PeerError<DataConnectionErrorType>) => any,
53+
) => void;
4154

4255
public get type() {
4356
return ConnectionType.Data;
@@ -46,6 +59,20 @@ export abstract class DataConnection extends BaseConnection<
4659
constructor(peerId: string, provider: Peer, options: any) {
4760
super(peerId, provider, options);
4861

62+
this.then = (
63+
onfulfilled?: (value: IDataConnection) => any,
64+
onrejected?: (reason: PeerError<DataConnectionErrorType>) => any,
65+
) => {
66+
// Remove 'then' to prevent potential recursion issues
67+
// `await` will wait for a Promise-like to resolve recursively
68+
delete this.then;
69+
70+
// We don’t need to worry about cleaning up listeners here
71+
// `await`ing a Promise will make sure only one of the paths executes
72+
this.once("open", () => onfulfilled(this));
73+
this.once("error", onrejected);
74+
};
75+
4976
this.connectionId =
5077
this.options.connectionId || DataConnection.ID_PREFIX + randomToken();
5178

@@ -87,7 +114,6 @@ export abstract class DataConnection extends BaseConnection<
87114
* Exposed functionality for users.
88115
*/
89116

90-
/** Allows user to close connection. */
91117
close(options?: { flush?: boolean }): void {
92118
if (options?.flush) {
93119
this.send({
@@ -126,7 +152,6 @@ export abstract class DataConnection extends BaseConnection<
126152

127153
protected abstract _send(data: any, chunked: boolean): void;
128154

129-
/** Allows user to send data. */
130155
public send(data: any, chunked = false) {
131156
if (!this.open) {
132157
this.emitError(

0 commit comments

Comments
 (0)