openrtc 3.1.2 → 3.1.3

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.
@@ -1 +1 @@
1
- import {b as b$3}from'./chunk-FKAQDDUM.js';import {b as b$6,a as a$4,c}from'./chunk-SSBR3IHA.js';import {a as a$1,b as b$4}from'./chunk-IUU6JCLK.js';import {b as b$2,a as a$3}from'./chunk-CCCYE3XN.js';import {b as b$1,a as a$2}from'./chunk-ZA44REGI.js';import {d,a,e}from'./chunk-L7N4T2PX.js';import {d as d$1,b as b$5}from'./chunk-2GX6GB6L.js';function S(a,e,t,i){let n=JSON.stringify({__openrtc:2,capability:i,kind:a,name:e,value:t});if(n===void 0||!n.includes('"value":'))throw new Error("[OpenRTC] Messages must be JSON-serializable values.");return new TextEncoder().encode(n)}function x(a){let e;try{e=a instanceof Uint8Array?JSON.parse(new TextDecoder().decode(a)):a&&typeof a=="object"?a:{};}catch{return null}return e!=null&&e.__openrtc===2&&typeof e.capability=="string"&&e.capability.length>0&&e.capability.length<=192&&/^(?:devices|space|room|ticket):[A-Za-z0-9_.:@-]+$/.test(e.capability)&&(e.kind==="raw"||e.kind==="channel"||e.kind==="state")&&typeof e.name=="string"&&e.name.length>0&&e.name.length<=80&&/^[A-Za-z0-9_.:@-]+$/.test(e.name)&&Object.prototype.hasOwnProperty.call(e,"value")?e:null}var b="openrtc-peer-stream/1",ue=32,ee=16,_=4294967295,pe=/^[A-Za-z0-9][A-Za-z0-9._/+:-]{0,127}$/,me=/^([0-9a-f]{64})-([0-9a-f]{64})$/i;function A(a){let e=a?.trim()??"";if(!pe.test(e))throw new Error("[OpenRTC] stream protocol must be 1-128 safe ASCII characters.");return e}function L(a){let e=a?.trim()??"",t=me.exec(e);return t?[t[1].toLowerCase(),t[2].toLowerCase()].sort().join("-"):e}function te(a){if(a===null||a===0)return null;if(!Number.isFinite(a)||a<0)throw new RangeError("[OpenRTC] datagram maximum age must be a non-negative finite number or null.");return Math.min(_,Math.ceil(a))}function ie(a){if(!Number.isSafeInteger(a)||a<1||a>_)throw new RangeError(`[OpenRTC] datagram buffer limits must be integers from 1 to ${_}.`);return a}var F=class{constructor(e,t){this.runtime=e;this.peerId=t;this.incomingAge=null;this.outgoingAge=null;this.incomingLimit=ee;this.outgoingLimit=ee;this.policyInstance=null;this.incomingWaiters=new Set;this.outgoingWaiters=new Set;this.outgoingAvailable=new Set;this.incomingError=null;this.receiveLoopStarted=false;this.sendLoop=null;this.closed=false;this.incomingClosed=false;this.outgoingClosed=false;this.maxDatagramSize=e.peerDatagramMaxSize?.()??1024,this.readable=new ReadableStream({pull:i=>this.pullIncoming(i),cancel:()=>this.closeIncoming()},{highWaterMark:0}),this.writable=new WritableStream({write:i=>this.enqueueOutgoing(i),close:async()=>{this.outgoingClosed=true,await this.sendLoop;},abort:()=>{this.outgoingClosed=true,this.policyInstance?.closeOutgoing(),this.wake(this.outgoingWaiters),this.wake(this.outgoingAvailable);}},{highWaterMark:1});}get incomingMaxAge(){return this.incomingAge}set incomingMaxAge(e){this.incomingAge=te(e),this.policy.setIncomingMaxAge(this.incomingAge??void 0,Date.now()),this.wake(this.incomingWaiters);}get outgoingMaxAge(){return this.outgoingAge}set outgoingMaxAge(e){this.outgoingAge=te(e),this.policy.setOutgoingMaxAge(this.outgoingAge??void 0);}get incomingMaxBufferedDatagrams(){return this.incomingLimit}set incomingMaxBufferedDatagrams(e){this.incomingLimit=ie(e),this.policy.setIncomingMaxBufferedDatagrams(this.incomingLimit);}get outgoingMaxBufferedDatagrams(){return this.outgoingLimit}set outgoingMaxBufferedDatagrams(e){this.outgoingLimit=ie(e),this.policy.setOutgoingMaxBufferedDatagrams(this.outgoingLimit),this.wake(this.outgoingWaiters);}getStats(){return this.policy.getStats(Date.now())}get policy(){if(!this.policyInstance){let e=this.runtime.createPeerDatagramPolicy;if(!e)throw new Error("[OpenRTC] Shared protected-datagram policy is unavailable in this runtime.");this.policyInstance=e();}return this.policyInstance}close(){this.closed||(this.closed=true,this.closeIncoming(),this.outgoingClosed=true,this.policyInstance?.closeOutgoing(),this.wake(this.outgoingWaiters),this.wake(this.outgoingAvailable));}async pullIncoming(e){for(this.receiveLoopStarted||(this.receiveLoopStarted=true,this.pumpIncoming());;){let t=this.policy.popIncoming(Date.now());if(t){e.enqueue(new Uint8Array(t));return}if(this.incomingError){e.error(this.incomingError);return}if(this.incomingClosed){e.close();return}await new Promise(i=>this.incomingWaiters.add(i));}}async pumpIncoming(){let e=this.runtime.receivePeerDatagram;if(!e){this.incomingError=new Error("[OpenRTC] Protected peer datagrams are unavailable in this runtime."),this.wake(this.incomingWaiters);return}try{for(;!this.incomingClosed;){let t=new Uint8Array(await e(this.peerId));if(this.incomingClosed)return;this.policy.pushIncoming(t,Date.now()),this.wake(this.incomingWaiters);}}catch(t){this.incomingClosed||(this.incomingError=t,this.wake(this.incomingWaiters));}}async enqueueOutgoing(e){if(this.closed||this.outgoingClosed)throw new Error("[OpenRTC] peer datagram stream is closed.");if(!(e instanceof Uint8Array)||e.byteLength>this.maxDatagramSize)throw new Error(`[OpenRTC] peer datagrams must be Uint8Array values up to ${this.maxDatagramSize} bytes.`);for(;!this.policy.pushOutgoing(e,Date.now())&&!this.closed;)await new Promise(t=>this.outgoingWaiters.add(t));if(this.closed||this.outgoingClosed)throw new Error("[OpenRTC] peer datagram stream is closed.");this.startSendLoop(),this.wake(this.outgoingAvailable);}startSendLoop(){this.sendLoop||this.closed||(this.sendLoop=this.pumpOutgoing());}async pumpOutgoing(){let e=this.runtime.sendPeerDatagram;if(!e){this.policy.closeOutgoing();return}for(;!this.closed;){let t=this.policy.popOutgoing(Date.now());if(!t){if(this.wake(this.outgoingWaiters),this.outgoingClosed)return;await new Promise(n=>this.outgoingAvailable.add(n));continue}this.wake(this.outgoingWaiters);let i=new Uint8Array(t.payload);try{await e(this.peerId,i,t.remainingMaxAgeMs??void 0)===!1?this.policy.recordExpiredOutgoing():this.policy.recordSent(i.byteLength);}catch{this.policy.recordSendFailure();}this.wake(this.outgoingWaiters);}}closeIncoming(){this.incomingClosed||(this.incomingClosed=true,this.policyInstance?.closeIncoming(),this.wake(this.incomingWaiters));}wake(e){for(let t of e)t();e.clear();}},O=class{constructor(){this.controller=null;this.closed=false;this.readable=new ReadableStream({start:e=>{this.controller=e;},cancel:()=>{this.closed=true,this.controller=null;}},{highWaterMark:ue});}enqueue(e){return this.closed||!this.controller||(this.controller.desiredSize??0)<=0?false:(this.controller.enqueue(e),true)}close(){this.closed||(this.closed=true,this.controller?.close(),this.controller=null);}},K=class{constructor(e,t,i,n){this.client=e;this.peerId=t;this.capabilityKey=n;this.incomingBi=new O;this.incomingUni=new O;this.incomingBidirectionalStreams=this.incomingBi.readable;this.incomingUnidirectionalStreams=this.incomingUni.readable;this.closed=false;this.protocolHandlers=new Map;this.datagrams=new F(i,this.peerId);}async createBidirectionalStream(e){let t=A(e.protocol),i=await this.client.channels.openBi(this.peerId,b,{timeoutMs:e.timeoutMs,channelMetadata:{protocol:t,[a$3]:this.capabilityKey}});return {protocol:t,readable:i.readable,writable:i.writable}}async createUnidirectionalStream(e){let t=A(e.protocol);return (await this.client.channels.openUni(this.peerId,b,{timeoutMs:e.timeoutMs,channelMetadata:{protocol:t,[a$3]:this.capabilityKey}})).writable}accept(e,t){if(e.type==="bi"){let n=e.stream;if(!n.recv||!n.send)return false;let s={peerId:this.peerId,protocol:t,readable:n.recv,writable:n.send},r=this.protocolHandlers.get(t);if(r){try{r(s);}catch{s.readable.cancel("incoming-protocol-handler-failed").catch(()=>{}),s.writable.abort("incoming-protocol-handler-failed").catch(()=>{});}return true}return this.incomingBi.enqueue(s)||(s.readable.cancel("incoming-peer-stream-queue-full").catch(()=>{}),s.writable.abort("incoming-peer-stream-queue-full").catch(()=>{})),true}let i=e.stream;return !i||typeof i.getReader!="function"?false:(this.incomingUni.enqueue({peerId:this.peerId,protocol:t,readable:i})||i.cancel("incoming-peer-stream-queue-full").catch(()=>{}),true)}onProtocol(e,t){let i=A(e);if(this.protocolHandlers.has(i))throw new Error(`[OpenRTC] stream protocol '${i}' already has an owning consumer.`);return this.protocolHandlers.set(i,t),()=>{this.protocolHandlers.get(i)===t&&this.protocolHandlers.delete(i);}}close(){this.closed=true,this.datagrams.close(),this.protocolHandlers.clear(),this.incomingBi.close(),this.incomingUni.close();}},T=class{constructor(e,t){this.client=e;this.capabilityKey=t;this.peers=new Map;this.peerIdsByConnection=new Map;this.registered=false;this.observed=0;this.accepted=0;this.declined=0;this.lastResolution="none";try{e.channels.register({id:b,kind:"application-stream",ownership:"shared",peerModel:"device-first",routing:"stream-envelope",readiness:"settled-peer",promotionPolicy:"never",signalingPolicy:"hosted",delivery:"reliable",description:"Transport-agnostic protected peer streams"}),this.stopIncoming=e.channels.onIncomingChannel(b,i=>this.accept(i)),this.registered=!0;}catch{this.stopIncoming=()=>{};}}forPeer(e){let t=this.peers.get(e);return t||(t=new K(this.client,e,this.client.advanced.runtime,this.capabilityKey),this.peers.set(e,t)),t}onProtocol(e,t,i){return this.forPeer(e).onProtocol(t,i)}bindConnection(e,t){let i=L(e),n=t.trim();!i||!n||this.peerIdsByConnection.set(i,n);}unbindConnection(e){this.peerIdsByConnection.delete(L(e));}diagnostics(){return {registered:this.registered,peers:this.peers.size,boundConnections:this.peerIdsByConnection.size,observed:this.observed,accepted:this.accepted,declined:this.declined,lastResolution:this.lastResolution}}closePeer(e){let t=this.peers.get(e);if(t){t.close(),this.peers.delete(e);for(let[i,n]of this.peerIdsByConnection)n===e&&this.peerIdsByConnection.delete(i);}}close(){this.stopIncoming();for(let e of this.peers.values())e.close();this.peers.clear(),this.peerIdsByConnection.clear(),this.registered&&this.client.channels.unregister(b);}accept(e){if(this.observed+=1,e.channel?.metadata?.[a$3]!==this.capabilityKey)return this.declined+=1,false;let i=e.channel?.metadata?.protocol;if(typeof i!="string")return this.declined+=1,false;let n;try{n=A(i);}catch{return this.declined+=1,false}let r=this.resolveExistingPeer(e.remoteNodeId,e.connectionId)?.accept(e,n)??false;return r?this.accepted+=1:this.declined+=1,r}resolveExistingPeer(e,t=""){let i=L(t);if(i){let r=this.peerIdsByConnection.get(i);if(!r)return this.lastResolution="unbound-connection",null;let o=this.peers.get(r);return o?(this.lastResolution="connection",o):(this.lastResolution="unbound-connection",null)}let n=this.peers.get(e);if(n)return this.lastResolution="remote-peer",n;let s=this.client.peers.get(e)??this.client.peers.listConnected().find(r=>[r.peerId,r.deviceId,r.deviceIdHint,r.connectionId,...r.connectionIds].some(o=>o===e));if(s){let r=new Set([s.peerId,s.deviceId,s.deviceIdHint,s.connectionId,...s.connectionIds].filter(c=>typeof c=="string"&&c.length>0)),o=[...this.peers.entries()].filter(([c])=>r.has(c)).map(([,c])=>c);if(o.length===1)return this.lastResolution="peer-alias",o[0]}return this.lastResolution="none",null}};var y=new WeakMap;function ve(a){let e=y.get(a);if(!e||a.closed)throw new Error("[OpenRTC] Capability runtime is unavailable or already closed.");return e}function Le(a,e){if(y.has(a))throw new Error("[OpenRTC] Capability runtime is already registered.");return y.set(a,ve(e)),()=>{y.delete(a);}}function ge(a){let e=a?.trim()??"";if(!/^pk_(?:live|test)_[0-9a-f]{40}$/.test(e))throw new Error("[OpenRTC] apiKey must be a public pk_live_ or pk_test_ key.");return e}function f(a){let e=a?.trim()??"";if(!e||e.length>160||!/^[A-Za-z0-9_.:@-]+$/.test(e))throw new Error("[OpenRTC] Capability id is invalid.");return e}var z=/^[A-Za-z0-9_.:@-]{1,160}$/,fe=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,ne=2,U=8,ye=U;function we(a){let e=typeof a=="string"?a.trim():"";if(!z.test(e))return null;let t=e.startsWith("device_")?e.slice(7):"";return fe.test(t)?t:e}function Ce(a){let e=`openrtc:v2:device-id:${a}`,t,i=(()=>{try{return t=globalThis.localStorage,we(t?.getItem(e))||crypto.randomUUID()}catch{return crypto.randomUUID()}})();try{t?.setItem(e,i);}catch{}return i}function re(a){let e=typeof a=="string"?a.trim():"";if(!z.test(e))throw new Error("[OpenRTC] The native host returned an invalid durable device ID.");return e}var se=250;function oe(a){if(a===void 0)return [];if(!Array.isArray(a))throw new Error("[OpenRTC] autoConnectExcludedDeviceIds must be an array.");let e=[...new Set(a.map(t=>{let i=typeof t=="string"?t.trim().toLowerCase():"";if(!z.test(i))throw new Error("[OpenRTC] autoConnectExcludedDeviceIds contains an invalid device ID.");return i}))].sort();if(e.length>se)throw new Error(`[OpenRTC] autoConnectExcludedDeviceIds supports at most ${se} devices.`);return e}function N(a){let e=b$1(a.token),t=typeof e.deviceKeyThumbprint=="string"?e.deviceKeyThumbprint.trim():"";if(!/^[A-Za-z0-9_-]{43}$/.test(t))throw new Error("[OpenRTC] Anonymous capability is missing its device-key binding.");return `anon_${t.slice(0,32)}`}var G=class{constructor(){this.descriptors=new Map;this.targets=new Map;}register(e){if(!e?.id?.trim())throw new Error("[OpenRTC] Channel id is required.");this.descriptors.set(e.id,{...e});for(let[t,i]of this.targets)t.channels.register({...e,delivery:e.delivery??i});return ()=>{this.descriptors.delete(e.id);for(let t of this.targets.keys())t.channels.unregister(e.id);}}list(){return [...this.descriptors.values()].map(e=>({...e}))}attach(e,t){this.targets.set(e,t);for(let i of this.descriptors.values())e.channels.register({...i,delivery:i.delivery??t});}detach(e){this.targets.delete(e);}};function ae(a$1){return d(a.TICKET_MESH_ALREADY_ACTIVE,`[OpenRTC] ticket:${a$1} is already active with different options.`,{retryable:false,plane:"admission"})}function le(a){return a.mesh===true?a.maxPeers??ye:a.maxPeers}function be(a){return JSON.stringify({identity:a.identity??(a.mesh===true?"session":null),maxPeers:le(a)??null,mesh:a.mesh===true,advancedFanout:a.advancedFanout===true})}function ce(a){let e=a?.trim()??"";if(!e||e.length>80||!/^[A-Za-z0-9_.:@-]+$/.test(e))throw new Error("[OpenRTC] Message name is invalid.");return e}var H=class{constructor(e,t,i){this.client=e;this.capabilityKey=t;this.rawConnections=new Map;this.logicalConnections=new Map;this.connectionListeners=new Map;this.rawListeners=new Map;this.closeListeners=new Map;this.channelListeners=new Map;this.stateListeners=new Map;this.remoteState=new Map;this.localState=new Map;this.stateSenders=new Map;this.stateReadyGenerations=new Map;this.mediaConnections=new Map;this.mediaRetirements=new Map;this.pendingRawConnections=new Map;this.connectionIdsByPeer=new Map;this.closed=false;this.cleanupComplete=false;this.closeAttempt=null;this.pendingStops=null;this.peerStreams=new T(e,t),this.stopMessage=e.onMessage((n,s)=>this.receive(n,s)),this.stopConnection=e.onConnection(n=>this.add(n)),this.stopDisconnection=e.onDisconnection(n=>this.remove(n)),e.getConnections().forEach(n=>this.add(n)),this.stopPeerLifecycle=e.peers.watchLifecycle(n=>this.observePeerLifecycle(n)),this.roomFanout=i?.create({client:e,capabilityKey:t,connections:()=>[...this.logicalConnections.values()].flatMap(({activeRaw:n})=>n?[n]:[]),deliver:(n,s,r)=>{let o=x(s);!o||o.capability!==this.capabilityKey||r!==void 0&&o.name!==r||r===void 0&&o.kind!=="channel"||this.deliverEnvelope(n,o);}});}state(e){if(this.assertOpen(),this.roomFanout?.isSparse())throw new Error("[OpenRTC] state() is not available in sparse gossip rooms; use a named channel with application-owned latest-state revisions.");let t=ce(e);return {set:i=>{this.assertOpen();let n=S("state",t,i,this.capabilityKey);if(this.localState.set(t,n),!this.roomFanout?.publishState(t,n))for(let{activeRaw:s}of this.logicalConnections.values())s&&this.sendState(s,t,n);},watch:i=>{this.assertOpen();let n=this.stateListeners.get(t);n||this.stateListeners.set(t,n=new Set);let s=(r,o)=>i({peerId:r,value:o});n.add(s);for(let[r,o]of this.remoteState)o.has(t)&&i({peerId:r,value:o.get(t)});return ()=>n?.delete(s)}}}channel(e){this.assertOpen();let t=ce(e),i=n=>S("channel",t,n,this.capabilityKey);return {send:async n=>{this.assertOpen();let s=i(n);await this.roomFanout?.sendChannel(t,s)||(this.assertOpen(),await Promise.all([...this.logicalConnections.values()].flatMap(({activeRaw:r})=>r?[this.sendPayload(r,s)]:[])));},sendTo:async(n,s)=>{this.assertOpen(),this.roomFanout?.assertTargetedSendAllowed();let r=this.logicalConnections.get(n)?.activeRaw;if(r){await this.sendPayload(r,i(s));return}throw d(a.DELIVERY_NOT_READY,`[OpenRTC] Peer '${n}' has no direct authorized route; sparse broadcasts never multi-hop targeted payloads.`,{retryable:true,plane:"delivery"})},onMessage:n=>{this.assertOpen();let s=this.channelListeners.get(t);s||this.channelListeners.set(t,s=new Set);let r=(o,c)=>n({peerId:o,message:c});return s.add(r),()=>s?.delete(r)}}}async sendPayload(e$1,t){try{await e$1.send(t);}catch(i){throw e(i)}}onConnection(e){this.assertOpen();let t=new Set;this.connectionListeners.set(e,t);for(let[i,n]of this.logicalConnections)n.activeRaw&&(t.add(i),e(n.view));return ()=>this.connectionListeners.delete(e)}assertOpen(){if(this.closed)throw new Error("[OpenRTC] Capability messages are closed.")}fence(){this.closed=true;}close(){if(this.cleanupComplete)return Promise.resolve();if(this.closeAttempt)return this.closeAttempt;this.closed=true;let e=this.releaseMessages();return this.closeAttempt=e,e.then(()=>{this.closeAttempt===e&&(this.closeAttempt=null);},()=>{this.closeAttempt===e&&(this.closeAttempt=null);}),e}async releaseMessages(){let e=[];this.pendingStops??(this.pendingStops=[()=>this.stopMessage(),()=>this.stopConnection(),()=>this.stopDisconnection(),()=>this.stopPeerLifecycle(),()=>this.roomFanout?.close()]),this.pendingStops=this.pendingStops.filter(i=>{try{return i(),!1}catch(n){return e.push(n),true}});let t=[];for(let i of this.logicalConnections.keys())try{t.push(this.retire(i));}catch(n){e.push(n);}this.pendingRawConnections.clear();try{this.peerStreams.close();}catch(i){e.push(i);}this.rawConnections.clear(),this.logicalConnections.clear(),this.connectionListeners.clear(),this.channelListeners.clear(),this.stateListeners.clear(),this.localState.clear(),this.remoteState.clear(),this.stateReadyGenerations.clear(),this.rawListeners.clear(),this.closeListeners.clear();for(let i of await Promise.allSettled(t))i.status==="rejected"&&e.push(i.reason);if(e.length===1)throw e[0];if(e.length)throw d(a.INTERNAL,"[OpenRTC] Capability message cleanup failed.",{cause:e,retryable:true,plane:"internal"});this.cleanupComplete=true;}add(e){if(this.closed)return;let t=this.rawConnections.get(e.id);if(t?.raw===e)return;t&&this.remove(t.raw);let i=e.remoteNodeId||e.id,n=this.mediaRetirements.get(i);if(n){let o={raw:e,peerId:i};this.pendingRawConnections.set(e.id,o),n.finally(()=>{this.closed||this.pendingRawConnections.get(e.id)!==o||(this.pendingRawConnections.delete(e.id),this.add(e));});return}this.rawConnections.set(e.id,{raw:e,peerId:i});let s=this.connectionIdsByPeer.get(i);s||this.connectionIdsByPeer.set(i,s=new Set),s.add(e.id),this.peerStreams.bindConnection(e.id,i);let r=this.logicalConnections.get(i);if(!r){let o=this.peerStreams.forPeer(i),c=new b$3(o,this.client.advanced.runtime,(h,l)=>this.peerStreams.onProtocol(i,h,l),()=>this.peerStreams.diagnostics());this.mediaConnections.set(i,c),r={activeRaw:e,rawIds:new Set,view:{id:i,peerId:i,streams:o,media:c,send:async h=>{let l=this.logicalConnections.get(i)?.activeRaw;if(!l)throw d(a.DELIVERY_NOT_READY,`[OpenRTC] Peer '${i}' is not connected.`,{retryable:true,plane:"delivery"});await this.sendPayload(l,S("raw","message",h,this.capabilityKey));},onMessage:h=>{let l=this.rawListeners.get(i);l||this.rawListeners.set(i,l=new Set);let p=h;return l.add(p),()=>l?.delete(p)},onClose:h=>{let l=this.closeListeners.get(i);return l||this.closeListeners.set(i,l=new Set),l.add(h),()=>l?.delete(h)}}},this.logicalConnections.set(i,r);}r.rawIds.add(e.id),r.activeRaw=e,this.observePeerLifecycle(this.client.peers.listConnected());for(let[o,c]of this.connectionListeners)c.has(i)||(c.add(i),o(r.view));for(let[o,c]of this.localState)this.sendState(e,o,c);}remove(e){if(this.pendingRawConnections.get(e.id)?.raw===e){this.pendingRawConnections.delete(e.id);return}let t=this.rawConnections.get(e.id);if(!t||t.raw!==e)return;this.rawConnections.delete(e.id),this.peerStreams.unbindConnection(e.id);let i=t.peerId,n=this.logicalConnections.get(i);if(n?.rawIds.delete(e.id),n?.activeRaw?.id===e.id){let o=[...n.rawIds],c=o[o.length-1];n.activeRaw=c?this.rawConnections.get(c)?.raw??null:null;}let s=this.connectionIdsByPeer.get(i);if(s?.delete(e.id),s?.size===0&&this.connectionIdsByPeer.delete(i),!n?.activeRaw){let o=this.remoteState.get(i);if(o){for(let c of o.keys())for(let d of this.stateListeners.get(c)??[])d(i,null);this.remoteState.delete(i);}}let r=this.stateSenders.get(e);if(r){for(let o of r.values())o.close();this.stateSenders.delete(e);}}observePeerLifecycle(e){for(let t of this.logicalConnections.keys()){let i=this.connectionIdsByPeer.get(t)??new Set,n=e.find(d=>d.peerId===t||d.connectionId===t||d.connectionIds.some(h=>i.has(h)));if(!n)continue;let s=n.status==="closed"&&n.logicalSessionTerminal===true&&n.routable!==true&&n.settledReady!==true;if(n.manualDisconnect||s){this.retire(t);continue}if(n.settledReady!==true||n.routable!==true){this.stateReadyGenerations.delete(t);continue}let r=n.transportStableId,o=n.transportGeneration,c=n.routeGeneration;if(Number.isSafeInteger(r)&&Number(r)>0&&Number.isSafeInteger(o)&&Number(o)>0&&Number.isSafeInteger(c)&&Number(c)>=0){let d=JSON.stringify([n.connectionId,n.generation,r,o,c]);if(this.stateReadyGenerations.get(t)!==d){this.stateReadyGenerations.set(t,d);let l=this.logicalConnections.get(t)?.activeRaw;if(l)for(let[p,m]of this.localState)this.sendState(l,p,m);}let h=this.mediaConnections.get(t);h&&h.observePhysicalGeneration({transportStableId:Number(r),transportGeneration:Number(o),routeGeneration:Number(c)}).catch(()=>{});}}}retire(e){let t=this.logicalConnections.get(e);if(!t)return this.mediaRetirements.get(e)??Promise.resolve();this.logicalConnections.delete(e),this.stateReadyGenerations.delete(e);for(let r of t.rawIds){let o=this.rawConnections.get(r)?.raw;if(this.rawConnections.delete(r),this.peerStreams.unbindConnection(r),!o)continue;let c=this.stateSenders.get(o);if(c){for(let d of c.values())d.close();this.stateSenders.delete(o);}}this.connectionIdsByPeer.delete(e);let i=this.remoteState.get(e);if(i){for(let r of i.keys())for(let o of this.stateListeners.get(r)??[])o(e,null);this.remoteState.delete(e);}let n=this.mediaConnections.get(e);this.mediaConnections.delete(e);let s=n?.close().catch(()=>{})??Promise.resolve();this.mediaRetirements.set(e,s),s.finally(()=>{this.mediaRetirements.get(e)===s&&this.mediaRetirements.delete(e);}),this.peerStreams.closePeer(e);for(let r of this.closeListeners.get(e)??[])r();this.closeListeners.delete(e),this.rawListeners.delete(e);for(let r of this.connectionListeners.values())r.delete(e);return s}receive(e,t){if(this.closed)return;this.add(e);let i=this.rawConnections.get(e.id)?.peerId??e.remoteNodeId??e.id;if(this.roomFanout?.receive(e,i,t))return;let n=x(t);if(!n){for(let s of this.rawListeners.get(i)??[])s(t);return}if(n.capability===this.capabilityKey){if(n.kind==="raw"){for(let s of this.rawListeners.get(i)??[])s(n.value);return}this.deliverEnvelope(i,n);}}deliverEnvelope(e,t){if(this.closed)return;if(t.kind==="raw"){for(let n of this.rawListeners.get(e)??[])n(t.value);return}if(t.kind==="channel"){for(let n of this.channelListeners.get(t.name)??[])n(e,t.value);return}let i=this.remoteState.get(e);i||this.remoteState.set(e,i=new Map),i.set(t.name,t.value);for(let n of this.stateListeners.get(t.name)??[])n(e,t.value);}sendState(e,t,i){let n=this.stateSenders.get(e);n||this.stateSenders.set(e,n=new Map);let s=n.get(t);s||(s=new a$1(r=>e.send(r)),n.set(t,s)),s.send(i).catch(()=>{});}},E=class{constructor(e,t,i,n,s){this.kind=e;this.id=t;this.client=i;this.onClosed=n;this.roomFanoutFactory=s;this.closed=false;this.retired=false;this.shutdownAttempt=null;y.set(this,i);}get peers(){return this.client.peers}get channels(){return this.client.channels}get diagnostics(){return this.client.diagnostics}state(e){return this.capabilityMessages().state(e)}channel(e){return this.capabilityMessages().channel(e)}onConnection(e){return this.capabilityMessages().onConnection(e)}projectRuntime(e){y.set(this,e);}setArchitecture(e){this.roomFanoutFactory?.setArchitecture(e);}close(){if(this.retired)return Promise.resolve();if(this.shutdownAttempt)return this.shutdownAttempt;this.fenceProductAccess();let e=this.releaseCapability();return this.shutdownAttempt=e,e.then(()=>{this.shutdownAttempt===e&&(this.shutdownAttempt=null);},()=>{this.shutdownAttempt===e&&(this.shutdownAttempt=null);}),e}beforeRuntimeShutdown(){}fenceProductAccess(){this.closed=true,this.messages?.fence();}async releaseCapability(){let e=[];try{this.beforeRuntimeShutdown();}catch(t){e.push(t);}try{await this.messages?.close();}catch(t){e.push(t);}try{await this.client.advanced.runtime.shutdown();}catch(t){e.push(t);}if(e.length===1)throw e[0];if(e.length)throw d(a.INTERNAL,"[OpenRTC] Capability cleanup failed.",{cause:e,retryable:true,plane:"internal"});this.onClosed(),y.delete(this),this.retired=true;}capabilityMessages(){if(this.closed)throw new Error("[OpenRTC] Capability is closed.");return this.messages??(this.messages=new H(this.client,b$2(this.kind,this.id).key,this.roomFanoutFactory))}},q=class extends E{constructor(t,i,n,s){super("space",t,i,n);this.delivery=s;this.kind="space";this.leave=()=>this.close();}},D=class extends E{constructor(t,i,n,s,r,o){super("ticket",t,i,n);this.token=s;this.ownsMesh=o;this.kind="ticket";this.closing=null;this.inviteListeners=new Set;this.stopInviteWatch=()=>{};this.meshStopped=false;if(this.currentInvite=r,o){let c=i.advanced.runtime;this.stopInviteWatch=c.watchTicketMeshInvite?.(t,d=>{this.closed||(this.currentInvite=d,this.inviteListeners.forEach(h=>h(d)));})??this.stopInviteWatch;}}get invite(){return this.closed?null:this.currentInvite}watchInvite(t){return this.closed?(t(null),()=>{}):(this.inviteListeners.add(t),t(this.currentInvite),()=>this.inviteListeners.delete(t))}async issuerNode(){if(this.closed)throw new Error("[OpenRTC] Capability is closed.");if(!this.ownsMesh)throw new Error("[OpenRTC] This ticket is not a mesh.");return this.client.advanced.runtime.ticketMeshIssuerNode(this.id)}get peers(){if(this.scopedPeers)return this.scopedPeers;let t=this.client.peers,i=`ticket:${this.id}`,n=r=>!this.closed&&r.scopes.includes(i)&&r.status==="connected"&&r.settledReady===true&&r.routable!==false&&r.logicalSessionTerminal!==true&&(!this.ownsMesh||this.client.advanced.runtime.isTicketMeshPeerReady(this.id,r)),s=(r,o)=>{let c=[],d=this.ownsMesh?this.client.advanced.runtime.watchTicketMeshPeers(this.id,()=>o(c.filter(n))):()=>{},h=t[r](l=>{c=l,o(l.filter(n));});return ()=>{h(),d();}};return this.scopedPeers={...t,watch:r=>s("watch",r),watchLifecycle:r=>s("watchLifecycle",r),get:r=>{let o=t.get(r);return o&&n(o)?o:void 0},listConnected:()=>t.listConnected().filter(n)}}get diagnostics(){if(this.scopedDiagnostics)return this.scopedDiagnostics;let t=this.client.diagnostics,i=`ticket:${this.id}`;return this.scopedDiagnostics={...t,capture:n=>c(s=>this.client.advanced.runtime.watchPeerStates(r=>s(this.closed?[]:r.filter(o=>o.scopes.includes(i)))),n),watchConnectionMetrics:n=>t.watchConnectionMetrics(s=>{n(this.closed?[]:s.filter(r=>r.scopes?.includes(i)));})}}close(){if(this.retired)return Promise.resolve();if(this.closing)return this.closing;this.fenceProductAccess();let t=this.closeOnce();return this.closing=t,t.catch(()=>{!this.retired&&this.closing===t&&(this.closing=null);}),t}async closeOnce(){this.ownsMesh&&!this.meshStopped&&(await this.client.advanced.runtime.closeTicketMesh(this.id),this.meshStopped=true),await super.close();}beforeRuntimeShutdown(){try{this.stopInviteWatch(),this.stopInviteWatch=()=>{};}finally{this.inviteListeners.clear();}}},M=class M{constructor(e,t){this.options=e;this.internals=t;this.diagnosticClientRef=++M.nextDiagnosticClient;this.nextDiagnosticOperation=0;this.channels=new G;this.broadcastSessions=new Set;this.broadcastPublishers=new Set;this.handles=new Set;this.activations=new Map;this.pendingCapabilityShutdowns=new Map;this.authorityCallableIds=new WeakMap;this.nextAuthorityCallableId=1;this.closed=false;this.closing=null;this.offline={support:async()=>(this.assertOpen(),this.internals.offlineSupport?.()??{provisioning:false,localMesh:false,cloudRequired:false,reason:"Browser-only OpenRTC cannot host the native LAN/Iroh offline runtime."}),createEnrollmentRequest:async e=>{if(this.assertOpen(),!this.internals.createOfflineEnrollmentRequest)throw new Error("[OpenRTC] Offline enrollment request signing requires a native Rust host.");return this.internals.createOfflineEnrollmentRequest({trustDomain:e.trustDomain,deviceId:await this.deviceId(),requestedRoles:e.requestedRoles})}};this.devices={localId:()=>(this.assertOpen(),this.deviceId()),start:(e={})=>{let t=e.auth??this.options.auth;return this.activateOnce("devices",JSON.stringify({autoConnect:e.autoConnect??"online",autoConnectExcludedDeviceIds:oe(e.autoConnectExcludedDeviceIds),maxPeers:e.maxPeers??null,advancedFanout:e.advancedFanout===true,profile:e.profile??null}),t,()=>this.startDevices(e))},listEnrolled:async(e={})=>{this.assertOpen();let t=e.auth??this.options.auth;if(!t)throw new Error("[OpenRTC] devices.listEnrolled() requires an auth provider.");let i=await(await this.controlPlane()).listEnrolledDevices(t,await this.deviceId()),{DeviceHandle:n}=await import('./deviceHandle-DFG3CCY3.js');for(let s of this.handles)s instanceof n&&s.replaceEnrolledDevices(i);return i},revoke:async(e,t={})=>{this.assertOpen();let i=t.auth??this.options.auth;if(!i)throw new Error("[OpenRTC] devices.revoke() requires an auth provider.");let n=re(e),s=await this.deviceId();await(await this.controlPlane()).revokeDevice(i,s,n);let{DeviceHandle:r}=await import('./deviceHandle-DFG3CCY3.js');for(let o of this.handles)o instanceof r&&o.removeEnrolledDevice(n);n===s&&this.retireAuthCapabilities(i);},revokeAll:async(e={})=>{this.assertOpen();let t=e.auth??this.options.auth;if(!t)throw new Error("[OpenRTC] devices.revokeAll() requires an auth provider.");if(await(await this.controlPlane()).revokeAllDevices(t,await this.deviceId(),e.exceptCurrent===true),e.exceptCurrent===true){let i=await this.deviceId(),{DeviceHandle:n}=await import('./deviceHandle-DFG3CCY3.js');for(let s of this.handles)s instanceof n&&s.retainCurrentEnrolledDevice(i);}e.exceptCurrent!==true&&this.retireAuthCapabilities(t);}};this.spaces={join:(e,t={})=>this.activateOnce(`space:${f(e)}`,JSON.stringify({payload:t.payload??"reliable",identity:t.identity??null,maxPeers:t.maxPeers??null,advancedFanout:t.advancedFanout===true}),void 0,()=>this.joinSpace(e,t))};this.rooms={join:async(e,t={})=>(await import('./room-ZQU7JFRG.js')).joinRoom(this,e,t)};this.tickets={issue:(e,t={})=>this.activateOnce(`ticket:${f(e)}`,be(t),void 0,()=>this.issueTicket(e,t),t.mesh===true?()=>ae(f(e)):void 0),join:e=>{let t=b$4(e);return t.mesh?this.activateOnce(`ticket:${f(t.id)}`,`join:${e}`,void 0,()=>this.joinTicket(e),()=>ae(f(t.id))):Promise.reject(d(a.TICKET_INVITE_INVALID,"[OpenRTC] This invitation does not describe a ticket mesh.",{retryable:false,plane:"admission"}))}};this.liveSession=null;this.liveRetirementConfirmed=false;this.liveOpening=null;this.live={open:async e=>{if(this.assertOpen(),this.liveOpening||this.liveSession&&!this.liveRetirementConfirmed)throw new Error("[OpenRTC] A live session is already active on this root.");if(!e||typeof e.credentials!="function"||!this.internals.liveHostFactory)throw new Error("[OpenRTC] Live coordination requires an app credential provider and a supported host.");let t={canceled:false,retirementUnconfirmed:false,host:void 0};this.liveOpening=t;try{let i=new URL("/v3/live",(this.internals.endpoints??a$2).gateway).toString(),n=await this.internals.liveHostFactory(i,this.internals.testingAllowInsecureLoopback===!0);if(t.host=n,t.canceled)throw await n.close(),new Error("[OpenRTC] Live activation was closed.");if(await n.open(e),t.canceled)throw await n.close(),new Error("[OpenRTC] Live activation was closed.");let s=new Set,r=new Set,o=l=>{try{l();}catch{}},c=n.onEvent(l=>{if(l.type==="message")for(let p of s)o(()=>p(Object.freeze({channel:l.channel,from:l.from,data:l.data})));if(l.type==="closed"){this.liveSession===h&&(this.liveRetirementConfirmed=!0);for(let p of r)o(p);s.clear(),r.clear();}}),d=l=>{if(typeof l!="string"||!/^[A-Za-z0-9_.:@/-]{1,128}$/.test(l))throw new Error("[OpenRTC] Invalid live channel.");return l},h={get closed(){return n.closed},renew:()=>n.renew(),subscribe:async l=>{await n.request({type:"subscribe",channel:d(l)});},unsubscribe:async l=>{await n.request({type:"unsubscribe",channel:d(l)});},publish:async(l,p)=>{if(typeof p!="string"||new TextEncoder().encode(p).byteLength>65536)throw new Error("[OpenRTC] Live publication exceeds 64 KiB.");let m=await n.request({type:"publish",channel:d(l),data:p});if(!Number.isSafeInteger(m.units)||m.units<1)throw new Error("[OpenRTC] Invalid live publication receipt.");return {units:m.units}},onMessage:l=>(n.closed||s.add(l),()=>{s.delete(l);}),onClose:l=>(n.closed?o(l):r.add(l),()=>{r.delete(l);}),close:async()=>{await n.close(),this.liveSession===h&&(this.liveRetirementConfirmed=!0),c(),s.clear(),r.clear();}};return this.liveSession=h,this.liveRetirementConfirmed=!1,h}catch(i){try{await t.host?.close();}catch(n){throw t.retirementUnconfirmed=true,n}throw i}finally{this.liveOpening===t&&!t.retirementUnconfirmed&&(this.liveOpening=null);}}};this.broadcasts={create:async e=>{this.assertOpen();let t=await this.broadcastHost();if(!t?.create)throw new Error("[OpenRTC] Managed broadcast creation is unavailable.");return t.create(e)},open:async e=>{this.assertOpen(),this.validateBroadcastGrant(e);let t=await this.broadcastHost();if(!t)throw new Error("[OpenRTC] Broadcast hosting is unavailable in this runtime.");return this.wrapBroadcastSession(await t.open(e))},subscribe:async e=>{this.assertOpen(),this.validateBroadcastGrant(e);let t=await this.broadcastHost();if(!t)throw new Error("[OpenRTC] Broadcast viewing is unavailable.");return this.wrapBroadcastSession(await t.open(e))},preparePublisher:async()=>{this.assertOpen();let e=await this.broadcastHost();if(!e?.preparePublisher)throw new Error("[OpenRTC] Broadcast publishing is unavailable in this runtime.");let t=await e.preparePublisher(),i=t.verificationKey.slice();if(i.byteLength!==32)throw await t.close(),new Error("[OpenRTC] Broadcast publisher key is invalid.");let n=false,s={verificationKey:i,open:async r=>{if(n)throw new Error("[OpenRTC] Broadcast publisher is closed.");return this.assertOpen(),this.validateBroadcastGrant(r),this.wrapBroadcastSession(await t.open(r))},close:async()=>{n||(n=true,await t.close(),this.broadcastPublishers.delete(s));}};return this.broadcastPublishers.add(s),s},renew:async(e,t={})=>{this.validateBroadcastGrant(e);let i=await this.broadcastHost();if(!i?.renew)throw new Error("[OpenRTC] Broadcast renewal is unavailable.");return i.renew(e,t.auth)},invite:async(e,t)=>{this.validateBroadcastGrant(e);let i=await this.broadcastHost();if(!i?.invite)throw new Error("[OpenRTC] Broadcast invitations are unavailable.");let{auth:n,...s}=t;return i.invite(e,s,n)},accept:async(e,t={})=>{if(!/^obi1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(e))throw new Error("[OpenRTC] Broadcast invitation is invalid.");let i=await this.broadcastHost();if(!i?.accept)throw new Error("[OpenRTC] Broadcast invitation acceptance is unavailable.");return i.accept(e,t.auth)},revoke:async(e,t)=>{if(this.validateBroadcastGrant(e),!/^obi1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(t.invite))throw new Error("[OpenRTC] Broadcast invitation is invalid.");let i=await this.broadcastHost();if(!i?.revoke)throw new Error("[OpenRTC] Broadcast revocation is unavailable.");await i.revoke(e,t.invite,t.auth);},leave:async(e,t={})=>{this.validateBroadcastGrant(e);let i=await this.broadcastHost();if(!i?.leave)throw new Error("[OpenRTC] Broadcast leave is unavailable.");await i.leave(e,t.auth);},close:async(e,t={})=>{this.validateBroadcastGrant(e);let i=await this.broadcastHost();if(!i?.closeGrant)throw new Error("[OpenRTC] Broadcast close is unavailable.");await i.closeGrant(e,t.auth);}};this.onClosed=e=>{this.handles.delete(e);for(let[t,i]of this.activations)i.handle===e&&this.activations.delete(t);};this.apiKey="profile"in e&&e.profile==="live"?"":ge(e.apiKey??"");let i=e.trust?.browserPersistence??"session";if(i!=="session"&&i!=="persistent")throw new Error("[OpenRTC] Invalid browser identity persistence policy.");this.browserPersistence=i,this.appTag=this.apiKey?`app_${this.apiKey.slice(-16)}`:"";}validateBroadcastGrant(e){if(typeof e!="string"||e.length<16||e.length>32768)throw new Error("[OpenRTC] Broadcast grant is invalid.")}broadcastHost(){return this.internals.broadcastHost?Promise.resolve(this.internals.broadcastHost):this.internals.broadcastHostFactory?this.broadcastHostPromise??(this.broadcastHostPromise=this.controlPlane().then(e=>this.internals.broadcastHostFactory({apiKey:this.apiKey,resolve:(t,i)=>e.resolveBroadcastAccess(t,i),manage:e.manageBroadcast.bind(e),deviceId:()=>this.deviceId(),defaultAuth:this.options.auth}))):Promise.resolve(void 0)}wrapBroadcastSession(e){let t=false,i={get id(){return e.id},get role(){return e.role},get state(){return e.state},media:e.media,getStats:()=>e.getStats(),close:async()=>{t||(t=true,this.broadcastSessions.delete(i),await e.close());}};return this.broadcastSessions.add(i),i}makeControlPlane(e){return Promise.all([import('./controlPlane-HOFWXQJW.js'),e]).then(([{ControlPlane:t},i])=>new t(this.apiKey,this.internals.endpoints??a$2,i,this.options.trust?.attestation,{onAuthEpochChanged:n=>this.retireAuthCapabilities(n)},this.options.trust?.botVerification,this.rootClientKey()))}rootClientKey(){return this.rootClientKeyPromise??(this.rootClientKeyPromise=this.internals.deviceKeyProvider?.getRootClientKey?this.internals.deviceKeyProvider.getRootClientKey(this.appTag):import('./deviceKey-4DLS246L.js').then(({createSessionDeviceKeyProvider:e})=>e().getOrCreate(this.appTag)))}controlPlane(){if("profile"in this.options&&this.options.profile==="live")throw new Error("[OpenRTC] This live-only root does not activate managed devices, rooms or peers.");return this.controlPlanePromise??(this.controlPlanePromise=this.makeControlPlane(this.internals.deviceKeyProvider?Promise.resolve(this.internals.deviceKeyProvider):import('./deviceKey-4DLS246L.js').then(({browserDeviceKeyProvider:e,createSessionDeviceKeyProvider:t})=>this.internals.platform!=="native"&&this.browserPersistence!=="persistent"?t():e)))}sessionPlane(){if("profile"in this.options&&this.options.profile==="live")throw new Error("[OpenRTC] This live-only root does not activate managed devices, rooms or peers.");return this.sessionPlanePromise??(this.sessionPlanePromise=this.makeControlPlane(import('./deviceKey-4DLS246L.js').then(({createSessionDeviceKeyProvider:e})=>e())))}assertOpen(){if(this.closed)throw new Error("[OpenRTC] Client is closed.");if(this.closing)throw new Error("[OpenRTC] Client is closing.")}activateOnce(e,t,i,n,s){this.assertOpen();let r=this.activations.get(e);if(r){if(r.handle?.closed)throw new Error(`[OpenRTC] ${e} is closing; retry close() to finish retirement.`);if(r.fingerprint!==t||r.auth!==i)throw s?s():new Error(`[OpenRTC] ${e} is already active with different options.`);return r.promise}let o={fingerprint:t,auth:i},c=this.options.diagnostics?.logger,d=c?performance.now():0,h=c?++this.nextDiagnosticOperation:0,l=e.split(":",1)[0],p=["devices","space","room","ticket"].includes(l)?l:"custom",m=u=>{c&&b$6(c,Object.freeze({sdkVersion:a$4,clientRef:this.diagnosticClientRef,name:"capability.activation",operationRef:h,avenue:p,outcome:u,timestampMs:Date.now(),elapsedMs:performance.now()-d}));},w;try{w=this.pendingCapabilityShutdowns.has(e)?this.settlePendingCapabilityShutdown(e).then(n):n();}catch(u){throw m("started"),m("failed"),u}let P=w.then(u=>(o.handle=u,m("succeeded"),u)).catch(u=>{throw m("failed"),this.activations.get(e)===o&&this.activations.delete(e),u});return o.promise=P,this.activations.set(e,o),m("started"),P}retainPendingCapabilityShutdown(e,t){this.pendingCapabilityShutdowns.has(e)||this.pendingCapabilityShutdowns.set(e,t);}async settlePendingCapabilityShutdown(e){let t=this.pendingCapabilityShutdowns.get(e);t&&(await t(),this.pendingCapabilityShutdowns.get(e)===t&&this.pendingCapabilityShutdowns.delete(e));}authorityCallableId(e){let t=this.authorityCallableIds.get(e);if(t)return t;let i=this.nextAuthorityCallableId++;return this.authorityCallableIds.set(e,i),i}retireAuthCapabilities(e){for(let t of this.activations.values())t.auth===e&&t.promise.then(i=>i.close()).catch(()=>{});}async deviceId(){let e=this.internals.deviceIdProvider?await this.internals.deviceIdProvider(this.appTag):this.internals.platform!=="native"&&this.browserPersistence==="session"?this.sessionDeviceId??(this.sessionDeviceId=crypto.randomUUID()):Ce(this.appTag);return re(e)}runtimeOptions(e){let t=this.options.transports,i=e.irohRelay&&t?.relay!==false,n=e.managedTurn&&t?.relay!==false,s=t?.privacy==="relay-only";if(s&&!i)throw new Error("[OpenRTC] transports.privacy: relay-only requires relay access.");let r=s?d$1(t?.priority?[...t.priority]:void 0,true):t?.priority?[...t.priority]:void 0,o=t?.webrtc,c=typeof o=="object"&&o.iceServers?.some(b$5)===true,d=!s||n||c;return {apiKey:this.apiKey,authMode:"external",discoveryMode:e.avenue?.kind==="user"?"user-scoped":"space",space:e.avenue?.id,localDeviceId:e.deviceId,deviceIdPersistence:"persistent",endpointIdPersistence:this.internals.platform==="native"?"persistent":"ephemeral",deviceName:e.deviceName?.trim()||void 0,coordinationPlatformType:e.devicePlatform?.trim()||void 0,initialAutoConnectExcludedDeviceIds:e.initialAutoConnectExcludedDeviceIds,nativeIdentityProvider:this.internals.platform==="native"&&e.nativeAuth?{providerId:e.nativeAuth.providerId,getSessionKey:async()=>e.nativeAuth.getSessionKey?.()??null,getAssertion:h=>e.nativeAuth.getAssertion(h)}:void 0,coordinationAvenueOverride:e.avenue,coordinationRoomGossipFanout:e.roomGossipFanout===true,coordinationRoomArchitecture:e.roomArchitecture,coordinationDevicePublicKeyX:e.devicePublicKeyX,coordinationDeviceSign:e.deviceSign,coordinationGateway:{endpoint:(this.internals.endpoints??a$2).gateway,environment:"production",grantProvider:e.grantProvider,onServiceError:this.options.onServiceError,testingAllowInsecureLoopback:this.internals.testingAllowInsecureLoopback},turnCredentialsProvider:n?e.turnProvider:void 0,transports:{relay:i,iroh:s?{relayOnly:true,relayTransportPolicy:"websocketRequired",localDiscovery:false,persistenceMode:this.internals.platform==="native"?"persistent":"ephemeral",...this.internals.irohTestRelayUrl?{testRelayUrl:this.internals.irohTestRelayUrl}:{}}:this.internals.irohTestRelayUrl?{testRelayUrl:this.internals.irohTestRelayUrl,persistenceMode:this.internals.platform==="native"?"persistent":"ephemeral"}:t?.iroh??true,webrtc:d?typeof o=="object"?s?{...o,privacyMode:true,useTurn:true,useDefaultIceServers:false}:o:o===true?s?{privacyMode:true,useTurn:true,useDefaultIceServers:false}:true:false:false,ble:t?.ble??false,moq:i?t?.moq??false:false,privacy:t?.privacy??"direct",optimizeFor:t?.optimizeFor??"balanced",priority:r},transportPriority:r}}async activate(e){let t=e.authority?null:e.controlPlane??await this.controlPlane(),i=this.options.transports?.relay!==false,n=e.source.irohRelay&&i,s=e.source.managedTurn&&i,r={irohRelay:n,managedTurn:s,moq:n&&!!this.options.transports?.moq,ble:this.options.transports?.ble===true,advancedFanout:e.architecture==="sparse"||e.advancedFanout===true,durableMembership:e.durableMembership===true},o=e.source,c=null,d=()=>e.authority?{userId:e.principalId}:{userId:e.principalId,token:o.token,tokenProvider:async()=>o.token,expiresAtMs:o.expiresAtMs},h=e.authority?.devicePublicKeyX??String((await t.deviceSigningPublicKey()).x??""),l=e.authority,p=l?async u=>{let{rootClientProof:de}=await import('./deviceKey-4DLS246L.js'),he=await de(await this.rootClientKey(),["authority-service-grant",this.appTag,u.avenue.id,l.serviceId,String(l.generation),[...l.shardIds].sort().join(","),l.assignmentPublicKeyX,u.deviceId,u.runtimeInstanceId,u.ticketFingerprint]);return l.grantProvider({...u,rootProof:he})}:void 0,m=this.runtimeOptions({avenue:e.source.avenue,grantProvider:p??t.grantProvider(e.source,{maxPeers:e.maxPeers,features:r,architecture:e.architecture,roomDelivery:e.kind==="room"?e.defaultDelivery:void 0,deviceProfile:e.deviceName&&e.devicePlatform?{name:e.deviceName,platform:e.devicePlatform}:void 0,onSourceRenewed:async u=>{o={...o,...u},await c?.setAuth(d());}}),deviceId:e.deviceId,userId:e.principalId,roomGossipFanout:(e.kind==="room"||e.kind==="space")&&(e.architecture==="sparse"||e.advancedFanout===true),roomArchitecture:e.kind==="room"?e.architecture:void 0,devicePublicKeyX:h,deviceSign:e.authority?.deviceSign??(u=>t.signDeviceBytes(u)),irohRelay:e.source.irohRelay,managedTurn:e.source.managedTurn,turnProvider:s&&t?t.turnProvider(()=>o):void 0,deviceName:e.deviceName,devicePlatform:e.devicePlatform,initialAutoConnectExcludedDeviceIds:e.initialAutoConnectExcludedDeviceIds,nativeAuth:e.nativeAuth}),[w,{wrapAssembly:P}]=await Promise.all([this.internals.runtimeFactory(m),import('./coreClient.js')]);c=P(w,this.internals.platform==="native"?"native":"web"),await c.setAuth(d()),this.channels.attach(c,e.defaultDelivery??"reliable");try{await c.devices.startSession({browserTrustPersistence:this.browserPersistence,sessionKind:e.kind==="devices"?"app-user-device":"scoped-guest",scope:`v2:${e.kind}:${e.id}`,userId:e.principalId,localDeviceId:e.deviceId,metadata:e.deviceMetadata,autoConnectPolicy:e.autoConnect?"enabled":"disabled",presencePolicy:"online"});}catch(u){throw this.channels.detach(c),await c.advanced.runtime.shutdown().catch(()=>{}),u}return c}trackHandle(e){return this.handles.add(e),e}async startDevices(e={}){this.assertOpen();let t=oe(e.autoConnectExcludedDeviceIds),i=e.auth??this.options.auth;if(!i)throw new Error("[OpenRTC] devices.start() requires an auth provider.");let n=await this.deviceId(),{resolveDeviceProfile:s}=await import('./deviceProfile-CR2C7OYR.js'),r=s(e.profile,this.internals.platform==="native"?"native":"web"),o=await this.controlPlane(),c=await o.deviceCertificate(i,n,void 0,r),d=await this.activate({kind:"devices",id:c.principalId,source:c.source,principalId:c.principalId,deviceId:n,maxPeers:e.maxPeers,autoConnect:e.autoConnect!=="none",initialAutoConnectExcludedDeviceIds:t,advancedFanout:e.advancedFanout,deviceName:r.name,devicePlatform:r.platform,deviceMetadata:r.metadata,nativeAuth:i}),h=[];if(this.internals.platform!=="native")try{h=await o.listEnrolledDevices(i,n);}catch(w){throw this.channels.detach(d),await d.advanced.runtime.shutdown().catch(()=>{}),w}let{AuthenticatedDeviceRoster:l}=await import('./deviceRoster-EUF6BBF5.js'),{DeviceHandle:p}=await import('./deviceHandle-DFG3CCY3.js'),m;return m=new p(c.principalId,d,()=>{this.channels.detach(d),this.onClosed(m);},new l(h)),this.handles.add(m),m}async joinSpace(e,t={}){this.assertOpen();let i=f(e),n=await(t.identity==="session"?this.sessionPlane():this.controlPlane()),s=await n.capability("space",i,t.maxPeers,t.advancedFanout),r=String(b$1(s.token).principalId),o=await this.activate({kind:"space",id:i,source:s,principalId:r,deviceId:N(s),maxPeers:t.maxPeers,autoConnect:true,defaultDelivery:t.payload??"reliable",advancedFanout:t.advancedFanout,controlPlane:n}),c;return c=new q(i,o,()=>{this.channels.detach(o),this.onClosed(c);},t.payload??"reliable"),this.handles.add(c),c}async openAuthorityRoom(e){return (await import('./room-ZQU7JFRG.js')).openAuthorityRoom(this,e)}async issueTicket(e,t={}){this.assertOpen();let i=f(e);if(t.mesh===true&&t.advancedFanout===true)throw d(a.TICKET_MESH_INVALID_OPTIONS,"[OpenRTC] Ticket mesh cannot use advancedFanout.",{retryable:false,plane:"admission"});let n=le(t);if(t.mesh===true&&(!Number.isSafeInteger(n)||n<ne||n>U))throw d(a.TICKET_MESH_INVALID_OPTIONS,`[OpenRTC] Ticket mesh maxPeers must be an integer between ${ne} and ${U}.`,{retryable:false,plane:"admission"});let s=await(t.identity==="session"||t.mesh===true?this.sessionPlane():this.controlPlane()),r=await s.capability("ticket",i,n,t.advancedFanout),o=String(b$1(r.token).principalId),c=await this.activate({kind:"ticket",id:i,source:r,principalId:o,deviceId:N(r),maxPeers:n,autoConnect:false,advancedFanout:t.advancedFanout,controlPlane:s}),d$1=null;if(t.mesh===true)try{d$1=await c.advanced.runtime.issueTicketMesh(i,n);}catch(l){await this.shutdownFailedTicketActivation(i,c,l);}let h;return h=new D(i,c,()=>{this.channels.detach(c),this.onClosed(h);},r.token,d$1,t.mesh===true),this.handles.add(h),h}async joinTicket(e){this.assertOpen();let t=b$4(e);if(!t.mesh)throw d(a.TICKET_INVITE_INVALID,"[OpenRTC] This invitation does not describe a ticket mesh.",{retryable:false,plane:"admission"});let i=f(t.id),n=await this.sessionPlane(),s=await n.capability("ticket",i,t.maxPeers,false),r=String(b$1(s.token).principalId),o=await this.activate({kind:"ticket",id:i,source:s,principalId:r,deviceId:N(s),maxPeers:t.maxPeers,autoConnect:false,advancedFanout:false,controlPlane:n});try{await o.advanced.runtime.joinTicketMesh(e);}catch(d){await this.shutdownFailedTicketActivation(i,o,d);}let c;return c=new D(i,o,()=>{this.channels.detach(o),this.onClosed(c);},s.token,e,true),this.handles.add(c),c}async shutdownFailedTicketActivation(e,t,i){this.channels.detach(t);try{await t.advanced.runtime.shutdown();}catch(n){throw this.retainPendingCapabilityShutdown(`ticket:${e}`,()=>t.advanced.runtime.shutdown()),d(a.TICKET_MESH_UNAVAILABLE,"[OpenRTC] Ticket mesh startup failed and runtime teardown was not confirmed.",{retryable:true,plane:"coordination",cause:{startError:i,shutdownError:n}})}throw i}async close(){if(this.closed)return;if(this.closing)return this.closing;let e=this.closeOnce();this.closing=e;try{await e;}finally{this.closing===e&&(this.closing=null);}}async closeOnce(){if(this.liveOpening){let e=this.liveOpening;e.canceled=true,await e.host?.close(),this.liveOpening===e&&(this.liveOpening=null);}await this.liveSession?.close(),await Promise.allSettled([...this.activations.values()].map(({promise:e})=>e)),await Promise.all([...this.handles].map(e=>e.close())),await Promise.all([...this.pendingCapabilityShutdowns.keys()].map(e=>this.settlePendingCapabilityShutdown(e))),await Promise.all([...this.broadcastSessions].map(e=>e.close())),await Promise.all([...this.broadcastPublishers].map(e=>e.close())),await Promise.all([this.controlPlanePromise,this.sessionPlanePromise].map(e=>e?.then(t=>t.dispose(),()=>{}))),this.activations.clear(),this.broadcastSessions.clear(),this.broadcastPublishers.clear(),await this.broadcastHostPromise?.then(e=>e?.close?.(),()=>{}),await this.internals.broadcastHost?.close?.(),await this.internals.close?.(),this.closed=true;}};M.nextDiagnosticClient=0;var k=M;function _e(a,e){return new k(a,e)}function Fe(a,e){if(!(a instanceof k))throw new TypeError("[OpenRTC] ServiceNode requires a client created by this OpenRTC package.");return a.openAuthorityRoom(e)}export{S as a,x as b,ve as c,Le as d,f as e,re as f,N as g,E as h,_e as i,Fe as j};
1
+ import {b as b$3}from'./chunk-FKAQDDUM.js';import {b as b$6,a as a$4,c}from'./chunk-BKCUXUHW.js';import {a as a$1,b as b$4}from'./chunk-IUU6JCLK.js';import {b as b$2,a as a$3}from'./chunk-CCCYE3XN.js';import {b as b$1,a as a$2}from'./chunk-ZA44REGI.js';import {d,a,e}from'./chunk-L7N4T2PX.js';import {d as d$1,b as b$5}from'./chunk-2GX6GB6L.js';function S(a,e,t,i){let n=JSON.stringify({__openrtc:2,capability:i,kind:a,name:e,value:t});if(n===void 0||!n.includes('"value":'))throw new Error("[OpenRTC] Messages must be JSON-serializable values.");return new TextEncoder().encode(n)}function x(a){let e;try{e=a instanceof Uint8Array?JSON.parse(new TextDecoder().decode(a)):a&&typeof a=="object"?a:{};}catch{return null}return e!=null&&e.__openrtc===2&&typeof e.capability=="string"&&e.capability.length>0&&e.capability.length<=192&&/^(?:devices|space|room|ticket):[A-Za-z0-9_.:@-]+$/.test(e.capability)&&(e.kind==="raw"||e.kind==="channel"||e.kind==="state")&&typeof e.name=="string"&&e.name.length>0&&e.name.length<=80&&/^[A-Za-z0-9_.:@-]+$/.test(e.name)&&Object.prototype.hasOwnProperty.call(e,"value")?e:null}var b="openrtc-peer-stream/1",ue=32,ee=16,_=4294967295,pe=/^[A-Za-z0-9][A-Za-z0-9._/+:-]{0,127}$/,me=/^([0-9a-f]{64})-([0-9a-f]{64})$/i;function A(a){let e=a?.trim()??"";if(!pe.test(e))throw new Error("[OpenRTC] stream protocol must be 1-128 safe ASCII characters.");return e}function L(a){let e=a?.trim()??"",t=me.exec(e);return t?[t[1].toLowerCase(),t[2].toLowerCase()].sort().join("-"):e}function te(a){if(a===null||a===0)return null;if(!Number.isFinite(a)||a<0)throw new RangeError("[OpenRTC] datagram maximum age must be a non-negative finite number or null.");return Math.min(_,Math.ceil(a))}function ie(a){if(!Number.isSafeInteger(a)||a<1||a>_)throw new RangeError(`[OpenRTC] datagram buffer limits must be integers from 1 to ${_}.`);return a}var F=class{constructor(e,t){this.runtime=e;this.peerId=t;this.incomingAge=null;this.outgoingAge=null;this.incomingLimit=ee;this.outgoingLimit=ee;this.policyInstance=null;this.incomingWaiters=new Set;this.outgoingWaiters=new Set;this.outgoingAvailable=new Set;this.incomingError=null;this.receiveLoopStarted=false;this.sendLoop=null;this.closed=false;this.incomingClosed=false;this.outgoingClosed=false;this.maxDatagramSize=e.peerDatagramMaxSize?.()??1024,this.readable=new ReadableStream({pull:i=>this.pullIncoming(i),cancel:()=>this.closeIncoming()},{highWaterMark:0}),this.writable=new WritableStream({write:i=>this.enqueueOutgoing(i),close:async()=>{this.outgoingClosed=true,await this.sendLoop;},abort:()=>{this.outgoingClosed=true,this.policyInstance?.closeOutgoing(),this.wake(this.outgoingWaiters),this.wake(this.outgoingAvailable);}},{highWaterMark:1});}get incomingMaxAge(){return this.incomingAge}set incomingMaxAge(e){this.incomingAge=te(e),this.policy.setIncomingMaxAge(this.incomingAge??void 0,Date.now()),this.wake(this.incomingWaiters);}get outgoingMaxAge(){return this.outgoingAge}set outgoingMaxAge(e){this.outgoingAge=te(e),this.policy.setOutgoingMaxAge(this.outgoingAge??void 0);}get incomingMaxBufferedDatagrams(){return this.incomingLimit}set incomingMaxBufferedDatagrams(e){this.incomingLimit=ie(e),this.policy.setIncomingMaxBufferedDatagrams(this.incomingLimit);}get outgoingMaxBufferedDatagrams(){return this.outgoingLimit}set outgoingMaxBufferedDatagrams(e){this.outgoingLimit=ie(e),this.policy.setOutgoingMaxBufferedDatagrams(this.outgoingLimit),this.wake(this.outgoingWaiters);}getStats(){return this.policy.getStats(Date.now())}get policy(){if(!this.policyInstance){let e=this.runtime.createPeerDatagramPolicy;if(!e)throw new Error("[OpenRTC] Shared protected-datagram policy is unavailable in this runtime.");this.policyInstance=e();}return this.policyInstance}close(){this.closed||(this.closed=true,this.closeIncoming(),this.outgoingClosed=true,this.policyInstance?.closeOutgoing(),this.wake(this.outgoingWaiters),this.wake(this.outgoingAvailable));}async pullIncoming(e){for(this.receiveLoopStarted||(this.receiveLoopStarted=true,this.pumpIncoming());;){let t=this.policy.popIncoming(Date.now());if(t){e.enqueue(new Uint8Array(t));return}if(this.incomingError){e.error(this.incomingError);return}if(this.incomingClosed){e.close();return}await new Promise(i=>this.incomingWaiters.add(i));}}async pumpIncoming(){let e=this.runtime.receivePeerDatagram;if(!e){this.incomingError=new Error("[OpenRTC] Protected peer datagrams are unavailable in this runtime."),this.wake(this.incomingWaiters);return}try{for(;!this.incomingClosed;){let t=new Uint8Array(await e(this.peerId));if(this.incomingClosed)return;this.policy.pushIncoming(t,Date.now()),this.wake(this.incomingWaiters);}}catch(t){this.incomingClosed||(this.incomingError=t,this.wake(this.incomingWaiters));}}async enqueueOutgoing(e){if(this.closed||this.outgoingClosed)throw new Error("[OpenRTC] peer datagram stream is closed.");if(!(e instanceof Uint8Array)||e.byteLength>this.maxDatagramSize)throw new Error(`[OpenRTC] peer datagrams must be Uint8Array values up to ${this.maxDatagramSize} bytes.`);for(;!this.policy.pushOutgoing(e,Date.now())&&!this.closed;)await new Promise(t=>this.outgoingWaiters.add(t));if(this.closed||this.outgoingClosed)throw new Error("[OpenRTC] peer datagram stream is closed.");this.startSendLoop(),this.wake(this.outgoingAvailable);}startSendLoop(){this.sendLoop||this.closed||(this.sendLoop=this.pumpOutgoing());}async pumpOutgoing(){let e=this.runtime.sendPeerDatagram;if(!e){this.policy.closeOutgoing();return}for(;!this.closed;){let t=this.policy.popOutgoing(Date.now());if(!t){if(this.wake(this.outgoingWaiters),this.outgoingClosed)return;await new Promise(n=>this.outgoingAvailable.add(n));continue}this.wake(this.outgoingWaiters);let i=new Uint8Array(t.payload);try{await e(this.peerId,i,t.remainingMaxAgeMs??void 0)===!1?this.policy.recordExpiredOutgoing():this.policy.recordSent(i.byteLength);}catch{this.policy.recordSendFailure();}this.wake(this.outgoingWaiters);}}closeIncoming(){this.incomingClosed||(this.incomingClosed=true,this.policyInstance?.closeIncoming(),this.wake(this.incomingWaiters));}wake(e){for(let t of e)t();e.clear();}},O=class{constructor(){this.controller=null;this.closed=false;this.readable=new ReadableStream({start:e=>{this.controller=e;},cancel:()=>{this.closed=true,this.controller=null;}},{highWaterMark:ue});}enqueue(e){return this.closed||!this.controller||(this.controller.desiredSize??0)<=0?false:(this.controller.enqueue(e),true)}close(){this.closed||(this.closed=true,this.controller?.close(),this.controller=null);}},K=class{constructor(e,t,i,n){this.client=e;this.peerId=t;this.capabilityKey=n;this.incomingBi=new O;this.incomingUni=new O;this.incomingBidirectionalStreams=this.incomingBi.readable;this.incomingUnidirectionalStreams=this.incomingUni.readable;this.closed=false;this.protocolHandlers=new Map;this.datagrams=new F(i,this.peerId);}async createBidirectionalStream(e){let t=A(e.protocol),i=await this.client.channels.openBi(this.peerId,b,{timeoutMs:e.timeoutMs,channelMetadata:{protocol:t,[a$3]:this.capabilityKey}});return {protocol:t,readable:i.readable,writable:i.writable}}async createUnidirectionalStream(e){let t=A(e.protocol);return (await this.client.channels.openUni(this.peerId,b,{timeoutMs:e.timeoutMs,channelMetadata:{protocol:t,[a$3]:this.capabilityKey}})).writable}accept(e,t){if(e.type==="bi"){let n=e.stream;if(!n.recv||!n.send)return false;let s={peerId:this.peerId,protocol:t,readable:n.recv,writable:n.send},r=this.protocolHandlers.get(t);if(r){try{r(s);}catch{s.readable.cancel("incoming-protocol-handler-failed").catch(()=>{}),s.writable.abort("incoming-protocol-handler-failed").catch(()=>{});}return true}return this.incomingBi.enqueue(s)||(s.readable.cancel("incoming-peer-stream-queue-full").catch(()=>{}),s.writable.abort("incoming-peer-stream-queue-full").catch(()=>{})),true}let i=e.stream;return !i||typeof i.getReader!="function"?false:(this.incomingUni.enqueue({peerId:this.peerId,protocol:t,readable:i})||i.cancel("incoming-peer-stream-queue-full").catch(()=>{}),true)}onProtocol(e,t){let i=A(e);if(this.protocolHandlers.has(i))throw new Error(`[OpenRTC] stream protocol '${i}' already has an owning consumer.`);return this.protocolHandlers.set(i,t),()=>{this.protocolHandlers.get(i)===t&&this.protocolHandlers.delete(i);}}close(){this.closed=true,this.datagrams.close(),this.protocolHandlers.clear(),this.incomingBi.close(),this.incomingUni.close();}},T=class{constructor(e,t){this.client=e;this.capabilityKey=t;this.peers=new Map;this.peerIdsByConnection=new Map;this.registered=false;this.observed=0;this.accepted=0;this.declined=0;this.lastResolution="none";try{e.channels.register({id:b,kind:"application-stream",ownership:"shared",peerModel:"device-first",routing:"stream-envelope",readiness:"settled-peer",promotionPolicy:"never",signalingPolicy:"hosted",delivery:"reliable",description:"Transport-agnostic protected peer streams"}),this.stopIncoming=e.channels.onIncomingChannel(b,i=>this.accept(i)),this.registered=!0;}catch{this.stopIncoming=()=>{};}}forPeer(e){let t=this.peers.get(e);return t||(t=new K(this.client,e,this.client.advanced.runtime,this.capabilityKey),this.peers.set(e,t)),t}onProtocol(e,t,i){return this.forPeer(e).onProtocol(t,i)}bindConnection(e,t){let i=L(e),n=t.trim();!i||!n||this.peerIdsByConnection.set(i,n);}unbindConnection(e){this.peerIdsByConnection.delete(L(e));}diagnostics(){return {registered:this.registered,peers:this.peers.size,boundConnections:this.peerIdsByConnection.size,observed:this.observed,accepted:this.accepted,declined:this.declined,lastResolution:this.lastResolution}}closePeer(e){let t=this.peers.get(e);if(t){t.close(),this.peers.delete(e);for(let[i,n]of this.peerIdsByConnection)n===e&&this.peerIdsByConnection.delete(i);}}close(){this.stopIncoming();for(let e of this.peers.values())e.close();this.peers.clear(),this.peerIdsByConnection.clear(),this.registered&&this.client.channels.unregister(b);}accept(e){if(this.observed+=1,e.channel?.metadata?.[a$3]!==this.capabilityKey)return this.declined+=1,false;let i=e.channel?.metadata?.protocol;if(typeof i!="string")return this.declined+=1,false;let n;try{n=A(i);}catch{return this.declined+=1,false}let r=this.resolveExistingPeer(e.remoteNodeId,e.connectionId)?.accept(e,n)??false;return r?this.accepted+=1:this.declined+=1,r}resolveExistingPeer(e,t=""){let i=L(t);if(i){let r=this.peerIdsByConnection.get(i);if(!r)return this.lastResolution="unbound-connection",null;let o=this.peers.get(r);return o?(this.lastResolution="connection",o):(this.lastResolution="unbound-connection",null)}let n=this.peers.get(e);if(n)return this.lastResolution="remote-peer",n;let s=this.client.peers.get(e)??this.client.peers.listConnected().find(r=>[r.peerId,r.deviceId,r.deviceIdHint,r.connectionId,...r.connectionIds].some(o=>o===e));if(s){let r=new Set([s.peerId,s.deviceId,s.deviceIdHint,s.connectionId,...s.connectionIds].filter(c=>typeof c=="string"&&c.length>0)),o=[...this.peers.entries()].filter(([c])=>r.has(c)).map(([,c])=>c);if(o.length===1)return this.lastResolution="peer-alias",o[0]}return this.lastResolution="none",null}};var y=new WeakMap;function ve(a){let e=y.get(a);if(!e||a.closed)throw new Error("[OpenRTC] Capability runtime is unavailable or already closed.");return e}function Le(a,e){if(y.has(a))throw new Error("[OpenRTC] Capability runtime is already registered.");return y.set(a,ve(e)),()=>{y.delete(a);}}function ge(a){let e=a?.trim()??"";if(!/^pk_(?:live|test)_[0-9a-f]{40}$/.test(e))throw new Error("[OpenRTC] apiKey must be a public pk_live_ or pk_test_ key.");return e}function f(a){let e=a?.trim()??"";if(!e||e.length>160||!/^[A-Za-z0-9_.:@-]+$/.test(e))throw new Error("[OpenRTC] Capability id is invalid.");return e}var z=/^[A-Za-z0-9_.:@-]{1,160}$/,fe=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,ne=2,U=8,ye=U;function we(a){let e=typeof a=="string"?a.trim():"";if(!z.test(e))return null;let t=e.startsWith("device_")?e.slice(7):"";return fe.test(t)?t:e}function Ce(a){let e=`openrtc:v2:device-id:${a}`,t,i=(()=>{try{return t=globalThis.localStorage,we(t?.getItem(e))||crypto.randomUUID()}catch{return crypto.randomUUID()}})();try{t?.setItem(e,i);}catch{}return i}function re(a){let e=typeof a=="string"?a.trim():"";if(!z.test(e))throw new Error("[OpenRTC] The native host returned an invalid durable device ID.");return e}var se=250;function oe(a){if(a===void 0)return [];if(!Array.isArray(a))throw new Error("[OpenRTC] autoConnectExcludedDeviceIds must be an array.");let e=[...new Set(a.map(t=>{let i=typeof t=="string"?t.trim().toLowerCase():"";if(!z.test(i))throw new Error("[OpenRTC] autoConnectExcludedDeviceIds contains an invalid device ID.");return i}))].sort();if(e.length>se)throw new Error(`[OpenRTC] autoConnectExcludedDeviceIds supports at most ${se} devices.`);return e}function N(a){let e=b$1(a.token),t=typeof e.deviceKeyThumbprint=="string"?e.deviceKeyThumbprint.trim():"";if(!/^[A-Za-z0-9_-]{43}$/.test(t))throw new Error("[OpenRTC] Anonymous capability is missing its device-key binding.");return `anon_${t.slice(0,32)}`}var G=class{constructor(){this.descriptors=new Map;this.targets=new Map;}register(e){if(!e?.id?.trim())throw new Error("[OpenRTC] Channel id is required.");this.descriptors.set(e.id,{...e});for(let[t,i]of this.targets)t.channels.register({...e,delivery:e.delivery??i});return ()=>{this.descriptors.delete(e.id);for(let t of this.targets.keys())t.channels.unregister(e.id);}}list(){return [...this.descriptors.values()].map(e=>({...e}))}attach(e,t){this.targets.set(e,t);for(let i of this.descriptors.values())e.channels.register({...i,delivery:i.delivery??t});}detach(e){this.targets.delete(e);}};function ae(a$1){return d(a.TICKET_MESH_ALREADY_ACTIVE,`[OpenRTC] ticket:${a$1} is already active with different options.`,{retryable:false,plane:"admission"})}function le(a){return a.mesh===true?a.maxPeers??ye:a.maxPeers}function be(a){return JSON.stringify({identity:a.identity??(a.mesh===true?"session":null),maxPeers:le(a)??null,mesh:a.mesh===true,advancedFanout:a.advancedFanout===true})}function ce(a){let e=a?.trim()??"";if(!e||e.length>80||!/^[A-Za-z0-9_.:@-]+$/.test(e))throw new Error("[OpenRTC] Message name is invalid.");return e}var H=class{constructor(e,t,i){this.client=e;this.capabilityKey=t;this.rawConnections=new Map;this.logicalConnections=new Map;this.connectionListeners=new Map;this.rawListeners=new Map;this.closeListeners=new Map;this.channelListeners=new Map;this.stateListeners=new Map;this.remoteState=new Map;this.localState=new Map;this.stateSenders=new Map;this.stateReadyGenerations=new Map;this.mediaConnections=new Map;this.mediaRetirements=new Map;this.pendingRawConnections=new Map;this.connectionIdsByPeer=new Map;this.closed=false;this.cleanupComplete=false;this.closeAttempt=null;this.pendingStops=null;this.peerStreams=new T(e,t),this.stopMessage=e.onMessage((n,s)=>this.receive(n,s)),this.stopConnection=e.onConnection(n=>this.add(n)),this.stopDisconnection=e.onDisconnection(n=>this.remove(n)),e.getConnections().forEach(n=>this.add(n)),this.stopPeerLifecycle=e.peers.watchLifecycle(n=>this.observePeerLifecycle(n)),this.roomFanout=i?.create({client:e,capabilityKey:t,connections:()=>[...this.logicalConnections.values()].flatMap(({activeRaw:n})=>n?[n]:[]),deliver:(n,s,r)=>{let o=x(s);!o||o.capability!==this.capabilityKey||r!==void 0&&o.name!==r||r===void 0&&o.kind!=="channel"||this.deliverEnvelope(n,o);}});}state(e){if(this.assertOpen(),this.roomFanout?.isSparse())throw new Error("[OpenRTC] state() is not available in sparse gossip rooms; use a named channel with application-owned latest-state revisions.");let t=ce(e);return {set:i=>{this.assertOpen();let n=S("state",t,i,this.capabilityKey);if(this.localState.set(t,n),!this.roomFanout?.publishState(t,n))for(let{activeRaw:s}of this.logicalConnections.values())s&&this.sendState(s,t,n);},watch:i=>{this.assertOpen();let n=this.stateListeners.get(t);n||this.stateListeners.set(t,n=new Set);let s=(r,o)=>i({peerId:r,value:o});n.add(s);for(let[r,o]of this.remoteState)o.has(t)&&i({peerId:r,value:o.get(t)});return ()=>n?.delete(s)}}}channel(e){this.assertOpen();let t=ce(e),i=n=>S("channel",t,n,this.capabilityKey);return {send:async n=>{this.assertOpen();let s=i(n);await this.roomFanout?.sendChannel(t,s)||(this.assertOpen(),await Promise.all([...this.logicalConnections.values()].flatMap(({activeRaw:r})=>r?[this.sendPayload(r,s)]:[])));},sendTo:async(n,s)=>{this.assertOpen(),this.roomFanout?.assertTargetedSendAllowed();let r=this.logicalConnections.get(n)?.activeRaw;if(r){await this.sendPayload(r,i(s));return}throw d(a.DELIVERY_NOT_READY,`[OpenRTC] Peer '${n}' has no direct authorized route; sparse broadcasts never multi-hop targeted payloads.`,{retryable:true,plane:"delivery"})},onMessage:n=>{this.assertOpen();let s=this.channelListeners.get(t);s||this.channelListeners.set(t,s=new Set);let r=(o,c)=>n({peerId:o,message:c});return s.add(r),()=>s?.delete(r)}}}async sendPayload(e$1,t){try{await e$1.send(t);}catch(i){throw e(i)}}onConnection(e){this.assertOpen();let t=new Set;this.connectionListeners.set(e,t);for(let[i,n]of this.logicalConnections)n.activeRaw&&(t.add(i),e(n.view));return ()=>this.connectionListeners.delete(e)}assertOpen(){if(this.closed)throw new Error("[OpenRTC] Capability messages are closed.")}fence(){this.closed=true;}close(){if(this.cleanupComplete)return Promise.resolve();if(this.closeAttempt)return this.closeAttempt;this.closed=true;let e=this.releaseMessages();return this.closeAttempt=e,e.then(()=>{this.closeAttempt===e&&(this.closeAttempt=null);},()=>{this.closeAttempt===e&&(this.closeAttempt=null);}),e}async releaseMessages(){let e=[];this.pendingStops??(this.pendingStops=[()=>this.stopMessage(),()=>this.stopConnection(),()=>this.stopDisconnection(),()=>this.stopPeerLifecycle(),()=>this.roomFanout?.close()]),this.pendingStops=this.pendingStops.filter(i=>{try{return i(),!1}catch(n){return e.push(n),true}});let t=[];for(let i of this.logicalConnections.keys())try{t.push(this.retire(i));}catch(n){e.push(n);}this.pendingRawConnections.clear();try{this.peerStreams.close();}catch(i){e.push(i);}this.rawConnections.clear(),this.logicalConnections.clear(),this.connectionListeners.clear(),this.channelListeners.clear(),this.stateListeners.clear(),this.localState.clear(),this.remoteState.clear(),this.stateReadyGenerations.clear(),this.rawListeners.clear(),this.closeListeners.clear();for(let i of await Promise.allSettled(t))i.status==="rejected"&&e.push(i.reason);if(e.length===1)throw e[0];if(e.length)throw d(a.INTERNAL,"[OpenRTC] Capability message cleanup failed.",{cause:e,retryable:true,plane:"internal"});this.cleanupComplete=true;}add(e){if(this.closed)return;let t=this.rawConnections.get(e.id);if(t?.raw===e)return;t&&this.remove(t.raw);let i=e.remoteNodeId||e.id,n=this.mediaRetirements.get(i);if(n){let o={raw:e,peerId:i};this.pendingRawConnections.set(e.id,o),n.finally(()=>{this.closed||this.pendingRawConnections.get(e.id)!==o||(this.pendingRawConnections.delete(e.id),this.add(e));});return}this.rawConnections.set(e.id,{raw:e,peerId:i});let s=this.connectionIdsByPeer.get(i);s||this.connectionIdsByPeer.set(i,s=new Set),s.add(e.id),this.peerStreams.bindConnection(e.id,i);let r=this.logicalConnections.get(i);if(!r){let o=this.peerStreams.forPeer(i),c=new b$3(o,this.client.advanced.runtime,(h,l)=>this.peerStreams.onProtocol(i,h,l),()=>this.peerStreams.diagnostics());this.mediaConnections.set(i,c),r={activeRaw:e,rawIds:new Set,view:{id:i,peerId:i,streams:o,media:c,send:async h=>{let l=this.logicalConnections.get(i)?.activeRaw;if(!l)throw d(a.DELIVERY_NOT_READY,`[OpenRTC] Peer '${i}' is not connected.`,{retryable:true,plane:"delivery"});await this.sendPayload(l,S("raw","message",h,this.capabilityKey));},onMessage:h=>{let l=this.rawListeners.get(i);l||this.rawListeners.set(i,l=new Set);let p=h;return l.add(p),()=>l?.delete(p)},onClose:h=>{let l=this.closeListeners.get(i);return l||this.closeListeners.set(i,l=new Set),l.add(h),()=>l?.delete(h)}}},this.logicalConnections.set(i,r);}r.rawIds.add(e.id),r.activeRaw=e,this.observePeerLifecycle(this.client.peers.listConnected());for(let[o,c]of this.connectionListeners)c.has(i)||(c.add(i),o(r.view));for(let[o,c]of this.localState)this.sendState(e,o,c);}remove(e){if(this.pendingRawConnections.get(e.id)?.raw===e){this.pendingRawConnections.delete(e.id);return}let t=this.rawConnections.get(e.id);if(!t||t.raw!==e)return;this.rawConnections.delete(e.id),this.peerStreams.unbindConnection(e.id);let i=t.peerId,n=this.logicalConnections.get(i);if(n?.rawIds.delete(e.id),n?.activeRaw?.id===e.id){let o=[...n.rawIds],c=o[o.length-1];n.activeRaw=c?this.rawConnections.get(c)?.raw??null:null;}let s=this.connectionIdsByPeer.get(i);if(s?.delete(e.id),s?.size===0&&this.connectionIdsByPeer.delete(i),!n?.activeRaw){let o=this.remoteState.get(i);if(o){for(let c of o.keys())for(let d of this.stateListeners.get(c)??[])d(i,null);this.remoteState.delete(i);}}let r=this.stateSenders.get(e);if(r){for(let o of r.values())o.close();this.stateSenders.delete(e);}}observePeerLifecycle(e){for(let t of this.logicalConnections.keys()){let i=this.connectionIdsByPeer.get(t)??new Set,n=e.find(d=>d.peerId===t||d.connectionId===t||d.connectionIds.some(h=>i.has(h)));if(!n)continue;let s=n.status==="closed"&&n.logicalSessionTerminal===true&&n.routable!==true&&n.settledReady!==true;if(n.manualDisconnect||s){this.retire(t);continue}if(n.settledReady!==true||n.routable!==true){this.stateReadyGenerations.delete(t);continue}let r=n.transportStableId,o=n.transportGeneration,c=n.routeGeneration;if(Number.isSafeInteger(r)&&Number(r)>0&&Number.isSafeInteger(o)&&Number(o)>0&&Number.isSafeInteger(c)&&Number(c)>=0){let d=JSON.stringify([n.connectionId,n.generation,r,o,c]);if(this.stateReadyGenerations.get(t)!==d){this.stateReadyGenerations.set(t,d);let l=this.logicalConnections.get(t)?.activeRaw;if(l)for(let[p,m]of this.localState)this.sendState(l,p,m);}let h=this.mediaConnections.get(t);h&&h.observePhysicalGeneration({transportStableId:Number(r),transportGeneration:Number(o),routeGeneration:Number(c)}).catch(()=>{});}}}retire(e){let t=this.logicalConnections.get(e);if(!t)return this.mediaRetirements.get(e)??Promise.resolve();this.logicalConnections.delete(e),this.stateReadyGenerations.delete(e);for(let r of t.rawIds){let o=this.rawConnections.get(r)?.raw;if(this.rawConnections.delete(r),this.peerStreams.unbindConnection(r),!o)continue;let c=this.stateSenders.get(o);if(c){for(let d of c.values())d.close();this.stateSenders.delete(o);}}this.connectionIdsByPeer.delete(e);let i=this.remoteState.get(e);if(i){for(let r of i.keys())for(let o of this.stateListeners.get(r)??[])o(e,null);this.remoteState.delete(e);}let n=this.mediaConnections.get(e);this.mediaConnections.delete(e);let s=n?.close().catch(()=>{})??Promise.resolve();this.mediaRetirements.set(e,s),s.finally(()=>{this.mediaRetirements.get(e)===s&&this.mediaRetirements.delete(e);}),this.peerStreams.closePeer(e);for(let r of this.closeListeners.get(e)??[])r();this.closeListeners.delete(e),this.rawListeners.delete(e);for(let r of this.connectionListeners.values())r.delete(e);return s}receive(e,t){if(this.closed)return;this.add(e);let i=this.rawConnections.get(e.id)?.peerId??e.remoteNodeId??e.id;if(this.roomFanout?.receive(e,i,t))return;let n=x(t);if(!n){for(let s of this.rawListeners.get(i)??[])s(t);return}if(n.capability===this.capabilityKey){if(n.kind==="raw"){for(let s of this.rawListeners.get(i)??[])s(n.value);return}this.deliverEnvelope(i,n);}}deliverEnvelope(e,t){if(this.closed)return;if(t.kind==="raw"){for(let n of this.rawListeners.get(e)??[])n(t.value);return}if(t.kind==="channel"){for(let n of this.channelListeners.get(t.name)??[])n(e,t.value);return}let i=this.remoteState.get(e);i||this.remoteState.set(e,i=new Map),i.set(t.name,t.value);for(let n of this.stateListeners.get(t.name)??[])n(e,t.value);}sendState(e,t,i){let n=this.stateSenders.get(e);n||this.stateSenders.set(e,n=new Map);let s=n.get(t);s||(s=new a$1(r=>e.send(r)),n.set(t,s)),s.send(i).catch(()=>{});}},E=class{constructor(e,t,i,n,s){this.kind=e;this.id=t;this.client=i;this.onClosed=n;this.roomFanoutFactory=s;this.closed=false;this.retired=false;this.shutdownAttempt=null;y.set(this,i);}get peers(){return this.client.peers}get channels(){return this.client.channels}get diagnostics(){return this.client.diagnostics}state(e){return this.capabilityMessages().state(e)}channel(e){return this.capabilityMessages().channel(e)}onConnection(e){return this.capabilityMessages().onConnection(e)}projectRuntime(e){y.set(this,e);}setArchitecture(e){this.roomFanoutFactory?.setArchitecture(e);}close(){if(this.retired)return Promise.resolve();if(this.shutdownAttempt)return this.shutdownAttempt;this.fenceProductAccess();let e=this.releaseCapability();return this.shutdownAttempt=e,e.then(()=>{this.shutdownAttempt===e&&(this.shutdownAttempt=null);},()=>{this.shutdownAttempt===e&&(this.shutdownAttempt=null);}),e}beforeRuntimeShutdown(){}fenceProductAccess(){this.closed=true,this.messages?.fence();}async releaseCapability(){let e=[];try{this.beforeRuntimeShutdown();}catch(t){e.push(t);}try{await this.messages?.close();}catch(t){e.push(t);}try{await this.client.advanced.runtime.shutdown();}catch(t){e.push(t);}if(e.length===1)throw e[0];if(e.length)throw d(a.INTERNAL,"[OpenRTC] Capability cleanup failed.",{cause:e,retryable:true,plane:"internal"});this.onClosed(),y.delete(this),this.retired=true;}capabilityMessages(){if(this.closed)throw new Error("[OpenRTC] Capability is closed.");return this.messages??(this.messages=new H(this.client,b$2(this.kind,this.id).key,this.roomFanoutFactory))}},q=class extends E{constructor(t,i,n,s){super("space",t,i,n);this.delivery=s;this.kind="space";this.leave=()=>this.close();}},D=class extends E{constructor(t,i,n,s,r,o){super("ticket",t,i,n);this.token=s;this.ownsMesh=o;this.kind="ticket";this.closing=null;this.inviteListeners=new Set;this.stopInviteWatch=()=>{};this.meshStopped=false;if(this.currentInvite=r,o){let c=i.advanced.runtime;this.stopInviteWatch=c.watchTicketMeshInvite?.(t,d=>{this.closed||(this.currentInvite=d,this.inviteListeners.forEach(h=>h(d)));})??this.stopInviteWatch;}}get invite(){return this.closed?null:this.currentInvite}watchInvite(t){return this.closed?(t(null),()=>{}):(this.inviteListeners.add(t),t(this.currentInvite),()=>this.inviteListeners.delete(t))}async issuerNode(){if(this.closed)throw new Error("[OpenRTC] Capability is closed.");if(!this.ownsMesh)throw new Error("[OpenRTC] This ticket is not a mesh.");return this.client.advanced.runtime.ticketMeshIssuerNode(this.id)}get peers(){if(this.scopedPeers)return this.scopedPeers;let t=this.client.peers,i=`ticket:${this.id}`,n=r=>!this.closed&&r.scopes.includes(i)&&r.status==="connected"&&r.settledReady===true&&r.routable!==false&&r.logicalSessionTerminal!==true&&(!this.ownsMesh||this.client.advanced.runtime.isTicketMeshPeerReady(this.id,r)),s=(r,o)=>{let c=[],d=this.ownsMesh?this.client.advanced.runtime.watchTicketMeshPeers(this.id,()=>o(c.filter(n))):()=>{},h=t[r](l=>{c=l,o(l.filter(n));});return ()=>{h(),d();}};return this.scopedPeers={...t,watch:r=>s("watch",r),watchLifecycle:r=>s("watchLifecycle",r),get:r=>{let o=t.get(r);return o&&n(o)?o:void 0},listConnected:()=>t.listConnected().filter(n)}}get diagnostics(){if(this.scopedDiagnostics)return this.scopedDiagnostics;let t=this.client.diagnostics,i=`ticket:${this.id}`;return this.scopedDiagnostics={...t,capture:n=>c(s=>this.client.advanced.runtime.watchPeerStates(r=>s(this.closed?[]:r.filter(o=>o.scopes.includes(i)))),n),watchConnectionMetrics:n=>t.watchConnectionMetrics(s=>{n(this.closed?[]:s.filter(r=>r.scopes?.includes(i)));})}}close(){if(this.retired)return Promise.resolve();if(this.closing)return this.closing;this.fenceProductAccess();let t=this.closeOnce();return this.closing=t,t.catch(()=>{!this.retired&&this.closing===t&&(this.closing=null);}),t}async closeOnce(){this.ownsMesh&&!this.meshStopped&&(await this.client.advanced.runtime.closeTicketMesh(this.id),this.meshStopped=true),await super.close();}beforeRuntimeShutdown(){try{this.stopInviteWatch(),this.stopInviteWatch=()=>{};}finally{this.inviteListeners.clear();}}},M=class M{constructor(e,t){this.options=e;this.internals=t;this.diagnosticClientRef=++M.nextDiagnosticClient;this.nextDiagnosticOperation=0;this.channels=new G;this.broadcastSessions=new Set;this.broadcastPublishers=new Set;this.handles=new Set;this.activations=new Map;this.pendingCapabilityShutdowns=new Map;this.authorityCallableIds=new WeakMap;this.nextAuthorityCallableId=1;this.closed=false;this.closing=null;this.offline={support:async()=>(this.assertOpen(),this.internals.offlineSupport?.()??{provisioning:false,localMesh:false,cloudRequired:false,reason:"Browser-only OpenRTC cannot host the native LAN/Iroh offline runtime."}),createEnrollmentRequest:async e=>{if(this.assertOpen(),!this.internals.createOfflineEnrollmentRequest)throw new Error("[OpenRTC] Offline enrollment request signing requires a native Rust host.");return this.internals.createOfflineEnrollmentRequest({trustDomain:e.trustDomain,deviceId:await this.deviceId(),requestedRoles:e.requestedRoles})}};this.devices={localId:()=>(this.assertOpen(),this.deviceId()),start:(e={})=>{let t=e.auth??this.options.auth;return this.activateOnce("devices",JSON.stringify({autoConnect:e.autoConnect??"online",autoConnectExcludedDeviceIds:oe(e.autoConnectExcludedDeviceIds),maxPeers:e.maxPeers??null,advancedFanout:e.advancedFanout===true,profile:e.profile??null}),t,()=>this.startDevices(e))},listEnrolled:async(e={})=>{this.assertOpen();let t=e.auth??this.options.auth;if(!t)throw new Error("[OpenRTC] devices.listEnrolled() requires an auth provider.");let i=await(await this.controlPlane()).listEnrolledDevices(t,await this.deviceId()),{DeviceHandle:n}=await import('./deviceHandle-2QAMK7MC.js');for(let s of this.handles)s instanceof n&&s.replaceEnrolledDevices(i);return i},revoke:async(e,t={})=>{this.assertOpen();let i=t.auth??this.options.auth;if(!i)throw new Error("[OpenRTC] devices.revoke() requires an auth provider.");let n=re(e),s=await this.deviceId();await(await this.controlPlane()).revokeDevice(i,s,n);let{DeviceHandle:r}=await import('./deviceHandle-2QAMK7MC.js');for(let o of this.handles)o instanceof r&&o.removeEnrolledDevice(n);n===s&&this.retireAuthCapabilities(i);},revokeAll:async(e={})=>{this.assertOpen();let t=e.auth??this.options.auth;if(!t)throw new Error("[OpenRTC] devices.revokeAll() requires an auth provider.");if(await(await this.controlPlane()).revokeAllDevices(t,await this.deviceId(),e.exceptCurrent===true),e.exceptCurrent===true){let i=await this.deviceId(),{DeviceHandle:n}=await import('./deviceHandle-2QAMK7MC.js');for(let s of this.handles)s instanceof n&&s.retainCurrentEnrolledDevice(i);}e.exceptCurrent!==true&&this.retireAuthCapabilities(t);}};this.spaces={join:(e,t={})=>this.activateOnce(`space:${f(e)}`,JSON.stringify({payload:t.payload??"reliable",identity:t.identity??null,maxPeers:t.maxPeers??null,advancedFanout:t.advancedFanout===true}),void 0,()=>this.joinSpace(e,t))};this.rooms={join:async(e,t={})=>(await import('./room-7KFI2WBG.js')).joinRoom(this,e,t)};this.tickets={issue:(e,t={})=>this.activateOnce(`ticket:${f(e)}`,be(t),void 0,()=>this.issueTicket(e,t),t.mesh===true?()=>ae(f(e)):void 0),join:e=>{let t=b$4(e);return t.mesh?this.activateOnce(`ticket:${f(t.id)}`,`join:${e}`,void 0,()=>this.joinTicket(e),()=>ae(f(t.id))):Promise.reject(d(a.TICKET_INVITE_INVALID,"[OpenRTC] This invitation does not describe a ticket mesh.",{retryable:false,plane:"admission"}))}};this.liveSession=null;this.liveRetirementConfirmed=false;this.liveOpening=null;this.live={open:async e=>{if(this.assertOpen(),this.liveOpening||this.liveSession&&!this.liveRetirementConfirmed)throw new Error("[OpenRTC] A live session is already active on this root.");if(!e||typeof e.credentials!="function"||!this.internals.liveHostFactory)throw new Error("[OpenRTC] Live coordination requires an app credential provider and a supported host.");let t={canceled:false,retirementUnconfirmed:false,host:void 0};this.liveOpening=t;try{let i=new URL("/v3/live",(this.internals.endpoints??a$2).gateway).toString(),n=await this.internals.liveHostFactory(i,this.internals.testingAllowInsecureLoopback===!0);if(t.host=n,t.canceled)throw await n.close(),new Error("[OpenRTC] Live activation was closed.");if(await n.open(e),t.canceled)throw await n.close(),new Error("[OpenRTC] Live activation was closed.");let s=new Set,r=new Set,o=l=>{try{l();}catch{}},c=n.onEvent(l=>{if(l.type==="message")for(let p of s)o(()=>p(Object.freeze({channel:l.channel,from:l.from,data:l.data})));if(l.type==="closed"){this.liveSession===h&&(this.liveRetirementConfirmed=!0);for(let p of r)o(p);s.clear(),r.clear();}}),d=l=>{if(typeof l!="string"||!/^[A-Za-z0-9_.:@/-]{1,128}$/.test(l))throw new Error("[OpenRTC] Invalid live channel.");return l},h={get closed(){return n.closed},renew:()=>n.renew(),subscribe:async l=>{await n.request({type:"subscribe",channel:d(l)});},unsubscribe:async l=>{await n.request({type:"unsubscribe",channel:d(l)});},publish:async(l,p)=>{if(typeof p!="string"||new TextEncoder().encode(p).byteLength>65536)throw new Error("[OpenRTC] Live publication exceeds 64 KiB.");let m=await n.request({type:"publish",channel:d(l),data:p});if(!Number.isSafeInteger(m.units)||m.units<1)throw new Error("[OpenRTC] Invalid live publication receipt.");return {units:m.units}},onMessage:l=>(n.closed||s.add(l),()=>{s.delete(l);}),onClose:l=>(n.closed?o(l):r.add(l),()=>{r.delete(l);}),close:async()=>{await n.close(),this.liveSession===h&&(this.liveRetirementConfirmed=!0),c(),s.clear(),r.clear();}};return this.liveSession=h,this.liveRetirementConfirmed=!1,h}catch(i){try{await t.host?.close();}catch(n){throw t.retirementUnconfirmed=true,n}throw i}finally{this.liveOpening===t&&!t.retirementUnconfirmed&&(this.liveOpening=null);}}};this.broadcasts={create:async e=>{this.assertOpen();let t=await this.broadcastHost();if(!t?.create)throw new Error("[OpenRTC] Managed broadcast creation is unavailable.");return t.create(e)},open:async e=>{this.assertOpen(),this.validateBroadcastGrant(e);let t=await this.broadcastHost();if(!t)throw new Error("[OpenRTC] Broadcast hosting is unavailable in this runtime.");return this.wrapBroadcastSession(await t.open(e))},subscribe:async e=>{this.assertOpen(),this.validateBroadcastGrant(e);let t=await this.broadcastHost();if(!t)throw new Error("[OpenRTC] Broadcast viewing is unavailable.");return this.wrapBroadcastSession(await t.open(e))},preparePublisher:async()=>{this.assertOpen();let e=await this.broadcastHost();if(!e?.preparePublisher)throw new Error("[OpenRTC] Broadcast publishing is unavailable in this runtime.");let t=await e.preparePublisher(),i=t.verificationKey.slice();if(i.byteLength!==32)throw await t.close(),new Error("[OpenRTC] Broadcast publisher key is invalid.");let n=false,s={verificationKey:i,open:async r=>{if(n)throw new Error("[OpenRTC] Broadcast publisher is closed.");return this.assertOpen(),this.validateBroadcastGrant(r),this.wrapBroadcastSession(await t.open(r))},close:async()=>{n||(n=true,await t.close(),this.broadcastPublishers.delete(s));}};return this.broadcastPublishers.add(s),s},renew:async(e,t={})=>{this.validateBroadcastGrant(e);let i=await this.broadcastHost();if(!i?.renew)throw new Error("[OpenRTC] Broadcast renewal is unavailable.");return i.renew(e,t.auth)},invite:async(e,t)=>{this.validateBroadcastGrant(e);let i=await this.broadcastHost();if(!i?.invite)throw new Error("[OpenRTC] Broadcast invitations are unavailable.");let{auth:n,...s}=t;return i.invite(e,s,n)},accept:async(e,t={})=>{if(!/^obi1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(e))throw new Error("[OpenRTC] Broadcast invitation is invalid.");let i=await this.broadcastHost();if(!i?.accept)throw new Error("[OpenRTC] Broadcast invitation acceptance is unavailable.");return i.accept(e,t.auth)},revoke:async(e,t)=>{if(this.validateBroadcastGrant(e),!/^obi1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(t.invite))throw new Error("[OpenRTC] Broadcast invitation is invalid.");let i=await this.broadcastHost();if(!i?.revoke)throw new Error("[OpenRTC] Broadcast revocation is unavailable.");await i.revoke(e,t.invite,t.auth);},leave:async(e,t={})=>{this.validateBroadcastGrant(e);let i=await this.broadcastHost();if(!i?.leave)throw new Error("[OpenRTC] Broadcast leave is unavailable.");await i.leave(e,t.auth);},close:async(e,t={})=>{this.validateBroadcastGrant(e);let i=await this.broadcastHost();if(!i?.closeGrant)throw new Error("[OpenRTC] Broadcast close is unavailable.");await i.closeGrant(e,t.auth);}};this.onClosed=e=>{this.handles.delete(e);for(let[t,i]of this.activations)i.handle===e&&this.activations.delete(t);};this.apiKey="profile"in e&&e.profile==="live"?"":ge(e.apiKey??"");let i=e.trust?.browserPersistence??"session";if(i!=="session"&&i!=="persistent")throw new Error("[OpenRTC] Invalid browser identity persistence policy.");this.browserPersistence=i,this.appTag=this.apiKey?`app_${this.apiKey.slice(-16)}`:"";}validateBroadcastGrant(e){if(typeof e!="string"||e.length<16||e.length>32768)throw new Error("[OpenRTC] Broadcast grant is invalid.")}broadcastHost(){return this.internals.broadcastHost?Promise.resolve(this.internals.broadcastHost):this.internals.broadcastHostFactory?this.broadcastHostPromise??(this.broadcastHostPromise=this.controlPlane().then(e=>this.internals.broadcastHostFactory({apiKey:this.apiKey,resolve:(t,i)=>e.resolveBroadcastAccess(t,i),manage:e.manageBroadcast.bind(e),deviceId:()=>this.deviceId(),defaultAuth:this.options.auth}))):Promise.resolve(void 0)}wrapBroadcastSession(e){let t=false,i={get id(){return e.id},get role(){return e.role},get state(){return e.state},media:e.media,getStats:()=>e.getStats(),close:async()=>{t||(t=true,this.broadcastSessions.delete(i),await e.close());}};return this.broadcastSessions.add(i),i}makeControlPlane(e){return Promise.all([import('./controlPlane-HOFWXQJW.js'),e]).then(([{ControlPlane:t},i])=>new t(this.apiKey,this.internals.endpoints??a$2,i,this.options.trust?.attestation,{onAuthEpochChanged:n=>this.retireAuthCapabilities(n)},this.options.trust?.botVerification,this.rootClientKey()))}rootClientKey(){return this.rootClientKeyPromise??(this.rootClientKeyPromise=this.internals.deviceKeyProvider?.getRootClientKey?this.internals.deviceKeyProvider.getRootClientKey(this.appTag):import('./deviceKey-4DLS246L.js').then(({createSessionDeviceKeyProvider:e})=>e().getOrCreate(this.appTag)))}controlPlane(){if("profile"in this.options&&this.options.profile==="live")throw new Error("[OpenRTC] This live-only root does not activate managed devices, rooms or peers.");return this.controlPlanePromise??(this.controlPlanePromise=this.makeControlPlane(this.internals.deviceKeyProvider?Promise.resolve(this.internals.deviceKeyProvider):import('./deviceKey-4DLS246L.js').then(({browserDeviceKeyProvider:e,createSessionDeviceKeyProvider:t})=>this.internals.platform!=="native"&&this.browserPersistence!=="persistent"?t():e)))}sessionPlane(){if("profile"in this.options&&this.options.profile==="live")throw new Error("[OpenRTC] This live-only root does not activate managed devices, rooms or peers.");return this.sessionPlanePromise??(this.sessionPlanePromise=this.makeControlPlane(import('./deviceKey-4DLS246L.js').then(({createSessionDeviceKeyProvider:e})=>e())))}assertOpen(){if(this.closed)throw new Error("[OpenRTC] Client is closed.");if(this.closing)throw new Error("[OpenRTC] Client is closing.")}activateOnce(e,t,i,n,s){this.assertOpen();let r=this.activations.get(e);if(r){if(r.handle?.closed)throw new Error(`[OpenRTC] ${e} is closing; retry close() to finish retirement.`);if(r.fingerprint!==t||r.auth!==i)throw s?s():new Error(`[OpenRTC] ${e} is already active with different options.`);return r.promise}let o={fingerprint:t,auth:i},c=this.options.diagnostics?.logger,d=c?performance.now():0,h=c?++this.nextDiagnosticOperation:0,l=e.split(":",1)[0],p=["devices","space","room","ticket"].includes(l)?l:"custom",m=u=>{c&&b$6(c,Object.freeze({sdkVersion:a$4,clientRef:this.diagnosticClientRef,name:"capability.activation",operationRef:h,avenue:p,outcome:u,timestampMs:Date.now(),elapsedMs:performance.now()-d}));},w;try{w=this.pendingCapabilityShutdowns.has(e)?this.settlePendingCapabilityShutdown(e).then(n):n();}catch(u){throw m("started"),m("failed"),u}let P=w.then(u=>(o.handle=u,m("succeeded"),u)).catch(u=>{throw m("failed"),this.activations.get(e)===o&&this.activations.delete(e),u});return o.promise=P,this.activations.set(e,o),m("started"),P}retainPendingCapabilityShutdown(e,t){this.pendingCapabilityShutdowns.has(e)||this.pendingCapabilityShutdowns.set(e,t);}async settlePendingCapabilityShutdown(e){let t=this.pendingCapabilityShutdowns.get(e);t&&(await t(),this.pendingCapabilityShutdowns.get(e)===t&&this.pendingCapabilityShutdowns.delete(e));}authorityCallableId(e){let t=this.authorityCallableIds.get(e);if(t)return t;let i=this.nextAuthorityCallableId++;return this.authorityCallableIds.set(e,i),i}retireAuthCapabilities(e){for(let t of this.activations.values())t.auth===e&&t.promise.then(i=>i.close()).catch(()=>{});}async deviceId(){let e=this.internals.deviceIdProvider?await this.internals.deviceIdProvider(this.appTag):this.internals.platform!=="native"&&this.browserPersistence==="session"?this.sessionDeviceId??(this.sessionDeviceId=crypto.randomUUID()):Ce(this.appTag);return re(e)}runtimeOptions(e){let t=this.options.transports,i=e.irohRelay&&t?.relay!==false,n=e.managedTurn&&t?.relay!==false,s=t?.privacy==="relay-only";if(s&&!i)throw new Error("[OpenRTC] transports.privacy: relay-only requires relay access.");let r=s?d$1(t?.priority?[...t.priority]:void 0,true):t?.priority?[...t.priority]:void 0,o=t?.webrtc,c=typeof o=="object"&&o.iceServers?.some(b$5)===true,d=!s||n||c;return {apiKey:this.apiKey,authMode:"external",discoveryMode:e.avenue?.kind==="user"?"user-scoped":"space",space:e.avenue?.id,localDeviceId:e.deviceId,deviceIdPersistence:"persistent",endpointIdPersistence:this.internals.platform==="native"?"persistent":"ephemeral",deviceName:e.deviceName?.trim()||void 0,coordinationPlatformType:e.devicePlatform?.trim()||void 0,initialAutoConnectExcludedDeviceIds:e.initialAutoConnectExcludedDeviceIds,nativeIdentityProvider:this.internals.platform==="native"&&e.nativeAuth?{providerId:e.nativeAuth.providerId,getSessionKey:async()=>e.nativeAuth.getSessionKey?.()??null,getAssertion:h=>e.nativeAuth.getAssertion(h)}:void 0,coordinationAvenueOverride:e.avenue,coordinationRoomGossipFanout:e.roomGossipFanout===true,coordinationRoomArchitecture:e.roomArchitecture,coordinationDevicePublicKeyX:e.devicePublicKeyX,coordinationDeviceSign:e.deviceSign,coordinationGateway:{endpoint:(this.internals.endpoints??a$2).gateway,environment:"production",grantProvider:e.grantProvider,onServiceError:this.options.onServiceError,testingAllowInsecureLoopback:this.internals.testingAllowInsecureLoopback},turnCredentialsProvider:n?e.turnProvider:void 0,transports:{relay:i,iroh:s?{relayOnly:true,relayTransportPolicy:"websocketRequired",localDiscovery:false,persistenceMode:this.internals.platform==="native"?"persistent":"ephemeral",...this.internals.irohTestRelayUrl?{testRelayUrl:this.internals.irohTestRelayUrl}:{}}:this.internals.irohTestRelayUrl?{testRelayUrl:this.internals.irohTestRelayUrl,persistenceMode:this.internals.platform==="native"?"persistent":"ephemeral"}:t?.iroh??true,webrtc:d?typeof o=="object"?s?{...o,privacyMode:true,useTurn:true,useDefaultIceServers:false}:o:o===true?s?{privacyMode:true,useTurn:true,useDefaultIceServers:false}:true:false:false,ble:t?.ble??false,moq:i?t?.moq??false:false,privacy:t?.privacy??"direct",optimizeFor:t?.optimizeFor??"balanced",priority:r},transportPriority:r}}async activate(e){let t=e.authority?null:e.controlPlane??await this.controlPlane(),i=this.options.transports?.relay!==false,n=e.source.irohRelay&&i,s=e.source.managedTurn&&i,r={irohRelay:n,managedTurn:s,moq:n&&!!this.options.transports?.moq,ble:this.options.transports?.ble===true,advancedFanout:e.architecture==="sparse"||e.advancedFanout===true,durableMembership:e.durableMembership===true},o=e.source,c=null,d=()=>e.authority?{userId:e.principalId}:{userId:e.principalId,token:o.token,tokenProvider:async()=>o.token,expiresAtMs:o.expiresAtMs},h=e.authority?.devicePublicKeyX??String((await t.deviceSigningPublicKey()).x??""),l=e.authority,p=l?async u=>{let{rootClientProof:de}=await import('./deviceKey-4DLS246L.js'),he=await de(await this.rootClientKey(),["authority-service-grant",this.appTag,u.avenue.id,l.serviceId,String(l.generation),[...l.shardIds].sort().join(","),l.assignmentPublicKeyX,u.deviceId,u.runtimeInstanceId,u.ticketFingerprint]);return l.grantProvider({...u,rootProof:he})}:void 0,m=this.runtimeOptions({avenue:e.source.avenue,grantProvider:p??t.grantProvider(e.source,{maxPeers:e.maxPeers,features:r,architecture:e.architecture,roomDelivery:e.kind==="room"?e.defaultDelivery:void 0,deviceProfile:e.deviceName&&e.devicePlatform?{name:e.deviceName,platform:e.devicePlatform}:void 0,onSourceRenewed:async u=>{o={...o,...u},await c?.setAuth(d());}}),deviceId:e.deviceId,userId:e.principalId,roomGossipFanout:(e.kind==="room"||e.kind==="space")&&(e.architecture==="sparse"||e.advancedFanout===true),roomArchitecture:e.kind==="room"?e.architecture:void 0,devicePublicKeyX:h,deviceSign:e.authority?.deviceSign??(u=>t.signDeviceBytes(u)),irohRelay:e.source.irohRelay,managedTurn:e.source.managedTurn,turnProvider:s&&t?t.turnProvider(()=>o):void 0,deviceName:e.deviceName,devicePlatform:e.devicePlatform,initialAutoConnectExcludedDeviceIds:e.initialAutoConnectExcludedDeviceIds,nativeAuth:e.nativeAuth}),[w,{wrapAssembly:P}]=await Promise.all([this.internals.runtimeFactory(m),import('./coreClient.js')]);c=P(w,this.internals.platform==="native"?"native":"web"),await c.setAuth(d()),this.channels.attach(c,e.defaultDelivery??"reliable");try{await c.devices.startSession({browserTrustPersistence:this.browserPersistence,sessionKind:e.kind==="devices"?"app-user-device":"scoped-guest",scope:`v2:${e.kind}:${e.id}`,userId:e.principalId,localDeviceId:e.deviceId,metadata:e.deviceMetadata,autoConnectPolicy:e.autoConnect?"enabled":"disabled",presencePolicy:"online"});}catch(u){throw this.channels.detach(c),await c.advanced.runtime.shutdown().catch(()=>{}),u}return c}trackHandle(e){return this.handles.add(e),e}async startDevices(e={}){this.assertOpen();let t=oe(e.autoConnectExcludedDeviceIds),i=e.auth??this.options.auth;if(!i)throw new Error("[OpenRTC] devices.start() requires an auth provider.");let n=await this.deviceId(),{resolveDeviceProfile:s}=await import('./deviceProfile-CR2C7OYR.js'),r=s(e.profile,this.internals.platform==="native"?"native":"web"),o=await this.controlPlane(),c=await o.deviceCertificate(i,n,void 0,r),d=await this.activate({kind:"devices",id:c.principalId,source:c.source,principalId:c.principalId,deviceId:n,maxPeers:e.maxPeers,autoConnect:e.autoConnect!=="none",initialAutoConnectExcludedDeviceIds:t,advancedFanout:e.advancedFanout,deviceName:r.name,devicePlatform:r.platform,deviceMetadata:r.metadata,nativeAuth:i}),h=[];if(this.internals.platform!=="native")try{h=await o.listEnrolledDevices(i,n);}catch(w){throw this.channels.detach(d),await d.advanced.runtime.shutdown().catch(()=>{}),w}let{AuthenticatedDeviceRoster:l}=await import('./deviceRoster-EUF6BBF5.js'),{DeviceHandle:p}=await import('./deviceHandle-2QAMK7MC.js'),m;return m=new p(c.principalId,d,()=>{this.channels.detach(d),this.onClosed(m);},new l(h)),this.handles.add(m),m}async joinSpace(e,t={}){this.assertOpen();let i=f(e),n=await(t.identity==="session"?this.sessionPlane():this.controlPlane()),s=await n.capability("space",i,t.maxPeers,t.advancedFanout),r=String(b$1(s.token).principalId),o=await this.activate({kind:"space",id:i,source:s,principalId:r,deviceId:N(s),maxPeers:t.maxPeers,autoConnect:true,defaultDelivery:t.payload??"reliable",advancedFanout:t.advancedFanout,controlPlane:n}),c;return c=new q(i,o,()=>{this.channels.detach(o),this.onClosed(c);},t.payload??"reliable"),this.handles.add(c),c}async openAuthorityRoom(e){return (await import('./room-7KFI2WBG.js')).openAuthorityRoom(this,e)}async issueTicket(e,t={}){this.assertOpen();let i=f(e);if(t.mesh===true&&t.advancedFanout===true)throw d(a.TICKET_MESH_INVALID_OPTIONS,"[OpenRTC] Ticket mesh cannot use advancedFanout.",{retryable:false,plane:"admission"});let n=le(t);if(t.mesh===true&&(!Number.isSafeInteger(n)||n<ne||n>U))throw d(a.TICKET_MESH_INVALID_OPTIONS,`[OpenRTC] Ticket mesh maxPeers must be an integer between ${ne} and ${U}.`,{retryable:false,plane:"admission"});let s=await(t.identity==="session"||t.mesh===true?this.sessionPlane():this.controlPlane()),r=await s.capability("ticket",i,n,t.advancedFanout),o=String(b$1(r.token).principalId),c=await this.activate({kind:"ticket",id:i,source:r,principalId:o,deviceId:N(r),maxPeers:n,autoConnect:false,advancedFanout:t.advancedFanout,controlPlane:s}),d$1=null;if(t.mesh===true)try{d$1=await c.advanced.runtime.issueTicketMesh(i,n);}catch(l){await this.shutdownFailedTicketActivation(i,c,l);}let h;return h=new D(i,c,()=>{this.channels.detach(c),this.onClosed(h);},r.token,d$1,t.mesh===true),this.handles.add(h),h}async joinTicket(e){this.assertOpen();let t=b$4(e);if(!t.mesh)throw d(a.TICKET_INVITE_INVALID,"[OpenRTC] This invitation does not describe a ticket mesh.",{retryable:false,plane:"admission"});let i=f(t.id),n=await this.sessionPlane(),s=await n.capability("ticket",i,t.maxPeers,false),r=String(b$1(s.token).principalId),o=await this.activate({kind:"ticket",id:i,source:s,principalId:r,deviceId:N(s),maxPeers:t.maxPeers,autoConnect:false,advancedFanout:false,controlPlane:n});try{await o.advanced.runtime.joinTicketMesh(e);}catch(d){await this.shutdownFailedTicketActivation(i,o,d);}let c;return c=new D(i,o,()=>{this.channels.detach(o),this.onClosed(c);},s.token,e,true),this.handles.add(c),c}async shutdownFailedTicketActivation(e,t,i){this.channels.detach(t);try{await t.advanced.runtime.shutdown();}catch(n){throw this.retainPendingCapabilityShutdown(`ticket:${e}`,()=>t.advanced.runtime.shutdown()),d(a.TICKET_MESH_UNAVAILABLE,"[OpenRTC] Ticket mesh startup failed and runtime teardown was not confirmed.",{retryable:true,plane:"coordination",cause:{startError:i,shutdownError:n}})}throw i}async close(){if(this.closed)return;if(this.closing)return this.closing;let e=this.closeOnce();this.closing=e;try{await e;}finally{this.closing===e&&(this.closing=null);}}async closeOnce(){if(this.liveOpening){let e=this.liveOpening;e.canceled=true,await e.host?.close(),this.liveOpening===e&&(this.liveOpening=null);}await this.liveSession?.close(),await Promise.allSettled([...this.activations.values()].map(({promise:e})=>e)),await Promise.all([...this.handles].map(e=>e.close())),await Promise.all([...this.pendingCapabilityShutdowns.keys()].map(e=>this.settlePendingCapabilityShutdown(e))),await Promise.all([...this.broadcastSessions].map(e=>e.close())),await Promise.all([...this.broadcastPublishers].map(e=>e.close())),await Promise.all([this.controlPlanePromise,this.sessionPlanePromise].map(e=>e?.then(t=>t.dispose(),()=>{}))),this.activations.clear(),this.broadcastSessions.clear(),this.broadcastPublishers.clear(),await this.broadcastHostPromise?.then(e=>e?.close?.(),()=>{}),await this.internals.broadcastHost?.close?.(),await this.internals.close?.(),this.closed=true;}};M.nextDiagnosticClient=0;var k=M;function _e(a,e){return new k(a,e)}function Fe(a,e){if(!(a instanceof k))throw new TypeError("[OpenRTC] ServiceNode requires a client created by this OpenRTC package.");return a.openAuthorityRoom(e)}export{S as a,x as b,ve as c,Le as d,f as e,re as f,N as g,E as h,_e as i,Fe as j};
@@ -1 +1 @@
1
- var w="3.1.2";function R(t,o){if(t)try{Promise.resolve(t(o)).catch(()=>{});}catch{}}var y=new Set(["transport-healthy","missing-active-transport","native-main-route-pending","session-admission-pending","application-crypto-key-pending","application-crypto-confirmation-pending","bounded-health-confirmation-pending","authoritative-device-binding-pending","device-offline","manual-disconnect","waiting-for-transport","transport-attached-awaiting-readiness-confirmation","transport-connected-health-check-pending","readiness-confirmation-timed-out","transport-closed","connection-failed"]),_=new Set(["user-device","persistent","trusted-device","ticket","room","space","share","drive-grant"]),O=new Set(["connected","connecting","disconnected","failed","closed"]),P=new Set(["unknown","pending","admitted","rejected","expired"]),x=new Set(["iroh","iroh-quic","iroh-lan","iroh-relay","webrtc","moq","ble"]),g=t=>Number.isSafeInteger(t)&&t>=0?t:null;function k(t,o={}){let a=o.maxEvents??256;if(!Number.isInteger(a)||a<1||a>1024)throw new RangeError("Diagnostic maxEvents must be an integer between 1 and 1024");let h=Date.now(),S=performance.now(),r=new Map,c=new Map,d=[],D=0,f=0,p=false,v=false,b=(s,n)=>{let e=Object.freeze({sequence:++D,timestampMs:Date.now(),elapsedMs:performance.now()-S,level:n.hasError||n.state==="failed"?"warn":n.ready?"info":"debug",name:s,peer:Object.freeze({...n,scopeKinds:Object.freeze([...n.scopeKinds])})});d.length===a&&(d.shift(),f++),d.push(e),R(o.logger,e);},E=t(s=>{if(p)return;let n=new Map;for(let e of s){let i=r.get(e.peerId);if(!i){if(r.size===64){v=true;continue}i=`peer-${r.size+1}`,r.set(e.peerId,i);}let m=e.readinessReason==="manual disconnect"?"manual-disconnect":e.readinessReason,l={peerRef:i,state:O.has(e.status)?e.status:"unknown",admission:e.admissionState&&P.has(e.admissionState)?e.admissionState:"unknown",ready:e.settledReady===true,readinessCode:m&&y.has(m)?m:"unclassified",scopeKinds:[...new Set(e.scopes.map(u=>u.split(":",1)[0]).map(u=>_.has(u)?u:"custom"))].sort(),transportGeneration:g(e.transportGeneration),routeGeneration:g(e.routeGeneration),transportStableId:g(e.transportStableId??void 0),transport:e.activeTransport&&x.has(e.activeTransport)?e.activeTransport:"unknown",hasError:!!e.error};n.set(i,l),JSON.stringify(c.get(i))!==JSON.stringify(l)&&b("peer.changed",l);}for(let[e,i]of c)n.has(e)||b("peer.removed",{...i,ready:false,state:"disconnected"});c=n;});return {snapshot:()=>({schemaVersion:1,sdkVersion:w,startedAtMs:h,stopped:p,droppedEvents:f,peerLimitReached:v,events:d.map(s=>({...s,peer:{...s.peer,scopeKinds:[...s.peer.scopeKinds]}}))}),stop:()=>{p||(p=true,E(),r.clear(),c.clear());}}}export{w as a,R as b,k as c};
1
+ var w="3.1.3";function R(t,o){if(t)try{Promise.resolve(t(o)).catch(()=>{});}catch{}}var y=new Set(["transport-healthy","missing-active-transport","native-main-route-pending","session-admission-pending","application-crypto-key-pending","application-crypto-confirmation-pending","bounded-health-confirmation-pending","authoritative-device-binding-pending","device-offline","manual-disconnect","waiting-for-transport","transport-attached-awaiting-readiness-confirmation","transport-connected-health-check-pending","readiness-confirmation-timed-out","transport-closed","connection-failed"]),_=new Set(["user-device","persistent","trusted-device","ticket","room","space","share","drive-grant"]),O=new Set(["connected","connecting","disconnected","failed","closed"]),P=new Set(["unknown","pending","admitted","rejected","expired"]),x=new Set(["iroh","iroh-quic","iroh-lan","iroh-relay","webrtc","moq","ble"]),g=t=>Number.isSafeInteger(t)&&t>=0?t:null;function k(t,o={}){let a=o.maxEvents??256;if(!Number.isInteger(a)||a<1||a>1024)throw new RangeError("Diagnostic maxEvents must be an integer between 1 and 1024");let h=Date.now(),S=performance.now(),r=new Map,c=new Map,d=[],D=0,f=0,p=false,v=false,b=(s,n)=>{let e=Object.freeze({sequence:++D,timestampMs:Date.now(),elapsedMs:performance.now()-S,level:n.hasError||n.state==="failed"?"warn":n.ready?"info":"debug",name:s,peer:Object.freeze({...n,scopeKinds:Object.freeze([...n.scopeKinds])})});d.length===a&&(d.shift(),f++),d.push(e),R(o.logger,e);},E=t(s=>{if(p)return;let n=new Map;for(let e of s){let i=r.get(e.peerId);if(!i){if(r.size===64){v=true;continue}i=`peer-${r.size+1}`,r.set(e.peerId,i);}let m=e.readinessReason==="manual disconnect"?"manual-disconnect":e.readinessReason,l={peerRef:i,state:O.has(e.status)?e.status:"unknown",admission:e.admissionState&&P.has(e.admissionState)?e.admissionState:"unknown",ready:e.settledReady===true,readinessCode:m&&y.has(m)?m:"unclassified",scopeKinds:[...new Set(e.scopes.map(u=>u.split(":",1)[0]).map(u=>_.has(u)?u:"custom"))].sort(),transportGeneration:g(e.transportGeneration),routeGeneration:g(e.routeGeneration),transportStableId:g(e.transportStableId??void 0),transport:e.activeTransport&&x.has(e.activeTransport)?e.activeTransport:"unknown",hasError:!!e.error};n.set(i,l),JSON.stringify(c.get(i))!==JSON.stringify(l)&&b("peer.changed",l);}for(let[e,i]of c)n.has(e)||b("peer.removed",{...i,ready:false,state:"disconnected"});c=n;});return {snapshot:()=>({schemaVersion:1,sdkVersion:w,startedAtMs:h,stopped:p,droppedEvents:f,peerLimitReached:v,events:d.map(s=>({...s,peer:{...s.peer,scopeKinds:[...s.peer.scopeKinds]}}))}),stop:()=>{p||(p=true,E(),r.clear(),c.clear());}}}export{w as a,R as b,k as c};
@@ -1,2 +1,2 @@
1
- import {g,b,d as d$1,c}from'./chunk-XNJI6KCI.js';import {j,d as d$2,c as c$1}from'./chunk-RUOVYQ2P.js';var N=/^[A-Za-z0-9_.:@-]+$/,k=/^[A-Za-z0-9_-]{43}$/,_=/^[A-Za-z0-9_.:@-]+$/,G=/^[A-Za-z0-9._-]+$/,U=120*6e4,E=new TextEncoder;function d(r,e,t=160){let n=r.trim();if(!n||n.length>t||!N.test(n))throw new TypeError(`[OpenRTC] ${e} is invalid.`);return n}function u(r,e,t=Number.MAX_SAFE_INTEGER){if(!Number.isSafeInteger(r)||r<1||r>t)throw new RangeError(`[OpenRTC] ${e} must be a positive safe integer.`);return r}function M(r){let e="";for(let t of r)e+=String.fromCharCode(t);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}async function m(r,e){let t=await r.publicJwk();if(t.kty!=="OKP"||t.crv!=="Ed25519"||typeof t.x!="string"||!k.test(t.x)||t.d!==void 0)throw new TypeError(`[OpenRTC] ${e} must return an Ed25519 public JWK.`);return {kty:"OKP",crv:"Ed25519",x:t.x}}async function y(r,e,t){let n=await r.sign(e);if(!(n instanceof Uint8Array)||n.byteLength!==64)throw new TypeError(`[OpenRTC] ${t} returned an invalid Ed25519 signature.`);return M(n)}function J(r){if(!/^pk_(?:live|test)_[A-Za-z0-9]+$/.test(r))throw new TypeError("[OpenRTC] apiKey is invalid.");return `app_${r.slice(-16)}`}function l(r){return r!==null&&typeof r=="object"&&!Array.isArray(r)?r:null}function v(r,e,t,n){if(typeof r!="string"||r.length<1||r.length>t||r!==r.trim()||n&&!n.test(r))throw new Error(`[OpenRTC] authority service grant ${e} is invalid.`);return r}function L(r){let e=v(r,"gatewayUrl",2048),t;try{t=new URL(e);}catch{throw new Error("[OpenRTC] authority service grant gatewayUrl is invalid.")}let n=t.protocol==="http:"&&["127.0.0.1","localhost","::1"].includes(t.hostname.toLowerCase());if(t.protocol!=="https:"&&!n||t.username||t.password||t.search||t.hash)throw new Error("[OpenRTC] authority service grant gatewayUrl is invalid.");return e}function $(r,e){let t=l(r),n=l(t?.avenue),i=l(t?.roomAuthority),a=l(i?.assignmentPublicKeyJwk),c=Date.now(),o=t?.expiresAtMs,s=t?.maxPeers;if(!t||t.protocolVersion!==2||t.architecture!=="authority"||n?.kind!=="room"||n.id!==e.roomId||i?.serviceId!==e.serviceId||i.generation!==e.generation||!Array.isArray(i.shardIds)||i.shardIds.length!==e.shardIds.length||i.shardIds.some((g,h)=>g!==e.shardIds[h])||a?.kty!=="OKP"||a.crv!=="Ed25519"||a.x!==e.assignmentPublicKeyX||!Number.isSafeInteger(o)||o<=c||o>c+U||!Number.isSafeInteger(s)||s<1||s>e.maxPeers)throw new Error("[OpenRTC] authority service grant response is inconsistent.");return {protocolVersion:2,gatewayUrl:L(t.gatewayUrl),routeKey:v(t.routeKey,"routeKey",256,_),token:v(t.token,"token",24e3,G),expiresAtMs:o,avenue:{kind:"room",id:e.roomId},maxPeers:s,architecture:"authority",roomAuthority:{serviceId:e.serviceId,generation:e.generation,shardIds:[...e.shardIds],assignmentPublicKeyJwk:{kty:"OKP",crv:"Ed25519",x:e.assignmentPublicKeyX}}}}var p=class{constructor(e){if(this.apiKey=e.apiKey,this.applicationTag=J(e.apiKey),this.rootClientKey=g().getOrCreate(this.applicationTag),typeof e.grantIssuer!="function")throw new TypeError("[OpenRTC] ServiceNode requires a browser-safe grantIssuer.");if(this.grantIssuer=e.grantIssuer,this.serviceId=d(e.serviceId,"serviceId",80),this.generation=u(e.generation,"generation"),this.shardIds=[...new Set(e.shardIds.map(t=>d(t,"shardId",80)))].sort(),this.shardIds.length<1||this.shardIds.length>64||this.shardIds.length!==e.shardIds.length)throw new RangeError("[OpenRTC] shardIds must contain 1..64 unique identifiers.");this.deviceId=d(e.deviceId,"deviceId"),this.deviceSigner=e.deviceSigner,this.assignmentSigner=e.assignmentSigner;}async requestGrant(e){let t=d(e.roomId,"roomId"),n=d(e.runtimeInstanceId,"runtimeInstanceId");if(!k.test(e.ticketFingerprint))throw new TypeError("[OpenRTC] ticketFingerprint is invalid.");e.maxPeers!==void 0&&u(e.maxPeers,"maxPeers",50);let i=await m(this.assignmentSigner,"assignmentSigner.publicJwk()"),a=await m(this.deviceSigner,"deviceSigner.publicJwk()"),c$1=crypto.randomUUID().replace(/-/g,""),o=Math.floor(Date.now()/1e3),s=["authority-service-grant",this.applicationTag,t,this.serviceId,String(this.generation),this.shardIds.join(","),String(i.x),this.deviceId,n,e.ticketFingerprint],g=e.rootProof===void 0?await this.rootClientKey:void 0,h=e.rootProof??(g?await b(g,s):void 0),f=h?await d$1(h.publicKeyJwk):void 0,x=f?c(s,f,c$1,o):["openrtc:v2:authority-service-grant",this.applicationTag,t,this.serviceId,String(this.generation),this.shardIds.join(","),i.x,n,c$1,o].join(":"),T={avenue:{kind:"room",id:t},serviceId:this.serviceId,generation:this.generation,shardIds:this.shardIds,assignmentPublicKeyJwk:i,deviceId:this.deviceId,runtimeInstanceId:n,ticketFingerprint:e.ticketFingerprint,deviceProof:{publicKeyJwk:a,nonce:c$1,issuedAt:o,signature:await y(this.deviceSigner,E.encode(x),"deviceSigner.sign()")},...e.maxPeers===void 0?{}:{maxPeers:e.maxPeers},...e.refreshGrant?{refreshGrant:e.refreshGrant}:{},...h?{rootProof:h}:{},features:e.features??{}},O=`authority_${crypto.randomUUID().replace(/-/g,"")}`,D=await this.grantIssuer({apiKey:this.apiKey,idempotencyKey:O,body:T});return $(D,{roomId:t,serviceId:this.serviceId,generation:this.generation,shardIds:this.shardIds,assignmentPublicKeyX:i.x,maxPeers:e.maxPeers??50})}async devicePublicKey(){return m(this.deviceSigner,"deviceSigner.publicJwk()")}async assignmentPublicKey(){return m(this.assignmentSigner,"assignmentSigner.publicJwk()")}async signDeviceBytes(e){return y(this.deviceSigner,e,"deviceSigner.sign()")}async signAssignment(e){let t=e.ttlMs??6e4;u(t,"ttlMs",2*6e4);let n=d(e.shardId,"shardId",80);if(!this.shardIds.includes(n))throw new RangeError("[OpenRTC] assignment shard is not owned by this service.");let i=e.priorityDeviceIds??[],a=e.relevantEntityIds??[];if(i.length>8||a.length>32)throw new RangeError("[OpenRTC] assignment exceeds the 8-edge or 32-entity bound.");let c=Date.now(),o={policyVersion:"room-authority-assignment-v1",serviceId:this.serviceId,generation:this.generation,revision:u(e.revision,"revision"),subjectDeviceId:d(e.subjectDeviceId,"subjectDeviceId"),shardId:n,priorityDeviceIds:i.map(s=>d(s,"priorityDeviceId")),relevantEntityIds:a.map(s=>d(s,"relevantEntityId")),issuedAtMs:c,expiresAtMs:c+t};if(new Set(o.priorityDeviceIds).size!==o.priorityDeviceIds.length||new Set(o.relevantEntityIds).size!==o.relevantEntityIds.length)throw new RangeError("[OpenRTC] assignment identifiers must be unique.");return {assignment:o,signature:await y(this.assignmentSigner,E.encode(JSON.stringify(o)),"assignmentSigner.sign()")}}},I=class{constructor(e,t,n){this.room=e;this.authority=t;this.onClosed=n;this.releaseRuntimeAlias=d$2(this,e);}get kind(){return this.room.kind}get id(){return this.room.id}get peers(){return this.room.peers}get channels(){return this.room.channels}get diagnostics(){return this.room.diagnostics}get closed(){return this.room.closed}get membership(){return this.room.membership}get members(){return this.room.members}state(e){return this.room.state(e)}channel(e){return this.room.channel(e)}onConnection(e){return this.room.onConnection(e)}architecture(){return this.room.architecture()}onArchitectureChanged(e){return this.room.onArchitectureChanged(e)}authorityAssignment(){return this.room.authorityAssignment()}onAuthorityAssignmentChanged(e){return this.room.onAuthorityAssignmentChanged(e)}leave(){return this.retire(()=>this.room.leave())}close(){return this.retire(()=>this.room.close())}async publishAssignment(e){let t=await this.authority.signAssignment(e);return await c$1(this.room).advanced.runtime.publishAuthorityAssignment(t),t.assignment}retire(e){return this.retirement??(this.retirement=e().finally(()=>{this.releaseRuntimeAlias(),this.onClosed();}))}},K=class{constructor(e){this.options=e;this.rooms=new Map;this.connectionListeners=new Set;this.connectionCleanups=new Map;this.closed=false;if("secretKey"in e)throw new TypeError("[OpenRTC] ServiceNode never accepts secretKey; delegate short-lived grants.");this.authority=new p(e);}listen(e){if(this.closed)throw new Error("[OpenRTC] ServiceNode is closed.");let t=d(e,"roomId"),n=this.rooms.get(t);if(n)return n.promise;let i={};return i.promise=this.openRoom(t,()=>this.evictRoom(t,i)).catch(a=>{throw this.evictRoom(t,i),a}),this.rooms.set(t,i),i.promise}onConnection(e){if(this.connectionListeners.add(e),this.connectionListeners.size===1)for(let[t,n]of this.rooms)n.promise.then(i=>this.attachConnectionListener(t,i),()=>{});return ()=>{if(this.connectionListeners.delete(e),this.connectionListeners.size===0){for(let t of this.connectionCleanups.values())t();this.connectionCleanups.clear();}}}async close(){if(this.closed)return;this.closed=true;for(let t of this.connectionCleanups.values())t();this.connectionCleanups.clear();let e=await Promise.allSettled([...this.rooms.values()].map(t=>t.promise));await Promise.all(e.flatMap(t=>t.status==="fulfilled"?[t.value.close()]:[])),this.rooms.clear(),this.connectionListeners.clear();}async openRoom(e,t){let n=await this.options.client.devices.localId();if(n!==this.options.deviceId)throw new Error("[OpenRTC] ServiceNode deviceId must match the client installation.");let[i,a]=await Promise.all([this.authority.devicePublicKey(),this.authority.assignmentPublicKey()]),c=await j(this.options.client,{roomId:e,serviceId:this.options.serviceId,generation:this.options.generation,shardIds:this.options.shardIds,deviceId:n,maxPeers:this.options.maxPeers,irohRelay:this.options.irohRelay!==false,devicePublicKeyX:i.x,assignmentPublicKeyX:a.x,deviceSign:s=>this.authority.signDeviceBytes(s),grantProvider:async s=>{if(s.avenue.kind!=="room"||s.avenue.id!==e)throw new Error("[OpenRTC] ServiceNode grant request escaped its room.");if(s.deviceId!==n)throw new Error("[OpenRTC] ServiceNode grant request escaped its device.");return this.authority.requestGrant({roomId:e,runtimeInstanceId:s.runtimeInstanceId,ticketFingerprint:s.ticketFingerprint,rootProof:s.rootProof,maxPeers:this.options.maxPeers,refreshGrant:s.refreshGrant,features:{irohRelay:this.options.irohRelay!==false}})}}),o=new I(c,this.authority,t);return this.attachConnectionListener(e,o),o}evictRoom(e,t){this.rooms.get(e)===t&&(this.rooms.delete(e),this.connectionCleanups.get(e)?.(),this.connectionCleanups.delete(e));}attachConnectionListener(e,t){this.closed||this.connectionListeners.size===0||this.connectionCleanups.has(e)||this.connectionCleanups.set(e,t.onConnection(n=>{for(let i of this.connectionListeners)i({room:t,connection:n});}));}};
1
+ import {g,b,d as d$1,c}from'./chunk-XNJI6KCI.js';import {j,d as d$2,c as c$1}from'./chunk-3T57Y4EF.js';var N=/^[A-Za-z0-9_.:@-]+$/,k=/^[A-Za-z0-9_-]{43}$/,_=/^[A-Za-z0-9_.:@-]+$/,G=/^[A-Za-z0-9._-]+$/,U=120*6e4,E=new TextEncoder;function d(r,e,t=160){let n=r.trim();if(!n||n.length>t||!N.test(n))throw new TypeError(`[OpenRTC] ${e} is invalid.`);return n}function u(r,e,t=Number.MAX_SAFE_INTEGER){if(!Number.isSafeInteger(r)||r<1||r>t)throw new RangeError(`[OpenRTC] ${e} must be a positive safe integer.`);return r}function M(r){let e="";for(let t of r)e+=String.fromCharCode(t);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}async function m(r,e){let t=await r.publicJwk();if(t.kty!=="OKP"||t.crv!=="Ed25519"||typeof t.x!="string"||!k.test(t.x)||t.d!==void 0)throw new TypeError(`[OpenRTC] ${e} must return an Ed25519 public JWK.`);return {kty:"OKP",crv:"Ed25519",x:t.x}}async function y(r,e,t){let n=await r.sign(e);if(!(n instanceof Uint8Array)||n.byteLength!==64)throw new TypeError(`[OpenRTC] ${t} returned an invalid Ed25519 signature.`);return M(n)}function J(r){if(!/^pk_(?:live|test)_[A-Za-z0-9]+$/.test(r))throw new TypeError("[OpenRTC] apiKey is invalid.");return `app_${r.slice(-16)}`}function l(r){return r!==null&&typeof r=="object"&&!Array.isArray(r)?r:null}function v(r,e,t,n){if(typeof r!="string"||r.length<1||r.length>t||r!==r.trim()||n&&!n.test(r))throw new Error(`[OpenRTC] authority service grant ${e} is invalid.`);return r}function L(r){let e=v(r,"gatewayUrl",2048),t;try{t=new URL(e);}catch{throw new Error("[OpenRTC] authority service grant gatewayUrl is invalid.")}let n=t.protocol==="http:"&&["127.0.0.1","localhost","::1"].includes(t.hostname.toLowerCase());if(t.protocol!=="https:"&&!n||t.username||t.password||t.search||t.hash)throw new Error("[OpenRTC] authority service grant gatewayUrl is invalid.");return e}function $(r,e){let t=l(r),n=l(t?.avenue),i=l(t?.roomAuthority),a=l(i?.assignmentPublicKeyJwk),c=Date.now(),o=t?.expiresAtMs,s=t?.maxPeers;if(!t||t.protocolVersion!==2||t.architecture!=="authority"||n?.kind!=="room"||n.id!==e.roomId||i?.serviceId!==e.serviceId||i.generation!==e.generation||!Array.isArray(i.shardIds)||i.shardIds.length!==e.shardIds.length||i.shardIds.some((g,h)=>g!==e.shardIds[h])||a?.kty!=="OKP"||a.crv!=="Ed25519"||a.x!==e.assignmentPublicKeyX||!Number.isSafeInteger(o)||o<=c||o>c+U||!Number.isSafeInteger(s)||s<1||s>e.maxPeers)throw new Error("[OpenRTC] authority service grant response is inconsistent.");return {protocolVersion:2,gatewayUrl:L(t.gatewayUrl),routeKey:v(t.routeKey,"routeKey",256,_),token:v(t.token,"token",24e3,G),expiresAtMs:o,avenue:{kind:"room",id:e.roomId},maxPeers:s,architecture:"authority",roomAuthority:{serviceId:e.serviceId,generation:e.generation,shardIds:[...e.shardIds],assignmentPublicKeyJwk:{kty:"OKP",crv:"Ed25519",x:e.assignmentPublicKeyX}}}}var p=class{constructor(e){if(this.apiKey=e.apiKey,this.applicationTag=J(e.apiKey),this.rootClientKey=g().getOrCreate(this.applicationTag),typeof e.grantIssuer!="function")throw new TypeError("[OpenRTC] ServiceNode requires a browser-safe grantIssuer.");if(this.grantIssuer=e.grantIssuer,this.serviceId=d(e.serviceId,"serviceId",80),this.generation=u(e.generation,"generation"),this.shardIds=[...new Set(e.shardIds.map(t=>d(t,"shardId",80)))].sort(),this.shardIds.length<1||this.shardIds.length>64||this.shardIds.length!==e.shardIds.length)throw new RangeError("[OpenRTC] shardIds must contain 1..64 unique identifiers.");this.deviceId=d(e.deviceId,"deviceId"),this.deviceSigner=e.deviceSigner,this.assignmentSigner=e.assignmentSigner;}async requestGrant(e){let t=d(e.roomId,"roomId"),n=d(e.runtimeInstanceId,"runtimeInstanceId");if(!k.test(e.ticketFingerprint))throw new TypeError("[OpenRTC] ticketFingerprint is invalid.");e.maxPeers!==void 0&&u(e.maxPeers,"maxPeers",50);let i=await m(this.assignmentSigner,"assignmentSigner.publicJwk()"),a=await m(this.deviceSigner,"deviceSigner.publicJwk()"),c$1=crypto.randomUUID().replace(/-/g,""),o=Math.floor(Date.now()/1e3),s=["authority-service-grant",this.applicationTag,t,this.serviceId,String(this.generation),this.shardIds.join(","),String(i.x),this.deviceId,n,e.ticketFingerprint],g=e.rootProof===void 0?await this.rootClientKey:void 0,h=e.rootProof??(g?await b(g,s):void 0),f=h?await d$1(h.publicKeyJwk):void 0,x=f?c(s,f,c$1,o):["openrtc:v2:authority-service-grant",this.applicationTag,t,this.serviceId,String(this.generation),this.shardIds.join(","),i.x,n,c$1,o].join(":"),T={avenue:{kind:"room",id:t},serviceId:this.serviceId,generation:this.generation,shardIds:this.shardIds,assignmentPublicKeyJwk:i,deviceId:this.deviceId,runtimeInstanceId:n,ticketFingerprint:e.ticketFingerprint,deviceProof:{publicKeyJwk:a,nonce:c$1,issuedAt:o,signature:await y(this.deviceSigner,E.encode(x),"deviceSigner.sign()")},...e.maxPeers===void 0?{}:{maxPeers:e.maxPeers},...e.refreshGrant?{refreshGrant:e.refreshGrant}:{},...h?{rootProof:h}:{},features:e.features??{}},O=`authority_${crypto.randomUUID().replace(/-/g,"")}`,D=await this.grantIssuer({apiKey:this.apiKey,idempotencyKey:O,body:T});return $(D,{roomId:t,serviceId:this.serviceId,generation:this.generation,shardIds:this.shardIds,assignmentPublicKeyX:i.x,maxPeers:e.maxPeers??50})}async devicePublicKey(){return m(this.deviceSigner,"deviceSigner.publicJwk()")}async assignmentPublicKey(){return m(this.assignmentSigner,"assignmentSigner.publicJwk()")}async signDeviceBytes(e){return y(this.deviceSigner,e,"deviceSigner.sign()")}async signAssignment(e){let t=e.ttlMs??6e4;u(t,"ttlMs",2*6e4);let n=d(e.shardId,"shardId",80);if(!this.shardIds.includes(n))throw new RangeError("[OpenRTC] assignment shard is not owned by this service.");let i=e.priorityDeviceIds??[],a=e.relevantEntityIds??[];if(i.length>8||a.length>32)throw new RangeError("[OpenRTC] assignment exceeds the 8-edge or 32-entity bound.");let c=Date.now(),o={policyVersion:"room-authority-assignment-v1",serviceId:this.serviceId,generation:this.generation,revision:u(e.revision,"revision"),subjectDeviceId:d(e.subjectDeviceId,"subjectDeviceId"),shardId:n,priorityDeviceIds:i.map(s=>d(s,"priorityDeviceId")),relevantEntityIds:a.map(s=>d(s,"relevantEntityId")),issuedAtMs:c,expiresAtMs:c+t};if(new Set(o.priorityDeviceIds).size!==o.priorityDeviceIds.length||new Set(o.relevantEntityIds).size!==o.relevantEntityIds.length)throw new RangeError("[OpenRTC] assignment identifiers must be unique.");return {assignment:o,signature:await y(this.assignmentSigner,E.encode(JSON.stringify(o)),"assignmentSigner.sign()")}}},I=class{constructor(e,t,n){this.room=e;this.authority=t;this.onClosed=n;this.releaseRuntimeAlias=d$2(this,e);}get kind(){return this.room.kind}get id(){return this.room.id}get peers(){return this.room.peers}get channels(){return this.room.channels}get diagnostics(){return this.room.diagnostics}get closed(){return this.room.closed}get membership(){return this.room.membership}get members(){return this.room.members}state(e){return this.room.state(e)}channel(e){return this.room.channel(e)}onConnection(e){return this.room.onConnection(e)}architecture(){return this.room.architecture()}onArchitectureChanged(e){return this.room.onArchitectureChanged(e)}authorityAssignment(){return this.room.authorityAssignment()}onAuthorityAssignmentChanged(e){return this.room.onAuthorityAssignmentChanged(e)}leave(){return this.retire(()=>this.room.leave())}close(){return this.retire(()=>this.room.close())}async publishAssignment(e){let t=await this.authority.signAssignment(e);return await c$1(this.room).advanced.runtime.publishAuthorityAssignment(t),t.assignment}retire(e){return this.retirement??(this.retirement=e().finally(()=>{this.releaseRuntimeAlias(),this.onClosed();}))}},K=class{constructor(e){this.options=e;this.rooms=new Map;this.connectionListeners=new Set;this.connectionCleanups=new Map;this.closed=false;if("secretKey"in e)throw new TypeError("[OpenRTC] ServiceNode never accepts secretKey; delegate short-lived grants.");this.authority=new p(e);}listen(e){if(this.closed)throw new Error("[OpenRTC] ServiceNode is closed.");let t=d(e,"roomId"),n=this.rooms.get(t);if(n)return n.promise;let i={};return i.promise=this.openRoom(t,()=>this.evictRoom(t,i)).catch(a=>{throw this.evictRoom(t,i),a}),this.rooms.set(t,i),i.promise}onConnection(e){if(this.connectionListeners.add(e),this.connectionListeners.size===1)for(let[t,n]of this.rooms)n.promise.then(i=>this.attachConnectionListener(t,i),()=>{});return ()=>{if(this.connectionListeners.delete(e),this.connectionListeners.size===0){for(let t of this.connectionCleanups.values())t();this.connectionCleanups.clear();}}}async close(){if(this.closed)return;this.closed=true;for(let t of this.connectionCleanups.values())t();this.connectionCleanups.clear();let e=await Promise.allSettled([...this.rooms.values()].map(t=>t.promise));await Promise.all(e.flatMap(t=>t.status==="fulfilled"?[t.value.close()]:[])),this.rooms.clear(),this.connectionListeners.clear();}async openRoom(e,t){let n=await this.options.client.devices.localId();if(n!==this.options.deviceId)throw new Error("[OpenRTC] ServiceNode deviceId must match the client installation.");let[i,a]=await Promise.all([this.authority.devicePublicKey(),this.authority.assignmentPublicKey()]),c=await j(this.options.client,{roomId:e,serviceId:this.options.serviceId,generation:this.options.generation,shardIds:this.options.shardIds,deviceId:n,maxPeers:this.options.maxPeers,irohRelay:this.options.irohRelay!==false,devicePublicKeyX:i.x,assignmentPublicKeyX:a.x,deviceSign:s=>this.authority.signDeviceBytes(s),grantProvider:async s=>{if(s.avenue.kind!=="room"||s.avenue.id!==e)throw new Error("[OpenRTC] ServiceNode grant request escaped its room.");if(s.deviceId!==n)throw new Error("[OpenRTC] ServiceNode grant request escaped its device.");return this.authority.requestGrant({roomId:e,runtimeInstanceId:s.runtimeInstanceId,ticketFingerprint:s.ticketFingerprint,rootProof:s.rootProof,maxPeers:this.options.maxPeers,refreshGrant:s.refreshGrant,features:{irohRelay:this.options.irohRelay!==false}})}}),o=new I(c,this.authority,t);return this.attachConnectionListener(e,o),o}evictRoom(e,t){this.rooms.get(e)===t&&(this.rooms.delete(e),this.connectionCleanups.get(e)?.(),this.connectionCleanups.delete(e));}attachConnectionListener(e,t){this.closed||this.connectionListeners.size===0||this.connectionCleanups.has(e)||this.connectionCleanups.set(e,t.onConnection(n=>{for(let i of this.connectionListeners)i({room:t,connection:n});}));}};
2
2
  export{p as a,K as b};
