diff --git a/README.md b/README.md index 61ed19378..873676303 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,12 @@ const peer = new Peer("pick-an-id"); // You can pick your own id or omit the id if you want to get a random one from the server. ``` +**Socketio?** +* not supported on the official peer server you need to launch your own using this [link](https://github.com/Judimax/peerjs-server/tree/PR-socketio-support) +```js +const peer = new Peer("pick-an-id",{clientType:"socketio"}); +``` + ## Data connections **Connect** diff --git a/lib/baseconnection.ts b/lib/baseconnection.ts index 8c0c18402..424b09e6c 100644 --- a/lib/baseconnection.ts +++ b/lib/baseconnection.ts @@ -29,13 +29,10 @@ export interface BaseConnectionEvents< iceStateChanged: (state: RTCIceConnectionState) => void; } -export abstract class BaseConnection< - SubClassEvents extends ValidEventTypes, - ErrorType extends string = never, -> extends EventEmitterWithError< - ErrorType | BaseConnectionErrorType, - SubClassEvents & BaseConnectionEvents -> { +export abstract class BaseConnection extends + EventEmitterWithError< + ErrorType | BaseConnectionErrorType, SubClassEvents & BaseConnectionEvents + > { protected _open = false; /** diff --git a/lib/dataconnection/BufferedConnection/BinaryPack.ts b/lib/dataconnection/BufferedConnection/BinaryPack.ts index 856b86580..b516ae7da 100644 --- a/lib/dataconnection/BufferedConnection/BinaryPack.ts +++ b/lib/dataconnection/BufferedConnection/BinaryPack.ts @@ -4,6 +4,7 @@ import type { Peer } from "../../peer"; import { BufferedConnection } from "./BufferedConnection"; import { SerializationType } from "../../enums"; import { pack, type Packable, unpack } from "peerjs-js-binarypack"; +import { decode, encode } from "@msgpack/msgpack"; export class BinaryPack extends BufferedConnection { private readonly chunker = new BinaryPackChunker(); @@ -28,11 +29,19 @@ export class BinaryPack extends BufferedConnection { // Handles a DataChannel message. protected override _handleDataMessage({ data }: { data: Uint8Array }): void { - const deserializedData = unpack(data); - + let deserializedData + if(this.options.msgpackType ==="peerjs"){ + deserializedData = unpack(data); + }else{ + deserializedData = decode(data); + } // PeerJS specific message + // console.log(data) + // console.log(deserializedData) const peerData = deserializedData["__peerData"]; if (peerData) { + + if (peerData.type === "close") { this.close(); return; @@ -53,6 +62,7 @@ export class BinaryPack extends BufferedConnection { total: number; data: ArrayBuffer; }): void { + logger.chunk(data) const id = data.__peerData; const chunkInfo = this._chunkedData[id] || { data: [], @@ -76,7 +86,13 @@ export class BinaryPack extends BufferedConnection { } protected override _send(data: Packable, chunked: boolean) { - const blob = pack(data); + + let blob + if(this.options.msgpackType ==="peerjs"){ + blob = pack(data); + }else{ + blob = encode(data); + } if (blob instanceof Promise) { return this._send_blob(blob); } @@ -88,6 +104,7 @@ export class BinaryPack extends BufferedConnection { this._bufferedSend(blob); } + private async _send_blob(blobPromise: Promise) { const blob = await blobPromise; if (blob.byteLength > this.chunker.chunkedMTU) { @@ -99,10 +116,13 @@ export class BinaryPack extends BufferedConnection { } private _sendChunks(blob: ArrayBuffer) { + this.chunker.chunkedMTU = this.messageSize; const blobs = this.chunker.chunk(blob); - logger.log(`DC#${this.connectionId} Try to send ${blobs.length} chunks...`); + logger.chunk(`DC#${this.connectionId} Try to send ${blobs.length} chunks...`); + for (const blob of blobs) { + logger.chunk(`chunk data ${blob.toString()}`); this.send(blob, true); } } diff --git a/lib/dataconnection/BufferedConnection/binaryPackChunker.ts b/lib/dataconnection/BufferedConnection/binaryPackChunker.ts index 168529fa6..26c133465 100644 --- a/lib/dataconnection/BufferedConnection/binaryPackChunker.ts +++ b/lib/dataconnection/BufferedConnection/binaryPackChunker.ts @@ -1,5 +1,5 @@ export class BinaryPackChunker { - readonly chunkedMTU = 16300; // The original 60000 bytes setting does not work when sending data from Firefox to Chrome, which is "cut off" after 16384 bytes and delivered individually. + chunkedMTU = 16300; // The original 60000 bytes setting does not work when sending data from Firefox to Chrome, which is "cut off" after 16384 bytes and delivered individually. // Binary stuff diff --git a/lib/dataconnection/DataConnection.ts b/lib/dataconnection/DataConnection.ts index 828fe80e5..7bcdb2432 100644 --- a/lib/dataconnection/DataConnection.ts +++ b/lib/dataconnection/DataConnection.ts @@ -11,6 +11,7 @@ import { BaseConnection, type BaseConnectionEvents } from "../baseconnection"; import type { ServerMessage } from "../servermessage"; import type { EventsWithError } from "../peerError"; import { randomToken } from "../utils/randomToken"; +import { BinaryPackChunker } from "./BufferedConnection/binaryPackChunker"; export interface DataConnectionEvents extends EventsWithError, @@ -38,6 +39,7 @@ export abstract class DataConnection extends BaseConnection< private _negotiator: Negotiator; abstract readonly serialization: string; readonly reliable: boolean; + messageSize =new BinaryPackChunker().chunkedMTU; public get type() { return ConnectionType.Data; @@ -62,13 +64,45 @@ export abstract class DataConnection extends BaseConnection< ); } + protected parseMaximumSize(description?: RTCSessionDescription): number { + const remoteLines = description?.sdp?.split('\r\n') ?? []; + logger.log("peerDescription\n" +remoteLines) + let remoteMaximumSize = 0; + for (const line of remoteLines) { + if (line.startsWith('a=max-message-size:')) { + const string = line.substring('a=max-message-size:'.length); + remoteMaximumSize = parseInt(string, 10); + break; + } + } + + if (remoteMaximumSize === 0) { + logger.log('SENDER: No max message size session description'); + } + + // 16 kb should be supported on all clients so we can use it + // even if no max message is set + return Math.max(remoteMaximumSize, (new BinaryPackChunker()).chunkedMTU); + } + + protected async updateMaximumMessageSize(): Promise { + const local = await this.peerConnection!.localDescription; + const remote = await this.peerConnection!.remoteDescription; + const localMaximumSize = this.parseMaximumSize(local); + const remoteMaximumSize = this.parseMaximumSize(remote); + this.messageSize = Math.min(localMaximumSize, remoteMaximumSize); + + logger.log(`SENDER: Updated max message size: ${this.messageSize} Local: ${localMaximumSize} Remote: ${remoteMaximumSize}`); + } + /** Called by the Negotiator when the DataChannel is ready. */ override _initializeDataChannel(dc: RTCDataChannel): void { this.dataChannel = dc; - this.dataChannel.onopen = () => { + this.dataChannel.onopen = async () => { logger.log(`DC#${this.connectionId} dc connection success`); this._open = true; + await this.updateMaximumMessageSize() this.emit("open"); }; diff --git a/lib/logger.ts b/lib/logger.ts index fe4a55ebb..5f049ac0b 100644 --- a/lib/logger.ts +++ b/lib/logger.ts @@ -24,6 +24,10 @@ export enum LogLevel { * Prints all logs. */ All, + /** + * prints data Chunks + */ + DataChunk } class Logger { @@ -37,6 +41,12 @@ class Logger { this._logLevel = logLevel; } + chunk(...args: any[]) { + if (this._logLevel >= LogLevel.DataChunk) { + this._print(LogLevel.DataChunk, ...args); + } + } + log(...args: any[]) { if (this._logLevel >= LogLevel.All) { this._print(LogLevel.All, ...args); diff --git a/lib/peer.ts b/lib/peer.ts index 6fa306cbc..6ee710efd 100644 --- a/lib/peer.ts +++ b/lib/peer.ts @@ -65,6 +65,15 @@ class PeerOptions implements PeerJSOption { referrerPolicy?: ReferrerPolicy; logFunction?: (logLevel: LogLevel, ...rest: any[]) => void; serializers?: SerializerMapping; + /** + * choose whether peerjs will be a websocket client or a socketio client + */ + clientType?:"websocket" | "socketio" + /** + * whether to use peerjs own implemation or the standard it recommended to use the standard for cross platform + */ + msgpackType?:"standard" | "peerjs" + } export { type PeerOptions }; @@ -233,6 +242,8 @@ export class Peer extends EventEmitterWithError { config: util.defaultConfig, referrerPolicy: "strict-origin-when-cross-origin", serializers: {}, + clientType:"websocket", + msgpackType:"peerjs", ...options, }; this._options = options; @@ -288,13 +299,20 @@ export class Peer extends EventEmitterWithError { return; } + if (userId) { - this._initialize(userId); + this._initialize(userId).catch((error) => this._abort(PeerErrorType.ServerError, error)); } else { - this._api + if(this.options.clientType === "websocket"){ + this._api .retrieveId() .then((id) => this._initialize(id)) .catch((error) => this._abort(PeerErrorType.ServerError, error)); + } + else{ + this._initialize().catch((error) => this._abort(PeerErrorType.ServerError, error)); + } + } } @@ -305,6 +323,7 @@ export class Peer extends EventEmitterWithError { this._options.port!, this._options.path!, this._options.key!, + this._options.clientType, this._options.pingInterval, ); @@ -340,11 +359,16 @@ export class Peer extends EventEmitterWithError { } /** Initialize a connection with the server. */ - private _initialize(id: string): void { - this._id = id; - this.socket.start(id, this._options.token!); + private async _initialize(id?: string): Promise { + if(this.options.clientType === "websocket"){ + + this._id = id; + await this.socket.start(id, this._options.token!); + } else{ + await this.socket.start(id, this._options.token!); + this._id = this._socket._socketio.id + } } - /** Handles messages from the server. */ private _handleMessage(message: ServerMessage): void { const type = message.type; @@ -705,14 +729,15 @@ export class Peer extends EventEmitterWithError { * Destroyed peers cannot be reconnected. * If the connection fails (as an example, if the peer's old ID is now taken), * the peer's existing connections will not close, but any associated errors events will fire. + * should not be called often or at all with a socketio connection */ - reconnect(): void { + async reconnect() { if (this.disconnected && !this.destroyed) { logger.log( `Attempting reconnection to server with ID ${this._lastServerId}`, ); this._disconnected = false; - this._initialize(this._lastServerId!); + await this._initialize(this._lastServerId!); } else if (this.destroyed) { throw new Error( "This peer cannot reconnect to the server. It has already been destroyed.", diff --git a/lib/socket.ts b/lib/socket.ts index 31e6ae069..6319dfe34 100644 --- a/lib/socket.ts +++ b/lib/socket.ts @@ -2,6 +2,8 @@ import { EventEmitter } from "eventemitter3"; import logger from "./logger"; import { ServerMessageType, SocketEventType } from "./enums"; import { version } from "../package.json"; +import { PeerOptions } from "./peer"; +import { io, Socket as IOSocket } from "socket.io-client"; /** * An abstraction on top of WebSockets to provide fastest @@ -11,9 +13,13 @@ export class Socket extends EventEmitter { private _disconnected: boolean = true; private _id?: string; private _messagesQueue: Array = []; - private _socket?: WebSocket; + private _websocket?: WebSocket + _socketio?:IOSocket private _wsPingTimer?: any; - private readonly _baseUrl: string; + private readonly _baseWebSocketUrl: string; + private readonly _baseSocketioUrl: string + private _baseSocketioQueryParams: Object + private _clientType:PeerOptions["clientType"]="websocket" constructor( secure: any, @@ -21,67 +27,141 @@ export class Socket extends EventEmitter { port: number, path: string, key: string, + clientType:PeerOptions["clientType"], private readonly pingInterval: number = 5000, ) { super(); const wsProtocol = secure ? "wss://" : "ws://"; - this._baseUrl = wsProtocol + host + ":" + port + path + "peerjs?key=" + key; - } - - start(id: string, token: string): void { - this._id = id; - - const wsUrl = `${this._baseUrl}&id=${id}&token=${token}`; - - if (!!this._socket || !this._disconnected) { - return; + this._baseWebSocketUrl = wsProtocol + host + ":" + port + path + "peerjs?key=" + key; + this._baseSocketioUrl =wsProtocol + host + ":" + port; + this._baseSocketioQueryParams = { + key } + this._clientType = clientType + } - this._socket = new WebSocket(wsUrl + "&version=" + version); - this._disconnected = false; - - this._socket.onmessage = (event) => { - let data; - - try { - data = JSON.parse(event.data); - logger.log("Server message received:", data); - } catch (e) { - logger.log("Invalid server message", event.data); - return; + async start(id: string, token: string) { + return new Promise((resolve,reject)=>{ + let isResolved = false; + if (this._clientType === "websocket") { + resolve(); + this._id = id; } - this.emit(SocketEventType.Message, data); - }; - - this._socket.onclose = (event) => { - if (this._disconnected) { + if (!!this._websocket || !this._disconnected || !!this._socketio) { return; } - logger.log("Socket closed.", event); - this._cleanup(); - this._disconnected = true; + if (this._clientType === "websocket") { + const wsUrl = `${this._baseWebSocketUrl}&id=${id}&token=${token}`; + this._websocket = new WebSocket(wsUrl + "&version=" + version); + } else { + this._socketio = io(this._baseSocketioUrl+"/peerjs", + { + query:{ + ...this._baseSocketioQueryParams, + token,version + } - this.emit(SocketEventType.Disconnected); - }; + } + ); - // Take care of the queue of connections if necessary and make sure Peer knows - // socket is open. - this._socket.onopen = () => { - if (this._disconnected) { - return; } + this._disconnected = false; + + if (this._clientType === "websocket") { + this._websocket.onmessage = (event) => { + let data; + try { + data = JSON.parse(event.data); + logger.log("Server message received:", data); + } catch (e) { + logger.log("Invalid server message", event.data); + return; + } + + this.emit(SocketEventType.Message, data); + }; + + this._websocket.onclose = (event) => { + if (this._disconnected) { + return; + } + + logger.log("Socket closed.", event); + + this._cleanup(); + this._disconnected = true; + this.emit(SocketEventType.Disconnected); + if (!isResolved) { + reject('WebSocket connection closed'); + isResolved = true; + } + }; + + // Take care of the queue of connections if necessary and make sure Peer knows + // socket is open. + this._websocket.onopen = () => { + if (this._disconnected) { + return; + } + + this._sendQueuedMessages(); + logger.log("Socket open"); + this._scheduleHeartbeat(); + if (!isResolved) { + resolve(); + isResolved = true; + } + }; + } + else { + this._socketio.on("message", (data: any) => { + try { + logger.log("Server message received:", data); + } catch (e) { + logger.log("Invalid server message", data); + return; + } + + this.emit(SocketEventType.Message, data); + }); + + this._socketio.on("disconnect", (reason: string) => { + if (this._disconnected) { + return; + } + + logger.log("Socket closed.", reason); + this._cleanup(); + this._disconnected = true; + this.emit(SocketEventType.Disconnected); + if (!isResolved) { + reject(reason); + isResolved = true; + } + }); + + this._socketio.on("connect", () => { + this._id = this._socketio.id + if (this._disconnected) { + return; + } + + this._sendQueuedMessages(); + + logger.log("Socket open"); + if (!isResolved) { + resolve(); + isResolved = true; + } + }); - this._sendQueuedMessages(); - - logger.log("Socket open"); - - this._scheduleHeartbeat(); - }; + } + }); } private _scheduleHeartbeat(): void { @@ -96,16 +176,24 @@ export class Socket extends EventEmitter { return; } - const message = JSON.stringify({ type: ServerMessageType.Heartbeat }); + const message = { type: ServerMessageType.Heartbeat }; + + if (this._clientType === "websocket") {///////////// add ////////// + this._websocket.send(JSON.stringify(message)); + this._scheduleHeartbeat(); + } - this._socket!.send(message); - this._scheduleHeartbeat(); } /** Is the websocket currently open? */ private _wsOpen(): boolean { - return !!this._socket && this._socket.readyState === 1; + if (this._clientType === "websocket") { + return !!this._websocket && this._websocket.readyState === WebSocket.OPEN; + } + else{ + return !!this._socketio && this._socketio.connected; + } } /** Send queued messages. */ @@ -142,9 +230,12 @@ export class Socket extends EventEmitter { return; } - const message = JSON.stringify(data); - - this._socket!.send(message); + if (this._clientType === "websocket") { + const message = JSON.stringify(data); + this._websocket.send(message); + } else { + this._socketio.emit("message", data); + } } close(): void { @@ -158,14 +249,26 @@ export class Socket extends EventEmitter { } private _cleanup(): void { - if (this._socket) { - this._socket.onopen = - this._socket.onmessage = - this._socket.onclose = - null; - this._socket.close(); - this._socket = undefined; + if (this._clientType === "websocket"){ + if (this._websocket) { + this._websocket.onopen = + this._websocket.onmessage = + this._websocket.onclose = + null; + this._websocket.close(); + this._websocket = undefined; + } } + else{ + if(this._socketio){ + this._socketio.off("connect"); + this._socketio.off("message"); + this._socketio.off("disconnect"); + this._socketio.close(); + this._socketio = undefined + } + } + clearTimeout(this._wsPingTimer!); } diff --git a/package-lock.json b/package-lock.json index c085bf5d9..4a01e7ad4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@msgpack/msgpack": "^2.8.0", "eventemitter3": "^4.0.7", "peerjs-js-binarypack": "^2.1.0", + "socket.io-client": "^4.7.5", "webrtc-adapter": "^9.0.0" }, "devDependencies": { @@ -35,8 +36,10 @@ "jest": "^29.3.1", "jest-environment-jsdom": "^29.3.1", "mock-socket": "^9.0.0", + "nodemon": "^3.1.3", "parcel": "^2.9.3", "prettier": "^3.0.0", + "rimraf": "^5.0.7", "semantic-release": "^23.0.0", "ts-node": "^10.9.1", "typescript": "^5.0.0", @@ -4269,6 +4272,11 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + }, "node_modules/@swc/core": { "version": "1.5.25", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.5.25.tgz", @@ -7316,7 +7324,6 @@ "version": "4.3.5", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.1.2" @@ -7900,6 +7907,26 @@ "once": "^1.4.0" } }, + "node_modules/engine.io-client": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz", + "integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", + "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -9872,6 +9899,12 @@ "node": ">= 4" } }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, "node_modules/immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", @@ -12588,7 +12621,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, "license": "MIT" }, "node_modules/msgpackr": { @@ -12820,6 +12852,77 @@ "strict-event-emitter": "^0.1.0" } }, + "node_modules/nodemon": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", + "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/normalize-package-data": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.1.tgz", @@ -16523,6 +16626,12 @@ "dev": true, "license": "MIT" }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -17405,65 +17514,23 @@ "license": "MIT" }, "node_modules/rimraf": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", - "integrity": "sha512-Lw7SHMjssciQb/rRz7JyPIy9+bbUshEucPoLRvWqy09vC5zQixl8Uet+Zl+SROBB/JMWHJRdCk1qdxNWHNMvlQ==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", + "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", "dev": true, - "license": "ISC", "dependencies": { - "glob": "^7.0.5" + "glob": "^10.3.7" }, "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "rimraf": "dist/esm/bin.mjs" }, "engines": { - "node": "*" + "node": ">=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/run-async": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", @@ -18199,6 +18266,18 @@ "node": ">=4" } }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -18240,6 +18319,32 @@ "npm": ">= 3.0.0" } }, + "node_modules/socket.io-client": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz", + "integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/socks": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", @@ -18906,6 +19011,62 @@ "node": ">=0.8.0" } }, + "node_modules/temp-fs/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/temp-fs/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/temp-fs/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/temp-fs/node_modules/rimraf": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha512-Lw7SHMjssciQb/rRz7JyPIy9+bbUshEucPoLRvWqy09vC5zQixl8Uet+Zl+SROBB/JMWHJRdCk1qdxNWHNMvlQ==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.0.5" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/tempy": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", @@ -19192,6 +19353,15 @@ "node": ">=8.0" } }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, "node_modules/tough-cookie": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", @@ -19496,6 +19666,12 @@ "through": "^2.3.8" } }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -20098,11 +20274,9 @@ } }, "node_modules/ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", - "dev": true, - "license": "MIT", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "engines": { "node": ">=10.0.0" }, @@ -20136,6 +20310,14 @@ "dev": true, "license": "MIT" }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 9acfd30eb..9feba5673 100644 --- a/package.json +++ b/package.json @@ -117,10 +117,13 @@ "source": "lib/exports.ts" }, "main": { - "source": "lib/exports.ts", - "sourceMap": { - "inlineSources": true - } + "context": "browser", + "includeNodeModules": true, + "outputFormat": "esmodule", + "distDir": "./dist", + "publicUrl": "./", + "isLibrary": false, + "sourceMap": true }, "module": { "source": "lib/exports.ts", @@ -147,7 +150,10 @@ "engines": { "browsers": "chrome >= 83, edge >= 83, firefox >= 80, safari >= 15" }, - "source": "lib/global.ts" + "source": "lib/global.ts", + "sourceMap": { + "inlineSources": true + } }, "browser-minified-msgpack": { "context": "browser", @@ -164,7 +170,9 @@ "contributors": "git-authors-cli --print=false && prettier --write package.json && git add package.json package-lock.json && git commit -m \"chore(contributors): update and sort contributors list\"", "check": "tsc --noEmit && tsc -p e2e/tsconfig.json --noEmit", "watch": "parcel watch", - "build": "rm -rf dist && parcel build", + "watch:dev": "parcel watch lib/global.ts --dist-dir lib ", + "build": "rimraf dist && parcel build", + "dev": "nodemon --watch lib -e ts --exec \"npm run build \"", "prepublishOnly": "npm run build", "test": "jest", "test:watch": "jest --watch", @@ -196,8 +204,10 @@ "jest": "^29.3.1", "jest-environment-jsdom": "^29.3.1", "mock-socket": "^9.0.0", + "nodemon": "^3.1.3", "parcel": "^2.9.3", "prettier": "^3.0.0", + "rimraf": "^5.0.7", "semantic-release": "^23.0.0", "ts-node": "^10.9.1", "typescript": "^5.0.0", @@ -207,6 +217,7 @@ "@msgpack/msgpack": "^2.8.0", "eventemitter3": "^4.0.7", "peerjs-js-binarypack": "^2.1.0", + "socket.io-client": "^4.7.5", "webrtc-adapter": "^9.0.0" }, "alias": {