@dobuki/hello-worker 1.0.16 → 1.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.js +4 -0
- package/dist/browser/index.js.map +13 -0
- package/package.json +4 -3
- package/dist/enter-world.js +0 -101
- package/dist/enter-world.js.map +0 -1
- package/dist/impl/signal-room.js +0 -76
- package/dist/impl/signal-room.js.map +0 -1
- package/dist/index.js +0 -6
- package/dist/index.js.map +0 -1
- package/dist/sample/index.js +0 -145
- package/dist/sample/index.js.map +0 -1
- package/dist/sample.d.ts +0 -4
- package/dist/sample.d.ts.map +0 -1
- package/dist/sample.js +0 -147
- package/dist/sample.js.map +0 -1
- package/dist/signal-room.js +0 -59
- package/dist/signal-room.js.map +0 -1
- package/dist/webrtc-peer-collector.js +0 -155
- package/dist/webrtc-peer-collector.js.map +0 -1
- package/dist/webrtc-room.d.ts +0 -52
- package/dist/webrtc-room.d.ts.map +0 -1
- package/dist/webrtc-room.js +0 -216
- package/dist/webrtc-room.js.map +0 -1
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
function k({userId:M,appId:h,room:G,host:j,onOpen:N,onClose:S,onError:B,logLine:f,onPeerJoined:x,onPeerLeft:F,onMessage:H}){let W=`wss://${j}/room/${h}/${G}?userId=${encodeURIComponent(M)}`,$=new WebSocket(W),C=M,X=new Map,K=!1;function q(Z,c,D){if(K)return!1;let T={type:Z,to:c,payload:D};return $.send(JSON.stringify(T)),f?.("\uD83D\uDC64 ➡️ \uD83D\uDDA5️",T),!0}function R(Z){let c=[],D=[],T=new Set;if(Z.forEach(({userId:b,peerId:z})=>{if(b===C)return;if(!X.has(z)){let O={userId:b,peerId:z,receive:(A,V)=>q(A,z,V)};X.set(z,O),c.push(O)}T.add(z)}),X.values().forEach(({peerId:b,userId:z})=>{if(!T.has(b))X.delete(b),D.push({peerId:b,userId:z})}),c.length)x(c);if(D.length)F(D)}function Y(Z){let c;try{c=JSON.parse(Z.data)}catch{f?.("⚠️ ERROR",{error:"invalid-json"});return}if(f?.("\uD83D\uDDA5️ ➡️ \uD83D\uDC64",c),c.type==="peer-joined"){R(c.users);return}if(c.type==="peer-left"){R(c.users);return}if(c.peerId&&c.userId){let{userId:D,peerId:T}=c;H(c.type,c.payload,{userId:D,peerId:T,receive:(b,z)=>q(b,T,z)})}}if($.addEventListener("message",Y),N)$.addEventListener("open",N);if(S)$.addEventListener("close",S);if(B)$.addEventListener("error",B);return{exitRoom:()=>{if(K=!0,$.close(),$.removeEventListener("message",Y),N)$.removeEventListener("open",N);if(S)$.removeEventListener("close",S);if(B)$.removeEventListener("error",B)}}}function E({userId:M,appId:h,room:G,host:j,onOpen:N,onClose:S,onError:B,onPeerJoined:f,onPeerLeft:x,onMessage:F,logLine:H,workerUrl:W}){if(!W)return console.warn("Warning: enterRoom called without workerUrl; this may cause issues in some environments. You should pass workerUrl explicitly. Use:","https://cdn.jsdelivr.net/npm/@dobuki/hello-worker/dist/signal-room.worker.min.js"),k({userId:M,appId:h,room:G,host:j,onOpen:N,onClose:S,onError:B,onPeerJoined:f,onPeerLeft:x,onMessage:F});let $=new Worker(W,{type:"module"}),C=!1;function X({userId:q,peerId:R}){return{userId:q,peerId:R,receive:(Y,Z)=>{if(C)return!1;return $.postMessage({cmd:"send",toPeerId:R,type:Y,payload:Z}),!0}}}let K=(q)=>{let R=q.data;if(R.kind==="open")N?.();else if(R.kind==="close")$.terminate();else if(R.kind==="error")B?.();else if(R.kind==="peer-joined")f(R.users.map((Y)=>X({userId:Y.userId,peerId:Y.peerId})));else if(R.kind==="peer-left")x(R.users);else if(R.kind==="message")F(R.type,R.payload,X({userId:R.fromUserId,peerId:R.fromPeerId}));else if(R.kind==="log")H?.(R.direction,R.obj)};return $.addEventListener("message",K),$.postMessage({cmd:"enter",userId:M,appId:h,room:G,host:j}),{exitRoom:()=>{C=!0,$.removeEventListener("message",K),$.postMessage({cmd:"exit"})}}}var v=E;function U({userId:M,appId:h,receivePeerConnection:G,peerlessUserExpiration:j,rtcConfig:N={iceServers:[{urls:"stun:stun.l.google.com:19302"}]},enterRoomFunction:S=v,logLine:B=console.debug,onLeaveUser:f,workerUrl:x}){let F=new Map;function H(){return[...F.keys()]}let W=new Set;function $(c){let D=F.get(c.userId);if(!D){let T={userId:c.userId,pc:new RTCPeerConnection(N),pendingRemoteIce:[],peers:new Map};T.peers.set(c.peerId,c),F.set(c.userId,T),T.pc.onicecandidate=(b)=>{if(!b.candidate)return;for(let z of T.peers.values())if(z.receive("ice",b.candidate.toJSON()))break},T.pc.onconnectionstatechange=()=>{B("\uD83D\uDCAC",{event:"pc-state",userId:T.userId,state:T.pc.connectionState})},D=T,W.forEach((b)=>b(c.userId,"join",H())),F.set(D.userId,D)}else if(D)clearTimeout(D.expirationTimeout),D.expirationTimeout=0,D.peers.set(c.peerId,c);return D}function C(c){f?.(c);let D=F.get(c);if(!D)return;try{D.pc.close()}catch{}F.delete(c),W.forEach((T)=>T(c,"leave",H())),B("\uD83D\uDC64 USER LEFT",c)}async function X(c){if(!c.pc.remoteDescription)return;let D=c.pendingRemoteIce;c.pendingRemoteIce=[];for(let T of D)try{await c.pc.addIceCandidate(T)}catch(b){B("⚠️ ERROR",{error:"add-ice-failed",userId:c.userId,detail:String(b)})}}let K=new Map;function q({room:c,host:D}){let T=`${D}/room/${c}`,b=K.get(T);if(b)b.exitRoom(),K.delete(T)}function R({room:c,host:D}){return new Promise((T,b)=>{async function z(A){let _=$(A).pc,Q=await _.createOffer();await _.setLocalDescription(Q),A.receive("offer",_.localDescription?.toJSON())}let{exitRoom:O}=S({userId:M,appId:h,room:c,host:D,logLine:B,workerUrl:x,onOpen:T,onError:b,onPeerJoined(A){A.forEach((V)=>{let Q=$(V).pc;G({pc:Q,userId:V.userId,initiator:!0}),z(V)})},onPeerLeft(A){A.forEach(({userId:V,peerId:_})=>{let Q=F.get(V);if(!Q)return;if(Q.peers.delete(_),Q.peers.size===0)Q.expirationTimeout=setTimeout(()=>C(V),j??0)})},async onMessage(A,V,_){let Q=$(_),J=Q.pc;if(A==="offer"){G({pc:J,userId:_.userId,initiator:!1}),await J.setRemoteDescription(V);let y=await J.createAnswer();await J.setLocalDescription(y),_.receive("answer",J.localDescription?.toJSON()),await X(Q);return}if(A==="answer"){await J.setRemoteDescription(V),await X(Q),G({pc:J,userId:_.userId,initiator:!0});return}if(A==="ice"){let y=V;if(!J.remoteDescription){Q.pendingRemoteIce.push(y);return}try{await J.addIceCandidate(y)}catch(P){B("⚠️ ERROR",{error:"add-ice-failed",userId:Q.userId,detail:String(P)})}return}}});K.set(`${D}/room/${c}`,{exitRoom:O,room:c,host:D})})}function Y(c){W.delete(c)}function Z(c){return W.add(c),()=>{Y(c)}}return{enterRoom:R,exitRoom:q,leaveUser:C,getUsers:H,addUserListener:Z,removeUserListener:Y,getRooms(){return Array.from(K.values())},end(){K.forEach(({exitRoom:c})=>c()),K.clear(),F.forEach(({userId:c})=>C(c)),W.clear()}}}function L({uid:M,appId:h,logLine:G=console.debug,enterRoomFunction:j=E,peerlessUserExpiration:N,workerUrl:S}){let B=M??`user-${crypto.randomUUID()}`,f={iceServers:[{urls:"stun:stun.l.google.com:19302"}]},x=new Set;function F(D,T){T.onopen=()=>G("\uD83D\uDCAC",{event:"dc-open",userId:D}),T.onmessage=({data:b})=>{x.forEach((z)=>z(b,D)),G("\uD83D\uDCAC",{event:"dc-message",userId:D,data:b})},T.onclose=()=>G("\uD83D\uDCAC",{event:"dc-close",userId:D}),T.onerror=()=>G("⚠️ ERROR",{error:"dc-error",userId:D})}let H=new Map,{enterRoom:W,exitRoom:$,getUsers:C,leaveUser:X,addUserListener:K,removeUserListener:q,end:R}=U({userId:B,appId:h,rtcConfig:f,enterRoomFunction:j,logLine:G,workerUrl:S,peerlessUserExpiration:N,onLeaveUser(D){let T=H.get(D);try{T?.close()}catch{}H.delete(D)},receivePeerConnection({pc:D,userId:T,initiator:b}){if(b){let z=D.createDataChannel("data");F(T,z),H.set(T,z)}else D.ondatachannel=(z)=>{let O=z.channel;F(T,O),H.set(T,O)};G("\uD83D\uDCAC",{event:"pc-ready",userId:T,initiator:b})}});function Y(D,T){H.forEach((b,z)=>{if(T&&z!==T)return;if(b.readyState==="open")b.send(D)})}function Z(D){x.delete(D)}function c(D){return x.add(D),()=>{Z(D)}}return{userId:B,send:Y,enterRoom:W,exitRoom:$,leaveUser:X,getUsers:C,addMessageListener:c,removeMessageListener:Z,addUserListener:K,removeUserListener:q,end(){H.forEach((D)=>{try{D.close()}catch{}}),H.clear(),R()}}}export{L as enterWorld,k as enterRoom,U as collectPeerConnections};
|
|
2
|
+
|
|
3
|
+
//# debugId=7979C2C0F3726FCA64756E2164756E21
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/browser/impl/signal-room.ts", "../src/browser/signal-room.ts", "../src/browser/webrtc-peer-collector.ts", "../src/browser/enter-world.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"export interface IPeer<T extends string = string, P = any> {\n userId: string;\n peerId: string;\n receive(type: T, payload: P): boolean;\n}\n\n/**\n * enterRoom connects to the signaling room via WebSocket.\n */\nexport function enterRoom<T extends string, P = any>({\n userId,\n appId,\n room,\n host,\n onOpen,\n onClose,\n onError,\n logLine,\n onPeerJoined,\n onPeerLeft,\n onMessage,\n}: {\n userId: string;\n appId: string;\n room: string;\n host: string;\n onOpen?: () => void;\n onClose?: () => void;\n onError?: () => void;\n logLine?: (direction: string, obj?: any) => void;\n onPeerJoined(users: IPeer<T, P>[]) : void;\n onPeerLeft(users: {userId: string, peerId: string}[]) : void;\n onMessage(type: T, payload: P, from: IPeer<T, P>) : void;\n}): { exitRoom: () => void } {\n const wsUrl = `wss://${host}/room/${appId}/${room}?userId=${encodeURIComponent(userId)}`;\n const ws = new WebSocket(wsUrl);\n const selfUserId = userId;\n\n const peers = new Map<string, IPeer<T, P>>();\n let exited = false;\n function send(type: T, toPeerId: string, payload: P) {\n if (exited) return false;\n const obj = { type, to: toPeerId, payload };\n ws.send(JSON.stringify(obj));\n logLine?.(\"👤 ➡️ 🖥️\", obj);\n return true;\n }\n\n function updatePeers(updatedUsers: { peerId: string; userId: string }[]) {\n const joined: IPeer<T,P>[] = [];\n const left: Omit<IPeer<T,P>, \"receive\">[] = [];\n const updatedPeerSet = new Set<string>();\n updatedUsers.forEach(({ userId, peerId }) => {\n if (userId === selfUserId) return;\n if (!peers.has(peerId)) {\n const newPeer = { userId, peerId, receive: (type: T, payload: P) => send(type, peerId, payload)};\n peers.set(peerId, newPeer);\n joined.push(newPeer);\n }\n updatedPeerSet.add(peerId);\n });\n peers.values().forEach(({ peerId, userId }) => {\n if (!updatedPeerSet.has(peerId)) {\n peers.delete(peerId);\n left.push({ peerId, userId });\n }\n });\n if (joined.length) onPeerJoined(joined);\n if (left.length) onPeerLeft(left);\n }\n\n function onmessage(e: MessageEvent) {\n let msg: {\n type: T;\n peerId: string;\n userId: string;\n users: { peerId: string, userId: string }[],\n payload: P;\n };\n try { msg = JSON.parse(e.data); }\n catch {\n logLine?.(\"⚠️ ERROR\", { error: \"invalid-json\" });\n return;\n }\n\n logLine?.(\"🖥️ ➡️ 👤\", msg);\n\n // Existing client greets newcomers\n if (msg.type === \"peer-joined\") {\n updatePeers(msg.users);\n return;\n }\n if (msg.type === \"peer-left\") {\n updatePeers(msg.users);\n return;\n }\n if (msg.peerId && msg.userId) {\n const { userId, peerId } = msg;\n onMessage(msg.type, msg.payload, {\n userId,\n peerId,\n receive: (type: T, payload: P) => send(type, peerId, payload),\n });\n }\n };\n\n ws.addEventListener(\"message\", onmessage);\n if (onOpen) ws.addEventListener(\"open\", onOpen);\n if (onClose) ws.addEventListener(\"close\", onClose);\n if (onError) ws.addEventListener(\"error\", onError);\n return {\n exitRoom: () => {\n exited = true;\n ws.close();\n ws.removeEventListener(\"message\", onmessage);\n if (onOpen) ws.removeEventListener(\"open\", onOpen);\n if (onClose) ws.removeEventListener(\"close\", onClose);\n if (onError) ws.removeEventListener(\"error\", onError);\n },\n };\n}\n",
|
|
6
|
+
"import type { IPeer } from \"./impl/signal-room.js\";\nimport { enterRoom as baseEnterRoom } from \"./impl/signal-room.js\";\nimport { RoomEvent } from \"./signal-room.worker.js\";\n\nexport function enterRoom<T extends string, P = any>({\n userId,\n appId,\n room,\n host,\n onOpen,\n onClose,\n onError,\n onPeerJoined,\n onPeerLeft,\n onMessage,\n logLine,\n workerUrl,\n}: {\n userId: string;\n appId: string;\n room: string;\n host: string;\n onOpen?: () => void;\n onClose?: () => void;\n onError?: () => void;\n onPeerJoined: (users: IPeer<T, P>[]) => void;\n onPeerLeft: (users: {userId: string, peerId: string}[]) => void;\n onMessage: (type: T, payload: P, from: IPeer<T, P>) => void;\n logLine?: (direction: string, obj?: any) => void;\n\n // Pass the URL to your worker file (bundler will handle it)\n workerUrl?: URL;\n}): { exitRoom: () => void } {\n if (!workerUrl) {\n const CDN_WORKER_URL = `https://cdn.jsdelivr.net/npm/@dobuki/hello-worker/dist/signal-room.worker.min.js`;\n\n console.warn(\"Warning: enterRoom called without workerUrl; this may cause issues in some environments. You should pass workerUrl explicitly. Use:\", CDN_WORKER_URL);\n return baseEnterRoom<T, P>({\n userId,\n appId,\n room,\n host,\n onOpen,\n onClose,\n onError,\n onPeerJoined,\n onPeerLeft,\n onMessage,\n });\n }\n const worker = new Worker(workerUrl, { type: \"module\" });\n let exited = false;\n\n function makeUser({ userId, peerId }: { userId: string; peerId: string }): IPeer<T, P> {\n return {\n userId,\n peerId,\n receive: (type: T, payload: P) => {\n if (exited) return false;\n worker.postMessage({ cmd: \"send\", toPeerId: peerId, type, payload });\n return true;\n },\n };\n }\n\n const onWorkerMessage = (e: MessageEvent<RoomEvent<T, P>>) => {\n const ev = e.data;\n\n if (ev.kind === \"open\") onOpen?.();\n else if (ev.kind === \"close\") worker.terminate();\n else if (ev.kind === \"error\") onError?.();\n else if (ev.kind === \"peer-joined\") onPeerJoined(ev.users.map(ev => makeUser({ userId: ev.userId, peerId: ev.peerId })));\n else if (ev.kind === \"peer-left\") onPeerLeft(ev.users);\n else if (ev.kind === \"message\") onMessage(ev.type, ev.payload, makeUser({ userId: ev.fromUserId, peerId: ev.fromPeerId }));\n else if (ev.kind === \"log\") logLine?.(ev.direction, ev.obj);\n };\n\n worker.addEventListener(\"message\", onWorkerMessage);\n\n worker.postMessage({ cmd: \"enter\", userId, appId, room, host });\n\n return {\n exitRoom: () => {\n exited = true;\n worker.removeEventListener(\"message\", onWorkerMessage);\n worker.postMessage({ cmd: \"exit\" });\n },\n };\n}\n\nexport type EnterRoom<T extends string, P> = typeof enterRoom<T, P>;\n",
|
|
7
|
+
"import { IPeer } from \"./impl/signal-room\";\nimport { EnterRoom, enterRoom } from \"./signal-room\";\n\nexport type SigType = \"offer\" | \"answer\" | \"ice\";\nexport type SigPayload = RTCSessionDescriptionInit | RTCIceCandidateInit;\n\ntype UserState = {\n userId: string;\n pc: RTCPeerConnection;\n\n // ICE that arrived before we had remoteDescription\n pendingRemoteIce: RTCIceCandidateInit[];\n\n // the signaling \"user\" handle so we can send messages\n peers: Map<string, IPeer<SigType, SigPayload>>;\n\n expirationTimeout?: number;\n};\ntype UserListener = (user: string, action: \"join\"|\"leave\", users: string[]) => void;\n\nconst DEFAULT_ENTER_ROOM = enterRoom;\n\n\nexport function collectPeerConnections({\n userId,\n appId,\n receivePeerConnection,\n peerlessUserExpiration,\n rtcConfig = { iceServers: [{ urls: \"stun:stun.l.google.com:19302\" }] },\n enterRoomFunction: enterRoom = DEFAULT_ENTER_ROOM,\n logLine = console.debug,\n onLeaveUser,\n workerUrl,\n}: {\n userId: string;\n appId: string;\n rtcConfig?: RTCConfiguration;\n enterRoomFunction?: EnterRoom<SigType, SigPayload>;\n onLeaveUser?: (userId: string) => void;\n logLine?: (direction: string, obj?: any) => void;\n workerUrl?: URL;\n peerlessUserExpiration?: number;\n receivePeerConnection(connection: { pc: RTCPeerConnection, userId: string, initiator: boolean }): void;\n}) {\n const users: Map<string, UserState> = new Map();\n function getUsers() {\n return [...users.keys()];\n }\n\n const userListener: Set<UserListener> = new Set();\n function getPeer(peer: IPeer<SigType, SigPayload>): UserState {\n let state = users.get(peer.userId);\n if (!state) {\n const newState: UserState = {\n userId: peer.userId,\n pc: new RTCPeerConnection(rtcConfig),\n pendingRemoteIce: [],\n peers: new Map(),\n };\n newState.peers.set(peer.peerId, peer);\n users.set(peer.userId, newState);\n\n // Send local ICE candidates to this peer\n newState.pc.onicecandidate = (ev) => {\n if (!ev.candidate) return;\n for(let user of newState.peers.values()) {\n const success = user.receive(\"ice\", ev.candidate.toJSON());\n if (success) break;\n }\n };\n \n newState.pc.onconnectionstatechange = () => {\n logLine(\"💬\", { event: \"pc-state\", userId: newState.userId, state: newState.pc.connectionState });\n };\n state = newState;\n\n // New user\n userListener.forEach(listener => listener(peer.userId, \"join\", getUsers()));\n users.set(state.userId, state);\n } else if (state) {\n clearTimeout(state.expirationTimeout);\n state.expirationTimeout = 0;\n state.peers.set(peer.peerId, peer);\n }\n return state;\n }\n\n function leaveUser(userId: string) {\n onLeaveUser?.(userId);\n const p = users.get(userId);\n if (!p) return;\n try { p.pc.close(); } catch {}\n users.delete(userId);\n userListener.forEach(listener => listener(userId, \"leave\", getUsers()));\n logLine(\"👤 USER LEFT\", userId);\n }\n\n async function flushRemoteIce(state: UserState) {\n if (!state.pc.remoteDescription) return;\n\n const queued = state.pendingRemoteIce;\n state.pendingRemoteIce = [];\n\n for (const ice of queued) {\n try {\n await state.pc.addIceCandidate(ice);\n } catch (e) {\n logLine(\"⚠️ ERROR\", { error: \"add-ice-failed\", userId: state.userId, detail: String(e) });\n }\n }\n }\n\n const roomsEntered = new Map<string, { room: string; host: string; exitRoom: () => void }>();\n\n function exit({ room, host }: { room: string; host: string; }) {\n const key = `${host}/room/${room}`;\n const session = roomsEntered.get(key);\n if (session) {\n session.exitRoom();\n roomsEntered.delete(key);\n }\n }\n\n function enter({ room, host }: { room: string; host: string; }) {\n return new Promise<void>((resolve, reject) => {\n async function makeOffer(user: IPeer) {\n // Offer flow: createOffer -> setLocalDescription -> send localDescription\n const state = getPeer(user);\n const pc = state.pc;\n const offer = await pc.createOffer();\n await pc.setLocalDescription(offer);\n user.receive(\"offer\", pc.localDescription?.toJSON()!);\n }\n\n const { exitRoom } = enterRoom({\n userId,\n appId,\n room,\n host,\n logLine,\n workerUrl,\n\n onOpen: resolve,\n onError: reject,\n\n // Existing peers initiate to the newcomer (Option 1)\n onPeerJoined(joiningUsers: IPeer<SigType, SigPayload>[]) {\n joiningUsers.forEach(user => {\n const state = getPeer(user);\n const pc = state.pc;\n receivePeerConnection({ pc, userId: user.userId, initiator: true });\n makeOffer(user);\n });\n },\n\n onPeerLeft(leavingUsers: { userId: string; peerId: string }[]) {\n leavingUsers.forEach(({ userId, peerId }) => {\n const state = users.get(userId);\n if (!state) return;\n state.peers.delete(peerId);\n if (state.peers.size === 0) {\n state.expirationTimeout = setTimeout(() => leaveUser(userId), peerlessUserExpiration ?? 0);\n }\n });\n },\n\n async onMessage(type: SigType, payload: any, from: IPeer) {\n const state = getPeer(from);\n const pc = state.pc;\n\n if (type === \"offer\") {\n receivePeerConnection({ pc, userId: from.userId, initiator: false });\n // Responder: set remote offer\n await pc.setRemoteDescription(payload as RTCSessionDescriptionInit);\n\n // Create and send answer\n const answer = await pc.createAnswer();\n await pc.setLocalDescription(answer);\n\n from.receive(\"answer\", pc.localDescription?.toJSON()!);\n\n // Now safe to apply any queued ICE from this peer\n await flushRemoteIce(state);\n return;\n }\n\n if (type === \"answer\") {\n // Initiator: set remote answer\n await pc.setRemoteDescription(payload as RTCSessionDescriptionInit);\n await flushRemoteIce(state);\n receivePeerConnection({ pc, userId: from.userId, initiator: true });\n return;\n }\n\n if (type === \"ice\") {\n const ice = payload as RTCIceCandidateInit;\n\n // If we don't have remoteDescription yet, queue it\n if (!pc.remoteDescription) {\n state.pendingRemoteIce.push(ice);\n return;\n }\n\n try {\n await pc.addIceCandidate(ice);\n } catch (e) {\n logLine(\"⚠️ ERROR\", { error: \"add-ice-failed\", userId: state.userId, detail: String(e) });\n }\n return;\n }\n },\n });\n roomsEntered.set(`${host}/room/${room}`, { exitRoom, room, host });\n });\n }\n\n function removeUserListener(listener: UserListener) {\n userListener.delete(listener);\n }\n\n function addUserListener(listener: UserListener) {\n userListener.add(listener);\n return () => {\n removeUserListener(listener);\n };\n }\n\n return {\n enterRoom: enter,\n exitRoom: exit,\n leaveUser,\n getUsers,\n addUserListener,\n removeUserListener,\n getRooms() {\n return Array.from(roomsEntered.values());\n },\n end() {\n roomsEntered.forEach(({ exitRoom }) => exitRoom());\n roomsEntered.clear();\n users.forEach(({ userId }) => leaveUser(userId));\n userListener.clear();\n },\n };\n}\n\n\n\n",
|
|
8
|
+
"import { EnterRoom, enterRoom } from \"./signal-room\";\nimport { SigType, SigPayload, collectPeerConnections } from \"./webrtc-peer-collector\";\n\nexport function enterWorld({\n uid, appId, logLine = console.debug, enterRoomFunction = enterRoom, peerlessUserExpiration, workerUrl,\n}: {\n uid?: string;\n appId: string;\n logLine?: (direction: string, obj?: any) => void;\n enterRoomFunction?: EnterRoom<SigType, SigPayload>;\n peerlessUserExpiration?: number;\n workerUrl?: URL;\n}) {\n const userId = uid ?? `user-${crypto.randomUUID()}`;\n const rtcConfig: RTCConfiguration = {\n iceServers: [{ urls: \"stun:stun.l.google.com:19302\" }],\n };\n\n const messagesListeners = new Set<(data: any, from: string) => void>();\n\n function wireDataChannel(userId: string, dc: RTCDataChannel) {\n dc.onopen = () => logLine(\"💬\", { event: \"dc-open\", userId });\n dc.onmessage = ({ data }) => {\n messagesListeners.forEach(listener => listener(data as any, userId));\n logLine(\"💬\", { event: \"dc-message\", userId, data });\n };\n dc.onclose = () => logLine(\"💬\", { event: \"dc-close\", userId });\n dc.onerror = () => logLine(\"⚠️ ERROR\", { error: \"dc-error\", userId });\n }\n\n const dataChannels: Map<string, RTCDataChannel> = new Map();\n\n const { enterRoom, exitRoom, getUsers, leaveUser, addUserListener, removeUserListener, end: endPeerCollection } = collectPeerConnections({\n userId,\n appId,\n rtcConfig,\n enterRoomFunction,\n logLine,\n workerUrl,\n peerlessUserExpiration,\n onLeaveUser(userId: string) {\n const dc = dataChannels.get(userId);\n try { dc?.close(); } catch { }\n dataChannels.delete(userId);\n },\n receivePeerConnection({ pc, userId, initiator }) {\n if (initiator) {\n const dc = pc.createDataChannel(\"data\");\n wireDataChannel(userId, dc);\n dataChannels.set(userId, dc);\n } else {\n pc.ondatachannel = (ev) => {\n const dc = ev.channel;\n wireDataChannel(userId, dc);\n dataChannels.set(userId, dc);\n };\n }\n\n logLine(\"💬\", { event: \"pc-ready\", userId, initiator });\n },\n });\n\n function send(data: any, userId?: string) {\n dataChannels.forEach((dataChannel, pUserId) => {\n if (userId && pUserId !== userId) return;\n if (dataChannel.readyState === \"open\") dataChannel.send(data);\n });\n }\n\n function removeMessageListener(listener: (data: any, from: string) => void) {\n messagesListeners.delete(listener);\n }\n\n function addMessageListener(listener: (data: any, from: string) => void) {\n messagesListeners.add(listener);\n return () => {\n removeMessageListener(listener);\n };\n }\n\n return {\n userId,\n send,\n enterRoom,\n exitRoom,\n leaveUser,\n getUsers,\n addMessageListener,\n removeMessageListener,\n addUserListener,\n removeUserListener,\n end() {\n dataChannels.forEach((dataChannel) => {\n try { dataChannel.close(); } catch { }\n });\n dataChannels.clear();\n endPeerCollection();\n },\n };\n}\n"
|
|
9
|
+
],
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "7979C2C0F3726FCA64756E2164756E21",
|
|
12
|
+
"names": []
|
|
13
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dobuki/hello-worker",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.18",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -19,8 +19,9 @@
|
|
|
19
19
|
"build:worker": "bun build src/browser/signal-room.worker.ts --target browser --format esm --outdir dist --minify --sourcemap",
|
|
20
20
|
"build:sample": "bun build src/browser/sample/index.ts src/browser/signal-room.worker.ts --target browser --format esm --outdir public --minify --sourcemap",
|
|
21
21
|
"build:types": "tsc -p tsconfig.json",
|
|
22
|
-
"build": "bun
|
|
23
|
-
"
|
|
22
|
+
"build:main": "bun build src/browser --target browser --format esm --outdir dist --minify --sourcemap",
|
|
23
|
+
"build": "bun i && bun run build:worker && bun run build:main && bun run build:sample && bun run build:types",
|
|
24
|
+
"prepublishOnly": "bun run build",
|
|
24
25
|
"npm-patch": "npm version patch && npm publish"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
package/dist/enter-world.js
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { enterRoom } from "./signal-room";
|
|
2
|
-
import { collectPeerConnections } from "./webrtc-peer-collector";
|
|
3
|
-
export function enterWorld({ uid, logLine = console.debug, enterRoomFunction = enterRoom, autoLeaveUsers = false, workerUrl, }) {
|
|
4
|
-
const userId = uid ?? `user-${crypto.randomUUID()}`;
|
|
5
|
-
const rtcConfig = {
|
|
6
|
-
iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
|
|
7
|
-
};
|
|
8
|
-
const messagesListeners = new Set();
|
|
9
|
-
const usersListener = new Set();
|
|
10
|
-
function wireDataChannel(userId, dc) {
|
|
11
|
-
dc.onopen = () => logLine("💬", { event: "dc-open", userId });
|
|
12
|
-
dc.onmessage = ({ data }) => {
|
|
13
|
-
messagesListeners.forEach(listener => listener(data, userId));
|
|
14
|
-
logLine("💬", { event: "dc-message", userId, data });
|
|
15
|
-
};
|
|
16
|
-
dc.onclose = () => logLine("💬", { event: "dc-close", userId });
|
|
17
|
-
dc.onerror = () => logLine("⚠️ ERROR", { error: "dc-error", userId });
|
|
18
|
-
}
|
|
19
|
-
const dataChannels = new Map();
|
|
20
|
-
const { enterRoom, exitRoom, leaveUser, getUsers, getRooms } = collectPeerConnections({
|
|
21
|
-
userId,
|
|
22
|
-
rtcConfig,
|
|
23
|
-
enterRoomFunction,
|
|
24
|
-
logLine,
|
|
25
|
-
workerUrl,
|
|
26
|
-
leaveUserWithoutPeer: autoLeaveUsers,
|
|
27
|
-
onLeaveUser(userId) {
|
|
28
|
-
const dc = dataChannels.get(userId);
|
|
29
|
-
try {
|
|
30
|
-
dc?.close();
|
|
31
|
-
}
|
|
32
|
-
catch { }
|
|
33
|
-
dataChannels.delete(userId);
|
|
34
|
-
},
|
|
35
|
-
receivePeerConnection({ pc, userId, initiator }) {
|
|
36
|
-
if (initiator) {
|
|
37
|
-
const dc = pc.createDataChannel("data");
|
|
38
|
-
wireDataChannel(userId, dc);
|
|
39
|
-
dataChannels.set(userId, dc);
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
pc.ondatachannel = (ev) => {
|
|
43
|
-
const dc = ev.channel;
|
|
44
|
-
wireDataChannel(userId, dc);
|
|
45
|
-
dataChannels.set(userId, dc);
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
logLine("💬", { event: "pc-ready", userId, initiator });
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
function send(data, userId) {
|
|
52
|
-
dataChannels.forEach((dataChannel, pUserId) => {
|
|
53
|
-
if (userId && pUserId !== userId)
|
|
54
|
-
return;
|
|
55
|
-
if (dataChannel.readyState === "open")
|
|
56
|
-
dataChannel.send(data);
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
function removeMessageListener(listener) {
|
|
60
|
-
messagesListeners.delete(listener);
|
|
61
|
-
}
|
|
62
|
-
function addMessageListener(listener) {
|
|
63
|
-
messagesListeners.add(listener);
|
|
64
|
-
return () => {
|
|
65
|
-
removeMessageListener(listener);
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
function removeUserListener(listener) {
|
|
69
|
-
usersListener.delete(listener);
|
|
70
|
-
}
|
|
71
|
-
function addUserListener(listener) {
|
|
72
|
-
usersListener.add(listener);
|
|
73
|
-
return () => {
|
|
74
|
-
removeUserListener(listener);
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
return {
|
|
78
|
-
userId,
|
|
79
|
-
send,
|
|
80
|
-
enterRoom,
|
|
81
|
-
exitRoom,
|
|
82
|
-
leaveUser,
|
|
83
|
-
getUsers,
|
|
84
|
-
addMessageListener,
|
|
85
|
-
removeMessageListener,
|
|
86
|
-
addUserListener,
|
|
87
|
-
removeUserListener,
|
|
88
|
-
end() {
|
|
89
|
-
getUsers().forEach(user => leaveUser(user));
|
|
90
|
-
getRooms().forEach(({ room, host }) => exitRoom({ room, host }));
|
|
91
|
-
dataChannels.forEach((dataChannel) => {
|
|
92
|
-
try {
|
|
93
|
-
dataChannel.close();
|
|
94
|
-
}
|
|
95
|
-
catch { }
|
|
96
|
-
});
|
|
97
|
-
dataChannels.clear();
|
|
98
|
-
},
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
//# sourceMappingURL=enter-world.js.map
|
package/dist/enter-world.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"enter-world.js","sourceRoot":"","sources":["../src/browser/enter-world.ts"],"names":[],"mappings":"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"}
|
package/dist/impl/signal-room.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* enterRoom connects to the signaling room via WebSocket.
|
|
3
|
-
*/
|
|
4
|
-
export function enterRoom({ userId, room, host, onOpen, onClose, onError, logLine, onPeerJoined, onPeerLeft, onMessage, }) {
|
|
5
|
-
const wsUrl = "wss://" + host + "/room/" + room + "?userId=" + encodeURIComponent(userId);
|
|
6
|
-
const ws = new WebSocket(wsUrl);
|
|
7
|
-
let exited = false;
|
|
8
|
-
function send(type, toPeerId, payload) {
|
|
9
|
-
if (exited)
|
|
10
|
-
return false;
|
|
11
|
-
const obj = { type, to: toPeerId, payload };
|
|
12
|
-
ws.send(JSON.stringify(obj));
|
|
13
|
-
logLine?.("👤 ➡️ 🖥️", obj);
|
|
14
|
-
return true;
|
|
15
|
-
}
|
|
16
|
-
function onmessage(e) {
|
|
17
|
-
let msg;
|
|
18
|
-
try {
|
|
19
|
-
msg = JSON.parse(e.data);
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
logLine?.("⚠️ ERROR", { error: "invalid-json" });
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
logLine?.("🖥️ ➡️ 👤", msg);
|
|
26
|
-
// Existing client greets newcomers
|
|
27
|
-
if (msg.type === "peer-joined" && msg.peerId && msg.userId) {
|
|
28
|
-
const { userId, peerId } = msg;
|
|
29
|
-
onPeerJoined({
|
|
30
|
-
userId,
|
|
31
|
-
peerId,
|
|
32
|
-
receive: (type, payload) => {
|
|
33
|
-
return send(type, peerId, payload);
|
|
34
|
-
},
|
|
35
|
-
});
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
if (msg.type === "peer-left" && msg.peerId && msg.userId) {
|
|
39
|
-
const { userId, peerId } = msg;
|
|
40
|
-
onPeerLeft(userId, peerId);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
if (msg.peerId && msg.userId) {
|
|
44
|
-
const { userId, peerId } = msg;
|
|
45
|
-
onMessage(msg.type, msg.payload, {
|
|
46
|
-
userId,
|
|
47
|
-
peerId,
|
|
48
|
-
receive: (type, payload) => {
|
|
49
|
-
return send(type, peerId, payload);
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
;
|
|
55
|
-
ws.addEventListener("message", onmessage);
|
|
56
|
-
if (onOpen)
|
|
57
|
-
ws.addEventListener("open", onOpen);
|
|
58
|
-
if (onClose)
|
|
59
|
-
ws.addEventListener("close", onClose);
|
|
60
|
-
if (onError)
|
|
61
|
-
ws.addEventListener("error", onError);
|
|
62
|
-
return {
|
|
63
|
-
exitRoom: () => {
|
|
64
|
-
exited = true;
|
|
65
|
-
ws.close();
|
|
66
|
-
ws.removeEventListener("message", onmessage);
|
|
67
|
-
if (onOpen)
|
|
68
|
-
ws.removeEventListener("open", onOpen);
|
|
69
|
-
if (onClose)
|
|
70
|
-
ws.removeEventListener("close", onClose);
|
|
71
|
-
if (onError)
|
|
72
|
-
ws.removeEventListener("error", onError);
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
//# sourceMappingURL=signal-room.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"signal-room.js","sourceRoot":"","sources":["../../src/browser/impl/signal-room.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
DELETED
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/browser/index.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,oCAAoC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/sample/index.js
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/// <reference lib="dom" />
|
|
2
|
-
/// <reference lib="dom.iterable" />
|
|
3
|
-
import { enterRoom } from "../signal-room.js";
|
|
4
|
-
import { enterWorld } from "../enter-world.js";
|
|
5
|
-
const statusEl = document.getElementById("status");
|
|
6
|
-
const logEl = document.getElementById("log");
|
|
7
|
-
const welcomeEl = document.getElementById("welcome");
|
|
8
|
-
function ts() {
|
|
9
|
-
// HH:MM:SS.mmm (local time)
|
|
10
|
-
const d = new Date();
|
|
11
|
-
const p2 = (n) => String(n).padStart(2, "0");
|
|
12
|
-
const p3 = (n) => String(n).padStart(3, "0");
|
|
13
|
-
return `${p2(d.getHours())}:${p2(d.getMinutes())}:${p2(d.getSeconds())}.${p3(d.getMilliseconds())}`;
|
|
14
|
-
}
|
|
15
|
-
function logLine(direction, obj) {
|
|
16
|
-
logEl.textContent += ts() + " " + direction + " " + (obj ? JSON.stringify(obj) : "") + "\n";
|
|
17
|
-
logEl.scrollTop = logEl.scrollHeight;
|
|
18
|
-
}
|
|
19
|
-
export function clearLog() {
|
|
20
|
-
logEl.textContent = "";
|
|
21
|
-
}
|
|
22
|
-
export function testWelcome() {
|
|
23
|
-
const { exitRoom } = enterRoom({
|
|
24
|
-
userId: crypto.randomUUID(),
|
|
25
|
-
room: "test",
|
|
26
|
-
host: location.host,
|
|
27
|
-
onOpen: () => {
|
|
28
|
-
statusEl.textContent = "🟢 connected";
|
|
29
|
-
logLine("🔗 CONNECTED");
|
|
30
|
-
},
|
|
31
|
-
onClose: () => {
|
|
32
|
-
statusEl.textContent = "🔴 closed";
|
|
33
|
-
logLine("⛓️💥 DISCONNECTED");
|
|
34
|
-
},
|
|
35
|
-
onError: () => {
|
|
36
|
-
statusEl.textContent = "🔴 error";
|
|
37
|
-
logLine("⚠️ ERROR");
|
|
38
|
-
},
|
|
39
|
-
onPeerJoined: (user) => {
|
|
40
|
-
user.receive("welcome", { note: welcomeEl.value });
|
|
41
|
-
},
|
|
42
|
-
onPeerLeft: (info) => {
|
|
43
|
-
logLine("👤 LEFT", info);
|
|
44
|
-
},
|
|
45
|
-
onMessage: (type, payload, user) => {
|
|
46
|
-
if (type === "welcome") {
|
|
47
|
-
user.receive("thanks", { note: "Thank you! 🙏" });
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
logLine,
|
|
51
|
-
workerUrl: new URL("../signal-room.worker.js", import.meta.url),
|
|
52
|
-
});
|
|
53
|
-
return () => {
|
|
54
|
-
exitRoom();
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
export function testWebRTC() {
|
|
58
|
-
// --- create a stage + emoji (if not already in HTML) ---
|
|
59
|
-
let stageEl = document.getElementById("stage");
|
|
60
|
-
if (!stageEl) {
|
|
61
|
-
stageEl = document.createElement("div");
|
|
62
|
-
stageEl.id = "stage";
|
|
63
|
-
stageEl.style.position = "relative";
|
|
64
|
-
stageEl.style.width = "100%";
|
|
65
|
-
stageEl.style.height = "280px";
|
|
66
|
-
stageEl.style.border = "1px solid #333";
|
|
67
|
-
stageEl.style.borderRadius = "8px";
|
|
68
|
-
stageEl.style.margin = "12px 0";
|
|
69
|
-
stageEl.style.userSelect = "none";
|
|
70
|
-
stageEl.style.touchAction = "none";
|
|
71
|
-
document.body.insertBefore(stageEl, welcomeEl);
|
|
72
|
-
}
|
|
73
|
-
welcomeEl.classList.add("hidden");
|
|
74
|
-
let emojiEl = document.getElementById("emoji");
|
|
75
|
-
if (!emojiEl) {
|
|
76
|
-
emojiEl = document.createElement("div");
|
|
77
|
-
emojiEl.id = "emoji";
|
|
78
|
-
emojiEl.textContent = "🦊";
|
|
79
|
-
emojiEl.style.position = "absolute";
|
|
80
|
-
emojiEl.style.left = "0px";
|
|
81
|
-
emojiEl.style.top = "0px";
|
|
82
|
-
emojiEl.style.transform = "translate(-50%, -50%)";
|
|
83
|
-
emojiEl.style.fontSize = "36px";
|
|
84
|
-
emojiEl.style.pointerEvents = "none";
|
|
85
|
-
stageEl.appendChild(emojiEl);
|
|
86
|
-
}
|
|
87
|
-
function setEmojiPos01(x01, y01) {
|
|
88
|
-
const r = stageEl.getBoundingClientRect();
|
|
89
|
-
const x = Math.max(0, Math.min(1, x01)) * r.width;
|
|
90
|
-
const y = Math.max(0, Math.min(1, y01)) * r.height;
|
|
91
|
-
emojiEl.style.left = `${x}px`;
|
|
92
|
-
emojiEl.style.top = `${y}px`;
|
|
93
|
-
}
|
|
94
|
-
// --- start WebRTC mesh using YOUR joinWebRTCRoom ---
|
|
95
|
-
statusEl.textContent = "🟡 connecting";
|
|
96
|
-
logLine("💬", { event: "start-webrtc-test" });
|
|
97
|
-
const session = enterWorld({
|
|
98
|
-
logLine,
|
|
99
|
-
workerUrl: new URL("../signal-room.worker.js", import.meta.url),
|
|
100
|
-
});
|
|
101
|
-
session.enterRoom({
|
|
102
|
-
room: "test",
|
|
103
|
-
host: location.host,
|
|
104
|
-
});
|
|
105
|
-
session.addMessageListener(data => {
|
|
106
|
-
try {
|
|
107
|
-
const { x, y } = JSON.parse(String(data));
|
|
108
|
-
if (typeof x === "number" && typeof y === "number") {
|
|
109
|
-
setEmojiPos01(x, y);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
catch {
|
|
113
|
-
// ignore non-json
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
// --- send mouse position over all open data channels ---
|
|
117
|
-
let lastSent = 0;
|
|
118
|
-
function broadcastMove(x01, y01) {
|
|
119
|
-
const now = performance.now();
|
|
120
|
-
if (now - lastSent < 16)
|
|
121
|
-
return; // ~60Hz throttle
|
|
122
|
-
lastSent = now;
|
|
123
|
-
const msg = JSON.stringify({ x: x01, y: y01 });
|
|
124
|
-
session.send(msg);
|
|
125
|
-
}
|
|
126
|
-
function onPointerMove(ev) {
|
|
127
|
-
const r = stageEl.getBoundingClientRect();
|
|
128
|
-
const x01 = (ev.clientX - r.left) / r.width;
|
|
129
|
-
const y01 = (ev.clientY - r.top) / r.height;
|
|
130
|
-
// move locally too (feels instant)
|
|
131
|
-
setEmojiPos01(x01, y01);
|
|
132
|
-
// broadcast to peers via datachannel
|
|
133
|
-
broadcastMove(x01, y01);
|
|
134
|
-
}
|
|
135
|
-
stageEl.addEventListener("pointermove", onPointerMove);
|
|
136
|
-
// return cleanup function (same pattern as testWelcome)
|
|
137
|
-
return () => {
|
|
138
|
-
stageEl.removeEventListener("pointermove", onPointerMove);
|
|
139
|
-
stageEl.remove();
|
|
140
|
-
welcomeEl.classList.remove("hidden");
|
|
141
|
-
session.end();
|
|
142
|
-
logLine("💬", { event: "stop-webrtc-test" });
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
//# sourceMappingURL=index.js.map
|
package/dist/sample/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/sample/index.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,oCAAoC;AAEpC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAE,CAAC;AACpD,MAAM,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAE,CAAC;AAC9C,MAAM,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAqB,CAAC;AAEzE,SAAS,EAAE;IACP,4BAA4B;IAC5B,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACrD,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,EAAE,CAAC;AACxG,CAAC;AAED,SAAS,OAAO,CAAC,SAAiB,EAAE,GAAS;IACzC,KAAK,CAAC,WAAW,IAAI,EAAE,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IAC9F,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,YAAY,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,QAAQ;IACpB,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,WAAW;IACvB,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;QAC3B,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE;QAC3B,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,MAAM,EAAE,GAAG,EAAE;YACT,QAAQ,CAAC,WAAW,GAAG,cAAc,CAAC;YACtC,OAAO,CAAC,eAAe,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,EAAE,GAAG,EAAE;YACV,QAAQ,CAAC,WAAW,GAAG,WAAW,CAAC;YACnC,OAAO,CAAC,qBAAqB,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,EAAE,GAAG,EAAE;YACV,QAAQ,CAAC,WAAW,GAAG,UAAU,CAAC;YAClC,OAAO,CAAC,UAAU,CAAC,CAAC;QACxB,CAAC;QACD,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE;YACnB,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;QACvD,CAAC;QACD,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE;YACjB,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC7B,CAAC;QACD,SAAS,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;YAC/B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACrB,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;YACtD,CAAC;QACL,CAAC;QACD,OAAO;QACP,SAAS,EAAE,IAAI,GAAG,CAAC,0BAA0B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;KAClE,CAAC,CAAC;IACH,OAAO,GAAG,EAAE;QACR,QAAQ,EAAE,CAAC;IACf,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,0DAA0D;IAC1D,IAAI,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,OAAO,CAA0B,CAAC;IACxE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACxC,OAAO,CAAC,EAAE,GAAG,OAAO,CAAC;QACrB,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC;QACpC,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,gBAAgB,CAAC;QACxC,OAAO,CAAC,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC;QACnC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC;QACnC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACjD,CAAC;IACD,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAElC,IAAI,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,OAAO,CAA0B,CAAC;IACxE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACxC,OAAO,CAAC,EAAE,GAAG,OAAO,CAAC;QACrB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC;QACpC,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,uBAAuB,CAAC;QAClD,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;QACrC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,SAAS,aAAa,CAAC,GAAW,EAAE,GAAW;QAC7C,MAAM,CAAC,GAAG,OAAQ,CAAC,qBAAqB,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;QAClD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;QACnD,OAAQ,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;QAC/B,OAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC;IAChC,CAAC;IAED,sDAAsD;IACtD,QAAQ,CAAC,WAAW,GAAG,eAAe,CAAC;IACvC,OAAO,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAE9C,MAAM,OAAO,GAAG,UAAU,CAAC;QACzB,OAAO;QACP,SAAS,EAAE,IAAI,GAAG,CAAC,0BAA0B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;KAChE,CAAC,CAAC;IACH,OAAO,CAAC,SAAS,CAAC;QAChB,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,QAAQ,CAAC,IAAI;KACpB,CAAC,CAAC;IACH,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE;QAChC,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YAC1C,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;gBACnD,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kBAAkB;QACpB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,0DAA0D;IAC1D,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,SAAS,aAAa,CAAC,GAAW,EAAE,GAAW;QAC7C,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAC9B,IAAI,GAAG,GAAG,QAAQ,GAAG,EAAE;YAAE,OAAO,CAAC,iBAAiB;QAClD,QAAQ,GAAG,GAAG,CAAC;QAEf,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAE/C,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;IAED,SAAS,aAAa,CAAC,EAAgB;QACrC,MAAM,CAAC,GAAG,OAAQ,CAAC,qBAAqB,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;QAC5C,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;QAE5C,mCAAmC;QACnC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAExB,qCAAqC;QACrC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,CAAC,gBAAgB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IAEvD,wDAAwD;IACxD,OAAO,GAAG,EAAE;QACV,OAAQ,CAAC,mBAAmB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;QAC3D,OAAQ,CAAC,MAAM,EAAE,CAAC;QAClB,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/sample.d.ts
DELETED
package/dist/sample.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sample.d.ts","sourceRoot":"","sources":["../src/browser/sample.ts"],"names":[],"mappings":"AAuBA,wBAAgB,QAAQ,SAEvB;AAED,wBAAgB,WAAW,eAmC1B;AAED,wBAAgB,UAAU,eAkGzB"}
|
package/dist/sample.js
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
/// <reference lib="dom" />
|
|
2
|
-
/// <reference lib="dom.iterable" />
|
|
3
|
-
import { enterRoom } from "./signal-room.js";
|
|
4
|
-
import { joinWebRTCRoom } from "./webrtc-room.js";
|
|
5
|
-
const statusEl = document.getElementById("status");
|
|
6
|
-
const logEl = document.getElementById("log");
|
|
7
|
-
const welcomeEl = document.getElementById("welcome");
|
|
8
|
-
function ts() {
|
|
9
|
-
// HH:MM:SS.mmm (local time)
|
|
10
|
-
const d = new Date();
|
|
11
|
-
const p2 = (n) => String(n).padStart(2, "0");
|
|
12
|
-
const p3 = (n) => String(n).padStart(3, "0");
|
|
13
|
-
return `${p2(d.getHours())}:${p2(d.getMinutes())}:${p2(d.getSeconds())}.${p3(d.getMilliseconds())}`;
|
|
14
|
-
}
|
|
15
|
-
function logLine(direction, obj) {
|
|
16
|
-
logEl.textContent += ts() + " " + direction + " " + (obj ? JSON.stringify(obj) : "") + "\n";
|
|
17
|
-
logEl.scrollTop = logEl.scrollHeight;
|
|
18
|
-
}
|
|
19
|
-
export function clearLog() {
|
|
20
|
-
logEl.textContent = "";
|
|
21
|
-
}
|
|
22
|
-
export function testWelcome() {
|
|
23
|
-
const { exitRoom } = enterRoom({
|
|
24
|
-
userId: crypto.randomUUID(),
|
|
25
|
-
room: "test",
|
|
26
|
-
host: location.host,
|
|
27
|
-
onOpen: () => {
|
|
28
|
-
statusEl.textContent = "connected";
|
|
29
|
-
logLine("🔗 CONNECTED");
|
|
30
|
-
},
|
|
31
|
-
onClose: () => {
|
|
32
|
-
statusEl.textContent = "closed";
|
|
33
|
-
logLine("⛓️💥 DISCONNECTED");
|
|
34
|
-
statusEl.textContent = "closed";
|
|
35
|
-
},
|
|
36
|
-
onError: () => {
|
|
37
|
-
statusEl.textContent = "error";
|
|
38
|
-
logLine("⚠️ ERROR");
|
|
39
|
-
},
|
|
40
|
-
onPeerJoined: (user) => {
|
|
41
|
-
user.receive("welcome", { note: welcomeEl.value });
|
|
42
|
-
},
|
|
43
|
-
onPeerLeft: (info) => {
|
|
44
|
-
logLine("👤 LEFT", info);
|
|
45
|
-
},
|
|
46
|
-
onMessage: (type, payload, user) => {
|
|
47
|
-
if (type === "welcome") {
|
|
48
|
-
user.receive("thanks", { note: "Thank you! 🙏" });
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
logLine,
|
|
52
|
-
workerUrl: new URL("./signal-room.worker.js", import.meta.url),
|
|
53
|
-
});
|
|
54
|
-
return () => {
|
|
55
|
-
exitRoom();
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
export function testWebRTC() {
|
|
59
|
-
// --- create a stage + emoji (if not already in HTML) ---
|
|
60
|
-
let stageEl = document.getElementById("stage");
|
|
61
|
-
if (!stageEl) {
|
|
62
|
-
stageEl = document.createElement("div");
|
|
63
|
-
stageEl.id = "stage";
|
|
64
|
-
stageEl.style.position = "relative";
|
|
65
|
-
stageEl.style.width = "100%";
|
|
66
|
-
stageEl.style.height = "280px";
|
|
67
|
-
stageEl.style.border = "1px solid #333";
|
|
68
|
-
stageEl.style.borderRadius = "8px";
|
|
69
|
-
stageEl.style.margin = "12px 0";
|
|
70
|
-
stageEl.style.userSelect = "none";
|
|
71
|
-
stageEl.style.touchAction = "none";
|
|
72
|
-
document.body.insertBefore(stageEl, welcomeEl);
|
|
73
|
-
}
|
|
74
|
-
welcomeEl.classList.add("hidden");
|
|
75
|
-
let emojiEl = document.getElementById("emoji");
|
|
76
|
-
if (!emojiEl) {
|
|
77
|
-
emojiEl = document.createElement("div");
|
|
78
|
-
emojiEl.id = "emoji";
|
|
79
|
-
emojiEl.textContent = "🦊";
|
|
80
|
-
emojiEl.style.position = "absolute";
|
|
81
|
-
emojiEl.style.left = "0px";
|
|
82
|
-
emojiEl.style.top = "0px";
|
|
83
|
-
emojiEl.style.transform = "translate(-50%, -50%)";
|
|
84
|
-
emojiEl.style.fontSize = "36px";
|
|
85
|
-
emojiEl.style.pointerEvents = "none";
|
|
86
|
-
stageEl.appendChild(emojiEl);
|
|
87
|
-
}
|
|
88
|
-
function setEmojiPos01(x01, y01) {
|
|
89
|
-
const r = stageEl.getBoundingClientRect();
|
|
90
|
-
const x = Math.max(0, Math.min(1, x01)) * r.width;
|
|
91
|
-
const y = Math.max(0, Math.min(1, y01)) * r.height;
|
|
92
|
-
emojiEl.style.left = `${x}px`;
|
|
93
|
-
emojiEl.style.top = `${y}px`;
|
|
94
|
-
}
|
|
95
|
-
// --- start WebRTC mesh using YOUR joinWebRTCRoom ---
|
|
96
|
-
statusEl.textContent = "connecting";
|
|
97
|
-
logLine("💬", { event: "start-webrtc-test" });
|
|
98
|
-
const session = joinWebRTCRoom({
|
|
99
|
-
logLine,
|
|
100
|
-
enterRoom,
|
|
101
|
-
onMessage: (data) => {
|
|
102
|
-
try {
|
|
103
|
-
const { x, y } = JSON.parse(String(data));
|
|
104
|
-
if (typeof x === "number" && typeof y === "number") {
|
|
105
|
-
setEmojiPos01(x, y);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
// ignore non-json
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
workerUrl: new URL("./signal-room.worker.js", import.meta.url),
|
|
113
|
-
});
|
|
114
|
-
session.enter({
|
|
115
|
-
room: "test",
|
|
116
|
-
host: location.host,
|
|
117
|
-
});
|
|
118
|
-
// --- send mouse position over all open data channels ---
|
|
119
|
-
let lastSent = 0;
|
|
120
|
-
function broadcastMove(x01, y01) {
|
|
121
|
-
const now = performance.now();
|
|
122
|
-
if (now - lastSent < 16)
|
|
123
|
-
return; // ~60Hz throttle
|
|
124
|
-
lastSent = now;
|
|
125
|
-
const msg = JSON.stringify({ x: x01, y: y01 });
|
|
126
|
-
session.sendToAll(msg);
|
|
127
|
-
}
|
|
128
|
-
function onPointerMove(ev) {
|
|
129
|
-
const r = stageEl.getBoundingClientRect();
|
|
130
|
-
const x01 = (ev.clientX - r.left) / r.width;
|
|
131
|
-
const y01 = (ev.clientY - r.top) / r.height;
|
|
132
|
-
// move locally too (feels instant)
|
|
133
|
-
setEmojiPos01(x01, y01);
|
|
134
|
-
// broadcast to peers via datachannel
|
|
135
|
-
broadcastMove(x01, y01);
|
|
136
|
-
}
|
|
137
|
-
stageEl.addEventListener("pointermove", onPointerMove);
|
|
138
|
-
// return cleanup function (same pattern as testWelcome)
|
|
139
|
-
return () => {
|
|
140
|
-
stageEl.removeEventListener("pointermove", onPointerMove);
|
|
141
|
-
stageEl.remove();
|
|
142
|
-
welcomeEl.classList.remove("hidden");
|
|
143
|
-
session.end();
|
|
144
|
-
logLine("💬", { event: "stop-webrtc-test" });
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
//# sourceMappingURL=sample.js.map
|
package/dist/sample.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sample.js","sourceRoot":"","sources":["../src/browser/sample.ts"],"names":[],"mappings":"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"}
|
package/dist/signal-room.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { enterRoom as baseEnterRoom } from "./impl/signal-room.js";
|
|
2
|
-
export function enterRoom({ userId, room, host, onOpen, onClose, onError, onPeerJoined, onPeerLeft, onMessage, logLine, workerUrl, }) {
|
|
3
|
-
if (!workerUrl) {
|
|
4
|
-
const CDN_WORKER_URL = `https://cdn.jsdelivr.net/npm/@dobuki/hello-worker/dist/signal-room.worker.min.js`;
|
|
5
|
-
console.warn("Warning: enterRoom called without workerUrl; this may cause issues in some environments. You should pass workerUrl explicitly. Use:", CDN_WORKER_URL);
|
|
6
|
-
return baseEnterRoom({
|
|
7
|
-
userId,
|
|
8
|
-
room,
|
|
9
|
-
host,
|
|
10
|
-
onOpen,
|
|
11
|
-
onClose,
|
|
12
|
-
onError,
|
|
13
|
-
onPeerJoined,
|
|
14
|
-
onPeerLeft,
|
|
15
|
-
onMessage,
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
const worker = new Worker(workerUrl, { type: "module" });
|
|
19
|
-
let exited = false;
|
|
20
|
-
function makeUser({ userId, peerId }) {
|
|
21
|
-
return {
|
|
22
|
-
userId,
|
|
23
|
-
peerId,
|
|
24
|
-
receive: (type, payload) => {
|
|
25
|
-
if (exited)
|
|
26
|
-
return false;
|
|
27
|
-
worker.postMessage({ cmd: "send", toPeerId: peerId, type, payload });
|
|
28
|
-
return true;
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
const onWorkerMessage = (e) => {
|
|
33
|
-
const ev = e.data;
|
|
34
|
-
if (ev.kind === "open")
|
|
35
|
-
onOpen?.();
|
|
36
|
-
else if (ev.kind === "close")
|
|
37
|
-
worker.terminate();
|
|
38
|
-
else if (ev.kind === "error")
|
|
39
|
-
onError?.();
|
|
40
|
-
else if (ev.kind === "peer-joined")
|
|
41
|
-
onPeerJoined(makeUser({ userId: ev.userId, peerId: ev.peerId }));
|
|
42
|
-
else if (ev.kind === "peer-left")
|
|
43
|
-
onPeerLeft(ev.userId, ev.peerId);
|
|
44
|
-
else if (ev.kind === "message")
|
|
45
|
-
onMessage(ev.type, ev.payload, makeUser({ userId: ev.fromUserId, peerId: ev.fromPeerId }));
|
|
46
|
-
else if (ev.kind === "log")
|
|
47
|
-
logLine?.(ev.direction, ev.obj);
|
|
48
|
-
};
|
|
49
|
-
worker.addEventListener("message", onWorkerMessage);
|
|
50
|
-
worker.postMessage({ cmd: "enter", userId, room, host });
|
|
51
|
-
return {
|
|
52
|
-
exitRoom: () => {
|
|
53
|
-
exited = true;
|
|
54
|
-
worker.removeEventListener("message", onWorkerMessage);
|
|
55
|
-
worker.postMessage({ cmd: "exit" });
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
//# sourceMappingURL=signal-room.js.map
|
package/dist/signal-room.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"signal-room.js","sourceRoot":"","sources":["../src/browser/signal-room.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { enterRoom } from "./signal-room";
|
|
2
|
-
const DEFAULT_ENTER_ROOM = enterRoom;
|
|
3
|
-
export function collectPeerConnections({ userId, receivePeerConnection, leaveUserWithoutPeer = false, rtcConfig = { iceServers: [{ urls: "stun:stun.l.google.com:19302" }] }, enterRoomFunction: enterRoom = DEFAULT_ENTER_ROOM, logLine = console.debug, onLeaveUser, workerUrl, }) {
|
|
4
|
-
const users = new Map();
|
|
5
|
-
function getPeer(peer) {
|
|
6
|
-
let state = users.get(peer.userId);
|
|
7
|
-
if (!state) {
|
|
8
|
-
const newState = {
|
|
9
|
-
userId: peer.userId,
|
|
10
|
-
pc: new RTCPeerConnection(rtcConfig),
|
|
11
|
-
pendingRemoteIce: [],
|
|
12
|
-
peers: new Set([peer]),
|
|
13
|
-
};
|
|
14
|
-
users.set(peer.userId, newState);
|
|
15
|
-
// Send local ICE candidates to this peer
|
|
16
|
-
newState.pc.onicecandidate = (ev) => {
|
|
17
|
-
if (!ev.candidate)
|
|
18
|
-
return;
|
|
19
|
-
for (let user of newState.peers) {
|
|
20
|
-
const success = user.receive("ice", ev.candidate.toJSON());
|
|
21
|
-
if (success)
|
|
22
|
-
break;
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
newState.pc.onconnectionstatechange = () => {
|
|
26
|
-
logLine("💬", { event: "pc-state", userId: newState.userId, state: newState.pc.connectionState });
|
|
27
|
-
};
|
|
28
|
-
state = newState;
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
state.peers.add(peer);
|
|
32
|
-
}
|
|
33
|
-
users.set(state.userId, state);
|
|
34
|
-
return state;
|
|
35
|
-
}
|
|
36
|
-
function leaveUser(userId) {
|
|
37
|
-
onLeaveUser?.(userId);
|
|
38
|
-
const p = users.get(userId);
|
|
39
|
-
if (!p)
|
|
40
|
-
return;
|
|
41
|
-
try {
|
|
42
|
-
p.pc.close();
|
|
43
|
-
}
|
|
44
|
-
catch { }
|
|
45
|
-
users.delete(userId);
|
|
46
|
-
logLine("👤 USER LEFT", userId);
|
|
47
|
-
}
|
|
48
|
-
async function flushRemoteIce(state) {
|
|
49
|
-
if (!state.pc.remoteDescription)
|
|
50
|
-
return;
|
|
51
|
-
const queued = state.pendingRemoteIce;
|
|
52
|
-
state.pendingRemoteIce = [];
|
|
53
|
-
for (const ice of queued) {
|
|
54
|
-
try {
|
|
55
|
-
await state.pc.addIceCandidate(ice);
|
|
56
|
-
}
|
|
57
|
-
catch (e) {
|
|
58
|
-
logLine("⚠️ ERROR", { error: "add-ice-failed", userId: state.userId, detail: String(e) });
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
const roomsEntered = new Map();
|
|
63
|
-
function exit({ room, host }) {
|
|
64
|
-
const key = `${host}/room/${room}`;
|
|
65
|
-
const session = roomsEntered.get(key);
|
|
66
|
-
if (session) {
|
|
67
|
-
session.exitRoom();
|
|
68
|
-
roomsEntered.delete(key);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
function enter({ room, host }) {
|
|
72
|
-
const { exitRoom } = enterRoom({
|
|
73
|
-
userId,
|
|
74
|
-
room,
|
|
75
|
-
host,
|
|
76
|
-
logLine,
|
|
77
|
-
workerUrl,
|
|
78
|
-
// Existing peers initiate to the newcomer (Option 1)
|
|
79
|
-
async onPeerJoined(user) {
|
|
80
|
-
const state = getPeer(user);
|
|
81
|
-
const pc = state.pc;
|
|
82
|
-
receivePeerConnection({ pc, userId: user.userId, initiator: true });
|
|
83
|
-
// Offer flow: createOffer -> setLocalDescription -> send localDescription
|
|
84
|
-
const offer = await pc.createOffer();
|
|
85
|
-
await pc.setLocalDescription(offer);
|
|
86
|
-
user.receive("offer", pc.localDescription?.toJSON());
|
|
87
|
-
},
|
|
88
|
-
onPeerLeft(userId, peerId) {
|
|
89
|
-
const state = users.get(userId);
|
|
90
|
-
if (!state)
|
|
91
|
-
return;
|
|
92
|
-
for (const user of state.peers) {
|
|
93
|
-
if (user.peerId === peerId) {
|
|
94
|
-
state.peers.delete(user);
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
if (state.peers.size === 0 && leaveUserWithoutPeer) {
|
|
99
|
-
leaveUser(userId);
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
async onMessage(type, payload, from) {
|
|
103
|
-
const state = getPeer(from);
|
|
104
|
-
const pc = state.pc;
|
|
105
|
-
if (type === "offer") {
|
|
106
|
-
receivePeerConnection({ pc, userId: from.userId, initiator: false });
|
|
107
|
-
// Responder: set remote offer
|
|
108
|
-
await pc.setRemoteDescription(payload);
|
|
109
|
-
// Create and send answer
|
|
110
|
-
const answer = await pc.createAnswer();
|
|
111
|
-
await pc.setLocalDescription(answer);
|
|
112
|
-
from.receive("answer", pc.localDescription?.toJSON());
|
|
113
|
-
// Now safe to apply any queued ICE from this peer
|
|
114
|
-
await flushRemoteIce(state);
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
if (type === "answer") {
|
|
118
|
-
// Initiator: set remote answer
|
|
119
|
-
await pc.setRemoteDescription(payload);
|
|
120
|
-
await flushRemoteIce(state);
|
|
121
|
-
receivePeerConnection({ pc, userId: from.userId, initiator: true });
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
if (type === "ice") {
|
|
125
|
-
const ice = payload;
|
|
126
|
-
// If we don't have remoteDescription yet, queue it
|
|
127
|
-
if (!pc.remoteDescription) {
|
|
128
|
-
state.pendingRemoteIce.push(ice);
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
try {
|
|
132
|
-
await pc.addIceCandidate(ice);
|
|
133
|
-
}
|
|
134
|
-
catch (e) {
|
|
135
|
-
logLine("⚠️ ERROR", { error: "add-ice-failed", userId: state.userId, detail: String(e) });
|
|
136
|
-
}
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
},
|
|
140
|
-
});
|
|
141
|
-
roomsEntered.set(`${host}/room/${room}`, { exitRoom, room, host });
|
|
142
|
-
}
|
|
143
|
-
return {
|
|
144
|
-
enterRoom: enter,
|
|
145
|
-
exitRoom: exit,
|
|
146
|
-
leaveUser,
|
|
147
|
-
getUsers() {
|
|
148
|
-
return Array.from(users.keys());
|
|
149
|
-
},
|
|
150
|
-
getRooms() {
|
|
151
|
-
return Array.from(roomsEntered.values());
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
//# sourceMappingURL=webrtc-peer-collector.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webrtc-peer-collector.js","sourceRoot":"","sources":["../src/browser/webrtc-peer-collector.ts"],"names":[],"mappings":"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"}
|
package/dist/webrtc-room.d.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { EnterRoom } from "./signal-room";
|
|
2
|
-
type SigType = "offer" | "answer" | "ice";
|
|
3
|
-
type SigPayload = RTCSessionDescriptionInit | RTCIceCandidateInit;
|
|
4
|
-
export declare function collectPeerConnections({ userId, receivePeerConnection, leaveUserWithoutPeer, rtcConfig, enterRoomFunction: enterRoom, logLine, onLeaveUser, workerUrl, }: {
|
|
5
|
-
userId: string;
|
|
6
|
-
rtcConfig?: RTCConfiguration;
|
|
7
|
-
enterRoomFunction?: EnterRoom<SigType, SigPayload>;
|
|
8
|
-
onLeaveUser?: (userId: string) => void;
|
|
9
|
-
logLine?: (direction: string, obj?: any) => void;
|
|
10
|
-
workerUrl?: URL;
|
|
11
|
-
leaveUserWithoutPeer?: boolean;
|
|
12
|
-
receivePeerConnection(connection: {
|
|
13
|
-
pc: RTCPeerConnection;
|
|
14
|
-
userId: string;
|
|
15
|
-
initiator: boolean;
|
|
16
|
-
}): void;
|
|
17
|
-
}): {
|
|
18
|
-
enterRoom: ({ room, host }: {
|
|
19
|
-
room: string;
|
|
20
|
-
host: string;
|
|
21
|
-
}) => void;
|
|
22
|
-
exitRoom: ({ room, host }: {
|
|
23
|
-
room: string;
|
|
24
|
-
host: string;
|
|
25
|
-
}) => void;
|
|
26
|
-
leaveUser: (userId: string) => void;
|
|
27
|
-
getUsers(): string[];
|
|
28
|
-
};
|
|
29
|
-
export declare function joinWebRTCRoom({ uid, onMessage, logLine, enterRoomFunction, autoLeaveUsers, workerUrl, }: {
|
|
30
|
-
uid?: string;
|
|
31
|
-
onMessage?: (data: any, from: string) => void;
|
|
32
|
-
logLine?: (direction: string, obj?: any) => void;
|
|
33
|
-
enterRoomFunction?: EnterRoom<SigType, SigPayload>;
|
|
34
|
-
autoLeaveUsers?: boolean;
|
|
35
|
-
workerUrl?: URL;
|
|
36
|
-
}): {
|
|
37
|
-
userId: string;
|
|
38
|
-
send: (data: any, userId?: string) => void;
|
|
39
|
-
enterRoom: ({ room, host }: {
|
|
40
|
-
room: string;
|
|
41
|
-
host: string;
|
|
42
|
-
}) => void;
|
|
43
|
-
exitRoom: ({ room, host }: {
|
|
44
|
-
room: string;
|
|
45
|
-
host: string;
|
|
46
|
-
}) => void;
|
|
47
|
-
leaveUser: (userId: string) => void;
|
|
48
|
-
getUsers: () => string[];
|
|
49
|
-
end(): void;
|
|
50
|
-
};
|
|
51
|
-
export {};
|
|
52
|
-
//# sourceMappingURL=webrtc-room.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webrtc-room.d.ts","sourceRoot":"","sources":["../src/browser/webrtc-room.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAa,MAAM,eAAe,CAAC;AAErD,KAAK,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAC1C,KAAK,UAAU,GAAG,yBAAyB,GAAG,mBAAmB,CAAC;AAgBlE,wBAAgB,sBAAsB,CAAC,EACrC,MAAM,EACN,qBAAqB,EACrB,oBAA4B,EAC5B,SAAsE,EACtE,iBAAiB,EAAE,SAA8B,EACjD,OAAuB,EACvB,WAAW,EACX,SAAS,GACV,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,iBAAiB,CAAC,EAAE,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACnD,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IACjD,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,UAAU,EAAE;QAAE,EAAE,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;CACxG;gCAoEgC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;KAAE;+BAThC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;KAAE;wBA1BlC,MAAM;;EAsHlC;AAGD,wBAAgB,cAAc,CAAC,EAC7B,GAAG,EACH,SAAS,EACT,OAAuB,EACvB,iBAAsC,EACtC,cAAsB,EACtB,SAAS,GACV,EAAE;IACD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IACjD,iBAAiB,CAAC,EAAE,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACnD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,GAAG,CAAC;CACjB;;iBA+CqB,GAAG,WAAW,MAAM;gCAnJT;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;KAAE;+BAThC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;KAAE;wBA1BlC,MAAM;;;EA2MlC"}
|
package/dist/webrtc-room.js
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { enterRoom } from "./signal-room";
|
|
2
|
-
const DEFAULT_ENTER_ROOM = enterRoom;
|
|
3
|
-
export function collectPeerConnections({ userId, receivePeerConnection, leaveUserWithoutPeer = false, rtcConfig = { iceServers: [{ urls: "stun:stun.l.google.com:19302" }] }, enterRoomFunction: enterRoom = DEFAULT_ENTER_ROOM, logLine = console.debug, onLeaveUser, workerUrl, }) {
|
|
4
|
-
const users = new Map();
|
|
5
|
-
function getPeer(peer) {
|
|
6
|
-
let state = users.get(peer.userId);
|
|
7
|
-
if (!state) {
|
|
8
|
-
const newState = {
|
|
9
|
-
userId: peer.userId,
|
|
10
|
-
pc: new RTCPeerConnection(rtcConfig),
|
|
11
|
-
pendingRemoteIce: [],
|
|
12
|
-
peers: new Set([peer]),
|
|
13
|
-
};
|
|
14
|
-
users.set(peer.userId, newState);
|
|
15
|
-
// Send local ICE candidates to this peer
|
|
16
|
-
newState.pc.onicecandidate = (ev) => {
|
|
17
|
-
if (!ev.candidate)
|
|
18
|
-
return;
|
|
19
|
-
for (let user of newState.peers) {
|
|
20
|
-
const success = user.receive("ice", ev.candidate.toJSON());
|
|
21
|
-
if (success)
|
|
22
|
-
break;
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
newState.pc.onconnectionstatechange = () => {
|
|
26
|
-
logLine("💬", { event: "pc-state", userId: newState.userId, state: newState.pc.connectionState });
|
|
27
|
-
};
|
|
28
|
-
state = newState;
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
state.peers.add(peer);
|
|
32
|
-
}
|
|
33
|
-
users.set(state.userId, state);
|
|
34
|
-
return state;
|
|
35
|
-
}
|
|
36
|
-
function leaveUser(userId) {
|
|
37
|
-
onLeaveUser?.(userId);
|
|
38
|
-
const p = users.get(userId);
|
|
39
|
-
if (!p)
|
|
40
|
-
return;
|
|
41
|
-
try {
|
|
42
|
-
p.pc.close();
|
|
43
|
-
}
|
|
44
|
-
catch { }
|
|
45
|
-
users.delete(userId);
|
|
46
|
-
logLine("👤 USER LEFT", userId);
|
|
47
|
-
}
|
|
48
|
-
async function flushRemoteIce(state) {
|
|
49
|
-
if (!state.pc.remoteDescription)
|
|
50
|
-
return;
|
|
51
|
-
const queued = state.pendingRemoteIce;
|
|
52
|
-
state.pendingRemoteIce = [];
|
|
53
|
-
for (const ice of queued) {
|
|
54
|
-
try {
|
|
55
|
-
await state.pc.addIceCandidate(ice);
|
|
56
|
-
}
|
|
57
|
-
catch (e) {
|
|
58
|
-
logLine("⚠️ ERROR", { error: "add-ice-failed", userId: state.userId, detail: String(e) });
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
const roomsEntered = new Map();
|
|
63
|
-
function exit({ room, host }) {
|
|
64
|
-
const key = `${host}/room/${room}`;
|
|
65
|
-
const session = roomsEntered.get(key);
|
|
66
|
-
if (session) {
|
|
67
|
-
session.exitRoom();
|
|
68
|
-
roomsEntered.delete(key);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
function enter({ room, host }) {
|
|
72
|
-
const { exitRoom } = enterRoom({
|
|
73
|
-
userId,
|
|
74
|
-
room,
|
|
75
|
-
host,
|
|
76
|
-
logLine,
|
|
77
|
-
workerUrl,
|
|
78
|
-
// Existing peers initiate to the newcomer (Option 1)
|
|
79
|
-
async onPeerJoined(user) {
|
|
80
|
-
const state = getPeer(user);
|
|
81
|
-
const pc = state.pc;
|
|
82
|
-
// Offer flow: createOffer -> setLocalDescription -> send localDescription
|
|
83
|
-
const offer = await pc.createOffer();
|
|
84
|
-
await pc.setLocalDescription(offer);
|
|
85
|
-
user.receive("offer", pc.localDescription?.toJSON());
|
|
86
|
-
},
|
|
87
|
-
onPeerLeft(userId, peerId) {
|
|
88
|
-
const state = users.get(userId);
|
|
89
|
-
if (!state)
|
|
90
|
-
return;
|
|
91
|
-
for (const user of state.peers) {
|
|
92
|
-
if (user.peerId === peerId) {
|
|
93
|
-
state.peers.delete(user);
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
if (state.peers.size === 0 && leaveUserWithoutPeer) {
|
|
98
|
-
leaveUser(userId);
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
async onMessage(type, payload, from) {
|
|
102
|
-
const state = getPeer(from);
|
|
103
|
-
const pc = state.pc;
|
|
104
|
-
if (type === "offer") {
|
|
105
|
-
// Responder: set remote offer
|
|
106
|
-
await pc.setRemoteDescription(payload);
|
|
107
|
-
// Create and send answer
|
|
108
|
-
const answer = await pc.createAnswer();
|
|
109
|
-
await pc.setLocalDescription(answer);
|
|
110
|
-
from.receive("answer", pc.localDescription?.toJSON());
|
|
111
|
-
// Now safe to apply any queued ICE from this peer
|
|
112
|
-
await flushRemoteIce(state);
|
|
113
|
-
receivePeerConnection({ pc, userId: from.userId, initiator: false });
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
if (type === "answer") {
|
|
117
|
-
// Initiator: set remote answer
|
|
118
|
-
await pc.setRemoteDescription(payload);
|
|
119
|
-
await flushRemoteIce(state);
|
|
120
|
-
receivePeerConnection({ pc, userId: from.userId, initiator: true });
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
if (type === "ice") {
|
|
124
|
-
const ice = payload;
|
|
125
|
-
// If we don't have remoteDescription yet, queue it
|
|
126
|
-
if (!pc.remoteDescription) {
|
|
127
|
-
state.pendingRemoteIce.push(ice);
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
try {
|
|
131
|
-
await pc.addIceCandidate(ice);
|
|
132
|
-
}
|
|
133
|
-
catch (e) {
|
|
134
|
-
logLine("⚠️ ERROR", { error: "add-ice-failed", userId: state.userId, detail: String(e) });
|
|
135
|
-
}
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
},
|
|
139
|
-
});
|
|
140
|
-
roomsEntered.set(`${host}/room/${room}`, { exitRoom });
|
|
141
|
-
}
|
|
142
|
-
return { enterRoom: enter, exitRoom: exit, leaveUser, getUsers() { return Array.from(users.keys()); } };
|
|
143
|
-
}
|
|
144
|
-
export function joinWebRTCRoom({ uid, onMessage, logLine = console.debug, enterRoomFunction = DEFAULT_ENTER_ROOM, autoLeaveUsers = false, workerUrl, }) {
|
|
145
|
-
const userId = uid ?? `user-${crypto.randomUUID()}`;
|
|
146
|
-
const rtcConfig = {
|
|
147
|
-
iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
|
|
148
|
-
};
|
|
149
|
-
function wireDataChannel(userId, dc) {
|
|
150
|
-
dc.onopen = () => logLine("💬", { event: "dc-open", userId });
|
|
151
|
-
dc.onmessage = ({ data }) => {
|
|
152
|
-
onMessage?.(data, userId);
|
|
153
|
-
logLine("💬", { event: "dc-message", userId, data: data });
|
|
154
|
-
};
|
|
155
|
-
dc.onclose = () => logLine("💬", { event: "dc-close", userId });
|
|
156
|
-
dc.onerror = () => logLine("⚠️ ERROR", { error: "dc-error", userId });
|
|
157
|
-
}
|
|
158
|
-
const dataChannels = new Map();
|
|
159
|
-
const { enterRoom, exitRoom, leaveUser, getUsers } = collectPeerConnections({
|
|
160
|
-
userId,
|
|
161
|
-
rtcConfig,
|
|
162
|
-
enterRoomFunction,
|
|
163
|
-
logLine,
|
|
164
|
-
workerUrl,
|
|
165
|
-
leaveUserWithoutPeer: autoLeaveUsers,
|
|
166
|
-
onLeaveUser: (userId) => {
|
|
167
|
-
const dc = dataChannels.get(userId);
|
|
168
|
-
try {
|
|
169
|
-
dc?.close();
|
|
170
|
-
}
|
|
171
|
-
catch { }
|
|
172
|
-
dataChannels.delete(userId);
|
|
173
|
-
},
|
|
174
|
-
receivePeerConnection({ pc, userId, initiator }) {
|
|
175
|
-
if (initiator) {
|
|
176
|
-
const dc = pc.createDataChannel("data");
|
|
177
|
-
wireDataChannel(userId, dc);
|
|
178
|
-
dataChannels.set(userId, dc);
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
pc.ondatachannel = (ev) => {
|
|
182
|
-
const dc = ev.channel;
|
|
183
|
-
wireDataChannel(userId, dc);
|
|
184
|
-
dataChannels.set(userId, dc);
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
logLine("💬", { event: "pc-ready", userId, initiator });
|
|
188
|
-
},
|
|
189
|
-
});
|
|
190
|
-
function send(data, userId) {
|
|
191
|
-
dataChannels.forEach((dataChannel, pUserId) => {
|
|
192
|
-
if (userId && pUserId !== userId)
|
|
193
|
-
return;
|
|
194
|
-
if (dataChannel.readyState === "open")
|
|
195
|
-
dataChannel.send(data);
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
return {
|
|
199
|
-
userId,
|
|
200
|
-
send,
|
|
201
|
-
enterRoom,
|
|
202
|
-
exitRoom,
|
|
203
|
-
leaveUser,
|
|
204
|
-
getUsers,
|
|
205
|
-
end() {
|
|
206
|
-
dataChannels.forEach((dataChannel) => {
|
|
207
|
-
try {
|
|
208
|
-
dataChannel.close();
|
|
209
|
-
}
|
|
210
|
-
catch { }
|
|
211
|
-
});
|
|
212
|
-
dataChannels.clear();
|
|
213
|
-
},
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
//# sourceMappingURL=webrtc-room.js.map
|
package/dist/webrtc-room.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webrtc-room.js","sourceRoot":"","sources":["../src/browser/webrtc-room.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,SAAS,EAAE,MAAM,eAAe,CAAC;AAgBrD,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAGrC,MAAM,UAAU,sBAAsB,CAAC,EACrC,MAAM,EACN,qBAAqB,EACrB,oBAAoB,GAAG,KAAK,EAC5B,SAAS,GAAG,EAAE,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,8BAA8B,EAAE,CAAC,EAAE,EACtE,iBAAiB,EAAE,SAAS,GAAG,kBAAkB,EACjD,OAAO,GAAG,OAAO,CAAC,KAAK,EACvB,WAAW,EACX,SAAS,GAUV;IACC,MAAM,KAAK,GAA2B,IAAI,GAAG,EAAE,CAAC;IAChD,SAAS,OAAO,CAAC,IAAgC;QAC/C,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,MAAM,QAAQ,GAAc;gBAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,EAAE,EAAE,IAAI,iBAAiB,CAAC,SAAS,CAAC;gBACpC,gBAAgB,EAAE,EAAE;gBACpB,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;aACvB,CAAC;YACF,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAEjC,yCAAyC;YACzC,QAAQ,CAAC,EAAE,CAAC,cAAc,GAAG,CAAC,EAAE,EAAE,EAAE;gBAClC,IAAI,CAAC,EAAE,CAAC,SAAS;oBAAE,OAAO;gBAC1B,KAAI,IAAI,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;oBAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;oBAC3D,IAAI,OAAO;wBAAE,MAAM;gBACvB,CAAC;YACH,CAAC,CAAC;YAEF,QAAQ,CAAC,EAAE,CAAC,uBAAuB,GAAG,GAAG,EAAE;gBACzC,OAAO,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC;YACpG,CAAC,CAAC;YACF,KAAK,GAAG,QAAQ,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,SAAS,SAAS,CAAC,MAAc;QAC/B,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC;QACtB,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,IAAI,CAAC;YAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAC9B,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACrB,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,UAAU,cAAc,CAAC,KAAgB;QAC5C,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,iBAAiB;YAAE,OAAO;QAExC,MAAM,MAAM,GAAG,KAAK,CAAC,gBAAgB,CAAC;QACtC,KAAK,CAAC,gBAAgB,GAAG,EAAE,CAAC;QAE5B,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YACtC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5F,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,GAAG,EAAoC,CAAC;IAEjE,SAAS,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAmC;QAC3D,MAAM,GAAG,GAAG,GAAG,IAAI,SAAS,IAAI,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,QAAQ,EAAE,CAAC;YACnB,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,SAAS,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAmC;QAC5D,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;YAC7B,MAAM;YACN,IAAI;YACJ,IAAI;YACJ,OAAO;YACP,SAAS;YAET,qDAAqD;YACrD,KAAK,CAAC,YAAY,CAAC,IAAW;gBAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC5B,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;gBAEpB,0EAA0E;gBAC1E,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC;gBACrC,MAAM,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;gBAEpC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,gBAAgB,EAAE,MAAM,EAAG,CAAC,CAAC;YACxD,CAAC;YAED,UAAU,CAAC,MAAc,EAAE,MAAc;gBACvC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAChC,IAAI,CAAC,KAAK;oBAAE,OAAO;gBACnB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;oBAC/B,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;wBAC3B,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;wBACzB,MAAM;oBACR,CAAC;gBACH,CAAC;gBACD,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,oBAAoB,EAAE,CAAC;oBACnD,SAAS,CAAC,MAAM,CAAC,CAAC;gBACpB,CAAC;YACH,CAAC;YAED,KAAK,CAAC,SAAS,CAAC,IAAa,EAAE,OAAO,EAAE,IAAI;gBAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC5B,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;gBAEpB,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;oBACrB,8BAA8B;oBAC9B,MAAM,EAAE,CAAC,oBAAoB,CAAC,OAAoC,CAAC,CAAC;oBAEpE,yBAAyB;oBACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,YAAY,EAAE,CAAC;oBACvC,MAAM,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;oBAErC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,gBAAgB,EAAE,MAAM,EAAG,CAAC,CAAC;oBAEvD,kDAAkD;oBAClD,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;oBAC5B,qBAAqB,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;oBACrE,OAAO;gBACT,CAAC;gBAED,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACtB,+BAA+B;oBAC/B,MAAM,EAAE,CAAC,oBAAoB,CAAC,OAAoC,CAAC,CAAC;oBACpE,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;oBAC5B,qBAAqB,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;oBACpE,OAAO;gBACT,CAAC;gBAED,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;oBACnB,MAAM,GAAG,GAAG,OAA8B,CAAC;oBAE3C,mDAAmD;oBACnD,IAAI,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC;wBAC1B,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;wBACjC,OAAO;oBACT,CAAC;oBAED,IAAI,CAAC;wBACH,MAAM,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;oBAChC,CAAC;oBAAC,OAAO,CAAC,EAAE,CAAC;wBACX,OAAO,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC5F,CAAC;oBACD,OAAO;gBACT,CAAC;YACH,CAAC;SACF,CAAC,CAAC;QACH,YAAY,CAAC,GAAG,CAAC,GAAG,IAAI,SAAS,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,KAAK,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1G,CAAC;AAGD,MAAM,UAAU,cAAc,CAAC,EAC7B,GAAG,EACH,SAAS,EACT,OAAO,GAAG,OAAO,CAAC,KAAK,EACvB,iBAAiB,GAAG,kBAAkB,EACtC,cAAc,GAAG,KAAK,EACtB,SAAS,GAQV;IACC,MAAM,MAAM,GAAG,GAAG,IAAI,QAAQ,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC;IACpD,MAAM,SAAS,GAAqB;QAClC,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,8BAA8B,EAAE,CAAC;KACvD,CAAC;IAEF,SAAS,eAAe,CAAC,MAAc,EAAE,EAAkB;QACzD,EAAE,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9D,EAAE,CAAC,SAAS,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;YAC1B,SAAS,EAAE,CAAC,IAAW,EAAE,MAAM,CAAC,CAAC;YACjC,OAAO,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC,CAAC;QACF,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;QAChE,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,YAAY,GAAgC,IAAI,GAAG,EAAE,CAAC;IAE5D,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,sBAAsB,CAAC;QAC1E,MAAM;QACN,SAAS;QACT,iBAAiB;QACjB,OAAO;QACP,SAAS;QACT,oBAAoB,EAAE,cAAc;QACpC,WAAW,EAAE,CAAC,MAAc,EAAE,EAAE;YAC9B,MAAM,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,CAAC;gBAAC,EAAE,EAAE,KAAK,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YAC7B,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QACD,qBAAqB,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE;YAC7C,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;gBACxC,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBAC5B,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,EAAE,CAAC,aAAa,GAAG,CAAC,EAAE,EAAE,EAAE;oBACxB,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC;oBACtB,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;oBAC5B,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBAC/B,CAAC,CAAC;YACJ,CAAC;YAED,OAAO,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QAC1D,CAAC;KACF,CAAC,CAAC;IAEH,SAAS,IAAI,CAAC,IAAS,EAAE,MAAe;QACtC,YAAY,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE;YAC5C,IAAI,MAAM,IAAI,OAAO,KAAK,MAAM;gBAAE,OAAO;YACzC,IAAI,WAAW,CAAC,UAAU,KAAK,MAAM;gBAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,MAAM;QACN,IAAI;QACJ,SAAS;QACT,QAAQ;QACR,SAAS;QACT,QAAQ;QACR,GAAG;YACD,YAAY,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE;gBACnC,IAAI,CAAC;oBAAC,WAAW,CAAC,KAAK,EAAE,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAA,CAAC;YACvC,CAAC,CAAC,CAAC;YACH,YAAY,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC"}
|