@@ -1 +1 @@
1
- import {l}from'./chunk-WTOA6B2A.js';import'./chunk-OWKAJPOI.js';import {c}from'./chunk-SSBR3IHA.js';import'./chunk-2GX6GB6L.js';function w(o){let r=l({...o});if("auth"in o&&!o.authMode){let n=o.auth;r.authMode=n==="none"?"anonymous":n;}if("identity"in o){let n=o.identity,s=n==="temporary"?"ephemeral":n;!o.deviceIdPersistence&&!o.nodeIdPersistence&&(r.deviceIdPersistence=s),!o.endpointIdPersistence&&!o.nodeIdPersistence&&(r.endpointIdPersistence=s);}return "namespace"in o&&!o.storagePrefix&&(r.storagePrefix=o.namespace),"privacy"in o&&o.strictMode===void 0&&(r.strictMode=!!o.privacy),r}function O(o,r){let n=o.runtime,s=Object.create(n),d=async e=>{if(typeof e!="string")return e;let i=(await n.listDevices()).find(a=>a.deviceId===e);if(!i)throw new Error(`OpenRTC device '${e}' is not currently discoverable.`);return i},g=async e=>({...e,localDeviceId:e?.localDeviceId??await n.getLocalDeviceId()??""}),P=async e=>{let{device:t,scope:i,...a}=e,c=a.deviceId??(typeof t=="string"?t:t?.deviceId)??null,l=a.ticket??(typeof t=="string"?void 0:t?.ticket);c&&!l&&(l=(await d(c).catch(()=>null))?.ticket);let m={...a,scope:i??"session"};return c&&(m.deviceId=c),l&&(m.ticket=l),m},v={requestTransferPeer:e=>n.requestTransferPeer(e),transferPeerDemandStatus:(e,t)=>n.transferPeerDemandStatus(e,t),releaseTransferPeer:(e,t)=>n.releaseTransferPeer(e,t),setTransferPeerBudget:(e,t)=>n.setTransferPeerBudget(e,t),list:()=>n.listDevices(),startSession:(e={})=>n.startManagedSession({...e,platform:e.platform??r}),stopSession:e=>n.stopManagedSession(e),listWithStatus:()=>n.listDeviceStatus(),watch:e=>n.watchDevices(e),watchWithStatus:e=>n.watchDeviceStatus(e),connect:async(e,t)=>n.connectDevice(await d(e),await g(t)),connectWithRetry:async(e,t,i)=>n.connectWithRetry(await d(e),t,i),disconnect:e=>n.disconnectDevice(e),update:(e,t)=>n.updateDevice(e,t),delete:e=>n.deleteDevice(e),localId:()=>n.getLocalDeviceId(),localInfo:()=>n.getLocalDeviceInfo(),localProfile:e=>n.localDeviceProfile(e),updateLocalName:e=>n.updateDeviceName(e)},C={watch:e=>n.watchPeerStates(e),watchLifecycle:e=>typeof n.watchPeerLifecycle=="function"?n.watchPeerLifecycle(e):typeof n.watchPeerStates=="function"?n.watchPeerStates(e):()=>{},get:e=>n.getPeerState(e),listConnected:()=>n.listConnectedPeers(),connect:e=>n.connectPeer(e),disconnect:(e,t)=>n.disconnectPeer(e,t),forceDisconnect:e=>n.forceDisconnectPeer(e),session:e=>n.getPeerSession(e),sessions:()=>n.listPeerSessions(),waitConnected:(e,t)=>n.waitForConnectedPeer(e,t),readiness:(e,t)=>n.getPeerReadiness(e,t),health:e=>n.getPeerHealth(e),identity:e=>n.resolvePeerIdentity(e),addScope:(e,t)=>n.addPeerScope(e,t),releaseScope:(e,t)=>n.releasePeerScope(e,t),scopes:e=>n.getPeerScopes(e),refresh:()=>n.refreshPeerSnapshot()},h={register:e=>n.registerChannel(e),unregister:e=>n.unregisterChannel(e),list:()=>n.listChannels(),openBi:(e,t,i)=>n.openPeerBi(e,{...i,channelId:t}),openUni:(e,t,i)=>n.openPeerUni(e,{...i,channelId:t}),onIncoming:e=>n.onIncomingStream(e),onIncomingChannel:(e,t)=>n.onChannelStream(e,i=>{if(i.channel)return t(i)}),connect:async e=>n.connectScopedChannel(await P(e)),connectScoped:e=>n.connectScopedChannel(e)},S={create:e=>n.createRoom(e),join:(e,t)=>n.joinRoom(e,t),leave:e=>n.leaveRoom(e),watch:(e,t)=>n.watchRoom(e,t),members:e=>n.getRoomMembers(e)},f={raw:()=>n.getInvite(),share:e=>n.getTicketWithToken("share",e?.maxConnections??1),grant:(e,t)=>n.getTicketWithToken(e,t?.maxConnections??0),revoke:e=>n.revokeTokensByScope(e)},b={capture:e=>c(t=>n.watchPeerStates(t),e),status:()=>n.getRuntimeStatus(),policy:()=>n.getRuntimePolicy(),capabilities:()=>n.capabilities(),capabilityProfile:()=>n.getCapabilityProfile(),watchConnectionMetrics:e=>n.watchConnectionMetrics(e),connectionStates:()=>n.getConnectionStates(),onStateChange:e=>n.onStateChange(e),connections:()=>n.getConnections(),applicationReadyConnections:e=>n.readyConnections(e),onConnection:e=>n.onConnection(e),onDisconnection:e=>n.onDisconnection(e),onConnectionEvent:e=>n.onConnectionEvent(e),forceReconnect:()=>n.forceReconnect(),peerReconciliation:()=>n.reconciliationStats()},y={runtime:n,assembly:o,nodeId:()=>n.getNodeId(),nodeIdFromTicket:e=>n.getNodeIdFromTicket(e),endpointTicket:()=>n.getEndpointTicket(),connectRaw:e=>n.connectRaw(e),openBi:e=>n.openBi(e),openUni:e=>n.openUni(e),isConnected:e=>n.isConnected(e),disconnectNode:e=>n.disconnectNode(e),excludeAutoConnect:(e,t)=>n.excludeAutoConnect(e,t),notifyNetworkChange:e=>n.notifyNetworkChange(e)};return Object.defineProperties(s,{devices:{get:()=>v,enumerable:true},peers:{get:()=>C,enumerable:true},channels:{get:()=>h,enumerable:true},rooms:{get:()=>S,enumerable:true},tickets:{get:()=>f,enumerable:true},diagnostics:{get:()=>b,enumerable:true},advanced:{get:()=>y,enumerable:true},setAuth:{value:e=>o.setAuthContext(e),enumerable:true,writable:true,configurable:true},setAuthContext:{value:e=>o.setAuthContext(e),enumerable:true,writable:true,configurable:true},syncPlutoAuth:{value:e=>o.syncPlutoAuth(e),enumerable:true,writable:true,configurable:true},bindPlutoAuthHost:{value:()=>o.bindPlutoAuthHost(),enumerable:true,writable:true,configurable:true},signIn:{value:()=>o.signInWithPluto(),enumerable:true,writable:true,configurable:true},signOut:{value:()=>o.signOut(),enumerable:true,writable:true,configurable:true},runtime:{get:()=>n,enumerable:false},_assembly:{get:()=>o,enumerable:false}}),s}export{w as resolveOptions,O as wrapAssembly};
1
+ import {l}from'./chunk-WTOA6B2A.js';import'./chunk-OWKAJPOI.js';import {c}from'./chunk-BKCUXUHW.js';import'./chunk-2GX6GB6L.js';function w(o){let r=l({...o});if("auth"in o&&!o.authMode){let n=o.auth;r.authMode=n==="none"?"anonymous":n;}if("identity"in o){let n=o.identity,s=n==="temporary"?"ephemeral":n;!o.deviceIdPersistence&&!o.nodeIdPersistence&&(r.deviceIdPersistence=s),!o.endpointIdPersistence&&!o.nodeIdPersistence&&(r.endpointIdPersistence=s);}return "namespace"in o&&!o.storagePrefix&&(r.storagePrefix=o.namespace),"privacy"in o&&o.strictMode===void 0&&(r.strictMode=!!o.privacy),r}function O(o,r){let n=o.runtime,s=Object.create(n),d=async e=>{if(typeof e!="string")return e;let i=(await n.listDevices()).find(a=>a.deviceId===e);if(!i)throw new Error(`OpenRTC device '${e}' is not currently discoverable.`);return i},g=async e=>({...e,localDeviceId:e?.localDeviceId??await n.getLocalDeviceId()??""}),P=async e=>{let{device:t,scope:i,...a}=e,c=a.deviceId??(typeof t=="string"?t:t?.deviceId)??null,l=a.ticket??(typeof t=="string"?void 0:t?.ticket);c&&!l&&(l=(await d(c).catch(()=>null))?.ticket);let m={...a,scope:i??"session"};return c&&(m.deviceId=c),l&&(m.ticket=l),m},v={requestTransferPeer:e=>n.requestTransferPeer(e),transferPeerDemandStatus:(e,t)=>n.transferPeerDemandStatus(e,t),releaseTransferPeer:(e,t)=>n.releaseTransferPeer(e,t),setTransferPeerBudget:(e,t)=>n.setTransferPeerBudget(e,t),list:()=>n.listDevices(),startSession:(e={})=>n.startManagedSession({...e,platform:e.platform??r}),stopSession:e=>n.stopManagedSession(e),listWithStatus:()=>n.listDeviceStatus(),watch:e=>n.watchDevices(e),watchWithStatus:e=>n.watchDeviceStatus(e),connect:async(e,t)=>n.connectDevice(await d(e),await g(t)),connectWithRetry:async(e,t,i)=>n.connectWithRetry(await d(e),t,i),disconnect:e=>n.disconnectDevice(e),update:(e,t)=>n.updateDevice(e,t),delete:e=>n.deleteDevice(e),localId:()=>n.getLocalDeviceId(),localInfo:()=>n.getLocalDeviceInfo(),localProfile:e=>n.localDeviceProfile(e),updateLocalName:e=>n.updateDeviceName(e)},C={watch:e=>n.watchPeerStates(e),watchLifecycle:e=>typeof n.watchPeerLifecycle=="function"?n.watchPeerLifecycle(e):typeof n.watchPeerStates=="function"?n.watchPeerStates(e):()=>{},get:e=>n.getPeerState(e),listConnected:()=>n.listConnectedPeers(),connect:e=>n.connectPeer(e),disconnect:(e,t)=>n.disconnectPeer(e,t),forceDisconnect:e=>n.forceDisconnectPeer(e),session:e=>n.getPeerSession(e),sessions:()=>n.listPeerSessions(),waitConnected:(e,t)=>n.waitForConnectedPeer(e,t),readiness:(e,t)=>n.getPeerReadiness(e,t),health:e=>n.getPeerHealth(e),identity:e=>n.resolvePeerIdentity(e),addScope:(e,t)=>n.addPeerScope(e,t),releaseScope:(e,t)=>n.releasePeerScope(e,t),scopes:e=>n.getPeerScopes(e),refresh:()=>n.refreshPeerSnapshot()},h={register:e=>n.registerChannel(e),unregister:e=>n.unregisterChannel(e),list:()=>n.listChannels(),openBi:(e,t,i)=>n.openPeerBi(e,{...i,channelId:t}),openUni:(e,t,i)=>n.openPeerUni(e,{...i,channelId:t}),onIncoming:e=>n.onIncomingStream(e),onIncomingChannel:(e,t)=>n.onChannelStream(e,i=>{if(i.channel)return t(i)}),connect:async e=>n.connectScopedChannel(await P(e)),connectScoped:e=>n.connectScopedChannel(e)},S={create:e=>n.createRoom(e),join:(e,t)=>n.joinRoom(e,t),leave:e=>n.leaveRoom(e),watch:(e,t)=>n.watchRoom(e,t),members:e=>n.getRoomMembers(e)},f={raw:()=>n.getInvite(),share:e=>n.getTicketWithToken("share",e?.maxConnections??1),grant:(e,t)=>n.getTicketWithToken(e,t?.maxConnections??0),revoke:e=>n.revokeTokensByScope(e)},b={capture:e=>c(t=>n.watchPeerStates(t),e),status:()=>n.getRuntimeStatus(),policy:()=>n.getRuntimePolicy(),capabilities:()=>n.capabilities(),capabilityProfile:()=>n.getCapabilityProfile(),watchConnectionMetrics:e=>n.watchConnectionMetrics(e),connectionStates:()=>n.getConnectionStates(),onStateChange:e=>n.onStateChange(e),connections:()=>n.getConnections(),applicationReadyConnections:e=>n.readyConnections(e),onConnection:e=>n.onConnection(e),onDisconnection:e=>n.onDisconnection(e),onConnectionEvent:e=>n.onConnectionEvent(e),forceReconnect:()=>n.forceReconnect(),peerReconciliation:()=>n.reconciliationStats()},y={runtime:n,assembly:o,nodeId:()=>n.getNodeId(),nodeIdFromTicket:e=>n.getNodeIdFromTicket(e),endpointTicket:()=>n.getEndpointTicket(),connectRaw:e=>n.connectRaw(e),openBi:e=>n.openBi(e),openUni:e=>n.openUni(e),isConnected:e=>n.isConnected(e),disconnectNode:e=>n.disconnectNode(e),excludeAutoConnect:(e,t)=>n.excludeAutoConnect(e,t),notifyNetworkChange:e=>n.notifyNetworkChange(e)};return Object.defineProperties(s,{devices:{get:()=>v,enumerable:true},peers:{get:()=>C,enumerable:true},channels:{get:()=>h,enumerable:true},rooms:{get:()=>S,enumerable:true},tickets:{get:()=>f,enumerable:true},diagnostics:{get:()=>b,enumerable:true},advanced:{get:()=>y,enumerable:true},setAuth:{value:e=>o.setAuthContext(e),enumerable:true,writable:true,configurable:true},setAuthContext:{value:e=>o.setAuthContext(e),enumerable:true,writable:true,configurable:true},syncPlutoAuth:{value:e=>o.syncPlutoAuth(e),enumerable:true,writable:true,configurable:true},bindPlutoAuthHost:{value:()=>o.bindPlutoAuthHost(),enumerable:true,writable:true,configurable:true},signIn:{value:()=>o.signInWithPluto(),enumerable:true,writable:true,configurable:true},signOut:{value:()=>o.signOut(),enumerable:true,writable:true,configurable:true},runtime:{get:()=>n,enumerable:false},_assembly:{get:()=>o,enumerable:false}}),s}export{w as resolveOptions,O as wrapAssembly};
@@ -1 +1 @@
1
- import {h as h$1}from'./chunk-RUOVYQ2P.js';import'./chunk-FKAQDDUM.js';import'./chunk-SSBR3IHA.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';var h=class extends h$1{constructor(e,t,u,S){super("devices",e,t,u);this.roster=S;this.kind="devices";this.rosterStopped=false;this.localId=()=>this.client.devices.localId();this.localInfo=()=>this.client.devices.localInfo();this.list=async()=>this.roster.mergeDevices(await this.client.devices.list());this.listWithStatus=async()=>this.roster.mergeStatus(await this.client.devices.listWithStatus());this.watch=e=>this.client.devices.watch(t=>e(this.roster.mergeDevices(t)));this.requestTransferPeer=async e=>{if(this.closed)throw new Error("[OpenRTC] Capability is closed.");return this.client.devices.requestTransferPeer(e)};this.transferPeerDemandStatus=async(e,t)=>{if(this.closed)throw new Error("[OpenRTC] Capability is closed.");return this.client.devices.transferPeerDemandStatus(e,t)};this.releaseTransferPeer=async(e,t)=>{if(this.closed)throw new Error("[OpenRTC] Capability is closed.");return this.client.devices.releaseTransferPeer(e,t)};this.setTransferPeerBudget=async(e,t)=>{if(this.closed)throw new Error("[OpenRTC] Capability is closed.");return this.client.devices.setTransferPeerBudget(e,t)};this.connect=this.client.devices.connect;this.disconnect=this.client.devices.disconnect;let p=t.devices.list,m=t.devices.listWithStatus,c=t.devices.watch,f=t.devices.watchWithStatus,i=s=>(this.roster.reconcileLiveSnapshot(s),s),a=async()=>this.roster.mergeDevices(i(await p())),o=async()=>this.roster.mergeStatus(await m()),n=s=>c(r=>s(this.roster.mergeDevices(i(r)))),l=s=>f(r=>s(this.roster.mergeStatus(r))),d=Object.create(t);Object.defineProperties(d,{listDevices:{value:a,enumerable:false},listDeviceStatus:{value:o,enumerable:false},watchDevices:{value:n,enumerable:false},watchDeviceStatus:{value:l,enumerable:false},devices:{value:{...t.devices,list:a,listWithStatus:o,watch:n,watchWithStatus:l},enumerable:true}}),this.projectRuntime(d),this.stopRosterSync=c(i);}replaceEnrolledDevices(e){this.roster.replace(e);}removeEnrolledDevice(e){this.roster.remove(e);}retainCurrentEnrolledDevice(e){this.roster.retain(e);}beforeRuntimeShutdown(){this.rosterStopped||(this.stopRosterSync(),this.rosterStopped=true);}};export{h as DeviceHandle};
1
+ import {h as h$1}from'./chunk-3T57Y4EF.js';import'./chunk-FKAQDDUM.js';import'./chunk-BKCUXUHW.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';var h=class extends h$1{constructor(e,t,u,S){super("devices",e,t,u);this.roster=S;this.kind="devices";this.rosterStopped=false;this.localId=()=>this.client.devices.localId();this.localInfo=()=>this.client.devices.localInfo();this.list=async()=>this.roster.mergeDevices(await this.client.devices.list());this.listWithStatus=async()=>this.roster.mergeStatus(await this.client.devices.listWithStatus());this.watch=e=>this.client.devices.watch(t=>e(this.roster.mergeDevices(t)));this.requestTransferPeer=async e=>{if(this.closed)throw new Error("[OpenRTC] Capability is closed.");return this.client.devices.requestTransferPeer(e)};this.transferPeerDemandStatus=async(e,t)=>{if(this.closed)throw new Error("[OpenRTC] Capability is closed.");return this.client.devices.transferPeerDemandStatus(e,t)};this.releaseTransferPeer=async(e,t)=>{if(this.closed)throw new Error("[OpenRTC] Capability is closed.");return this.client.devices.releaseTransferPeer(e,t)};this.setTransferPeerBudget=async(e,t)=>{if(this.closed)throw new Error("[OpenRTC] Capability is closed.");return this.client.devices.setTransferPeerBudget(e,t)};this.connect=this.client.devices.connect;this.disconnect=this.client.devices.disconnect;let p=t.devices.list,m=t.devices.listWithStatus,c=t.devices.watch,f=t.devices.watchWithStatus,i=s=>(this.roster.reconcileLiveSnapshot(s),s),a=async()=>this.roster.mergeDevices(i(await p())),o=async()=>this.roster.mergeStatus(await m()),n=s=>c(r=>s(this.roster.mergeDevices(i(r)))),l=s=>f(r=>s(this.roster.mergeStatus(r))),d=Object.create(t);Object.defineProperties(d,{listDevices:{value:a,enumerable:false},listDeviceStatus:{value:o,enumerable:false},watchDevices:{value:n,enumerable:false},watchDeviceStatus:{value:l,enumerable:false},devices:{value:{...t.devices,list:a,listWithStatus:o,watch:n,watchWithStatus:l},enumerable:true}}),this.projectRuntime(d),this.stopRosterSync=c(i);}replaceEnrolledDevices(e){this.roster.replace(e);}removeEnrolledDevice(e){this.roster.remove(e);}retainCurrentEnrolledDevice(e){this.roster.retain(e);}beforeRuntimeShutdown(){this.rosterStopped||(this.stopRosterSync(),this.rosterStopped=true);}};export{h as DeviceHandle};
@@ -1,2 +1,2 @@
1
- import {a as a$1}from'./chunk-5VJXDYP6.js';import'./chunk-IXQ4KWGP.js';import'./chunk-AYHD4X2R.js';import {a}from'./chunk-KI7XXVXH.js';import'./chunk-XNJI6KCI.js';import {i}from'./chunk-RUOVYQ2P.js';import'./chunk-FKAQDDUM.js';import'./chunk-SSBR3IHA.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';async function K(r,e){if(!/^pk_(?:live|test)_[0-9a-f]{40}$/.test(r)||!/^[A-Za-z0-9_-]{1,64}$/.test(e))throw new Error("[OpenRTC] External broadcast identity is invalid.");return (await a(e).getOrCreate(`app_${r.slice(-16)}`)).publicKeyJwk}function h(r){let e=new URL(r),t=["localhost","127.0.0.1","[::1]"].includes(e.hostname);if(e.protocol!=="https:"&&!(t&&e.protocol==="http:")||e.pathname!=="/"||e.username||e.password||e.search||e.hash||r!==e.origin&&r!==`${e.origin}/`)throw new Error("[OpenRTC] External broadcast service must be an exact HTTPS origin.");return e.origin}function k(r){let e=r.replace(/-/g,"+").replace(/_/g,"/").padEnd(Math.ceil(r.length/4)*4,"=");return Uint8Array.from(atob(e),t=>t.charCodeAt(0))}function x(r){let e="";for(let t of r)e+=String.fromCharCode(t);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function C(r,e){if(!(r.issuerPublicKey instanceof Uint8Array)||r.issuerPublicKey.length!==32)throw new Error("[OpenRTC] External broadcast issuer key must be 32 bytes.");let t=r.relay;if(t.kind==="sfu"){let a=new URL(t.controlUrl,e);if(a.origin!==e||a.protocol!==new URL(e).protocol||a.pathname==="/"||a.username||a.password||a.search||a.hash)throw new Error("[OpenRTC] External SFU control must stay on the trusted service origin.");return {issuerPublicKey:r.issuerPublicKey,relay:{kind:"sfu",controlUrl:a.href.replace(/\/$/,"")}}}else {let a=new URL(t.relayUrl);if(a.protocol!=="https:"||a.username||a.password||!t.token||!t.namespace)throw new Error("[OpenRTC] External MoQ relay access is invalid.");if(t.serverCertificateHash&&!["localhost","127.0.0.1","[::1]"].includes(a.hostname))throw new Error("[OpenRTC] Custom relay certificate hashes are limited to loopback.")}return r}function P(r,e){if(!r||typeof r.apiKey!="string"||!/^pk_(?:live|test)_[0-9a-f]{40}$/.test(r.apiKey))throw new Error("[OpenRTC] External broadcast identity is invalid.");let t=h(e.serviceOrigin);if(!/^[A-Za-z0-9_-]{1,64}$/.test(e.keyNamespace)||typeof e.resolve!="function")throw new Error("[OpenRTC] External broadcast configuration is invalid.");let a$2=a(e.keyNamespace),d=`app_${r.apiKey.slice(-16)}`,l=()=>a$2.getOrCreate(d),u=async()=>{let{loadBrowserWasmRuntimeModule:i}=await import('./WasmBridge-3HYLCY5Y.js'),n=await i();return await n.initWasm(),n.start(),new n.WasmClient(r.apiKey)},w,f=()=>w??(w=u()),m=new a$1({loadWasm:f,resolve:async(i,n)=>{let o=await l(),s=C(await e.resolve(i,o.publicKeyJwk,n),t),g=s.relay.kind==="sfu"?{kind:"sfu",controlUrl:s.relay.controlUrl,grant:i,bindingPublicJwk:o.publicKeyJwk,...n?{publicationVerifyingKey:x(n)}:{}}:s.relay;return {token:i,issuerPublicKey:s.issuerPublicKey,relay:g,signBindingChallenge:async b=>k(await o.sign(b))}}});return {client:i(r,{platform:"web",endpoints:{controlPlane:t,gateway:t},testingAllowInsecureLoopback:t.startsWith("http:"),deviceKeyProvider:a$2,broadcastHost:m,runtimeFactory:async i=>{let{createWasmClient:n}=await import('./runtime/factories.js');return n(i)}}),bindingPublicJwk:async()=>(await l()).publicKeyJwk}}
1
+ import {a as a$1}from'./chunk-5VJXDYP6.js';import'./chunk-IXQ4KWGP.js';import'./chunk-AYHD4X2R.js';import {a}from'./chunk-KI7XXVXH.js';import'./chunk-XNJI6KCI.js';import {i}from'./chunk-3T57Y4EF.js';import'./chunk-FKAQDDUM.js';import'./chunk-BKCUXUHW.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';async function K(r,e){if(!/^pk_(?:live|test)_[0-9a-f]{40}$/.test(r)||!/^[A-Za-z0-9_-]{1,64}$/.test(e))throw new Error("[OpenRTC] External broadcast identity is invalid.");return (await a(e).getOrCreate(`app_${r.slice(-16)}`)).publicKeyJwk}function h(r){let e=new URL(r),t=["localhost","127.0.0.1","[::1]"].includes(e.hostname);if(e.protocol!=="https:"&&!(t&&e.protocol==="http:")||e.pathname!=="/"||e.username||e.password||e.search||e.hash||r!==e.origin&&r!==`${e.origin}/`)throw new Error("[OpenRTC] External broadcast service must be an exact HTTPS origin.");return e.origin}function k(r){let e=r.replace(/-/g,"+").replace(/_/g,"/").padEnd(Math.ceil(r.length/4)*4,"=");return Uint8Array.from(atob(e),t=>t.charCodeAt(0))}function x(r){let e="";for(let t of r)e+=String.fromCharCode(t);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function C(r,e){if(!(r.issuerPublicKey instanceof Uint8Array)||r.issuerPublicKey.length!==32)throw new Error("[OpenRTC] External broadcast issuer key must be 32 bytes.");let t=r.relay;if(t.kind==="sfu"){let a=new URL(t.controlUrl,e);if(a.origin!==e||a.protocol!==new URL(e).protocol||a.pathname==="/"||a.username||a.password||a.search||a.hash)throw new Error("[OpenRTC] External SFU control must stay on the trusted service origin.");return {issuerPublicKey:r.issuerPublicKey,relay:{kind:"sfu",controlUrl:a.href.replace(/\/$/,"")}}}else {let a=new URL(t.relayUrl);if(a.protocol!=="https:"||a.username||a.password||!t.token||!t.namespace)throw new Error("[OpenRTC] External MoQ relay access is invalid.");if(t.serverCertificateHash&&!["localhost","127.0.0.1","[::1]"].includes(a.hostname))throw new Error("[OpenRTC] Custom relay certificate hashes are limited to loopback.")}return r}function P(r,e){if(!r||typeof r.apiKey!="string"||!/^pk_(?:live|test)_[0-9a-f]{40}$/.test(r.apiKey))throw new Error("[OpenRTC] External broadcast identity is invalid.");let t=h(e.serviceOrigin);if(!/^[A-Za-z0-9_-]{1,64}$/.test(e.keyNamespace)||typeof e.resolve!="function")throw new Error("[OpenRTC] External broadcast configuration is invalid.");let a$2=a(e.keyNamespace),d=`app_${r.apiKey.slice(-16)}`,l=()=>a$2.getOrCreate(d),u=async()=>{let{loadBrowserWasmRuntimeModule:i}=await import('./WasmBridge-3HYLCY5Y.js'),n=await i();return await n.initWasm(),n.start(),new n.WasmClient(r.apiKey)},w,f=()=>w??(w=u()),m=new a$1({loadWasm:f,resolve:async(i,n)=>{let o=await l(),s=C(await e.resolve(i,o.publicKeyJwk,n),t),g=s.relay.kind==="sfu"?{kind:"sfu",controlUrl:s.relay.controlUrl,grant:i,bindingPublicJwk:o.publicKeyJwk,...n?{publicationVerifyingKey:x(n)}:{}}:s.relay;return {token:i,issuerPublicKey:s.issuerPublicKey,relay:g,signBindingChallenge:async b=>k(await o.sign(b))}}});return {client:i(r,{platform:"web",endpoints:{controlPlane:t,gateway:t},testingAllowInsecureLoopback:t.startsWith("http:"),deviceKeyProvider:a$2,broadcastHost:m,runtimeFactory:async i=>{let{createWasmClient:n}=await import('./runtime/factories.js');return n(i)}}),bindingPublicJwk:async()=>(await l()).publicKeyJwk}}
2
2
  export{P as createExternalBroadcastClient,K as externalBroadcastBindingPublicJwk};
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import {a as a$1}from'./chunk-5336XOTL.js';import {d as d$1}from'./chunk-72NEEJQG.js';import {i}from'./chunk-RUOVYQ2P.js';import'./chunk-FKAQDDUM.js';import'./chunk-SSBR3IHA.js';export{b as parseTicketInvite}from'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';export{a as ERROR_CODES,b as RTCError,e as classifyError,d as createError,c as projectError}from'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';function d(n){return i(n,{platform:"web",liveHostFactory:async(e,i)=>{let{BrowserCoordinationGatewaySignaling:r}=await import('./BrowserCoordinationGatewaySignaling-GOLSTJMA.js');return r.live(e,i)},broadcastHostFactory:async e=>{let[{BrowserManagedBroadcastHost:i},{loadBrowserWasmRuntimeModule:r}]=await Promise.all([import('./BrowserManagedBroadcastHost-6VGHQQMF.js'),import('./WasmBridge-3HYLCY5Y.js')]),t=r().then(async o=>(await o.initWasm(),o.start(),new o.WasmClient(e.apiKey)));return new i({resolve:e.resolve,manage:e.manage,deviceId:e.deviceId,defaultAuth:e.defaultAuth,loadWasm:()=>t})},runtimeFactory:async e=>{let{createWasmClient:i}=await import('./runtime/factories.js');return i(e)}})}d.native=function(n,e=d$1()){let i$1,r=()=>i$1??(i$1=import('./NativeProjectionBroker-Z6LCR4WB.js').then(({NativeProjectionBroker:t})=>new t));return i(n,{platform:"native",liveHostFactory:t=>new a(e,t),broadcastHostFactory:async t=>{let{NativeManagedBroadcastHost:o}=await import('./NativeManagedBroadcastHost-6A2QP3A7.js');return new o(e,t)},offlineSupport:()=>e.invoke("openrtc_offline_runtime_support"),createOfflineEnrollmentRequest:async t=>{let o=await e.invoke("start_iroh_node");return e.invoke("openrtc_create_offline_enrollment_request",{trustDomain:t.trustDomain,deviceId:t.deviceId,endpointId:o,enrollmentNonce:crypto.randomUUID(),requestedRoles:t.requestedRoles})},close:async()=>{i$1&&await(await i$1).close();},deviceKeyProvider:a$1(e),deviceIdProvider:async()=>{let t=await e.invoke("get_rtc_local_device_info");return String(t?.deviceId??"")},runtimeFactory:async t=>{let[{createIpcClient:o},l]=await Promise.all([import('./ipcFactory-6XD3J2UU.js'),r()]);return o(t,e,l)}})};var a=class{constructor(e,i){this.bridge=e;this.endpoint=i;this.retired=false;this.opened=false;this.certificate="";this.abort=new AbortController;this.listeners=new Set;}get closed(){return this.retired}onEvent(e){return this.listeners.add(e),()=>{this.listeners.delete(e);}}emit(e){for(let i of this.listeners)try{i(e);}catch{}}async credentials(e){if(this.retired)throw new Error("[OpenRTC] Live session is closed.");let i,r=new Promise((t,o)=>{i=()=>o(new Error("[OpenRTC] Live credentials were closed.")),this.abort.signal.aborted?i():this.abort.signal.addEventListener("abort",i,{once:true});});try{let t=await Promise.race([this.options.credentials({forceRefresh:e,signal:this.abort.signal}),r]);if(this.retired||!t||typeof t.certificate!="string"||t.certificate.length>8192||typeof t.session!="string"||t.session.length>24e3)throw new Error("[OpenRTC] Invalid or retired live credentials.");return t}finally{this.abort.signal.removeEventListener("abort",i);}}async open(e){if(this.opened||this.retired||!this.bridge.createChannel)throw new Error("[OpenRTC] Native live coordination is unavailable.");this.opened=true,this.options=e;let i=await this.bridge.createChannel(t=>{t.type==="credentials-required"?this.retired||this.renew().catch(()=>this.close()):t.type==="closed"?(this.retired=true,this.abort.abort(),this.emit(t)):!this.retired&&t.type==="message"&&this.emit(t);}),r=await this.credentials(false);if(this.certificate=r.certificate,this.opening=this.bridge.invoke("openrtc_open_live_coordination",{endpoint:this.endpoint,credentials:r,channel:i}),this.id=await this.opening,this.retired)throw await this.close(),new Error("[OpenRTC] Native live activation was closed.")}async renew(){if(this.renewal)return this.renewal;let e=false,i=(async()=>{let r=await this.credentials(true);if(r.certificate!==this.certificate)throw new Error("[OpenRTC] Live term changed; open a new session.");try{await this.request({type:"renew",token:r.session});}catch(t){throw e=(t instanceof Error?t.message:String(t))==="live-certificate-expiry",t}})();this.renewal=i;try{await i;}catch(r){throw e||await this.close(),r}finally{this.renewal===i&&(this.renewal=void 0);}}async request(e){if(this.retired||!this.id)throw new Error("[OpenRTC] Native live session is closed.");return this.bridge.invoke("openrtc_send_live_coordination",{sessionId:this.id,frame:e})}close(){if(this.closing)return this.closing;this.retired=true,this.abort.abort();let e=(async()=>{let i=this.id??await this.opening?.catch(()=>{});i&&await this.bridge.invoke("openrtc_close_live_coordination",{sessionId:i}),this.id=void 0,this.emit({type:"closed"}),this.listeners.clear();})();return this.closing=e,e.catch(i=>{throw this.closing===e&&(this.closing=void 0),i})}};export{d as OpenRTC};
1
+ import {a as a$1}from'./chunk-5336XOTL.js';import {d as d$1}from'./chunk-72NEEJQG.js';import {i}from'./chunk-3T57Y4EF.js';import'./chunk-FKAQDDUM.js';import'./chunk-BKCUXUHW.js';export{b as parseTicketInvite}from'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';export{a as ERROR_CODES,b as RTCError,e as classifyError,d as createError,c as projectError}from'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';function d(n){return i(n,{platform:"web",liveHostFactory:async(e,i)=>{let{BrowserCoordinationGatewaySignaling:r}=await import('./BrowserCoordinationGatewaySignaling-GOLSTJMA.js');return r.live(e,i)},broadcastHostFactory:async e=>{let[{BrowserManagedBroadcastHost:i},{loadBrowserWasmRuntimeModule:r}]=await Promise.all([import('./BrowserManagedBroadcastHost-6VGHQQMF.js'),import('./WasmBridge-3HYLCY5Y.js')]),t=r().then(async o=>(await o.initWasm(),o.start(),new o.WasmClient(e.apiKey)));return new i({resolve:e.resolve,manage:e.manage,deviceId:e.deviceId,defaultAuth:e.defaultAuth,loadWasm:()=>t})},runtimeFactory:async e=>{let{createWasmClient:i}=await import('./runtime/factories.js');return i(e)}})}d.native=function(n,e=d$1()){let i$1,r=()=>i$1??(i$1=import('./NativeProjectionBroker-Z6LCR4WB.js').then(({NativeProjectionBroker:t})=>new t));return i(n,{platform:"native",liveHostFactory:t=>new a(e,t),broadcastHostFactory:async t=>{let{NativeManagedBroadcastHost:o}=await import('./NativeManagedBroadcastHost-6A2QP3A7.js');return new o(e,t)},offlineSupport:()=>e.invoke("openrtc_offline_runtime_support"),createOfflineEnrollmentRequest:async t=>{let o=await e.invoke("start_iroh_node");return e.invoke("openrtc_create_offline_enrollment_request",{trustDomain:t.trustDomain,deviceId:t.deviceId,endpointId:o,enrollmentNonce:crypto.randomUUID(),requestedRoles:t.requestedRoles})},close:async()=>{i$1&&await(await i$1).close();},deviceKeyProvider:a$1(e),deviceIdProvider:async()=>{let t=await e.invoke("get_rtc_local_device_info");return String(t?.deviceId??"")},runtimeFactory:async t=>{let[{createIpcClient:o},l]=await Promise.all([import('./ipcFactory-6XD3J2UU.js'),r()]);return o(t,e,l)}})};var a=class{constructor(e,i){this.bridge=e;this.endpoint=i;this.retired=false;this.opened=false;this.certificate="";this.abort=new AbortController;this.listeners=new Set;}get closed(){return this.retired}onEvent(e){return this.listeners.add(e),()=>{this.listeners.delete(e);}}emit(e){for(let i of this.listeners)try{i(e);}catch{}}async credentials(e){if(this.retired)throw new Error("[OpenRTC] Live session is closed.");let i,r=new Promise((t,o)=>{i=()=>o(new Error("[OpenRTC] Live credentials were closed.")),this.abort.signal.aborted?i():this.abort.signal.addEventListener("abort",i,{once:true});});try{let t=await Promise.race([this.options.credentials({forceRefresh:e,signal:this.abort.signal}),r]);if(this.retired||!t||typeof t.certificate!="string"||t.certificate.length>8192||typeof t.session!="string"||t.session.length>24e3)throw new Error("[OpenRTC] Invalid or retired live credentials.");return t}finally{this.abort.signal.removeEventListener("abort",i);}}async open(e){if(this.opened||this.retired||!this.bridge.createChannel)throw new Error("[OpenRTC] Native live coordination is unavailable.");this.opened=true,this.options=e;let i=await this.bridge.createChannel(t=>{t.type==="credentials-required"?this.retired||this.renew().catch(()=>this.close()):t.type==="closed"?(this.retired=true,this.abort.abort(),this.emit(t)):!this.retired&&t.type==="message"&&this.emit(t);}),r=await this.credentials(false);if(this.certificate=r.certificate,this.opening=this.bridge.invoke("openrtc_open_live_coordination",{endpoint:this.endpoint,credentials:r,channel:i}),this.id=await this.opening,this.retired)throw await this.close(),new Error("[OpenRTC] Native live activation was closed.")}async renew(){if(this.renewal)return this.renewal;let e=false,i=(async()=>{let r=await this.credentials(true);if(r.certificate!==this.certificate)throw new Error("[OpenRTC] Live term changed; open a new session.");try{await this.request({type:"renew",token:r.session});}catch(t){throw e=(t instanceof Error?t.message:String(t))==="live-certificate-expiry",t}})();this.renewal=i;try{await i;}catch(r){throw e||await this.close(),r}finally{this.renewal===i&&(this.renewal=void 0);}}async request(e){if(this.retired||!this.id)throw new Error("[OpenRTC] Native live session is closed.");return this.bridge.invoke("openrtc_send_live_coordination",{sessionId:this.id,frame:e})}close(){if(this.closing)return this.closing;this.retired=true,this.abort.abort();let e=(async()=>{let i=this.id??await this.opening?.catch(()=>{});i&&await this.bridge.invoke("openrtc_close_live_coordination",{sessionId:i}),this.id=void 0,this.emit({type:"closed"}),this.listeners.clear();})();return this.closing=e,e.catch(i=>{throw this.closing===e&&(this.closing=void 0),i})}};export{d as OpenRTC};
package/dist/native.js CHANGED
@@ -1 +1 @@
1
- import {a}from'./chunk-XXZEDZUU.js';import'./chunk-TPF643LU.js';import {a as a$1}from'./chunk-5336XOTL.js';import {d}from'./chunk-72NEEJQG.js';import {i}from'./chunk-RUOVYQ2P.js';import'./chunk-FKAQDDUM.js';import'./chunk-SSBR3IHA.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';function u(p,t=d()){let r=new a;return i(p,{platform:"native",broadcastHostFactory:async e=>{let{NativeManagedBroadcastHost:o}=await import('./NativeManagedBroadcastHost-6A2QP3A7.js');return new o(t,e)},offlineSupport:()=>t.invoke("openrtc_offline_runtime_support"),createOfflineEnrollmentRequest:async e=>{let o=await t.invoke("start_iroh_node");return t.invoke("openrtc_create_offline_enrollment_request",{trustDomain:e.trustDomain,deviceId:e.deviceId,endpointId:o,enrollmentNonce:crypto.randomUUID(),requestedRoles:e.requestedRoles})},close:()=>r.close(),deviceKeyProvider:a$1(t),deviceIdProvider:async()=>{let e=await t.invoke("get_rtc_local_device_info");return String(e?.deviceId??"")},runtimeFactory:async e=>{let{createIpcClient:o}=await import('./ipcFactory-6XD3J2UU.js');return o(e,t,r)}})}export{u as OpenRTC};
1
+ import {a}from'./chunk-XXZEDZUU.js';import'./chunk-TPF643LU.js';import {a as a$1}from'./chunk-5336XOTL.js';import {d}from'./chunk-72NEEJQG.js';import {i}from'./chunk-3T57Y4EF.js';import'./chunk-FKAQDDUM.js';import'./chunk-BKCUXUHW.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';function u(p,t=d()){let r=new a;return i(p,{platform:"native",broadcastHostFactory:async e=>{let{NativeManagedBroadcastHost:o}=await import('./NativeManagedBroadcastHost-6A2QP3A7.js');return new o(t,e)},offlineSupport:()=>t.invoke("openrtc_offline_runtime_support"),createOfflineEnrollmentRequest:async e=>{let o=await t.invoke("start_iroh_node");return t.invoke("openrtc_create_offline_enrollment_request",{trustDomain:e.trustDomain,deviceId:e.deviceId,endpointId:o,enrollmentNonce:crypto.randomUUID(),requestedRoles:e.requestedRoles})},close:()=>r.close(),deviceKeyProvider:a$1(t),deviceIdProvider:async()=>{let e=await t.invoke("get_rtc_local_device_info");return String(e?.deviceId??"")},runtimeFactory:async e=>{let{createIpcClient:o}=await import('./ipcFactory-6XD3J2UU.js');return o(e,t,r)}})}export{u as OpenRTC};
package/dist/node.js CHANGED
@@ -1,2 +1,2 @@
1
- import {a}from'./chunk-XXZEDZUU.js';import {a as a$2}from'./chunk-TPF643LU.js';import {a as a$1}from'./chunk-5336XOTL.js';import {c}from'./chunk-72NEEJQG.js';import {i,b as b$2,a as a$3}from'./chunk-RUOVYQ2P.js';import'./chunk-FKAQDDUM.js';import'./chunk-SSBR3IHA.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import {e as e$1,b as b$3}from'./chunk-L7N4T2PX.js';import {b as b$1,d,e}from'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';import {spawn}from'child_process';import {constants}from'fs';import {access,readFile}from'fs/promises';import {isAbsolute,resolve,dirname}from'path';import {fileURLToPath}from'url';import {isDeepStrictEqual}from'util';import {randomUUID,verify,createHash}from'crypto';var E=1,F=24*1024,U=96*1024,N=128*1024,C=64*1024,ne=256,ie=256,L=3e4,se=/^[A-Za-z0-9_.:@-]+$/,ae=/(?:^|_)(?:SECRET|TOKEN|PASSWORD|PRIVATE(?:_KEY)?|CREDENTIALS?)(?:_|$)/i,ce=1;function de(r){return Buffer.from(JSON.stringify({schema:r.schema,kind:r.kind,platform:r.platform,arch:r.arch,rustTarget:r.rustTarget,sourceCommit:r.sourceCommit,sourceDigest:r.sourceDigest,binarySha256:r.binarySha256,protocol:r.protocol,signingKeySha256:r.signingKeySha256,signatureAlgorithm:r.signatureAlgorithm}),"utf8")}async function le(r,e,t){let[o,n,c]=await Promise.all([readFile(t),readFile(resolve(e,"openrtc-node-host.manifest.json")),readFile(resolve(r,"native","openrtc-node-host-signing-public.pem"))]).catch(()=>{throw new Error("[OpenRTC] Packaged Node host provenance is incomplete.")}),i;try{i=JSON.parse(n.toString("utf8"));}catch{throw new Error("[OpenRTC] Packaged Node host manifest is invalid.")}let a=s=>createHash("sha256").update(s).digest("hex"),u={"darwin-arm64":"aarch64-apple-darwin","darwin-x64":"x86_64-apple-darwin","linux-x64":"x86_64-unknown-linux-gnu"}[`${process.platform}-${process.arch}`];if(!(i!=null&&u!==void 0&&i.schema===ce&&i.kind==="openrtc-node-host"&&i.platform===process.platform&&i.arch===process.arch&&i.rustTarget===u&&/^[0-9a-f]{40}$/.test(i.sourceCommit)&&/^[0-9a-f]{64}$/.test(i.sourceDigest)&&i.binarySha256===a(o)&&i.signingKeySha256===a(c)&&i.signatureAlgorithm==="ed25519"&&/^[A-Za-z0-9+/]{86}==$/.test(i.signature)&&verify(null,de(i),c,Buffer.from(i.signature,"base64"))))throw new Error("[OpenRTC] Packaged Node host provenance verification failed.")}function z(r){return Object.fromEntries(Object.entries(process.env).filter(([e,t])=>!ae.test(e)&&(!r||!t?.includes(r))))}function f(r,e){queueMicrotask(()=>{try{let t=r(e);t&&typeof t.then=="function"&&t.catch(()=>{try{process.emitWarning("[OpenRTC] ServiceNode callback failed.",{code:"OPENRTC_SERVICE_CALLBACK"});}catch{}});}catch{try{process.emitWarning("[OpenRTC] ServiceNode callback failed.",{code:"OPENRTC_SERVICE_CALLBACK"});}catch{}}});}function $(r){let e=/^\d{1,20}$/;return typeof r.transportStableId!="string"||!e.test(r.transportStableId)||!e.test(r.transportGeneration)||!e.test(r.routeGeneration)?null:{transportStableId:r.transportStableId,transportGeneration:r.transportGeneration,routeGeneration:r.routeGeneration}}function ue(r,e){return r.transportStableId===e.transportStableId&&r.transportGeneration===e.transportGeneration&&r.routeGeneration===e.routeGeneration}function m(r,e,t=160){let o=r.trim();if(!o||o.length>t||!se.test(o))throw new TypeError(`[OpenRTC] ${e} is invalid.`);return o}function v(r,e,t=Number.MAX_SAFE_INTEGER){if(!Number.isSafeInteger(r)||r<1||r>t)throw new RangeError(`[OpenRTC] ${e} must be a positive safe integer.`);return r}function pe(r){if(!/^pk_(?:live|test)_[A-Za-z0-9]+$/.test(r.apiKey))throw new TypeError("[OpenRTC] apiKey is invalid.");if(!/^sk_(?:live|test)_[A-Za-z0-9_-]+$/.test(r.secretKey)||r.secretKey.length>128)throw new TypeError("[OpenRTC] secretKey is invalid.");let e=[...r.shardIds].map(t=>m(t,"shardId",80)).sort();if(e.length<1||e.length>64||new Set(e).size!==e.length)throw new RangeError("[OpenRTC] shardIds must contain 1..64 unique identifiers.");if(!isAbsolute(r.stateDirectory))throw new TypeError("[OpenRTC] stateDirectory must be absolute.");return r.maxPeers!==void 0&&v(r.maxPeers,"maxPeers",50),r.startupTimeoutMs!==void 0&&v(r.startupTimeoutMs,"startupTimeoutMs",12e4),{...r,serviceId:m(r.serviceId,"serviceId",80),generation:v(r.generation,"generation"),shardIds:e,deviceId:m(r.deviceId,"deviceId"),deviceName:r.deviceName?.trim()||"OpenRTC Node service"}}async function y(r){try{return await access(r,process.platform==="win32"?constants.F_OK:constants.X_OK),!0}catch{return false}}async function V(r,e,t,o,n){return new Promise((c,i)=>{let a=spawn(r,e,{cwd:t,env:z(n),stdio:["ignore","pipe","pipe"]}),d=Buffer.alloc(0),u=Buffer.alloc(0),l=(p,Y)=>Buffer.concat([p,Y]).subarray(-N);a.stdout.on("data",p=>{d=l(d,p);}),a.stderr.on("data",p=>{u=l(u,p);});let s=setTimeout(()=>{a.kill(),i(new Error(`[OpenRTC] Node host command timed out: ${r}.`));},o);a.once("error",p=>{clearTimeout(s),i(p);}),a.once("exit",p=>{clearTimeout(s),p===0?c(d.toString("utf8")):i(new Error(`[OpenRTC] Node host command failed (${p??"signal"}): ${u.toString("utf8").trim().slice(-4096)}`));});})}async function J(r){let e=r.binaryPath||process.env.OPENRTC_NODE_HOST_BINARY;if(e){if(!isAbsolute(e)||!await y(e))throw new Error("[OpenRTC] Node host binaryPath must name an executable absolute path.");return {command:e,args:[...r.binaryArgs??[]]}}if(r.buildFromSource){let c=r.sourceRoot||process.env.OPENRTC_SOURCE_ROOT;if(!c||!isAbsolute(c))throw new Error("[OpenRTC] buildFromSource requires an absolute sourceRoot or OPENRTC_SOURCE_ROOT.");let i=resolve(c,"crates/openrtc/Cargo.toml"),a=resolve(c,"target");await V("cargo",["build","--locked","--manifest-path",i,"--features","node-host","--bin","openrtc-node-host","--target-dir",a],c,12e4,r.secretKey);let d=resolve(a,"debug",`openrtc-node-host${process.platform==="win32"?".exe":""}`);if(!await y(d))throw new Error("[OpenRTC] local Node host build did not produce an executable.");return {command:d,args:[]}}let t=resolve(dirname(fileURLToPath(import.meta.url)),".."),o=resolve(t,"native",`${process.platform}-${process.arch}`),n=resolve(o,`openrtc-node-host${process.platform==="win32"?".exe":""}`);if(!await y(n))throw new Error(`[OpenRTC] This package has no Node host for ${process.platform}-${process.arch}. Install a supported OpenRTC package, set OPENRTC_NODE_HOST_BINARY, or use buildFromSource with sourceRoot.`);return await le(t,o,n),{command:n,args:[]}}async function X(r,e){let t=await V(r.command,[...r.args,"--protocol-info"],process.cwd(),12e4,e),o=JSON.parse(t);if(o.protocolVersion!==E||o.lifecycleOwner!=="rust-peer-session"||o.maxConfigBytes!==F||o.maxCommandBytes!==U||o.maxApplicationPayloadBytes!==C)throw new Error("[OpenRTC] Node host protocol is incompatible.");return o}var I=class{constructor(e,t,o){this.options=e;this.roomId=t;this.onEvent=o;this.child=null;this.childClosed=Promise.resolve();this.output=Buffer.alloc(0);this.stderr=Buffer.alloc(0);this.pending=new Map;this.writeQueue=Promise.resolve();this.stopped=false;this.closing=null;}async start(){let e=await J(this.options),t=await X(e,this.options.secretKey),o=new Promise((n,c)=>{let i=spawn(e.command,[...e.args],{env:z(this.options.secretKey),stdio:["pipe","pipe","pipe"]});this.child=i,this.childClosed=new Promise(l=>i.once("close",()=>l()));let a,d=setTimeout(()=>{c(this.failure("Node host startup timed out")),i.kill();},this.options.startupTimeoutMs??L),u=l=>{clearTimeout(d);let s=b$3.is(l)?l:this.failure(l.message);this.terminalFailure=a??s,c(s),this.failAll(s);};i.once("error",u),i.stdin.on("error",l=>{u(a??l),i.kill();}),i.stderr.on("data",l=>{this.stderr=Buffer.concat([this.stderr,l]).subarray(-4096);}),i.stdout.on("data",l=>{try{for(let s of this.parse(l)){if(s.type==="failure"){a=this.failure(s.error,s.serviceError),u(a);continue}if(t.testLane&&process.env.OPENRTC_NODE_HOST_LOCAL_TRACE==="1"&&s.type==="connection-state"&&console.error("[openrtc-local-node]",this.options.deviceId,{connectionId:s.snapshot.connectionId,deviceId:s.snapshot.deviceId,state:s.snapshot.state,routable:s.snapshot.routable,transportStableId:s.transportStableId,transportGeneration:s.transportGeneration,routeGeneration:s.routeGeneration}),s.type==="ready"){if(s.protocolVersion!==E||s.roomId!==this.roomId||s.deviceId!==this.options.deviceId||!isDeepStrictEqual(s.testLane,t.testLane))throw new Error("Node host returned inconsistent readiness metadata");clearTimeout(d),n();}this.dispatch(s);}}catch(s){u(s instanceof Error?s:new Error(String(s))),i.kill();}}),i.once("exit",(l,s)=>{clearTimeout(d),this.stopped=true;let p=a??this.failure(`Node host exited (${l??s??"unknown"})`);this.onEvent({type:"host-exit",error:p}),u(p);});});o.catch(()=>{});try{await this.writeLine({protocolVersion:E,apiKey:this.options.apiKey,secretKey:this.options.secretKey,serviceId:this.options.serviceId,generation:this.options.generation,shardIds:this.options.shardIds,deviceId:this.options.deviceId,roomId:this.roomId,deviceName:this.options.deviceName,stateDirectory:this.options.stateDirectory,maxPeers:this.options.maxPeers,irohRelay:this.options.irohRelay!==!1},F),await o;}catch(n){throw this.terminalFailure??n}}async request(e,t){if(!this.child||this.stopped||!this.child.stdin.writable)throw new Error("[OpenRTC] Node host is closed.");if(this.pending.size>=ne)throw new Error("[OpenRTC] Node host has too many pending requests.");let o=randomUUID(),n=new Promise((c,i)=>{let a=setTimeout(()=>{this.pending.delete(o),i(new Error(`[OpenRTC] Node host ${e} response timed out.`));},L);this.pending.set(o,{resolve:c,reject:i,timer:a});});n.catch(()=>{});try{await this.writeLine({type:e,id:o,...t},U);}catch(c){let i=this.pending.get(o);i&&(clearTimeout(i.timer),this.pending.delete(o),i.reject(this.terminalFailure??this.failure(c instanceof Error?c.message:String(c))));}return n}close(){return this.closing??(this.closing=this.stop())}async stop(){if(!this.child)return;let e=this.child;try{this.stopped||await this.request("shutdown",{});}finally{e.stdin.end();let t=setTimeout(()=>e.kill("SIGTERM"),2e3),o=setTimeout(()=>e.kill("SIGKILL"),4e3);try{await this.childClosed;}finally{clearTimeout(t),clearTimeout(o);}}}parse(e){if(this.output=Buffer.concat([this.output,e]),this.output.length>N&&!this.output.includes(10))throw new Error("Node host output line exceeded its byte limit");let t=[];for(;;){let o=this.output.indexOf(10);if(o<0)break;if(o>N)throw new Error("Node host output line exceeded its byte limit");let n=this.output.subarray(0,o).toString("utf8").trim();this.output=this.output.subarray(o+1),n&&t.push(JSON.parse(n));}return t}writeLine(e,t){let o=`${JSON.stringify(e)}
1
+ import {a}from'./chunk-XXZEDZUU.js';import {a as a$2}from'./chunk-TPF643LU.js';import {a as a$1}from'./chunk-5336XOTL.js';import {c}from'./chunk-72NEEJQG.js';import {i,b as b$2,a as a$3}from'./chunk-3T57Y4EF.js';import'./chunk-FKAQDDUM.js';import'./chunk-BKCUXUHW.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import {e as e$1,b as b$3}from'./chunk-L7N4T2PX.js';import {b as b$1,d,e}from'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';import {spawn}from'child_process';import {constants}from'fs';import {access,readFile}from'fs/promises';import {isAbsolute,resolve,dirname}from'path';import {fileURLToPath}from'url';import {isDeepStrictEqual}from'util';import {randomUUID,verify,createHash}from'crypto';var E=1,F=24*1024,U=96*1024,N=128*1024,C=64*1024,ne=256,ie=256,L=3e4,se=/^[A-Za-z0-9_.:@-]+$/,ae=/(?:^|_)(?:SECRET|TOKEN|PASSWORD|PRIVATE(?:_KEY)?|CREDENTIALS?)(?:_|$)/i,ce=1;function de(r){return Buffer.from(JSON.stringify({schema:r.schema,kind:r.kind,platform:r.platform,arch:r.arch,rustTarget:r.rustTarget,sourceCommit:r.sourceCommit,sourceDigest:r.sourceDigest,binarySha256:r.binarySha256,protocol:r.protocol,signingKeySha256:r.signingKeySha256,signatureAlgorithm:r.signatureAlgorithm}),"utf8")}async function le(r,e,t){let[o,n,c]=await Promise.all([readFile(t),readFile(resolve(e,"openrtc-node-host.manifest.json")),readFile(resolve(r,"native","openrtc-node-host-signing-public.pem"))]).catch(()=>{throw new Error("[OpenRTC] Packaged Node host provenance is incomplete.")}),i;try{i=JSON.parse(n.toString("utf8"));}catch{throw new Error("[OpenRTC] Packaged Node host manifest is invalid.")}let a=s=>createHash("sha256").update(s).digest("hex"),u={"darwin-arm64":"aarch64-apple-darwin","darwin-x64":"x86_64-apple-darwin","linux-x64":"x86_64-unknown-linux-gnu"}[`${process.platform}-${process.arch}`];if(!(i!=null&&u!==void 0&&i.schema===ce&&i.kind==="openrtc-node-host"&&i.platform===process.platform&&i.arch===process.arch&&i.rustTarget===u&&/^[0-9a-f]{40}$/.test(i.sourceCommit)&&/^[0-9a-f]{64}$/.test(i.sourceDigest)&&i.binarySha256===a(o)&&i.signingKeySha256===a(c)&&i.signatureAlgorithm==="ed25519"&&/^[A-Za-z0-9+/]{86}==$/.test(i.signature)&&verify(null,de(i),c,Buffer.from(i.signature,"base64"))))throw new Error("[OpenRTC] Packaged Node host provenance verification failed.")}function z(r){return Object.fromEntries(Object.entries(process.env).filter(([e,t])=>!ae.test(e)&&(!r||!t?.includes(r))))}function f(r,e){queueMicrotask(()=>{try{let t=r(e);t&&typeof t.then=="function"&&t.catch(()=>{try{process.emitWarning("[OpenRTC] ServiceNode callback failed.",{code:"OPENRTC_SERVICE_CALLBACK"});}catch{}});}catch{try{process.emitWarning("[OpenRTC] ServiceNode callback failed.",{code:"OPENRTC_SERVICE_CALLBACK"});}catch{}}});}function $(r){let e=/^\d{1,20}$/;return typeof r.transportStableId!="string"||!e.test(r.transportStableId)||!e.test(r.transportGeneration)||!e.test(r.routeGeneration)?null:{transportStableId:r.transportStableId,transportGeneration:r.transportGeneration,routeGeneration:r.routeGeneration}}function ue(r,e){return r.transportStableId===e.transportStableId&&r.transportGeneration===e.transportGeneration&&r.routeGeneration===e.routeGeneration}function m(r,e,t=160){let o=r.trim();if(!o||o.length>t||!se.test(o))throw new TypeError(`[OpenRTC] ${e} is invalid.`);return o}function v(r,e,t=Number.MAX_SAFE_INTEGER){if(!Number.isSafeInteger(r)||r<1||r>t)throw new RangeError(`[OpenRTC] ${e} must be a positive safe integer.`);return r}function pe(r){if(!/^pk_(?:live|test)_[A-Za-z0-9]+$/.test(r.apiKey))throw new TypeError("[OpenRTC] apiKey is invalid.");if(!/^sk_(?:live|test)_[A-Za-z0-9_-]+$/.test(r.secretKey)||r.secretKey.length>128)throw new TypeError("[OpenRTC] secretKey is invalid.");let e=[...r.shardIds].map(t=>m(t,"shardId",80)).sort();if(e.length<1||e.length>64||new Set(e).size!==e.length)throw new RangeError("[OpenRTC] shardIds must contain 1..64 unique identifiers.");if(!isAbsolute(r.stateDirectory))throw new TypeError("[OpenRTC] stateDirectory must be absolute.");return r.maxPeers!==void 0&&v(r.maxPeers,"maxPeers",50),r.startupTimeoutMs!==void 0&&v(r.startupTimeoutMs,"startupTimeoutMs",12e4),{...r,serviceId:m(r.serviceId,"serviceId",80),generation:v(r.generation,"generation"),shardIds:e,deviceId:m(r.deviceId,"deviceId"),deviceName:r.deviceName?.trim()||"OpenRTC Node service"}}async function y(r){try{return await access(r,process.platform==="win32"?constants.F_OK:constants.X_OK),!0}catch{return false}}async function V(r,e,t,o,n){return new Promise((c,i)=>{let a=spawn(r,e,{cwd:t,env:z(n),stdio:["ignore","pipe","pipe"]}),d=Buffer.alloc(0),u=Buffer.alloc(0),l=(p,Y)=>Buffer.concat([p,Y]).subarray(-N);a.stdout.on("data",p=>{d=l(d,p);}),a.stderr.on("data",p=>{u=l(u,p);});let s=setTimeout(()=>{a.kill(),i(new Error(`[OpenRTC] Node host command timed out: ${r}.`));},o);a.once("error",p=>{clearTimeout(s),i(p);}),a.once("exit",p=>{clearTimeout(s),p===0?c(d.toString("utf8")):i(new Error(`[OpenRTC] Node host command failed (${p??"signal"}): ${u.toString("utf8").trim().slice(-4096)}`));});})}async function J(r){let e=r.binaryPath||process.env.OPENRTC_NODE_HOST_BINARY;if(e){if(!isAbsolute(e)||!await y(e))throw new Error("[OpenRTC] Node host binaryPath must name an executable absolute path.");return {command:e,args:[...r.binaryArgs??[]]}}if(r.buildFromSource){let c=r.sourceRoot||process.env.OPENRTC_SOURCE_ROOT;if(!c||!isAbsolute(c))throw new Error("[OpenRTC] buildFromSource requires an absolute sourceRoot or OPENRTC_SOURCE_ROOT.");let i=resolve(c,"crates/openrtc/Cargo.toml"),a=resolve(c,"target");await V("cargo",["build","--locked","--manifest-path",i,"--features","node-host","--bin","openrtc-node-host","--target-dir",a],c,12e4,r.secretKey);let d=resolve(a,"debug",`openrtc-node-host${process.platform==="win32"?".exe":""}`);if(!await y(d))throw new Error("[OpenRTC] local Node host build did not produce an executable.");return {command:d,args:[]}}let t=resolve(dirname(fileURLToPath(import.meta.url)),".."),o=resolve(t,"native",`${process.platform}-${process.arch}`),n=resolve(o,`openrtc-node-host${process.platform==="win32"?".exe":""}`);if(!await y(n))throw new Error(`[OpenRTC] This package has no Node host for ${process.platform}-${process.arch}. Install a supported OpenRTC package, set OPENRTC_NODE_HOST_BINARY, or use buildFromSource with sourceRoot.`);return await le(t,o,n),{command:n,args:[]}}async function X(r,e){let t=await V(r.command,[...r.args,"--protocol-info"],process.cwd(),12e4,e),o=JSON.parse(t);if(o.protocolVersion!==E||o.lifecycleOwner!=="rust-peer-session"||o.maxConfigBytes!==F||o.maxCommandBytes!==U||o.maxApplicationPayloadBytes!==C)throw new Error("[OpenRTC] Node host protocol is incompatible.");return o}var I=class{constructor(e,t,o){this.options=e;this.roomId=t;this.onEvent=o;this.child=null;this.childClosed=Promise.resolve();this.output=Buffer.alloc(0);this.stderr=Buffer.alloc(0);this.pending=new Map;this.writeQueue=Promise.resolve();this.stopped=false;this.closing=null;}async start(){let e=await J(this.options),t=await X(e,this.options.secretKey),o=new Promise((n,c)=>{let i=spawn(e.command,[...e.args],{env:z(this.options.secretKey),stdio:["pipe","pipe","pipe"]});this.child=i,this.childClosed=new Promise(l=>i.once("close",()=>l()));let a,d=setTimeout(()=>{c(this.failure("Node host startup timed out")),i.kill();},this.options.startupTimeoutMs??L),u=l=>{clearTimeout(d);let s=b$3.is(l)?l:this.failure(l.message);this.terminalFailure=a??s,c(s),this.failAll(s);};i.once("error",u),i.stdin.on("error",l=>{u(a??l),i.kill();}),i.stderr.on("data",l=>{this.stderr=Buffer.concat([this.stderr,l]).subarray(-4096);}),i.stdout.on("data",l=>{try{for(let s of this.parse(l)){if(s.type==="failure"){a=this.failure(s.error,s.serviceError),u(a);continue}if(t.testLane&&process.env.OPENRTC_NODE_HOST_LOCAL_TRACE==="1"&&s.type==="connection-state"&&console.error("[openrtc-local-node]",this.options.deviceId,{connectionId:s.snapshot.connectionId,deviceId:s.snapshot.deviceId,state:s.snapshot.state,routable:s.snapshot.routable,transportStableId:s.transportStableId,transportGeneration:s.transportGeneration,routeGeneration:s.routeGeneration}),s.type==="ready"){if(s.protocolVersion!==E||s.roomId!==this.roomId||s.deviceId!==this.options.deviceId||!isDeepStrictEqual(s.testLane,t.testLane))throw new Error("Node host returned inconsistent readiness metadata");clearTimeout(d),n();}this.dispatch(s);}}catch(s){u(s instanceof Error?s:new Error(String(s))),i.kill();}}),i.once("exit",(l,s)=>{clearTimeout(d),this.stopped=true;let p=a??this.failure(`Node host exited (${l??s??"unknown"})`);this.onEvent({type:"host-exit",error:p}),u(p);});});o.catch(()=>{});try{await this.writeLine({protocolVersion:E,apiKey:this.options.apiKey,secretKey:this.options.secretKey,serviceId:this.options.serviceId,generation:this.options.generation,shardIds:this.options.shardIds,deviceId:this.options.deviceId,roomId:this.roomId,deviceName:this.options.deviceName,stateDirectory:this.options.stateDirectory,maxPeers:this.options.maxPeers,irohRelay:this.options.irohRelay!==!1},F),await o;}catch(n){throw this.terminalFailure??n}}async request(e,t){if(!this.child||this.stopped||!this.child.stdin.writable)throw new Error("[OpenRTC] Node host is closed.");if(this.pending.size>=ne)throw new Error("[OpenRTC] Node host has too many pending requests.");let o=randomUUID(),n=new Promise((c,i)=>{let a=setTimeout(()=>{this.pending.delete(o),i(new Error(`[OpenRTC] Node host ${e} response timed out.`));},L);this.pending.set(o,{resolve:c,reject:i,timer:a});});n.catch(()=>{});try{await this.writeLine({type:e,id:o,...t},U);}catch(c){let i=this.pending.get(o);i&&(clearTimeout(i.timer),this.pending.delete(o),i.reject(this.terminalFailure??this.failure(c instanceof Error?c.message:String(c))));}return n}close(){return this.closing??(this.closing=this.stop())}async stop(){if(!this.child)return;let e=this.child;try{this.stopped||await this.request("shutdown",{});}finally{e.stdin.end();let t=setTimeout(()=>e.kill("SIGTERM"),2e3),o=setTimeout(()=>e.kill("SIGKILL"),4e3);try{await this.childClosed;}finally{clearTimeout(t),clearTimeout(o);}}}parse(e){if(this.output=Buffer.concat([this.output,e]),this.output.length>N&&!this.output.includes(10))throw new Error("Node host output line exceeded its byte limit");let t=[];for(;;){let o=this.output.indexOf(10);if(o<0)break;if(o>N)throw new Error("Node host output line exceeded its byte limit");let n=this.output.subarray(0,o).toString("utf8").trim();this.output=this.output.subarray(o+1),n&&t.push(JSON.parse(n));}return t}writeLine(e,t){let o=`${JSON.stringify(e)}
2
2
  `;if(Buffer.byteLength(o,"utf8")-1>t)return Promise.reject(new Error("Node host input line exceeded its byte limit"));let n=this.writeQueue.then(()=>new Promise((c,i)=>{if(!this.child||this.stopped||!this.child.stdin.writable){i(new Error("Node host is closed"));return}this.child.stdin.write(o,a=>{a?i(a):c();});}));return this.writeQueue=n.catch(()=>{}),n}dispatch(e){if(e.type!=="response"){this.onEvent(e);return}let t=this.pending.get(e.id);t&&(clearTimeout(t.timer),this.pending.delete(e.id),e.ok?t.resolve(e.value):t.reject(this.failure(e.error||"Node host request failed",e.serviceError)));}failure(e$2,t){let o=a=>a.split(this.options.secretKey).join("[REDACTED]"),n=o(e$2),c=o(this.stderr.toString("utf8")).trim(),i=`[OpenRTC] ${n}.${c?` Host stderr: ${c}`:""}`;if(t&&typeof t=="object"&&!Array.isArray(t)){let a=t,d$1=b$1(a.code);if(d(a.code)||d$1){let u=e(a);return e$1({...u,requestId:u.requestId?o(u.requestId):void 0,code:a.code,retryable:typeof a.retryable=="boolean"?a.retryable:!!d$1,message:i})}}return new Error(i)}failAll(e){for(let t of this.pending.values())clearTimeout(t.timer),t.reject(e);this.pending.clear();}},S=class{constructor(e,t,o,n,c){this.id=e;this.peerId=t;this.host=o;this.nativeGeneration=n;this.capabilityKey=c;this.messages=new Set;this.closeListeners=new Set;this.queued=[];this.isClosed=false;}async send(e){if(this.isClosed)throw new Error("[OpenRTC] Connection is closed.");let t=he(e instanceof Uint8Array||e instanceof ArrayBuffer?e:a$3("raw","message",e,this.capabilityKey));await this.host.request("send",{connectionId:this.id,payloadBase64:t.toString("base64")});}onMessage(e){let t=e;this.messages.add(t);for(let o of this.queued.splice(0))f(t,o);return ()=>this.messages.delete(t)}onClose(e){return this.isClosed?f(e,void 0):this.closeListeners.add(e),()=>this.closeListeners.delete(e)}receive(e){if(!this.isClosed){if(this.messages.size===0){this.queued.length===ie&&this.queued.shift(),this.queued.push(e);return}for(let t of this.messages)f(t,e);}}close(){if(!this.isClosed){this.isClosed=true,this.queued.length=0;for(let e of this.closeListeners)f(e,void 0);this.messages.clear(),this.closeListeners.clear();}}accepts(e){return ue(e,this.nativeGeneration)}replaceGeneration(e){this.nativeGeneration=e;}},T=class{constructor(e,t,o){this.id=e;this.host=t;this.onServiceError=o;this.kind="room";this.listeners=new Set;this.connections=new Map;this.closed=false;}publishAssignment(e){if(this.closed)return Promise.reject(new Error("[OpenRTC] Service room is closed."));let t=(e.priorityDeviceIds??[]).map(n=>m(n,"priorityDeviceId")),o=(e.relevantEntityIds??[]).map(n=>m(n,"relevantEntityId"));return t.length>8||o.length>32||new Set(t).size!==t.length||new Set(o).size!==o.length?Promise.reject(new Error("[OpenRTC] Authority assignment identifiers are invalid.")):this.host.request("publish-assignment",{revision:v(e.revision,"revision"),subjectDeviceId:m(e.subjectDeviceId,"subjectDeviceId"),shardId:m(e.shardId,"shardId",80),priorityDeviceIds:t,relevantEntityIds:o,ttlMs:e.ttlMs===void 0?void 0:v(e.ttlMs,"ttlMs",12e4)})}onConnection(e){this.listeners.add(e);for(let t of this.connections.values())f(e,t);return ()=>this.listeners.delete(e)}project(e){if(this.closed)return;if(e.type==="host-exit"){this.closed=true;for(let d of this.connections.values())d.close();this.connections.clear(),this.listeners.clear();return}if(e.type==="service-error"){let d=e.avenue;if(!d||typeof d!="object"||Array.isArray(d))return;let u=d;if(u.kind!=="room"||u.id!==this.id||typeof e.runtimeInstanceId!="string"||e.runtimeInstanceId.trim().length===0)return;let l=a$2(e.serviceError,{kind:"room",id:this.id});l&&this.onServiceError&&f(()=>{if(!this.closed)return this.onServiceError?.(l)},void 0);return}if(e.type==="peer-message"){let d=this.connections.get(e.connectionId),u=$(e);if(d&&u&&d.accepts(u)){let l=fe(e.payloadBase64),s=b$2(l);s?s.capability===`room:${this.id}`&&s.kind==="raw"&&d.receive(s.value):d.receive(l);}return}if(e.type!=="connection-state")return;let t=e.snapshot,o=$(e);if(typeof t.connectionId!="string"||!o)return;let n=this.connections.get(t.connectionId);if(typeof t.state=="string"&&["closed","failed"].includes(t.state.toLowerCase())){n?.accepts(o)&&(n.close(),this.connections.delete(t.connectionId));return}if(n){t.routable===true&&n.replaceGeneration(o);return}let i=typeof t.remoteNodeId=="string"?t.remoteNodeId:null;if(t.routable!==true||!i)return;let a=new S(t.connectionId,i,this.host,o,`room:${this.id}`);this.connections.set(a.id,a);for(let d of this.listeners)f(d,a);}async close(){if(this.closed)return this.host.close();this.closed=true;for(let e of this.connections.values())e.close();this.connections.clear(),this.listeners.clear(),await this.host.close();}};function he(r){let e;if(r instanceof Uint8Array)e=Buffer.from(r);else if(r instanceof ArrayBuffer)e=Buffer.from(r);else if(typeof r=="string")e=Buffer.from(r,"utf8");else {let t=JSON.stringify(r);if(t===void 0)throw new TypeError("[OpenRTC] Message must be a string, bytes, or JSON value.");e=Buffer.from(t,"utf8");}if(e.length>C)throw new RangeError("[OpenRTC] Message exceeds the Node host payload limit.");return e}function fe(r){let e=Buffer.from(r,"base64");if(e.length>C)throw new Error("[OpenRTC] Node host returned an oversized application payload.");try{let t=new TextDecoder("utf-8",{fatal:!0}).decode(e);try{return JSON.parse(t)}catch{return t}}catch{return new Uint8Array(e)}}var b=class{constructor(e){this.listeners=new Set;this.roomPromise=null;this.roomId=null;this.closed=false;this.closing=null;this.options=pe(e);}onConnection(e){if(this.closed)throw new Error("[OpenRTC] ServiceNode is closed.");return this.listeners.add(e),()=>this.listeners.delete(e)}listen(e){return this.closed?Promise.reject(new Error("[OpenRTC] ServiceNode is closed.")):(e=m(e,"roomId"),this.roomId&&this.roomId!==e?Promise.reject(new Error("[OpenRTC] A Node ServiceNode owns exactly one room.")):this.roomPromise?this.roomPromise:(this.roomId=e,this.roomPromise=this.open(e),this.roomPromise))}close(){return this.closing??(this.closing=this.stop())}async stop(){this.closed=true,await(await this.roomPromise?.catch(()=>null))?.close(),this.listeners.clear();}async open(e){let t,o=new I(this.options,e,n=>t?.project(n));t=new T(e,o,this.options.onServiceError);try{return await o.start(),t.onConnection(n=>{for(let c of this.listeners)f(c,{room:t,connection:n});}),t}catch(n){throw await o.close().catch(()=>{}),this.roomPromise=null,this.roomId=null,n}}};async function me(r){let e=await J(r);return X(e)}function ke(r,e){let t=c(e,"openrtc/node"),o=new a;return i(r,{platform:"native",broadcastHostFactory:async n=>{let{NativeManagedBroadcastHost:c}=await import('./NativeManagedBroadcastHost-6A2QP3A7.js');return new c(t,n)},offlineSupport:()=>t.invoke("openrtc_offline_runtime_support"),createOfflineEnrollmentRequest:async n=>{let c=await t.invoke("start_iroh_node");return t.invoke("openrtc_create_offline_enrollment_request",{trustDomain:n.trustDomain,deviceId:n.deviceId,endpointId:c,enrollmentNonce:crypto.randomUUID(),requestedRoles:n.requestedRoles})},close:()=>o.close(),deviceKeyProvider:a$1(t),deviceIdProvider:async()=>{let n=await t.invoke("get_rtc_local_device_info");return String(n?.deviceId??"")},runtimeFactory:async n=>{let{createIpcClient:c}=await import('./ipcFactory-6XD3J2UU.js');return c(n,t,o)}})}export{ke as OpenRTC,b as ServiceNode,me as inspectNodeHost};
Binary file
@@ -1 +1 @@
1
- import {h,e,g,f}from'./chunk-RUOVYQ2P.js';import'./chunk-FKAQDDUM.js';import'./chunk-SSBR3IHA.js';import {a}from'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import {b}from'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';function D(r){let e=r.architecture??(r.advancedFanout===true?"sparse":"auto");if(r.advancedFanout===true&&e!=="sparse")throw new Error("[OpenRTC] advancedFanout conflicts with architecture; use architecture: sparse only.");return {architecture:e,delivery:r.payload??(r.advancedFanout===true?"latest-state":"reliable")}}var R=class{constructor(e){this.mode=e==="sparse"?"sparse":"direct";}create(e){return new w(e,()=>this.mode)}setArchitecture(e){e.phase==="settled"&&(this.mode=e.effective==="sparse"?"sparse":e.effective==="managed"?"managed":"direct");}},w=class{constructor(e,t){this.host=e;this.mode=t;this.stateSenders=new Map;this.sparseForwardQueue=[];this.sparseForwardRunning=false;this.sparseForwardQueueDropsPending=0;this.sparseForwardDropReport=null;this.closed=false;let i=e.client.advanced.runtime.onManagedRoomMessage;this.stopManagedMessage=typeof i=="function"?i.call(e.client.advanced.runtime,o=>{e.deliver(o.senderId,o.payload,o.channel);}):()=>{};}isSparse(){return this.mode()==="sparse"}publishState(e,t){if(this.mode()!=="managed")return false;let i=this.stateSenders.get(e);return i||(i=new a(o=>this.publishManaged(e,o)),this.stateSenders.set(e,i)),i.send(t).catch(()=>{}),true}async sendChannel(e,t){let i=this.mode();if(i==="managed")return await this.publishManaged(e,t),true;if(i!=="sparse")return false;let o=this.host.connections();if(o.length===0)return true;let a=await this.host.client.advanced.runtime.encodeSparseFanoutMessage(this.host.capabilityKey,t);return await Promise.all(o.map(n=>n.send(a))),true}assertTargetedSendAllowed(){if(this.mode()==="managed")throw new Error("[OpenRTC] Targeted messages are not available in managed fanout rooms; use authority mode for targeted request semantics.")}receive(e,t,i){return this.mode()!=="sparse"?false:(i instanceof Uint8Array&&this.receiveSparseBroadcast(e,t,i),true)}close(){if(!this.closed){this.closed=true,this.stopManagedMessage();for(let e of this.stateSenders.values())e.close();this.stateSenders.clear(),this.sparseForwardQueue.length=0;}}publishManaged(e,t){return this.host.client.advanced.runtime.publishManagedRoomMessage({messageId:crypto.randomUUID(),channel:e,priority:1,payload:t})}async receiveSparseBroadcast(e,t,i){let o;try{o=await this.host.client.advanced.runtime.acceptSparseFanoutMessage(this.host.capabilityKey,t,i);}catch{return}if(o.forward){let a=Number.isSafeInteger(o.forwardPeerLimit)&&o.forwardPeerLimit>0?o.forwardPeerLimit:0,n=Number.isSafeInteger(o.forwardQueueCapacity)&&o.forwardQueueCapacity>0?Math.min(o.forwardQueueCapacity,64):0,d=new Set(Array.isArray(o.forwardPeerIds)?o.forwardPeerIds.slice(0,a):[]),s=this.host.connections().filter(u=>u.id!==e.id).filter(u=>d.has(u.remoteNodeId)).slice(0,a);this.enqueueSparseForward(o.forward,s,n);}this.host.deliver(o.authorDeviceId,o.payload);}enqueueSparseForward(e,t,i){if(i===0||t.length===0||this.closed)return;if(this.sparseForwardQueue.length+(this.sparseForwardRunning?1:0)>=i){this.sparseForwardQueueDropsPending+=1,this.flushSparseForwardDropReport();return}this.sparseForwardQueue.push({payload:e,targets:t}),this.sparseForwardRunning||this.drainSparseForwardQueue();}async drainSparseForwardQueue(){if(!this.sparseForwardRunning){this.sparseForwardRunning=true;try{for(;!this.closed;){let e=this.sparseForwardQueue.shift();if(!e)break;await Promise.allSettled(e.targets.map(t=>t.send(e.payload)));}}finally{this.sparseForwardRunning=false,!this.closed&&this.sparseForwardQueue.length>0&&this.drainSparseForwardQueue();}}}flushSparseForwardDropReport(){if(this.sparseForwardDropReport||this.sparseForwardQueueDropsPending===0)return;let e=this.sparseForwardQueueDropsPending;this.sparseForwardQueueDropsPending=0,this.sparseForwardDropReport=this.host.client.advanced.runtime.recordSparseFanoutForwardQueueDrop(this.host.capabilityKey,e).catch(()=>{}).finally(()=>{this.sparseForwardDropReport=null,this.flushSparseForwardDropReport();});}};function F(r){return Object.freeze(r.filter(e=>!!(e.deviceId||e.nodeId)).map(e=>Object.freeze({deviceId:e.deviceId||e.nodeId,...e.nodeId?{nodeId:e.nodeId}:{},...typeof e.userId=="string"?{userId:e.userId}:{},...Number.isFinite(e.joinedAt)?{joinedAt:e.joinedAt}:{}})))}var y=class extends h{constructor(t,i,o,a,n,d="auto"){let s=new R(d);super("room",t,i,o,s);this.membership=a;this.onLeave=n;this.kind="room";this.left=false;this.memberWatches=new Map;this.members={list:async()=>{if(this.closed)return [];let t=await this.client.rooms.members(this.id);return this.closed?[]:F(t)},watch:t=>{if(this.closed)return t([]),()=>{};let i=true,o=this.client.rooms.watch(this.id,n=>{i&&!this.closed&&t(F(n));}),a=()=>{i&&(i=false,this.memberWatches.delete(a),o());};return this.memberWatches.set(a,t),a}};this.architectureListeners=new Set;this.authorityAssignmentSnapshot=null;this.authorityAssignmentListeners=new Set;this.architectureSnapshot=Q(d);let u=i.advanced.runtime.onRoomArchitectureChange;this.stopArchitecture=typeof u=="function"?u.call(i.advanced.runtime,c=>{if(!(c.epoch<this.architectureSnapshot.epoch)){this.architectureSnapshot=Object.freeze({...c}),this.setArchitecture(c);for(let h of this.architectureListeners)h(this.architectureSnapshot);}}):()=>{};let l=i.advanced.runtime.onRoomAuthorityAssignmentChange;this.stopAuthorityAssignment=typeof l=="function"?l.call(i.advanced.runtime,c=>{this.authorityAssignmentSnapshot=c?E(c):null;for(let h of this.authorityAssignmentListeners)h(M(this.authorityAssignmentSnapshot));}):()=>{};}architecture(){return {...this.architectureSnapshot}}onArchitectureChanged(t){return this.architectureListeners.add(t),t(this.architecture()),()=>this.architectureListeners.delete(t)}authorityAssignment(){return M(this.authorityAssignmentSnapshot)}onAuthorityAssignmentChanged(t){return this.authorityAssignmentListeners.add(t),t(this.authorityAssignment()),()=>this.authorityAssignmentListeners.delete(t)}async leave(){this.left||(this.left=true,await this.onLeave?.()),await this.close();}async close(){this.fenceProductAccess();let t=[...this.memberWatches];this.memberWatches.clear();for(let[i,o]of t)i(),o([]);this.stopArchitecture(),this.stopAuthorityAssignment(),this.architectureListeners.clear(),this.authorityAssignmentListeners.clear(),await super.close();}};async function j(r,e$1,t){r.assertOpen();let i=e(e$1),o=t.access??"capability",{architecture:a,delivery:n}=D(t);return r.activateOnce(`room:${i}`,JSON.stringify({access:o,membership:t.membership??"ephemeral",identity:t.identity??null,maxPeers:t.maxPeers??null,payload:n,architecture:a,advancedFanout:t.advancedFanout===true}),o==="authenticated"?t.auth??r.options.auth:void 0,()=>x(r,i,t,a,n))}async function x(r,e,t,i,o){let a=t.membership??"ephemeral",n=t.access??"capability";if(i==="sparse"&&o!=="latest-state")throw new Error("[OpenRTC] Sparse rooms require payload: latest-state.");if(a==="durable"&&n!=="authenticated")throw new Error("[OpenRTC] Durable room membership requires access: authenticated.");if(t.identity==="session"&&n!=="capability")throw new Error("[OpenRTC] Session room identity requires access: capability.");if(n==="authenticated"){let h=t.auth??r.options.auth;if(!h)throw new Error("[OpenRTC] Authenticated rooms require an auth provider.");let A=await r.deviceId(),v=await r.controlPlane(),m=await v.deviceCertificate(h,A,{kind:"room",id:e});a==="durable"&&await v.durableRoomMembership(m.source,e,"join");let f;try{f=await r.activate({kind:"room",id:e,source:m.source,principalId:m.principalId,deviceId:A,maxPeers:t.maxPeers,autoConnect:!0,durableMembership:a==="durable",advancedFanout:t.advancedFanout,architecture:i,defaultDelivery:o});}catch(O){throw a==="durable"&&await v.durableRoomMembership(m.source,e,"leave").catch(()=>{}),O}let g;return g=new y(e,f,()=>{r.channels.detach(f),r.onClosed(g);},a,a==="durable"?async()=>{await v.durableRoomMembership(m.source,e,"leave");}:void 0,i),r.trackHandle(g)}let d=await(t.identity==="session"?r.sessionPlane():r.controlPlane()),s=await d.capability("room",e,t.maxPeers,t.advancedFanout,i,o),u=String(b(s.token).principalId),l=await r.activate({kind:"room",id:e,source:s,principalId:u,deviceId:g(s),maxPeers:t.maxPeers,autoConnect:true,advancedFanout:t.advancedFanout,architecture:i,defaultDelivery:o,controlPlane:d}),c;return c=new y(e,l,()=>{r.channels.detach(l),r.onClosed(c);},"ephemeral",void 0,i),r.trackHandle(c)}function z(r,e$1){r.assertOpen();let t=e(e$1.roomId),i=e(e$1.serviceId),o=f(e$1.deviceId);if(!Number.isSafeInteger(e$1.generation)||e$1.generation<1)throw new Error("[OpenRTC] Authority service generation is invalid.");let a=[...e$1.shardIds].map(e).sort();if(a.length<1||a.length>64||new Set(a).size!==a.length)throw new Error("[OpenRTC] Authority service shards are invalid.");if(!/^[A-Za-z0-9_-]{43}$/.test(e$1.devicePublicKeyX))throw new Error("[OpenRTC] Authority service device public key is invalid.");if(!/^[A-Za-z0-9_-]{43}$/.test(e$1.assignmentPublicKeyX))throw new Error("[OpenRTC] Authority assignment public key is invalid.");if(e$1.maxPeers!==void 0&&(!Number.isSafeInteger(e$1.maxPeers)||e$1.maxPeers<1||e$1.maxPeers>50))throw new Error("[OpenRTC] Authority service maxPeers must be within 1..50.");return r.activateOnce(`room:${t}`,JSON.stringify({architecture:"authority",serviceId:i,generation:e$1.generation,shardIds:a,deviceId:o,maxPeers:e$1.maxPeers??null,irohRelay:e$1.irohRelay,devicePublicKeyX:e$1.devicePublicKeyX,assignmentPublicKeyX:e$1.assignmentPublicKeyX,deviceSignerId:r.authorityCallableId(e$1.deviceSign),grantProviderId:r.authorityCallableId(e$1.grantProvider)}),void 0,async()=>{let n={type:"capability",token:"",avenue:{kind:"room",id:t},expiresAtMs:Number.MAX_SAFE_INTEGER,irohRelay:e$1.irohRelay,managedTurn:false},d=await r.activate({kind:"room",id:t,source:n,principalId:i,deviceId:o,maxPeers:e$1.maxPeers,autoConnect:true,architecture:"authority",defaultDelivery:"reliable",authority:{serviceId:i,generation:e$1.generation,shardIds:a,deviceId:o,irohRelay:e$1.irohRelay,devicePublicKeyX:e$1.devicePublicKeyX,assignmentPublicKeyX:e$1.assignmentPublicKeyX,deviceSign:e$1.deviceSign,grantProvider:e$1.grantProvider}}),s;return s=new y(t,d,()=>{r.channels.detach(d),r.onClosed(s);},"ephemeral",void 0,"authority"),r.trackHandle(s)})}function E(r){return Object.freeze({...r,priorityDeviceIds:Object.freeze([...r.priorityDeviceIds]),relevantEntityIds:Object.freeze([...r.relevantEntityIds])})}function M(r){return r?{...r,priorityDeviceIds:[...r.priorityDeviceIds],relevantEntityIds:[...r.relevantEntityIds]}:null}function Q(r){return {requested:r,effective:r==="sparse"?"sparse":"mesh",epoch:0,phase:r==="mesh"||r==="sparse"?"settled":"preparing",reason:r==="auto"?"size":"manual"}}export{y as RoomHandle,j as joinRoom,z as openAuthorityRoom,D as resolveRoomJoinOptions};
1
+ import {h,e,g,f}from'./chunk-3T57Y4EF.js';import'./chunk-FKAQDDUM.js';import'./chunk-BKCUXUHW.js';import {a}from'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import {b}from'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';function D(r){let e=r.architecture??(r.advancedFanout===true?"sparse":"auto");if(r.advancedFanout===true&&e!=="sparse")throw new Error("[OpenRTC] advancedFanout conflicts with architecture; use architecture: sparse only.");return {architecture:e,delivery:r.payload??(r.advancedFanout===true?"latest-state":"reliable")}}var R=class{constructor(e){this.mode=e==="sparse"?"sparse":"direct";}create(e){return new w(e,()=>this.mode)}setArchitecture(e){e.phase==="settled"&&(this.mode=e.effective==="sparse"?"sparse":e.effective==="managed"?"managed":"direct");}},w=class{constructor(e,t){this.host=e;this.mode=t;this.stateSenders=new Map;this.sparseForwardQueue=[];this.sparseForwardRunning=false;this.sparseForwardQueueDropsPending=0;this.sparseForwardDropReport=null;this.closed=false;let i=e.client.advanced.runtime.onManagedRoomMessage;this.stopManagedMessage=typeof i=="function"?i.call(e.client.advanced.runtime,o=>{e.deliver(o.senderId,o.payload,o.channel);}):()=>{};}isSparse(){return this.mode()==="sparse"}publishState(e,t){if(this.mode()!=="managed")return false;let i=this.stateSenders.get(e);return i||(i=new a(o=>this.publishManaged(e,o)),this.stateSenders.set(e,i)),i.send(t).catch(()=>{}),true}async sendChannel(e,t){let i=this.mode();if(i==="managed")return await this.publishManaged(e,t),true;if(i!=="sparse")return false;let o=this.host.connections();if(o.length===0)return true;let a=await this.host.client.advanced.runtime.encodeSparseFanoutMessage(this.host.capabilityKey,t);return await Promise.all(o.map(n=>n.send(a))),true}assertTargetedSendAllowed(){if(this.mode()==="managed")throw new Error("[OpenRTC] Targeted messages are not available in managed fanout rooms; use authority mode for targeted request semantics.")}receive(e,t,i){return this.mode()!=="sparse"?false:(i instanceof Uint8Array&&this.receiveSparseBroadcast(e,t,i),true)}close(){if(!this.closed){this.closed=true,this.stopManagedMessage();for(let e of this.stateSenders.values())e.close();this.stateSenders.clear(),this.sparseForwardQueue.length=0;}}publishManaged(e,t){return this.host.client.advanced.runtime.publishManagedRoomMessage({messageId:crypto.randomUUID(),channel:e,priority:1,payload:t})}async receiveSparseBroadcast(e,t,i){let o;try{o=await this.host.client.advanced.runtime.acceptSparseFanoutMessage(this.host.capabilityKey,t,i);}catch{return}if(o.forward){let a=Number.isSafeInteger(o.forwardPeerLimit)&&o.forwardPeerLimit>0?o.forwardPeerLimit:0,n=Number.isSafeInteger(o.forwardQueueCapacity)&&o.forwardQueueCapacity>0?Math.min(o.forwardQueueCapacity,64):0,d=new Set(Array.isArray(o.forwardPeerIds)?o.forwardPeerIds.slice(0,a):[]),s=this.host.connections().filter(u=>u.id!==e.id).filter(u=>d.has(u.remoteNodeId)).slice(0,a);this.enqueueSparseForward(o.forward,s,n);}this.host.deliver(o.authorDeviceId,o.payload);}enqueueSparseForward(e,t,i){if(i===0||t.length===0||this.closed)return;if(this.sparseForwardQueue.length+(this.sparseForwardRunning?1:0)>=i){this.sparseForwardQueueDropsPending+=1,this.flushSparseForwardDropReport();return}this.sparseForwardQueue.push({payload:e,targets:t}),this.sparseForwardRunning||this.drainSparseForwardQueue();}async drainSparseForwardQueue(){if(!this.sparseForwardRunning){this.sparseForwardRunning=true;try{for(;!this.closed;){let e=this.sparseForwardQueue.shift();if(!e)break;await Promise.allSettled(e.targets.map(t=>t.send(e.payload)));}}finally{this.sparseForwardRunning=false,!this.closed&&this.sparseForwardQueue.length>0&&this.drainSparseForwardQueue();}}}flushSparseForwardDropReport(){if(this.sparseForwardDropReport||this.sparseForwardQueueDropsPending===0)return;let e=this.sparseForwardQueueDropsPending;this.sparseForwardQueueDropsPending=0,this.sparseForwardDropReport=this.host.client.advanced.runtime.recordSparseFanoutForwardQueueDrop(this.host.capabilityKey,e).catch(()=>{}).finally(()=>{this.sparseForwardDropReport=null,this.flushSparseForwardDropReport();});}};function F(r){return Object.freeze(r.filter(e=>!!(e.deviceId||e.nodeId)).map(e=>Object.freeze({deviceId:e.deviceId||e.nodeId,...e.nodeId?{nodeId:e.nodeId}:{},...typeof e.userId=="string"?{userId:e.userId}:{},...Number.isFinite(e.joinedAt)?{joinedAt:e.joinedAt}:{}})))}var y=class extends h{constructor(t,i,o,a,n,d="auto"){let s=new R(d);super("room",t,i,o,s);this.membership=a;this.onLeave=n;this.kind="room";this.left=false;this.memberWatches=new Map;this.members={list:async()=>{if(this.closed)return [];let t=await this.client.rooms.members(this.id);return this.closed?[]:F(t)},watch:t=>{if(this.closed)return t([]),()=>{};let i=true,o=this.client.rooms.watch(this.id,n=>{i&&!this.closed&&t(F(n));}),a=()=>{i&&(i=false,this.memberWatches.delete(a),o());};return this.memberWatches.set(a,t),a}};this.architectureListeners=new Set;this.authorityAssignmentSnapshot=null;this.authorityAssignmentListeners=new Set;this.architectureSnapshot=Q(d);let u=i.advanced.runtime.onRoomArchitectureChange;this.stopArchitecture=typeof u=="function"?u.call(i.advanced.runtime,c=>{if(!(c.epoch<this.architectureSnapshot.epoch)){this.architectureSnapshot=Object.freeze({...c}),this.setArchitecture(c);for(let h of this.architectureListeners)h(this.architectureSnapshot);}}):()=>{};let l=i.advanced.runtime.onRoomAuthorityAssignmentChange;this.stopAuthorityAssignment=typeof l=="function"?l.call(i.advanced.runtime,c=>{this.authorityAssignmentSnapshot=c?E(c):null;for(let h of this.authorityAssignmentListeners)h(M(this.authorityAssignmentSnapshot));}):()=>{};}architecture(){return {...this.architectureSnapshot}}onArchitectureChanged(t){return this.architectureListeners.add(t),t(this.architecture()),()=>this.architectureListeners.delete(t)}authorityAssignment(){return M(this.authorityAssignmentSnapshot)}onAuthorityAssignmentChanged(t){return this.authorityAssignmentListeners.add(t),t(this.authorityAssignment()),()=>this.authorityAssignmentListeners.delete(t)}async leave(){this.left||(this.left=true,await this.onLeave?.()),await this.close();}async close(){this.fenceProductAccess();let t=[...this.memberWatches];this.memberWatches.clear();for(let[i,o]of t)i(),o([]);this.stopArchitecture(),this.stopAuthorityAssignment(),this.architectureListeners.clear(),this.authorityAssignmentListeners.clear(),await super.close();}};async function j(r,e$1,t){r.assertOpen();let i=e(e$1),o=t.access??"capability",{architecture:a,delivery:n}=D(t);return r.activateOnce(`room:${i}`,JSON.stringify({access:o,membership:t.membership??"ephemeral",identity:t.identity??null,maxPeers:t.maxPeers??null,payload:n,architecture:a,advancedFanout:t.advancedFanout===true}),o==="authenticated"?t.auth??r.options.auth:void 0,()=>x(r,i,t,a,n))}async function x(r,e,t,i,o){let a=t.membership??"ephemeral",n=t.access??"capability";if(i==="sparse"&&o!=="latest-state")throw new Error("[OpenRTC] Sparse rooms require payload: latest-state.");if(a==="durable"&&n!=="authenticated")throw new Error("[OpenRTC] Durable room membership requires access: authenticated.");if(t.identity==="session"&&n!=="capability")throw new Error("[OpenRTC] Session room identity requires access: capability.");if(n==="authenticated"){let h=t.auth??r.options.auth;if(!h)throw new Error("[OpenRTC] Authenticated rooms require an auth provider.");let A=await r.deviceId(),v=await r.controlPlane(),m=await v.deviceCertificate(h,A,{kind:"room",id:e});a==="durable"&&await v.durableRoomMembership(m.source,e,"join");let f;try{f=await r.activate({kind:"room",id:e,source:m.source,principalId:m.principalId,deviceId:A,maxPeers:t.maxPeers,autoConnect:!0,durableMembership:a==="durable",advancedFanout:t.advancedFanout,architecture:i,defaultDelivery:o});}catch(O){throw a==="durable"&&await v.durableRoomMembership(m.source,e,"leave").catch(()=>{}),O}let g;return g=new y(e,f,()=>{r.channels.detach(f),r.onClosed(g);},a,a==="durable"?async()=>{await v.durableRoomMembership(m.source,e,"leave");}:void 0,i),r.trackHandle(g)}let d=await(t.identity==="session"?r.sessionPlane():r.controlPlane()),s=await d.capability("room",e,t.maxPeers,t.advancedFanout,i,o),u=String(b(s.token).principalId),l=await r.activate({kind:"room",id:e,source:s,principalId:u,deviceId:g(s),maxPeers:t.maxPeers,autoConnect:true,advancedFanout:t.advancedFanout,architecture:i,defaultDelivery:o,controlPlane:d}),c;return c=new y(e,l,()=>{r.channels.detach(l),r.onClosed(c);},"ephemeral",void 0,i),r.trackHandle(c)}function z(r,e$1){r.assertOpen();let t=e(e$1.roomId),i=e(e$1.serviceId),o=f(e$1.deviceId);if(!Number.isSafeInteger(e$1.generation)||e$1.generation<1)throw new Error("[OpenRTC] Authority service generation is invalid.");let a=[...e$1.shardIds].map(e).sort();if(a.length<1||a.length>64||new Set(a).size!==a.length)throw new Error("[OpenRTC] Authority service shards are invalid.");if(!/^[A-Za-z0-9_-]{43}$/.test(e$1.devicePublicKeyX))throw new Error("[OpenRTC] Authority service device public key is invalid.");if(!/^[A-Za-z0-9_-]{43}$/.test(e$1.assignmentPublicKeyX))throw new Error("[OpenRTC] Authority assignment public key is invalid.");if(e$1.maxPeers!==void 0&&(!Number.isSafeInteger(e$1.maxPeers)||e$1.maxPeers<1||e$1.maxPeers>50))throw new Error("[OpenRTC] Authority service maxPeers must be within 1..50.");return r.activateOnce(`room:${t}`,JSON.stringify({architecture:"authority",serviceId:i,generation:e$1.generation,shardIds:a,deviceId:o,maxPeers:e$1.maxPeers??null,irohRelay:e$1.irohRelay,devicePublicKeyX:e$1.devicePublicKeyX,assignmentPublicKeyX:e$1.assignmentPublicKeyX,deviceSignerId:r.authorityCallableId(e$1.deviceSign),grantProviderId:r.authorityCallableId(e$1.grantProvider)}),void 0,async()=>{let n={type:"capability",token:"",avenue:{kind:"room",id:t},expiresAtMs:Number.MAX_SAFE_INTEGER,irohRelay:e$1.irohRelay,managedTurn:false},d=await r.activate({kind:"room",id:t,source:n,principalId:i,deviceId:o,maxPeers:e$1.maxPeers,autoConnect:true,architecture:"authority",defaultDelivery:"reliable",authority:{serviceId:i,generation:e$1.generation,shardIds:a,deviceId:o,irohRelay:e$1.irohRelay,devicePublicKeyX:e$1.devicePublicKeyX,assignmentPublicKeyX:e$1.assignmentPublicKeyX,deviceSign:e$1.deviceSign,grantProvider:e$1.grantProvider}}),s;return s=new y(t,d,()=>{r.channels.detach(d),r.onClosed(s);},"ephemeral",void 0,"authority"),r.trackHandle(s)})}function E(r){return Object.freeze({...r,priorityDeviceIds:Object.freeze([...r.priorityDeviceIds]),relevantEntityIds:Object.freeze([...r.relevantEntityIds])})}function M(r){return r?{...r,priorityDeviceIds:[...r.priorityDeviceIds],relevantEntityIds:[...r.relevantEntityIds]}:null}function Q(r){return {requested:r,effective:r==="sparse"?"sparse":"mesh",epoch:0,phase:r==="mesh"||r==="sparse"?"settled":"preparing",reason:r==="auto"?"size":"manual"}}export{y as RoomHandle,j as joinRoom,z as openAuthorityRoom,D as resolveRoomJoinOptions};
@@ -1 +1 @@
1
- export{a as isDeviceActive,c as isDeviceConnectable,b as isDeviceRoutable}from'../chunk-CK6WQV7J.js';export{h as ConnectionActor,e as ConnectionActorError,i as ConnectionActors,a as ConnectionController,k as DEFAULT_MAX_FRAME_BYTES,t as IpcRuntimeAdapter,s as RuntimeClient,d as clog,q as concatRuntimeBytes,f as connectionActorKey,g as connectionActorKeyString,p as createJsonDecoder,l as createU32Decoder,n as decodeJsonPayload,o as encodeJsonFrame,m as encodeJsonPayload,j as encodeU32Frame,c as grantCorrelation,r as readRuntimeU32BE,b as renderCorrelation}from'../chunk-M4KL5XZU.js';import'../chunk-IXQ4KWGP.js';import'../chunk-CQHLD52E.js';export{u as BROWSER_CAPABILITIES,v as NATIVE_CAPABILITIES,s as RUNTIME_POLICY,x as browserCapabilities,z as capabilityProfile,w as cloneCapabilities,t as getRuntimePolicy,l as logTeardownTrace,h as openRtcDebug,g as openRtcDebugEnabled,i as openRtcDebugInfo,j as openRtcDebugLog,y as statusCapabilities}from'../chunk-LCJQ7RSR.js';import'../chunk-FPJAUAEU.js';import'../chunk-WTOA6B2A.js';import'../chunk-2AAZFBRZ.js';import'../chunk-FNCEVW7G.js';import'../chunk-LB27VQRL.js';import'../chunk-OWKAJPOI.js';import'../chunk-TPF643LU.js';export{a as classifyIpcFailure,b as isIpcUnavailable}from'../chunk-72NEEJQG.js';import'../chunk-L2ZZXECX.js';export{c as runtimeFromCapability}from'../chunk-RUOVYQ2P.js';import'../chunk-FKAQDDUM.js';import'../chunk-SSBR3IHA.js';import'../chunk-IUU6JCLK.js';import'../chunk-CCCYE3XN.js';import'../chunk-JPBW67B3.js';import'../chunk-ZA44REGI.js';import'../chunk-L7N4T2PX.js';import'../chunk-72MN7BNQ.js';import'../chunk-2GX6GB6L.js';
1
+ export{a as isDeviceActive,c as isDeviceConnectable,b as isDeviceRoutable}from'../chunk-CK6WQV7J.js';export{h as ConnectionActor,e as ConnectionActorError,i as ConnectionActors,a as ConnectionController,k as DEFAULT_MAX_FRAME_BYTES,t as IpcRuntimeAdapter,s as RuntimeClient,d as clog,q as concatRuntimeBytes,f as connectionActorKey,g as connectionActorKeyString,p as createJsonDecoder,l as createU32Decoder,n as decodeJsonPayload,o as encodeJsonFrame,m as encodeJsonPayload,j as encodeU32Frame,c as grantCorrelation,r as readRuntimeU32BE,b as renderCorrelation}from'../chunk-M4KL5XZU.js';import'../chunk-IXQ4KWGP.js';import'../chunk-CQHLD52E.js';export{u as BROWSER_CAPABILITIES,v as NATIVE_CAPABILITIES,s as RUNTIME_POLICY,x as browserCapabilities,z as capabilityProfile,w as cloneCapabilities,t as getRuntimePolicy,l as logTeardownTrace,h as openRtcDebug,g as openRtcDebugEnabled,i as openRtcDebugInfo,j as openRtcDebugLog,y as statusCapabilities}from'../chunk-LCJQ7RSR.js';import'../chunk-FPJAUAEU.js';import'../chunk-WTOA6B2A.js';import'../chunk-2AAZFBRZ.js';import'../chunk-FNCEVW7G.js';import'../chunk-LB27VQRL.js';import'../chunk-OWKAJPOI.js';import'../chunk-TPF643LU.js';export{a as classifyIpcFailure,b as isIpcUnavailable}from'../chunk-72NEEJQG.js';import'../chunk-L2ZZXECX.js';export{c as runtimeFromCapability}from'../chunk-3T57Y4EF.js';import'../chunk-FKAQDDUM.js';import'../chunk-BKCUXUHW.js';import'../chunk-IUU6JCLK.js';import'../chunk-CCCYE3XN.js';import'../chunk-JPBW67B3.js';import'../chunk-ZA44REGI.js';import'../chunk-L7N4T2PX.js';import'../chunk-72MN7BNQ.js';import'../chunk-2GX6GB6L.js';
package/dist/server.js CHANGED
@@ -1,2 +1,2 @@
1
- import {a}from'./chunk-V57WKJSB.js';import'./chunk-XNJI6KCI.js';import'./chunk-RUOVYQ2P.js';import'./chunk-FKAQDDUM.js';import'./chunk-SSBR3IHA.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';function y(n){let e=new URL(n??"https://api.openrtc.app"),t=e.protocol==="http:"&&["127.0.0.1","localhost","::1"].includes(e.hostname.toLowerCase());if(e.protocol!=="https:"&&!t||e.username||e.password||e.search||e.hash)throw new TypeError("[OpenRTC] authority control-plane endpoint is invalid.");return e.toString().replace(/\/$/,"")}function h(){if(typeof document<"u"||typeof window<"u")throw new Error("[OpenRTC] openrtc/server is unavailable in browsers; use openrtc/service-node with a delegated grant.")}var c=class{constructor(e){h();let t=e.secretKey?.trim()??"";if(!/^sk_(?:live|test)_[A-Za-z0-9_-]+$/.test(t))throw new TypeError("[OpenRTC] secretKey is invalid.");let i=e.fetch??globalThis.fetch;if(typeof i!="function")throw new TypeError("[OpenRTC] a Fetch-compatible implementation is required.");let u=y(e.endpoint);this.authority=new a({apiKey:e.apiKey,serviceId:e.serviceId,generation:e.generation,shardIds:e.shardIds,deviceId:e.deviceId,deviceSigner:e.deviceSigner,assignmentSigner:e.assignmentSigner,grantIssuer:async s=>{let r=await i(`${u}/v2/developer/authority/grants`,{method:"POST",headers:{authorization:`Bearer ${t}`,"content-type":"application/json","x-openrtc-idempotency-key":s.idempotencyKey},body:JSON.stringify(s.body)});if(!r.ok){let o=await r.json().catch(()=>null),d=typeof o?.error=="string"?o.error.slice(0,256):`HTTP ${r.status}`;throw new Error(`[OpenRTC] authority service grant failed: ${d}`)}return r.json()}});}requestGrant(e){return this.authority.requestGrant(e)}signAssignment(e){return this.authority.signAssignment(e)}devicePublicKey(){return this.authority.devicePublicKey()}signDeviceBytes(e){return this.authority.signDeviceBytes(e)}grantIssuer(){return async e=>{let t=e.body;return this.requestGrant({rootProof:t.rootProof??null,roomId:String(t.avenue?.id??""),runtimeInstanceId:String(t.runtimeInstanceId??""),ticketFingerprint:String(t.ticketFingerprint??""),maxPeers:typeof t.maxPeers=="number"?t.maxPeers:void 0,refreshGrant:typeof t.refreshGrant=="string"?t.refreshGrant:void 0,features:typeof t.features=="object"&&t.features?t.features:void 0})}}};
1
+ import {a}from'./chunk-GESNKWVM.js';import'./chunk-XNJI6KCI.js';import'./chunk-3T57Y4EF.js';import'./chunk-FKAQDDUM.js';import'./chunk-BKCUXUHW.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';function y(n){let e=new URL(n??"https://api.openrtc.app"),t=e.protocol==="http:"&&["127.0.0.1","localhost","::1"].includes(e.hostname.toLowerCase());if(e.protocol!=="https:"&&!t||e.username||e.password||e.search||e.hash)throw new TypeError("[OpenRTC] authority control-plane endpoint is invalid.");return e.toString().replace(/\/$/,"")}function h(){if(typeof document<"u"||typeof window<"u")throw new Error("[OpenRTC] openrtc/server is unavailable in browsers; use openrtc/service-node with a delegated grant.")}var c=class{constructor(e){h();let t=e.secretKey?.trim()??"";if(!/^sk_(?:live|test)_[A-Za-z0-9_-]+$/.test(t))throw new TypeError("[OpenRTC] secretKey is invalid.");let i=e.fetch??globalThis.fetch;if(typeof i!="function")throw new TypeError("[OpenRTC] a Fetch-compatible implementation is required.");let u=y(e.endpoint);this.authority=new a({apiKey:e.apiKey,serviceId:e.serviceId,generation:e.generation,shardIds:e.shardIds,deviceId:e.deviceId,deviceSigner:e.deviceSigner,assignmentSigner:e.assignmentSigner,grantIssuer:async s=>{let r=await i(`${u}/v2/developer/authority/grants`,{method:"POST",headers:{authorization:`Bearer ${t}`,"content-type":"application/json","x-openrtc-idempotency-key":s.idempotencyKey},body:JSON.stringify(s.body)});if(!r.ok){let o=await r.json().catch(()=>null),d=typeof o?.error=="string"?o.error.slice(0,256):`HTTP ${r.status}`;throw new Error(`[OpenRTC] authority service grant failed: ${d}`)}return r.json()}});}requestGrant(e){return this.authority.requestGrant(e)}signAssignment(e){return this.authority.signAssignment(e)}devicePublicKey(){return this.authority.devicePublicKey()}signDeviceBytes(e){return this.authority.signDeviceBytes(e)}grantIssuer(){return async e=>{let t=e.body;return this.requestGrant({rootProof:t.rootProof??null,roomId:String(t.avenue?.id??""),runtimeInstanceId:String(t.runtimeInstanceId??""),ticketFingerprint:String(t.ticketFingerprint??""),maxPeers:typeof t.maxPeers=="number"?t.maxPeers:void 0,refreshGrant:typeof t.refreshGrant=="string"?t.refreshGrant:void 0,features:typeof t.features=="object"&&t.features?t.features:void 0})}}};
2
2
  export{c as AuthorityServiceControlPlane};
@@ -1 +1 @@
1
- export{a as DelegatedAuthorityService,b as ServiceNode}from'./chunk-V57WKJSB.js';import'./chunk-XNJI6KCI.js';import'./chunk-RUOVYQ2P.js';import'./chunk-FKAQDDUM.js';import'./chunk-SSBR3IHA.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';
1
+ export{a as DelegatedAuthorityService,b as ServiceNode}from'./chunk-GESNKWVM.js';import'./chunk-XNJI6KCI.js';import'./chunk-3T57Y4EF.js';import'./chunk-FKAQDDUM.js';import'./chunk-BKCUXUHW.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';
@@ -1 +1 @@
1
- import {a}from'../chunk-XXZEDZUU.js';import'../chunk-TPF643LU.js';import {a as a$1}from'../chunk-5336XOTL.js';import {i}from'../chunk-RUOVYQ2P.js';import'../chunk-FKAQDDUM.js';import'../chunk-SSBR3IHA.js';import'../chunk-IUU6JCLK.js';import'../chunk-CCCYE3XN.js';import'../chunk-JPBW67B3.js';import'../chunk-ZA44REGI.js';import'../chunk-L7N4T2PX.js';import'../chunk-72MN7BNQ.js';import'../chunk-2GX6GB6L.js';function v(c,p,e){let o=new a;return i(c,{endpoints:p,testingAllowInsecureLoopback:true,platform:"native",close:()=>o.close(),deviceKeyProvider:a$1(e),deviceIdProvider:async()=>{let t=await e.invoke("get_rtc_local_device_info");return String(t?.deviceId??"")},runtimeFactory:async t=>{let{createIpcClient:a}=await import('../ipcFactory-6XD3J2UU.js');return a(t,e,o)}})}export{v as OpenRTC};
1
+ import {a}from'../chunk-XXZEDZUU.js';import'../chunk-TPF643LU.js';import {a as a$1}from'../chunk-5336XOTL.js';import {i}from'../chunk-3T57Y4EF.js';import'../chunk-FKAQDDUM.js';import'../chunk-BKCUXUHW.js';import'../chunk-IUU6JCLK.js';import'../chunk-CCCYE3XN.js';import'../chunk-JPBW67B3.js';import'../chunk-ZA44REGI.js';import'../chunk-L7N4T2PX.js';import'../chunk-72MN7BNQ.js';import'../chunk-2GX6GB6L.js';function v(c,p,e){let o=new a;return i(c,{endpoints:p,testingAllowInsecureLoopback:true,platform:"native",close:()=>o.close(),deviceKeyProvider:a$1(e),deviceIdProvider:async()=>{let t=await e.invoke("get_rtc_local_device_info");return String(t?.deviceId??"")},runtimeFactory:async t=>{let{createIpcClient:a}=await import('../ipcFactory-6XD3J2UU.js');return a(t,e,o)}})}export{v as OpenRTC};
package/dist/testing.js CHANGED
@@ -1 +1 @@
1
- import {a}from'./chunk-M2QMGAL2.js';import {a as a$1}from'./chunk-KI7XXVXH.js';import {a as a$2,d,c}from'./chunk-L2ZZXECX.js';import'./chunk-XNJI6KCI.js';import {i}from'./chunk-RUOVYQ2P.js';import'./chunk-FKAQDDUM.js';import'./chunk-SSBR3IHA.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';function v(i,o,e){let n=s=>{let t=new URL(s);return t.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(t.hostname)&&Number(t.port)>0&&t.pathname==="/"&&!t.username&&!t.password&&!t.search&&!t.hash};if(i.apiKey!=="pk_test_0000000000000000000000000000000000000000"||!n(o.controlPlane)||!n(o.gateway)||!/^[A-Za-z0-9_-]{1,64}$/.test(e.keyNamespace))throw new Error("Local broadcast testing requires the disposable loopback service lane")}function b(i){let o=i.replace(/-/g,"+").replace(/_/g,"/").padEnd(Math.ceil(i.length/4)*4,"=");return Uint8Array.from(atob(o),e=>e.charCodeAt(0))}function A(i,o,e){return new a(i,o,a$1(e))}function R(i$1,o,e={}){if(e.localBroadcast&&v(i$1,o,e.localBroadcast),e.initialTicketLifetimeMs!==void 0){let t=(p,c)=>{let a=new URL(p);return a.protocol===c&&["127.0.0.1","[::1]"].includes(a.hostname)&&Number(a.port)>0&&a.pathname==="/"&&!a.username&&!a.password&&!a.search&&!a.hash};if(e.initialTicketLifetimeMs!==9e4||i$1.apiKey!=="pk_test_0000000000000000000000000000000000000000"||!t(o.controlPlane,"http:")||!t(o.gateway,"http:")||!e.irohTestRelayUrl||!t(e.irohTestRelayUrl,"https:"))throw new Error("Short initial tickets require the disposable local service lane")}let n=e.localBroadcast,s=n?a$1(n.keyNamespace):void 0;return i(i$1,{endpoints:o,testingAllowInsecureLoopback:true,platform:"web",...s?{deviceKeyProvider:s}:{},...n&&s?{broadcastHostFactory:async t=>{let[{BrowserManagedBroadcastHost:p},{loadBrowserWasmRuntimeModule:c}]=await Promise.all([import('./BrowserManagedBroadcastHost-6VGHQQMF.js'),import('./WasmBridge-3HYLCY5Y.js')]),a=c().then(async r=>(await r.initWasm(),r.start(),new r.WasmClient(t.apiKey))),y=await s.getOrCreate(`app_${t.apiKey.slice(-16)}`);return new p({resolve:async(r,l)=>({token:r,...await n.resolve(r,l),signBindingChallenge:async m=>b(await y.sign(m))}),loadWasm:()=>a})}}:{},...e.deviceId?{deviceIdProvider:async()=>e.deviceId}:{},...e.irohTestRelayUrl?{irohTestRelayUrl:e.irohTestRelayUrl}:{},runtimeFactory:async t=>{let{createWasmClient:p}=await import('./runtime/factories.js'),c$1=await p(t);if(e.initialTicketLifetimeMs!==void 0){let a=c$1.runtime,y=a.getTicketWithToken.bind(a);a.getTicketWithToken=async(r,l=0)=>{if(a.getTicketWithToken=y,!r.startsWith("v2:room:"))throw new Error("Short initial ticket requires room scope");let{irohTicket:m,tokenSuffix:u}=a$2(await y(r,l)),d$1=u&&d(m,u);if(!d$1||!d$1.t||d$1.s!==r||d$1.m!==l)throw new Error("Invalid initial service ticket");let f=Date.now()+9e4;return await a.registerToken({token:d$1.t,scope:r,maxConnections:l,expiresAtMs:f}),c(m,d$1.t,r,l,f)};}return c$1}})}export{R as OpenRTC,A as controlPlane};
1
+ import {a}from'./chunk-M2QMGAL2.js';import {a as a$1}from'./chunk-KI7XXVXH.js';import {a as a$2,d,c}from'./chunk-L2ZZXECX.js';import'./chunk-XNJI6KCI.js';import {i}from'./chunk-3T57Y4EF.js';import'./chunk-FKAQDDUM.js';import'./chunk-BKCUXUHW.js';import'./chunk-IUU6JCLK.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-ZA44REGI.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';function v(i,o,e){let n=s=>{let t=new URL(s);return t.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(t.hostname)&&Number(t.port)>0&&t.pathname==="/"&&!t.username&&!t.password&&!t.search&&!t.hash};if(i.apiKey!=="pk_test_0000000000000000000000000000000000000000"||!n(o.controlPlane)||!n(o.gateway)||!/^[A-Za-z0-9_-]{1,64}$/.test(e.keyNamespace))throw new Error("Local broadcast testing requires the disposable loopback service lane")}function b(i){let o=i.replace(/-/g,"+").replace(/_/g,"/").padEnd(Math.ceil(i.length/4)*4,"=");return Uint8Array.from(atob(o),e=>e.charCodeAt(0))}function A(i,o,e){return new a(i,o,a$1(e))}function R(i$1,o,e={}){if(e.localBroadcast&&v(i$1,o,e.localBroadcast),e.initialTicketLifetimeMs!==void 0){let t=(p,c)=>{let a=new URL(p);return a.protocol===c&&["127.0.0.1","[::1]"].includes(a.hostname)&&Number(a.port)>0&&a.pathname==="/"&&!a.username&&!a.password&&!a.search&&!a.hash};if(e.initialTicketLifetimeMs!==9e4||i$1.apiKey!=="pk_test_0000000000000000000000000000000000000000"||!t(o.controlPlane,"http:")||!t(o.gateway,"http:")||!e.irohTestRelayUrl||!t(e.irohTestRelayUrl,"https:"))throw new Error("Short initial tickets require the disposable local service lane")}let n=e.localBroadcast,s=n?a$1(n.keyNamespace):void 0;return i(i$1,{endpoints:o,testingAllowInsecureLoopback:true,platform:"web",...s?{deviceKeyProvider:s}:{},...n&&s?{broadcastHostFactory:async t=>{let[{BrowserManagedBroadcastHost:p},{loadBrowserWasmRuntimeModule:c}]=await Promise.all([import('./BrowserManagedBroadcastHost-6VGHQQMF.js'),import('./WasmBridge-3HYLCY5Y.js')]),a=c().then(async r=>(await r.initWasm(),r.start(),new r.WasmClient(t.apiKey))),y=await s.getOrCreate(`app_${t.apiKey.slice(-16)}`);return new p({resolve:async(r,l)=>({token:r,...await n.resolve(r,l),signBindingChallenge:async m=>b(await y.sign(m))}),loadWasm:()=>a})}}:{},...e.deviceId?{deviceIdProvider:async()=>e.deviceId}:{},...e.irohTestRelayUrl?{irohTestRelayUrl:e.irohTestRelayUrl}:{},runtimeFactory:async t=>{let{createWasmClient:p}=await import('./runtime/factories.js'),c$1=await p(t);if(e.initialTicketLifetimeMs!==void 0){let a=c$1.runtime,y=a.getTicketWithToken.bind(a);a.getTicketWithToken=async(r,l=0)=>{if(a.getTicketWithToken=y,!r.startsWith("v2:room:"))throw new Error("Short initial ticket requires room scope");let{irohTicket:m,tokenSuffix:u}=a$2(await y(r,l)),d$1=u&&d(m,u);if(!d$1||!d$1.t||d$1.s!==r||d$1.m!==l)throw new Error("Invalid initial service ticket");let f=Date.now()+9e4;return await a.registerToken({token:d$1.t,scope:r,maxConnections:l,expiresAtMs:f}),c(m,d$1.t,r,l,f)};}return c$1}})}export{R as OpenRTC,A as controlPlane};
@@ -4,9 +4,9 @@
4
4
  "platform": "darwin",
5
5
  "arch": "arm64",
6
6
  "rustTarget": "aarch64-apple-darwin",
7
- "sourceCommit": "6c0166a67198e24ecfe66fd073db316737b2beee",
8
- "sourceDigest": "8c372e602fb32a1d0eb4b848b18a53d96ee251610b372abaf5669e00d7493af7",
9
- "binarySha256": "39fb169f9bc2ff6e7aa5eb38493343c93601b8c7cd8dbcd4f493c36d9c736074",
7
+ "sourceCommit": "31c34833f873d7730de596aacec18c582231150a",
8
+ "sourceDigest": "187f6ca35b7d1632a12ab9e9cf153d34d9176bfe0e7ea3ff3ce0a33e079bfde2",
9
+ "binarySha256": "d52bb806d7eb8322c062b91414537a52d22a9f4ef7fe50da2101d13d2a85fc6d",
10
10
  "protocol": {
11
11
  "lifecycleOwner": "rust-peer-session",
12
12
  "maxApplicationPayloadBytes": 65536,
@@ -16,5 +16,5 @@
16
16
  },
17
17
  "signingKeySha256": "0391c617f3df12611b419e129cace36fa792e73da03271649cbed9e9f9f155ef",
18
18
  "signatureAlgorithm": "ed25519",
19
- "signature": "wgk6OpLzNZqBuecu9p9aMIE3YV7F6wqMvX1Xr6HjBnQG1+/zWDkcQoOMCHLuh2PX40nw/AKhSQxtMYxzCaEkAw=="
19
+ "signature": "ceHoeJSD0TVcoNypKQyOdePNhR7n1PMdTux+BnqYsmgP8P/cQk+IXErECOo+61rJ+Ji3ihP6d9cp/fyDrprwCA=="
20
20
  }
Binary file
@@ -4,9 +4,9 @@
4
4
  "platform": "darwin",
5
5
  "arch": "x64",
6
6
  "rustTarget": "x86_64-apple-darwin",
7
- "sourceCommit": "6c0166a67198e24ecfe66fd073db316737b2beee",
8
- "sourceDigest": "8c372e602fb32a1d0eb4b848b18a53d96ee251610b372abaf5669e00d7493af7",
9
- "binarySha256": "45ff602853ae60c842330b46dad962f3dfacefa6e4d469ec02751bca6869cc6d",
7
+ "sourceCommit": "31c34833f873d7730de596aacec18c582231150a",
8
+ "sourceDigest": "187f6ca35b7d1632a12ab9e9cf153d34d9176bfe0e7ea3ff3ce0a33e079bfde2",
9
+ "binarySha256": "eb0430705e7d3311d06f1f4537bad510654350148d43cc64b696ad0606f3e070",
10
10
  "protocol": {
11
11
  "lifecycleOwner": "rust-peer-session",
12
12
  "maxApplicationPayloadBytes": 65536,
@@ -16,5 +16,5 @@
16
16
  },
17
17
  "signingKeySha256": "0391c617f3df12611b419e129cace36fa792e73da03271649cbed9e9f9f155ef",
18
18
  "signatureAlgorithm": "ed25519",
19
- "signature": "8TM3UoEke+fMY0t2RgaRQ1WX0oiJ2eXnyBN+nRuo30oIReN3z/iBRO5OCC2JIGlEQGLAkaCCcLv8InIy2MvZDg=="
19
+ "signature": "XPCOWZQmAPYIafKOGkjDYmhgrOdh4pFMdUMxXEDl3pVVr92YJFZnrhQ7M8ePdYhCeOKQqtfG+BKmS1NHXSGLBw=="
20
20
  }
Binary file
@@ -4,9 +4,9 @@
4
4
  "platform": "linux",
5
5
  "arch": "x64",
6
6
  "rustTarget": "x86_64-unknown-linux-gnu",
7
- "sourceCommit": "6c4afe9eb1f0f4181c95f2190d370fa7c29ccdb0",
8
- "sourceDigest": "8c372e602fb32a1d0eb4b848b18a53d96ee251610b372abaf5669e00d7493af7",
9
- "binarySha256": "11f2fbd128d6038ffb3a1ccb59b45bde3763890a65c09f0213b14d463cab191f",
7
+ "sourceCommit": "aa0b68ba5d7a516751bdc5c1a236cd5beb7a59d3",
8
+ "sourceDigest": "187f6ca35b7d1632a12ab9e9cf153d34d9176bfe0e7ea3ff3ce0a33e079bfde2",
9
+ "binarySha256": "514ca68220bbca3c968a1292d94c5fa81c21084681cd5e0dc40cb78ef112158e",
10
10
  "protocol": {
11
11
  "lifecycleOwner": "rust-peer-session",
12
12
  "maxApplicationPayloadBytes": 65536,
@@ -16,5 +16,5 @@
16
16
  },
17
17
  "signingKeySha256": "0391c617f3df12611b419e129cace36fa792e73da03271649cbed9e9f9f155ef",
18
18
  "signatureAlgorithm": "ed25519",
19
- "signature": "nsWY2smSGOD6I0oKN3eilemrCqQc3+g2BDYjUTIFNg3YYNI6u9yb91jcfO2FsAKFZxPxDbg9LUbvA9UZvHkQDg=="
19
+ "signature": "8piAznKHmyOexCAE0FuK34/2ylk1n6so/lWizcnic4LVycmohIJJYUKn/SdBc70UQ7DnBySBFlOSYbnUjUJIDw=="
20
20
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openrtc",
3
- "version": "3.1.2",
3
+ "version": "3.1.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "sideEffects": false,