Comparing version 2.0.0-beta.0 to 2.0.0
@@ -1,8 +0,8 @@ | ||
class EventEmitter{constructor(){this.listeners={};}on(a,b){return this.listeners[a]=this.listeners[a]||[],this.listeners[a].push(b),this}off(c,d){let a=this.listeners[c];if(!a)return this;for(let b=a.length;b>0;b-=1)if(a[b]===d){a.splice(b,1);break}return this}emit(d){for(var b=arguments.length,e=new Array(b>1?b-1:0),a=1;a<b;a++)e[a-1]=arguments[a];let c=this.listeners[d];return !!c&&(c.forEach(a=>{a(...e);}),!0)}} | ||
class EventEmitter{constructor(){this.eventMap={};}emit(d){for(var b=arguments.length,e=new Array(b>1?b-1:0),a=1;a<b;a++)e[a-1]=arguments[a];let c=this.eventMap[d];return !!c&&(c.forEach(a=>{a(...e);}),!0)}on(a,c){var b;return this.eventMap[a]=null!==(b=this.eventMap[a])&& void 0!==b?b:[],this.eventMap[a].push(c),this}off(d,e){var b;let c=null!==(b=this.eventMap[d])&& void 0!==b?b:[];for(let a=c.length;a>0;a-=1)if(c[a]===e){c.splice(a,1);break}return this}offAll(a){if(a){let b=this.eventMap[a];if(!b)return this;delete this.eventMap[a];}else this.eventMap={};return this}} | ||
function getDefaultCamConstraints(){let a={},b=navigator.mediaDevices.getSupportedConstraints();b.facingMode&&(a.facingMode="user"),b.frameRate&&(a.frameRate={max:30});let c=!(Object.keys(a).length>0)||a;return {audio:!0,video:c}}function randomHex(b){let a=new Uint8Array(b);return crypto.getRandomValues(a),Array.from(a).map(a=>a.toString(16).padStart(2,"0")).join("")}function filterByTrack(a){return b=>b===a}function removeTracks(a,b){a.getTracks().filter(b).forEach(b=>{b.stop(),a.removeTrack(b);});}function removeTracksFromPeer(a,b){a.getSenders().filter(a=>a.track&&b(a.track)).forEach(b=>a.removeTrack(b));} | ||
class g{constructor(b){this.streamLocal=new MediaStream,this.channels=new Map,this.channelsPending=new Map,this.emitter=new EventEmitter,this.polite=!0,this.isActive=!1,this.makingOffer=!1,this.ignoreOffer=!1,this.options={batchCandidates:!0,batchCandidatesTimeout:200,name:"peer",config:{iceServers:[{urls:["stun:stun.l.google.com:19302"]}]},offerOptions:{},enableDataChannels:!1,channelLabel:randomHex(20),channelOptions:{},sdpTransform:a=>a},this.options={...this.options,...b},this.peer=this.init();}init(){if("new"===this.status())return this.peer;this.destroy(),this.peer=new RTCPeerConnection(this.options.config),this.streamLocal.getTracks().forEach(a=>this.peer.addTrack(a,this.streamLocal));let{channelLabel:a,channelOptions:b,enableDataChannels:c}=this.options;c&&this.addDataChannel(a,b);let d=[],e;function f(){clearTimeout(e),d.length=0;}return this.peer.onicecandidate=a=>{(null==a?void 0:a.candidate)&&(this.options.batchCandidates?(clearTimeout(e),d.push(a.candidate),"complete"===this.peer.iceGatheringState?this.emit("onicecandidates",d):e=setTimeout(()=>{d.length&&(this.emit("onicecandidates",d),f());},this.options.batchCandidatesTimeout)):this.emit("onicecandidates",[a.candidate]));},this.peer.ontrack=a=>{a.streams&&this.emit("streamRemote",a.streams[0]);},this.peer.oniceconnectionstatechange=()=>{switch(this.emit("status",this.status()),this.status()){case"closed":case"failed":case"disconnected":f(),this.destroy();break;case"checking":this.emit("connecting");break;case"connected":this.emit("connected");}},this.peer.onnegotiationneeded=async()=>{try{if(!this.isActive)return;this.makingOffer=!0;let{offerOptions:c,sdpTransform:d}=this.options;this.createDataChannels();let a=await this.peer.createOffer(c);if("stable"!==this.peer.signalingState)return;a.sdp=a.sdp&&d(a.sdp),await this.peer.setLocalDescription(a),this.peer.localDescription&&this.emit("signal",this.peer.localDescription);}catch(b){b instanceof Error&&this.error("Failed in negotiationNeeded",b);}finally{this.makingOffer=!1;}},this.peer.ondatachannel=b=>{let{channel:a}=b;this.options.enableDataChannels&&(this.channels.set(a.label,a),this.addDataChannelEvents(a));},this.peer}start(){let{polite:b=!0}=arguments.length>0&& void 0!==arguments[0]?arguments[0]:{};try{"have-local-offer"===this.peer.signalingState&&this.destroy(),this.isClosed()&&this.init(),this.isActive=!0,this.polite=b,this.peer.restartIce();}catch(a){if(a instanceof Error)throw this.error("Failed to start",a),a}}async signal(b){try{this.isClosed()&&this.init(),this.isActive=!0;let d="offer"===b.type&&(this.makingOffer||"stable"!==this.peer.signalingState);if(this.ignoreOffer=!this.polite&&d,this.ignoreOffer)return;if(await this.peer.setRemoteDescription(b),"offer"===b.type){this.createDataChannels();let a=await this.peer.createAnswer();a.sdp=a.sdp&&this.options.sdpTransform(a.sdp),await this.peer.setLocalDescription(a),this.emit("signal",a);}this.polite=!0;}catch(c){if(c instanceof Error)throw this.error("Failed to signal",c),c}}async addIceCandidate(b){try{await this.peer.addIceCandidate(b);}catch(a){if(!this.ignoreOffer&&a instanceof Error)throw this.error("Failed to addIceCandidate",a),a}}send(b){let c=arguments.length>1&& void 0!==arguments[1]?arguments[1]:this.options.channelLabel,a=this.channels.get(c);return (null==a?void 0:a.readyState)==="open"&&!!b&&(a.send(b),this.emit("channelData",{channel:a,data:b,source:"outgoing"}),!0)}addDataChannel(){let a=arguments.length>0&& void 0!==arguments[0]?arguments[0]:this.options.channelLabel,b=arguments.length>1&& void 0!==arguments[1]?arguments[1]:{};if(!this.options.enableDataChannels){this.error('Failed to addDataChannel as "enableDataChannels" is false');return}if(this.isClosed()){this.error("Failed to addDataChannel as peer connection is closed");return}this.channels.has(a)||this.channelsPending.set(a,b),this.isActive&&this.createDataChannels();}getDataChannel(){let a=arguments.length>0&& void 0!==arguments[0]?arguments[0]:this.options.channelLabel;return this.channels.get(a)}createDataChannels(){try{Array.from(this.channelsPending.entries()).forEach(c=>{let[a,d]=c,b=this.peer.createDataChannel(a,d);this.channels.set(a,b),this.addDataChannelEvents(b);}),this.channelsPending.clear();}catch(a){if(a instanceof Error)throw this.error("Failed to createDataChannels",a),a}}addDataChannelEvents(a){a.onopen=()=>this.emit("channelOpen",{channel:a}),a.onerror=b=>{this.emit("channelError",{channel:a,event:b});},a.onclose=()=>{this.channels.delete(a.label),this.emit("channelClosed",{channel:a});},a.onmessage=b=>{this.emit("channelData",{channel:a,data:b.data,source:"incoming"});};}destroy(){this.isClosed()||(this.polite=!0,this.isActive=!1,this.makingOffer=!1,this.ignoreOffer=!1,this.channels.clear(),this.channelsPending.clear(),this.peer.close(),this.emit("disconnected"));}status(){var a,b;return null!==(b=null===(a=this.peer)|| void 0===a?void 0:a.iceConnectionState)&& void 0!==b?b:"closed"}isConnected(){return "connected"===this.status()}isClosed(){return "closed"===this.status()}get(){return this.peer}getStreamLocal(){return this.streamLocal}error(a,b){this.emit("error",{name:this.options.name,message:a,error:b});}addStream(a){let b=arguments.length>1&& void 0!==arguments[1]&&arguments[1];b&&this.removeTracks(this.streamLocal.getTracks()),a.getTracks().forEach(a=>this.addTrack(a));}removeStream(a){this.removeTracks(a.getTracks());}addTrack(b){try{this.streamLocal.addTrack(b),this.emit("streamLocal",this.streamLocal),this.isClosed()||this.peer.addTrack(b,this.streamLocal);}catch(a){if(a instanceof Error)throw this.error("Failed to addTrack",a),a}}removeTracks(a){a.forEach(a=>this.removeTrack(a));}removeTrack(a){removeTracks(this.streamLocal,filterByTrack(a)),this.isClosed()||removeTracksFromPeer(this.peer,filterByTrack(a));}async replaceTrack(c,d){try{if(!this.isClosed()){let[f]=this.peer.getSenders().filter(a=>a.track===c);f?(removeTracks(this.streamLocal,filterByTrack(c)),this.streamLocal.addTrack(d),await f.replaceTrack(d),this.emit("streamLocal",this.streamLocal)):this.error(`Failed to find track to replace: ${c.id}`);}}catch(a){if(a instanceof Error)throw this.error("Failed to replaceTrack",a),a}}on(a,b){return this.emitter.on(a,b)}off(a,b){return this.emitter.off(a,b)}emit(d){for(var b=arguments.length,c=new Array(b>1?b-1:0),a=1;a<b;a++)c[a-1]=arguments[a];return this.emitter.emit(d,...c)}static getUserMedia(a){return navigator.mediaDevices.getUserMedia({...getDefaultCamConstraints(),...a})}} | ||
class g{constructor(b){this.streamLocal=new MediaStream,this.channels=new Map,this.channelsPending=new Map,this.emitter=new EventEmitter,this.polite=!0,this.isActive=!1,this.makingOffer=!1,this.ignoreOffer=!1,this.options={batchCandidates:!0,batchCandidatesTimeout:200,id:randomHex(4),config:{iceServers:[{urls:["stun:stun.l.google.com:19302"]}]},offerOptions:{},enableDataChannels:!1,channelLabel:randomHex(20),channelOptions:{},sdpTransform:a=>a},this.options={...this.options,...b},this.peer=this.init();}init(){if("new"===this.status())return this.peer;this.destroy(),this.peer=new RTCPeerConnection(this.options.config),this.streamLocal.getTracks().forEach(a=>this.peer.addTrack(a,this.streamLocal));let{channelLabel:a,channelOptions:b,enableDataChannels:c}=this.options;c&&this.addDataChannel(a,b);let d=[],e;function f(){clearTimeout(e),d.length=0;}return this.peer.onicecandidate=a=>{(null==a?void 0:a.candidate)&&(this.options.batchCandidates?(clearTimeout(e),d.push(a.candidate),"complete"===this.peer.iceGatheringState?this.emit("onicecandidates",d):e=setTimeout(()=>{d.length&&(this.emit("onicecandidates",d),f());},this.options.batchCandidatesTimeout)):this.emit("onicecandidates",[a.candidate]));},this.peer.ontrack=a=>{a.streams&&this.emit("streamRemote",a.streams[0]);},this.peer.oniceconnectionstatechange=()=>{switch(this.emit("status",this.status()),this.status()){case"closed":case"failed":case"disconnected":f(),this.destroy();break;case"checking":this.emit("connecting");break;case"connected":this.emit("connected");}},this.peer.onnegotiationneeded=async()=>{try{if(!this.isActive)return;this.makingOffer=!0;let{offerOptions:c,sdpTransform:d}=this.options;this.createDataChannels();let a=await this.peer.createOffer(c);if("stable"!==this.peer.signalingState)return;a.sdp=a.sdp&&d(a.sdp),await this.peer.setLocalDescription(a),this.peer.localDescription&&this.emit("signal",this.peer.localDescription);}catch(b){b instanceof Error&&this.error("Failed in negotiationNeeded",b);}finally{this.makingOffer=!1;}},this.peer.ondatachannel=b=>{let{channel:a}=b;this.options.enableDataChannels&&(this.channels.set(a.label,a),this.addDataChannelEvents(a));},this.peer}start(){let{polite:b=!0}=arguments.length>0&& void 0!==arguments[0]?arguments[0]:{};try{"have-local-offer"===this.peer.signalingState&&this.destroy(),this.isClosed()&&this.init(),this.isActive=!0,this.polite=b,this.peer.restartIce();}catch(a){if(a instanceof Error)throw this.error("Failed to start",a),a}}async signal(b){try{this.isClosed()&&this.init(),this.isActive=!0;let d="offer"===b.type&&(this.makingOffer||"stable"!==this.peer.signalingState);if(this.ignoreOffer=!this.polite&&d,this.ignoreOffer)return;if(await this.peer.setRemoteDescription(b),"offer"===b.type){this.createDataChannels();let a=await this.peer.createAnswer();a.sdp=a.sdp&&this.options.sdpTransform(a.sdp),await this.peer.setLocalDescription(a),this.emit("signal",a);}this.polite=!0;}catch(c){if(c instanceof Error)throw this.error("Failed to signal",c),c}}async addIceCandidate(b){try{await this.peer.addIceCandidate(b);}catch(a){if(!this.ignoreOffer&&a instanceof Error)throw this.error("Failed to addIceCandidate",a),a}}send(b){let c=arguments.length>1&& void 0!==arguments[1]?arguments[1]:this.options.channelLabel,a=this.channels.get(c);return (null==a?void 0:a.readyState)==="open"&&!!b&&(a.send(b),this.emit("channelData",{channel:a,data:b,source:"outgoing"}),!0)}addDataChannel(){let a=arguments.length>0&& void 0!==arguments[0]?arguments[0]:this.options.channelLabel,b=arguments.length>1&& void 0!==arguments[1]?arguments[1]:{};if(!this.options.enableDataChannels){this.error('Failed to addDataChannel as "enableDataChannels" is false');return}if(this.isClosed()){this.error("Failed to addDataChannel as peer connection is closed");return}this.channels.has(a)||this.channelsPending.set(a,b),this.isActive&&this.createDataChannels();}getDataChannel(){let a=arguments.length>0&& void 0!==arguments[0]?arguments[0]:this.options.channelLabel;return this.channels.get(a)}createDataChannels(){try{Array.from(this.channelsPending.entries()).forEach(c=>{let[a,d]=c,b=this.peer.createDataChannel(a,d);this.channels.set(a,b),this.addDataChannelEvents(b);}),this.channelsPending.clear();}catch(a){if(a instanceof Error)throw this.error("Failed to createDataChannels",a),a}}addDataChannelEvents(a){a.onopen=()=>this.emit("channelOpen",{channel:a}),a.onerror=b=>{this.emit("channelError",{channel:a,event:b});},a.onclose=()=>{this.channels.delete(a.label),this.emit("channelClosed",{channel:a});},a.onmessage=b=>{this.emit("channelData",{channel:a,data:b.data,source:"incoming"});};}destroy(){this.isClosed()||(this.polite=!0,this.isActive=!1,this.makingOffer=!1,this.ignoreOffer=!1,this.channels.clear(),this.channelsPending.clear(),this.peer.close(),this.emit("disconnected"));}status(){var a,b;return null!==(b=null===(a=this.peer)|| void 0===a?void 0:a.iceConnectionState)&& void 0!==b?b:"closed"}isConnected(){return "connected"===this.status()}isClosed(){return "closed"===this.status()}get(){return this.peer}getStreamLocal(){return this.streamLocal}error(a,b){this.emit("error",{id:this.options.id,message:a,error:b});}addStream(a){let b=arguments.length>1&& void 0!==arguments[1]&&arguments[1];b&&this.removeTracks(this.streamLocal.getTracks()),a.getTracks().forEach(a=>this.addTrack(a));}removeStream(a){this.removeTracks(a.getTracks());}addTrack(b){try{this.streamLocal.addTrack(b),this.emit("streamLocal",this.streamLocal),this.isClosed()||this.peer.addTrack(b,this.streamLocal);}catch(a){if(a instanceof Error)throw this.error("Failed to addTrack",a),a}}removeTrack(a){removeTracks(this.streamLocal,filterByTrack(a)),this.isClosed()||removeTracksFromPeer(this.peer,filterByTrack(a));}removeTracks(a){a.forEach(a=>this.removeTrack(a));}async replaceTrack(c,d){try{if(!this.isClosed()){let[f]=this.peer.getSenders().filter(a=>a.track===c);f?(removeTracks(this.streamLocal,filterByTrack(c)),this.streamLocal.addTrack(d),await f.replaceTrack(d),this.emit("streamLocal",this.streamLocal)):this.error(`Failed to find track to replace: ${c.id}`);}}catch(a){if(a instanceof Error)throw this.error("Failed to replaceTrack",a),a}}on(a,b){return this.emitter.on(a,b)}off(a,b){return this.emitter.off(a,b)}offAll(a){return this.emitter.offAll(a)}emit(d){for(var b=arguments.length,c=new Array(b>1?b-1:0),a=1;a<b;a++)c[a-1]=arguments[a];return this.emitter.emit(d,...c)}static getUserMedia(a){return navigator.mediaDevices.getUserMedia({...getDefaultCamConstraints(),...a})}} | ||
export { g as default }; | ||
//# sourceMappingURL=index.es.js.map |
@@ -7,7 +7,7 @@ (function (global, factory) { | ||
class EventEmitter{constructor(){this.listeners={};}on(a,b){return this.listeners[a]=this.listeners[a]||[],this.listeners[a].push(b),this}off(c,d){let a=this.listeners[c];if(!a)return this;for(let b=a.length;b>0;b-=1)if(a[b]===d){a.splice(b,1);break}return this}emit(d){for(var b=arguments.length,e=new Array(b>1?b-1:0),a=1;a<b;a++)e[a-1]=arguments[a];let c=this.listeners[d];return !!c&&(c.forEach(a=>{a(...e);}),!0)}} | ||
class EventEmitter{constructor(){this.eventMap={};}emit(d){for(var b=arguments.length,e=new Array(b>1?b-1:0),a=1;a<b;a++)e[a-1]=arguments[a];let c=this.eventMap[d];return !!c&&(c.forEach(a=>{a(...e);}),!0)}on(a,c){var b;return this.eventMap[a]=null!==(b=this.eventMap[a])&& void 0!==b?b:[],this.eventMap[a].push(c),this}off(d,e){var b;let c=null!==(b=this.eventMap[d])&& void 0!==b?b:[];for(let a=c.length;a>0;a-=1)if(c[a]===e){c.splice(a,1);break}return this}offAll(a){if(a){let b=this.eventMap[a];if(!b)return this;delete this.eventMap[a];}else this.eventMap={};return this}} | ||
function getDefaultCamConstraints(){let a={},b=navigator.mediaDevices.getSupportedConstraints();b.facingMode&&(a.facingMode="user"),b.frameRate&&(a.frameRate={max:30});let c=!(Object.keys(a).length>0)||a;return {audio:!0,video:c}}function randomHex(b){let a=new Uint8Array(b);return crypto.getRandomValues(a),Array.from(a).map(a=>a.toString(16).padStart(2,"0")).join("")}function filterByTrack(a){return b=>b===a}function removeTracks(a,b){a.getTracks().filter(b).forEach(b=>{b.stop(),a.removeTrack(b);});}function removeTracksFromPeer(a,b){a.getSenders().filter(a=>a.track&&b(a.track)).forEach(b=>a.removeTrack(b));} | ||
class g{constructor(b){this.streamLocal=new MediaStream,this.channels=new Map,this.channelsPending=new Map,this.emitter=new EventEmitter,this.polite=!0,this.isActive=!1,this.makingOffer=!1,this.ignoreOffer=!1,this.options={batchCandidates:!0,batchCandidatesTimeout:200,name:"peer",config:{iceServers:[{urls:["stun:stun.l.google.com:19302"]}]},offerOptions:{},enableDataChannels:!1,channelLabel:randomHex(20),channelOptions:{},sdpTransform:a=>a},this.options={...this.options,...b},this.peer=this.init();}init(){if("new"===this.status())return this.peer;this.destroy(),this.peer=new RTCPeerConnection(this.options.config),this.streamLocal.getTracks().forEach(a=>this.peer.addTrack(a,this.streamLocal));let{channelLabel:a,channelOptions:b,enableDataChannels:c}=this.options;c&&this.addDataChannel(a,b);let d=[],e;function f(){clearTimeout(e),d.length=0;}return this.peer.onicecandidate=a=>{(null==a?void 0:a.candidate)&&(this.options.batchCandidates?(clearTimeout(e),d.push(a.candidate),"complete"===this.peer.iceGatheringState?this.emit("onicecandidates",d):e=setTimeout(()=>{d.length&&(this.emit("onicecandidates",d),f());},this.options.batchCandidatesTimeout)):this.emit("onicecandidates",[a.candidate]));},this.peer.ontrack=a=>{a.streams&&this.emit("streamRemote",a.streams[0]);},this.peer.oniceconnectionstatechange=()=>{switch(this.emit("status",this.status()),this.status()){case"closed":case"failed":case"disconnected":f(),this.destroy();break;case"checking":this.emit("connecting");break;case"connected":this.emit("connected");}},this.peer.onnegotiationneeded=async()=>{try{if(!this.isActive)return;this.makingOffer=!0;let{offerOptions:c,sdpTransform:d}=this.options;this.createDataChannels();let a=await this.peer.createOffer(c);if("stable"!==this.peer.signalingState)return;a.sdp=a.sdp&&d(a.sdp),await this.peer.setLocalDescription(a),this.peer.localDescription&&this.emit("signal",this.peer.localDescription);}catch(b){b instanceof Error&&this.error("Failed in negotiationNeeded",b);}finally{this.makingOffer=!1;}},this.peer.ondatachannel=b=>{let{channel:a}=b;this.options.enableDataChannels&&(this.channels.set(a.label,a),this.addDataChannelEvents(a));},this.peer}start(){let{polite:b=!0}=arguments.length>0&& void 0!==arguments[0]?arguments[0]:{};try{"have-local-offer"===this.peer.signalingState&&this.destroy(),this.isClosed()&&this.init(),this.isActive=!0,this.polite=b,this.peer.restartIce();}catch(a){if(a instanceof Error)throw this.error("Failed to start",a),a}}async signal(b){try{this.isClosed()&&this.init(),this.isActive=!0;let d="offer"===b.type&&(this.makingOffer||"stable"!==this.peer.signalingState);if(this.ignoreOffer=!this.polite&&d,this.ignoreOffer)return;if(await this.peer.setRemoteDescription(b),"offer"===b.type){this.createDataChannels();let a=await this.peer.createAnswer();a.sdp=a.sdp&&this.options.sdpTransform(a.sdp),await this.peer.setLocalDescription(a),this.emit("signal",a);}this.polite=!0;}catch(c){if(c instanceof Error)throw this.error("Failed to signal",c),c}}async addIceCandidate(b){try{await this.peer.addIceCandidate(b);}catch(a){if(!this.ignoreOffer&&a instanceof Error)throw this.error("Failed to addIceCandidate",a),a}}send(b){let c=arguments.length>1&& void 0!==arguments[1]?arguments[1]:this.options.channelLabel,a=this.channels.get(c);return (null==a?void 0:a.readyState)==="open"&&!!b&&(a.send(b),this.emit("channelData",{channel:a,data:b,source:"outgoing"}),!0)}addDataChannel(){let a=arguments.length>0&& void 0!==arguments[0]?arguments[0]:this.options.channelLabel,b=arguments.length>1&& void 0!==arguments[1]?arguments[1]:{};if(!this.options.enableDataChannels){this.error('Failed to addDataChannel as "enableDataChannels" is false');return}if(this.isClosed()){this.error("Failed to addDataChannel as peer connection is closed");return}this.channels.has(a)||this.channelsPending.set(a,b),this.isActive&&this.createDataChannels();}getDataChannel(){let a=arguments.length>0&& void 0!==arguments[0]?arguments[0]:this.options.channelLabel;return this.channels.get(a)}createDataChannels(){try{Array.from(this.channelsPending.entries()).forEach(c=>{let[a,d]=c,b=this.peer.createDataChannel(a,d);this.channels.set(a,b),this.addDataChannelEvents(b);}),this.channelsPending.clear();}catch(a){if(a instanceof Error)throw this.error("Failed to createDataChannels",a),a}}addDataChannelEvents(a){a.onopen=()=>this.emit("channelOpen",{channel:a}),a.onerror=b=>{this.emit("channelError",{channel:a,event:b});},a.onclose=()=>{this.channels.delete(a.label),this.emit("channelClosed",{channel:a});},a.onmessage=b=>{this.emit("channelData",{channel:a,data:b.data,source:"incoming"});};}destroy(){this.isClosed()||(this.polite=!0,this.isActive=!1,this.makingOffer=!1,this.ignoreOffer=!1,this.channels.clear(),this.channelsPending.clear(),this.peer.close(),this.emit("disconnected"));}status(){var a,b;return null!==(b=null===(a=this.peer)|| void 0===a?void 0:a.iceConnectionState)&& void 0!==b?b:"closed"}isConnected(){return "connected"===this.status()}isClosed(){return "closed"===this.status()}get(){return this.peer}getStreamLocal(){return this.streamLocal}error(a,b){this.emit("error",{name:this.options.name,message:a,error:b});}addStream(a){let b=arguments.length>1&& void 0!==arguments[1]&&arguments[1];b&&this.removeTracks(this.streamLocal.getTracks()),a.getTracks().forEach(a=>this.addTrack(a));}removeStream(a){this.removeTracks(a.getTracks());}addTrack(b){try{this.streamLocal.addTrack(b),this.emit("streamLocal",this.streamLocal),this.isClosed()||this.peer.addTrack(b,this.streamLocal);}catch(a){if(a instanceof Error)throw this.error("Failed to addTrack",a),a}}removeTracks(a){a.forEach(a=>this.removeTrack(a));}removeTrack(a){removeTracks(this.streamLocal,filterByTrack(a)),this.isClosed()||removeTracksFromPeer(this.peer,filterByTrack(a));}async replaceTrack(c,d){try{if(!this.isClosed()){let[f]=this.peer.getSenders().filter(a=>a.track===c);f?(removeTracks(this.streamLocal,filterByTrack(c)),this.streamLocal.addTrack(d),await f.replaceTrack(d),this.emit("streamLocal",this.streamLocal)):this.error(`Failed to find track to replace: ${c.id}`);}}catch(a){if(a instanceof Error)throw this.error("Failed to replaceTrack",a),a}}on(a,b){return this.emitter.on(a,b)}off(a,b){return this.emitter.off(a,b)}emit(d){for(var b=arguments.length,c=new Array(b>1?b-1:0),a=1;a<b;a++)c[a-1]=arguments[a];return this.emitter.emit(d,...c)}static getUserMedia(a){return navigator.mediaDevices.getUserMedia({...getDefaultCamConstraints(),...a})}} | ||
class g{constructor(b){this.streamLocal=new MediaStream,this.channels=new Map,this.channelsPending=new Map,this.emitter=new EventEmitter,this.polite=!0,this.isActive=!1,this.makingOffer=!1,this.ignoreOffer=!1,this.options={batchCandidates:!0,batchCandidatesTimeout:200,id:randomHex(4),config:{iceServers:[{urls:["stun:stun.l.google.com:19302"]}]},offerOptions:{},enableDataChannels:!1,channelLabel:randomHex(20),channelOptions:{},sdpTransform:a=>a},this.options={...this.options,...b},this.peer=this.init();}init(){if("new"===this.status())return this.peer;this.destroy(),this.peer=new RTCPeerConnection(this.options.config),this.streamLocal.getTracks().forEach(a=>this.peer.addTrack(a,this.streamLocal));let{channelLabel:a,channelOptions:b,enableDataChannels:c}=this.options;c&&this.addDataChannel(a,b);let d=[],e;function f(){clearTimeout(e),d.length=0;}return this.peer.onicecandidate=a=>{(null==a?void 0:a.candidate)&&(this.options.batchCandidates?(clearTimeout(e),d.push(a.candidate),"complete"===this.peer.iceGatheringState?this.emit("onicecandidates",d):e=setTimeout(()=>{d.length&&(this.emit("onicecandidates",d),f());},this.options.batchCandidatesTimeout)):this.emit("onicecandidates",[a.candidate]));},this.peer.ontrack=a=>{a.streams&&this.emit("streamRemote",a.streams[0]);},this.peer.oniceconnectionstatechange=()=>{switch(this.emit("status",this.status()),this.status()){case"closed":case"failed":case"disconnected":f(),this.destroy();break;case"checking":this.emit("connecting");break;case"connected":this.emit("connected");}},this.peer.onnegotiationneeded=async()=>{try{if(!this.isActive)return;this.makingOffer=!0;let{offerOptions:c,sdpTransform:d}=this.options;this.createDataChannels();let a=await this.peer.createOffer(c);if("stable"!==this.peer.signalingState)return;a.sdp=a.sdp&&d(a.sdp),await this.peer.setLocalDescription(a),this.peer.localDescription&&this.emit("signal",this.peer.localDescription);}catch(b){b instanceof Error&&this.error("Failed in negotiationNeeded",b);}finally{this.makingOffer=!1;}},this.peer.ondatachannel=b=>{let{channel:a}=b;this.options.enableDataChannels&&(this.channels.set(a.label,a),this.addDataChannelEvents(a));},this.peer}start(){let{polite:b=!0}=arguments.length>0&& void 0!==arguments[0]?arguments[0]:{};try{"have-local-offer"===this.peer.signalingState&&this.destroy(),this.isClosed()&&this.init(),this.isActive=!0,this.polite=b,this.peer.restartIce();}catch(a){if(a instanceof Error)throw this.error("Failed to start",a),a}}async signal(b){try{this.isClosed()&&this.init(),this.isActive=!0;let d="offer"===b.type&&(this.makingOffer||"stable"!==this.peer.signalingState);if(this.ignoreOffer=!this.polite&&d,this.ignoreOffer)return;if(await this.peer.setRemoteDescription(b),"offer"===b.type){this.createDataChannels();let a=await this.peer.createAnswer();a.sdp=a.sdp&&this.options.sdpTransform(a.sdp),await this.peer.setLocalDescription(a),this.emit("signal",a);}this.polite=!0;}catch(c){if(c instanceof Error)throw this.error("Failed to signal",c),c}}async addIceCandidate(b){try{await this.peer.addIceCandidate(b);}catch(a){if(!this.ignoreOffer&&a instanceof Error)throw this.error("Failed to addIceCandidate",a),a}}send(b){let c=arguments.length>1&& void 0!==arguments[1]?arguments[1]:this.options.channelLabel,a=this.channels.get(c);return (null==a?void 0:a.readyState)==="open"&&!!b&&(a.send(b),this.emit("channelData",{channel:a,data:b,source:"outgoing"}),!0)}addDataChannel(){let a=arguments.length>0&& void 0!==arguments[0]?arguments[0]:this.options.channelLabel,b=arguments.length>1&& void 0!==arguments[1]?arguments[1]:{};if(!this.options.enableDataChannels){this.error('Failed to addDataChannel as "enableDataChannels" is false');return}if(this.isClosed()){this.error("Failed to addDataChannel as peer connection is closed");return}this.channels.has(a)||this.channelsPending.set(a,b),this.isActive&&this.createDataChannels();}getDataChannel(){let a=arguments.length>0&& void 0!==arguments[0]?arguments[0]:this.options.channelLabel;return this.channels.get(a)}createDataChannels(){try{Array.from(this.channelsPending.entries()).forEach(c=>{let[a,d]=c,b=this.peer.createDataChannel(a,d);this.channels.set(a,b),this.addDataChannelEvents(b);}),this.channelsPending.clear();}catch(a){if(a instanceof Error)throw this.error("Failed to createDataChannels",a),a}}addDataChannelEvents(a){a.onopen=()=>this.emit("channelOpen",{channel:a}),a.onerror=b=>{this.emit("channelError",{channel:a,event:b});},a.onclose=()=>{this.channels.delete(a.label),this.emit("channelClosed",{channel:a});},a.onmessage=b=>{this.emit("channelData",{channel:a,data:b.data,source:"incoming"});};}destroy(){this.isClosed()||(this.polite=!0,this.isActive=!1,this.makingOffer=!1,this.ignoreOffer=!1,this.channels.clear(),this.channelsPending.clear(),this.peer.close(),this.emit("disconnected"));}status(){var a,b;return null!==(b=null===(a=this.peer)|| void 0===a?void 0:a.iceConnectionState)&& void 0!==b?b:"closed"}isConnected(){return "connected"===this.status()}isClosed(){return "closed"===this.status()}get(){return this.peer}getStreamLocal(){return this.streamLocal}error(a,b){this.emit("error",{id:this.options.id,message:a,error:b});}addStream(a){let b=arguments.length>1&& void 0!==arguments[1]&&arguments[1];b&&this.removeTracks(this.streamLocal.getTracks()),a.getTracks().forEach(a=>this.addTrack(a));}removeStream(a){this.removeTracks(a.getTracks());}addTrack(b){try{this.streamLocal.addTrack(b),this.emit("streamLocal",this.streamLocal),this.isClosed()||this.peer.addTrack(b,this.streamLocal);}catch(a){if(a instanceof Error)throw this.error("Failed to addTrack",a),a}}removeTrack(a){removeTracks(this.streamLocal,filterByTrack(a)),this.isClosed()||removeTracksFromPeer(this.peer,filterByTrack(a));}removeTracks(a){a.forEach(a=>this.removeTrack(a));}async replaceTrack(c,d){try{if(!this.isClosed()){let[f]=this.peer.getSenders().filter(a=>a.track===c);f?(removeTracks(this.streamLocal,filterByTrack(c)),this.streamLocal.addTrack(d),await f.replaceTrack(d),this.emit("streamLocal",this.streamLocal)):this.error(`Failed to find track to replace: ${c.id}`);}}catch(a){if(a instanceof Error)throw this.error("Failed to replaceTrack",a),a}}on(a,b){return this.emitter.on(a,b)}off(a,b){return this.emitter.off(a,b)}offAll(a){return this.emitter.offAll(a)}emit(d){for(var b=arguments.length,c=new Array(b>1?b-1:0),a=1;a<b;a++)c[a-1]=arguments[a];return this.emitter.emit(d,...c)}static getUserMedia(a){return navigator.mediaDevices.getUserMedia({...getDefaultCamConstraints(),...a})}} | ||
@@ -14,0 +14,0 @@ return g; |
declare type ListenerFunction = (...args: any[]) => void; | ||
export declare class EventEmitter { | ||
private listeners; | ||
on(eventName: string, listener: ListenerFunction): this; | ||
off(eventName: string, listener: ListenerFunction): this; | ||
emit(eventName: string, ...args: any[]): boolean; | ||
private eventMap; | ||
emit(event: string, ...args: any[]): boolean; | ||
on(event: string, listener: ListenerFunction): this; | ||
off(event: string, listener: ListenerFunction): this; | ||
offAll(event?: string): this; | ||
} | ||
export {}; |
@@ -52,12 +52,13 @@ import { PeerEvents, PeerOptions, TypedEmitter } from './types'; | ||
addTrack(track: MediaStreamTrack): void; | ||
/** Remove track on peer */ | ||
removeTrack(track: MediaStreamTrack): void; | ||
/** Remove tracks on peer */ | ||
removeTracks(tracks: MediaStreamTrack[]): void; | ||
/** Remove track on peer */ | ||
removeTrack(track: MediaStreamTrack): void; | ||
/** Replace track with another track on peer */ | ||
replaceTrack(track: MediaStreamTrack, newTrack: MediaStreamTrack): Promise<void>; | ||
on<E extends keyof PeerEvents>(event: E, cb: PeerEvents[E]): TypedEmitter<PeerEvents>; | ||
off<E extends keyof PeerEvents>(event: E, cb: PeerEvents[E]): TypedEmitter<PeerEvents>; | ||
on<E extends keyof PeerEvents>(event: E, listener: PeerEvents[E]): TypedEmitter<PeerEvents>; | ||
off<E extends keyof PeerEvents>(event: E, listener: PeerEvents[E]): TypedEmitter<PeerEvents>; | ||
offAll<E extends keyof PeerEvents>(event?: E): TypedEmitter<PeerEvents>; | ||
private emit; | ||
static getUserMedia(constraints?: MediaStreamConstraints): Promise<MediaStream>; | ||
} |
@@ -6,2 +6,3 @@ export declare type Arguments<T> = [T] extends [(...args: infer U) => any] ? U : [T] extends [void] ? [] : [T]; | ||
off<E extends keyof Events>(event: E, listener: Events[E]): this; | ||
offAll<E extends keyof Events>(event?: E): this; | ||
emit<E extends keyof Events>(event: E, ...args: Arguments<Events[E]>): boolean; | ||
@@ -11,3 +12,3 @@ } | ||
error: (data: { | ||
name: string; | ||
id: string; | ||
message: string; | ||
@@ -45,4 +46,4 @@ error?: Error; | ||
batchCandidatesTimeout?: number; | ||
/** Peer name used when emitting errors */ | ||
name?: string; | ||
/** Peer id used when emitting errors */ | ||
id?: string; | ||
/** RTCPeerConnection options */ | ||
@@ -49,0 +50,0 @@ config?: RTCConfiguration; |
{ | ||
"name": "peer-lite", | ||
"description": "Lightweight WebRTC browser library that supports video, audio and data channels", | ||
"version": "2.0.0-beta.0", | ||
"version": "2.0.0", | ||
"license": "MIT", | ||
@@ -24,3 +24,5 @@ "keywords": [ | ||
"build": "rollup --config build/rollup.config.ts --configPlugin typescript", | ||
"test": "playwright test", | ||
"test": "yarn test:playwright && yarn test:jest", | ||
"test:playwright": "playwright test ./test/peer.spec.ts", | ||
"test:jest": "jest", | ||
"prepublishOnly": "npm run build", | ||
@@ -34,7 +36,9 @@ "lint": "eslint . --ext .tsx --ext .ts --ext .js" | ||
"@rollup/plugin-typescript": "^8.3.2", | ||
"@swc/core": "^1.2.194", | ||
"@types/node": "^17.0.35", | ||
"@swc/core": "^1.2.196", | ||
"@swc/jest": "^0.2.21", | ||
"@types/jest": "^28.1.0", | ||
"@types/node": "^17.0.38", | ||
"@types/webrtc": "^0.0.32", | ||
"@typescript-eslint/eslint-plugin": "^5.26.0", | ||
"@typescript-eslint/parser": "^5.26.0", | ||
"@typescript-eslint/eslint-plugin": "^5.27.0", | ||
"@typescript-eslint/parser": "^5.27.0", | ||
"eslint": "^8.16.0", | ||
@@ -45,2 +49,3 @@ "eslint-config-airbnb": "^19.0.4", | ||
"eslint-plugin-import": "^2.26.0", | ||
"eslint-plugin-jest": "^26.4.6", | ||
"eslint-plugin-jsx-a11y": "^6.5.1", | ||
@@ -50,6 +55,7 @@ "eslint-plugin-playwright": "^0.9.0", | ||
"eslint-plugin-react": "^7.30.0", | ||
"jest": "^28.1.0", | ||
"playwright": "^1.22.2", | ||
"prettier": "^2.6.2", | ||
"rimraf": "^3.0.2", | ||
"rollup": "^2.75.0", | ||
"rollup": "^2.75.5", | ||
"rollup-plugin-swc": "^0.2.1", | ||
@@ -60,3 +66,13 @@ "typescript": "^4.7.2" | ||
"dist" | ||
] | ||
], | ||
"jest": { | ||
"modulePathIgnorePatterns": [ | ||
"./test/peer.spec.ts" | ||
], | ||
"transform": { | ||
"^.+\\.(t|j)sx?$": [ | ||
"@swc/jest" | ||
] | ||
} | ||
} | ||
} |
@@ -10,3 +10,4 @@ # PeerLite | ||
* Zero dependencies | ||
* Using modern WebRTC APIs with TypeScript Types | ||
* Ships with TypeScript definitions | ||
* Uses modern WebRTC APIs | ||
* ["Perfect negotiation"](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Perfect_negotiation) pattern | ||
@@ -115,6 +116,5 @@ * Support for [renegotiation](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/onnegotiationneeded) of connection | ||
### Peer Options | ||
## Peer Options | ||
```typescript | ||
export interface PeerOptions { | ||
interface PeerOptions { | ||
/** Enable support for batching ICECandidates */ | ||
@@ -124,4 +124,4 @@ batchCandidates?: boolean; | ||
batchCandidatesTimeout?: number; | ||
/** Peer name used when emitting errors */ | ||
name?: string; | ||
/** Peer id used when emitting errors */ | ||
id?: string; | ||
/** RTCPeerConnection options */ | ||
@@ -142,6 +142,57 @@ config?: RTCConfiguration; | ||
### Peer Events | ||
## Peer API | ||
```typescript | ||
export interface PeerEvents { | ||
error: (data: { name: string; message: string; error?: Error }) => void; | ||
interface Peer { | ||
/** Create a peer instance */ | ||
constructor(options?: PeerOptions); | ||
/** Initialize the peer */ | ||
init(): RTCPeerConnection; | ||
/** Start the RTCPeerConnection signalling */ | ||
start({ polite }?: { | ||
polite?: boolean | undefined; | ||
}): void; | ||
/** Process a RTCSessionDescriptionInit on peer */ | ||
signal(description: RTCSessionDescriptionInit): Promise<void>; | ||
/** Add RTCIceCandidate to peer */ | ||
addIceCandidate(candidate: RTCIceCandidate): Promise<void>; | ||
/** Send data to connected peer using an RTCDataChannel */ | ||
send(data: string | Blob | ArrayBuffer | ArrayBufferView, label?: string): boolean; | ||
/** Add RTCDataChannel to peer */ | ||
addDataChannel(label?: string, options?: RTCDataChannelInit): void; | ||
/** Get RTCDataChannel added to peer */ | ||
getDataChannel(label?: string): RTCDataChannel | undefined; | ||
/** Close peer if active */ | ||
destroy(): void; | ||
/** Return the ICEConnectionState of the peer */ | ||
status(): RTCIceConnectionState; | ||
/** Return true if the peer is connected */ | ||
isConnected(): boolean; | ||
/** Return true if the peer is closed */ | ||
isClosed(): boolean; | ||
/** Return the RTCPeerConnection */ | ||
get(): RTCPeerConnection; | ||
/** Return the local stream */ | ||
getStreamLocal(): MediaStream; | ||
/** Add stream to peer */ | ||
addStream(stream: MediaStream, replace?: boolean): void; | ||
/** Remove stream from peer */ | ||
removeStream(stream: MediaStream): void; | ||
/** Add track to peer */ | ||
addTrack(track: MediaStreamTrack): void; | ||
/** Remove track on peer */ | ||
removeTrack(track: MediaStreamTrack): void; | ||
/** Remove tracks on peer */ | ||
removeTracks(tracks: MediaStreamTrack[]): void; | ||
/** Replace track with another track on peer */ | ||
replaceTrack(track: MediaStreamTrack, newTrack: MediaStreamTrack): Promise<void>; | ||
on<E extends keyof PeerEvents>(event: E, listener: PeerEvents[E]): TypedEmitter<PeerEvents>; | ||
off<E extends keyof PeerEvents>(event: E, listener: PeerEvents[E]): TypedEmitter<PeerEvents>; | ||
offAll<E extends keyof PeerEvents>(event?: E): TypedEmitter<PeerEvents>; | ||
} | ||
``` | ||
## Peer Events | ||
```typescript | ||
interface PeerEvents { | ||
error: (data: { id: string; message: string; error?: Error }) => void; | ||
// Connection Status | ||
@@ -175,3 +226,3 @@ connecting: VoidFunction; | ||
Run Tests (Chrome only) | ||
**Run Tests (Chrome only)** | ||
```bash | ||
@@ -181,3 +232,3 @@ yarn test | ||
Run Tests (Chrome + Firefox) | ||
**Run Tests (Chrome + Firefox)** | ||
```bash | ||
@@ -184,0 +235,0 @@ CI=true yarn test |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
63843
213
1
237
0
26