@oiij/web-rtc
Version:
Features:
205 lines (203 loc) • 5.96 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
useWebRTC: () => useWebRTC
});
module.exports = __toCommonJS(index_exports);
var import_vue = require("vue");
function useWebRTC(options) {
const { host = "127.0.0.1", port = 6789, path = "/_web-rtc", protocols = [], ...rtcConfig } = options ?? {};
const controller = new AbortController();
const id = (0, import_vue.ref)();
const connected = (0, import_vue.ref)([]);
const status = (0, import_vue.ref)("pending");
const ws = new WebSocket(`ws://${host}:${port}${path}`, protocols);
const peer = new RTCPeerConnection(rtcConfig);
const iceConnectionState = (0, import_vue.ref)(peer.iceConnectionState);
const signalingState = (0, import_vue.ref)(peer.signalingState);
const connectionState = (0, import_vue.ref)(peer.connectionState);
let onReadyFn = null;
function onReady() {
if (onReadyFn && typeof onReadyFn === "function") {
onReadyFn();
}
}
let onConnectionFn = null;
function onConnection(ev) {
if (onConnectionFn && typeof onConnectionFn === "function") {
onConnectionFn(ev);
}
}
let onConnectionStreamFn = null;
function onConnectionStream(ev) {
if (onConnectionStreamFn && typeof onConnectionStreamFn === "function") {
onConnectionStreamFn(ev);
}
}
function sendMessage(data) {
ws.send(JSON.stringify(data));
}
function onIcecandidate(ev) {
if (ev.candidate) {
sendMessage({
type: "ice-candidate",
payload: {
candidate: ev.candidate
}
});
}
}
async function onMessage(ev) {
try {
const { type, payload } = JSON.parse(ev.data);
const { key, desc, candidate } = payload;
switch (type) {
case "register":
id.value = key;
status.value = "ready";
onReady();
break;
case "offer":
{
if (!desc || !key)
return;
await peer.setRemoteDescription(desc);
const answer = await peer.createAnswer();
await peer.setLocalDescription(answer);
sendMessage({
type: "answer",
payload: {
key,
desc: answer
}
});
}
break;
case "answer":
if (!desc || !key)
return;
await peer.setRemoteDescription(desc);
sendMessage({
type: "answer-ok",
payload: {
key
}
});
break;
case "answer-ok":
if (!key) {
return;
}
status.value = "connected";
if (!connected.value.includes(key)) {
connected.value.push(key);
}
break;
case "ice-candidate":
if (!candidate)
return;
try {
await peer.addIceCandidate(candidate);
} catch (error) {
console.error(error);
}
break;
default:
break;
}
} catch (error) {
console.error(error);
}
}
async function connect(id2, label = "label") {
const dataChannel = peer.createDataChannel(label);
const offer = await peer.createOffer();
await peer.setLocalDescription(offer);
sendMessage({
type: "offer",
payload: {
key: id2,
desc: offer
}
});
return dataChannel;
}
async function connectStream(id2, stream) {
stream.getTracks().forEach((track) => {
peer.addTrack(track, stream);
});
const offer = await peer.createOffer();
await peer.setLocalDescription(offer);
sendMessage({
type: "offer",
payload: {
key: id2,
desc: offer
}
});
return peer;
}
ws.addEventListener("message", onMessage, { signal: controller.signal });
peer.addEventListener("icecandidate", onIcecandidate, { signal: controller.signal });
peer.addEventListener("iceconnectionstatechange", () => {
iceConnectionState.value = peer.iceConnectionState;
}, { signal: controller.signal });
peer.addEventListener("signalingstatechange", () => {
signalingState.value = peer.signalingState;
}, { signal: controller.signal });
peer.addEventListener("connectionstatechange", () => {
connectionState.value = peer.connectionState;
}, { signal: controller.signal });
peer.addEventListener("datachannel", onConnection, { signal: controller.signal });
peer.addEventListener("track", onConnectionStream, { signal: controller.signal });
function destroy() {
controller.abort();
ws.close();
peer.close();
}
(0, import_vue.onUnmounted)(() => {
destroy();
});
return {
id,
connected,
status,
ws,
peer,
signalingState,
connectionState,
onReady: (fn) => {
onReadyFn = fn;
},
connect,
onConnection: (fn) => {
onConnectionFn = fn;
},
connectStream,
onConnectionStream: (fn) => {
onConnectionStreamFn = fn;
}
};
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
useWebRTC
});