Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] refactoring of y-webrtc in typescript #31

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dist
node_modules
.vscode
.vscode
types
3,533 changes: 3,381 additions & 152 deletions package-lock.json

Large diffs are not rendered by default.

22 changes: 10 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
"version": "10.2.0",
"description": "WebRTC provider for Yjs",
"type": "module",
"main": "./dist/y-webrtc.cjs",
"types": "./dist/src/y-webrtc.d.ts",
"module": "./src/y-webrtc.js",
"unpkg": "./src/y-webrtc.mjs",
"main": "dist/y-webrtc.js",
"module": "dist/y-webrtc.module.js",
"umd:main": "dist/y-webrtc.umd.js",
"source": "src/index.ts",
"types": "types/index.d.ts",
"sideEffects": false,
"funding": {
"type": "GitHub Sponsors ❤",
Expand All @@ -17,13 +18,13 @@
"require": "./dist/y-webrtc.cjs"
},
"scripts": {
"clean": "rm -rf dist",
"clean": "rimraf -rf dist",
"start": "node ./bin/server.js",
"debug": "concurrently 'http-server -o index.html' 'npm run watch'",
"demo": "concurrently 'http-server -o demo/index.html' 'npm run watch'",
"dist": "rollup -c",
"dist": "npm run clean && microbundle build --raw --no-compress --tsconfig tsconfig.json",
"types": "tsc",
"watch": "rollup -wc",
"watch": "microbundle watch",
"test": "npm run lint",
"lint": "standard && tsc",
"preversion": "npm run clean && npm run lint && npm run dist && npm run types"
Expand Down Expand Up @@ -61,14 +62,11 @@
"y-protocols": "^1.0.5"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^11.1.0",
"@rollup/plugin-node-resolve": "^7.1.3",
"microbundle": "^0.13.0",
"rimraf": "^3.0.2",
"@types/simple-peer": "^9.6.3",
"concurrently": "^5.3.0",
"http-server": "^0.12.3",
"rollup": "^1.32.1",
"rollup-cli": "^1.0.9",
"rollup-plugin-terser": "^5.3.1",
"standard": "^14.3.4",
"typescript": "^3.9.9",
"yjs": "^13.5.6"
Expand Down
109 changes: 0 additions & 109 deletions rollup.config.js

This file was deleted.

156 changes: 156 additions & 0 deletions src/BaseWebrtcProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import * as error from "lib0/error";
import * as logging from "lib0/logging";
import * as map from "lib0/map";
import * as math from "lib0/math";
import { Observable } from "lib0/observable";
import * as random from "lib0/random";
import * as cryptoutils from "./crypto";
import { globalRooms, globalSignalingConns } from "./globalResources";
import { Room } from "./Room";
import { SignalingConn } from "./SignalingConn";

const log = logging.createModuleLogger("y-webrtc");

const openRoom = (
provider: BaseWebrtcProvider,
onCustomMessage: (
message: Uint8Array,
reply: (message: Uint8Array) => void
) => void,
onPeerConnected: (reply: (message: Uint8Array) => void) => void,
name: string,
key: CryptoKey | undefined
) => {
// there must only be one room
if (globalRooms.has(name)) {
throw error.create(`A Yjs Doc connected to room "${name}" already exists!`);
}
const room = new Room(provider, onCustomMessage, onPeerConnected, name, key);
globalRooms.set(name, room);
return room;
};

export abstract class BaseWebrtcProvider extends Observable<string> {
// public readonly awareness: awarenessProtocol.Awareness;
private shouldConnect = false;
public readonly filterBcConns: boolean = true;
private readonly signalingUrls: string[];
private readonly signalingConns: SignalingConn[];
public readonly peerOpts: any;
public readonly maxConns: number;
private readonly key: Promise<CryptoKey | undefined>;
protected room: Room | undefined;

protected abstract onCustomMessage: (
message: Uint8Array,
reply: (message: Uint8Array) => void
) => void;
protected abstract onPeerConnected: (
reply: (message: Uint8Array) => void
) => void;

constructor(
private readonly roomName: string,

// public readonly doc: Y.Doc,
{
signaling = [
"wss://signaling.yjs.dev",
"wss://y-webrtc-signaling-eu.herokuapp.com",
"wss://y-webrtc-signaling-us.herokuapp.com",
],
password = undefined as undefined | string,
// awareness = new awarenessProtocol.Awareness(doc),
maxConns = 20 + math.floor(random.rand() * 15), // the random factor reduces the chance that n clients form a cluster
filterBcConns = true,
peerOpts = {}, // simple-peer options. See https://github.com/feross/simple-peer#peer--new-peeropts
} = {}
) {
super();
this.filterBcConns = filterBcConns;
// this.awareness = awareness;
this.shouldConnect = false;
this.signalingUrls = signaling;
this.signalingConns = [];
this.maxConns = maxConns;
this.peerOpts = { iceServers: [] };
this.key = password
? cryptoutils.deriveKey(password, roomName)
: Promise.resolve(undefined);

this.key.then((key) => {
this.room = openRoom(
this,
this.onCustomMessage,
this.onPeerConnected,
roomName,
key
);
if (this.shouldConnect) {
this.room.connect();
} else {
this.room.disconnect();
}
});
this.connect();
// this.destroy = this.destroy.bind(this);
// doc.on("destroy", this.destroy);

// window.addEventListener("beforeunload", () => {
// awarenessProtocol.removeAwarenessStates(
// this.awareness,
// [doc.clientID],
// "window unload"
// );
// globalRooms.forEach((room) => {
// room.disconnect();
// });
// });
}

/**
* @type {boolean}
*/
get connected() {
return this.room !== null && this.shouldConnect;
}

connect() {
this.shouldConnect = true;
this.signalingUrls.forEach((url) => {
const signalingConn = map.setIfUndefined(
globalSignalingConns,
url,
() => new SignalingConn(url)
);
this.signalingConns.push(signalingConn);
signalingConn.providers.add(this);
});
if (this.room) {
this.room.connect();
}
}

disconnect() {
this.shouldConnect = false;
this.signalingConns.forEach((conn) => {
conn.providers.delete(this);
if (conn.providers.size === 0) {
conn.destroy();
globalSignalingConns.delete(conn.url);
}
});
if (this.room) {
this.room.disconnect();
}
}

destroy() {
// need to wait for key before deleting room
this.key.then(() => {
this.room?.destroy();
globalRooms.delete(this.roomName);
});
super.destroy();
}
}
Loading