openrtc 2.0.0-rc.26 → 2.0.0-rc.27

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.
@@ -0,0 +1 @@
1
+ import {a,b as b$1}from'./chunk-XPL7PUBW.js';var x={"identity.assertion.exchange":25692e-8,"identity.monthly-active-principal":110352e-9,"capability.issue":212346e-9,"device.enroll":218946e-9,"gateway.grant.issue":202146e-9,"gateway.grant.refresh":200346e-9,"security.attestation.verify":29694e-8,"room.create":388056e-9,"room.join":209946e-9,"room.leave":200346e-9,"coordination.connection.open":299532e-9,"coordination.credential.refresh":259662e-9,"coordination.presence.offline":253638e-9,"coordination.signal.send":259638e-9,"coordination.session.put":259638e-9,"coordination.session.delete":253638e-9,"coordination.usage.ingest":197088e-9};var g=new WeakMap;function $(r){let e=g.get(r);if(!e)throw new Error("[OpenRTC] Capability runtime is unavailable or already closed.");return e}function F(r){let e=r?.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 C(r){let e=r?.trim()??"";if(!e||e.length>160||!/^[A-Za-z0-9_.:@-]+$/.test(e))throw new Error("[OpenRTC] Capability id is invalid.");return e}var _=/^[A-Za-z0-9_.:@-]{1,160}$/,N=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function U(r){let e=typeof r=="string"?r.trim():"";if(!_.test(e))return null;let t=e.startsWith("device_")?e.slice(7):"";return N.test(t)?t:e}function M(r,e){try{let t=r.getItem(`pluto_rtc_web_device_identity_${e}`);if(!t)return null;let i=JSON.parse(t);return U(i?.deviceId)}catch{return null}}function H(r){let e=`openrtc:v2:device-id:${r}`,t=`pluto_rtc_web_device_identity_${r}`,i,n=(()=>{try{return i=globalThis.localStorage,i&&M(i,r)||U(i?.getItem(e))||crypto.randomUUID()}catch{return crypto.randomUUID()}})();try{i?.setItem(e,n),i?.setItem(t,JSON.stringify({deviceId:n}));}catch{}return n}function E(r){let e=typeof r=="string"?r.trim():"";if(!_.test(e))throw new Error("[OpenRTC] The native host returned an invalid durable device ID.");return e}function b(r){let e=b$1(r.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 I=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);}},D=class{constructor(e){this.options=e;this.total=0;this.warned=false;}get sessionCreditsUsd(){return this.total}estimate(e){let t=Math.max(0,Math.floor(e.units??1));return {creditsUsd:(x[e.operation]??0)*t,estimated:true}}assertCanSpend(e,t=1){let i=this.options?.maxSessionCreditsUsd;if(i===void 0||this.total+this.estimate({operation:e,units:t}).creditsUsd<=i)return;let a={sessionCreditsUsd:this.total,operation:e,estimated:true,thresholdCreditsUsd:i,kind:"session-limit"};throw this.options?.onWarning?.(a),new Error("[OpenRTC] The client-side session credit limit was reached.")}record(e,t=1){let i=this.estimate({operation:e,units:t}).creditsUsd;this.total+=i;let n={sessionCreditsUsd:this.total,operation:e,estimated:true};this.options?.onUsage?.(n);let a=this.options?.warnAtSessionCreditsUsd;!this.warned&&a!==void 0&&this.total>=a&&(this.warned=true,this.options?.onWarning?.({...n,thresholdCreditsUsd:a,kind:"warning"}));}},R=class{constructor(e,t,i,n){this.kind=e;this.id=t;this.client=i;this.onClosed=n;this.closed=false;g.set(this,i);}get peers(){return this.client.peers}get channels(){return this.client.channels}get diagnostics(){return this.client.diagnostics}async close(){if(!this.closed){this.closed=true;try{await this.client.advanced.runtime.shutdown();}finally{g.delete(this),this.onClosed();}}}},f=class extends R{constructor(t,i,n,a){super("devices",t,i,n);this.roster=a;this.kind="devices";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=t=>this.client.devices.watch(i=>t(this.roster.mergeDevices(i)));this.connect=this.client.devices.connect;this.disconnect=this.client.devices.disconnect;let s=i.devices.list,o=i.devices.listWithStatus,c=i.devices.watch,d=i.devices.watchWithStatus,l=v=>(this.roster.reconcileLiveSnapshot(v),v),p=async()=>this.roster.mergeDevices(l(await s())),h=async()=>this.roster.mergeStatus(await o()),u=v=>c(T=>v(this.roster.mergeDevices(l(T)))),y=v=>d(T=>v(this.roster.mergeStatus(T))),m=Object.create(i);Object.defineProperties(m,{listDevices:{value:p,enumerable:false},listDevicesWithStatus:{value:h,enumerable:false},watchDevices:{value:u,enumerable:false},watchDevicesWithStatus:{value:y,enumerable:false},devices:{value:{...i.devices,list:p,listWithStatus:h,watch:u,watchWithStatus:y},enumerable:true}}),g.set(this,m),this.stopRosterSync=c(l);}replaceEnrolledDevices(t){this.roster.replace(t);}removeEnrolledDevice(t){this.roster.remove(t);}retainCurrentEnrolledDevice(t){this.roster.retain(t);}async close(){this.stopRosterSync(),await super.close();}},S=class extends R{constructor(t,i,n,a){super("space",t,i,n);this.delivery=a;this.kind="space";this.leave=()=>this.close();}},w=class extends R{constructor(t,i,n,a,s){super("room",t,i,n);this.membership=a;this.onLeave=s;this.kind="room";this.left=false;}async leave(){this.left||(this.left=true,await this.onLeave?.()),await this.close();}},k=class extends R{constructor(t,i,n,a){super("ticket",t,i,n);this.token=a;this.kind="ticket";}},A=class{constructor(e,t){this.options=e;this.internals=t;this.channels=new I;this.handles=new Set;this.activations=new Map;this.closed=false;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",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());for(let n of this.handles)n instanceof f&&n.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=E(e),a=await this.deviceId();await(await this.controlPlane()).revokeDevice(i,a,n);for(let s of this.handles)s instanceof f&&s.removeEnrolledDevice(n);n===a&&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();for(let n of this.handles)n instanceof f&&n.retainCurrentEnrolledDevice(i);}e.exceptCurrent!==true&&this.retireAuthCapabilities(t);}};this.spaces={join:(e,t={})=>this.activateOnce(`space:${C(e)}`,JSON.stringify({payload:t.payload??"reliable",maxPeers:t.maxPeers??null,advancedFanout:t.advancedFanout===true}),void 0,()=>this.joinSpace(e,t))};this.rooms={join:(e,t={})=>{let i=t.access??"capability";return this.activateOnce(`room:${C(e)}`,JSON.stringify({access:i,membership:t.membership??"ephemeral",maxPeers:t.maxPeers??null,advancedFanout:t.advancedFanout===true}),i==="authenticated"?t.auth??this.options.auth:void 0,()=>this.joinRoom(e,t))}};this.tickets={issue:(e,t={})=>this.activateOnce(`ticket:${C(e)}`,JSON.stringify({maxPeers:t.maxPeers??null,advancedFanout:t.advancedFanout===true}),void 0,()=>this.issueTicket(e,t))};this.onClosed=e=>{this.handles.delete(e);for(let[t,i]of this.activations)i.handle===e&&this.activations.delete(t);};this.apiKey=F(e.apiKey),this.appTag=`app_${this.apiKey.slice(-16)}`,this.usage=new D(e.usage);}controlPlane(){return this.controlPlanePromise??(this.controlPlanePromise=Promise.all([import('./controlPlane-HW224SPX.js'),this.internals.deviceKeyProvider?Promise.resolve(this.internals.deviceKeyProvider):import('./deviceKey-SBNKLVYF.js').then(({browserDeviceKeyProvider:e})=>e)]).then(([{OpenRTCV2ControlPlane:e},t])=>new e(this.apiKey,this.internals.endpoints??a,t,this.options.trust?.attestation,{beforeLogicalOperation:i=>this.usage.assertCanSpend(i),onLogicalOperation:i=>this.usage.record(i),onAuthEpochChanged:i=>this.retireAuthCapabilities(i)},this.options.trust?.botVerification)))}assertOpen(){if(this.closed)throw new Error("[OpenRTC] Client is closed.")}activateOnce(e,t,i,n){this.assertOpen();let a=this.activations.get(e);if(a){if(a.fingerprint!==t||a.auth!==i)throw new Error(`[OpenRTC] ${e} is already active with different options.`);return a.promise}let s={fingerprint:t,auth:i},o=n().then(c=>(s.handle=c,c)).catch(c=>{throw this.activations.get(e)===s&&this.activations.delete(e),c});return s.promise=o,this.activations.set(e,s),o}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):H(this.appTag);return E(e)}runtimeOptions(e){let t=this.options.transports,i=t?.privacy==="relay-only";if(i&&t?.relay!==true)throw new Error("[OpenRTC] transports.privacy: relay-only requires transports.relay: true.");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,nativeApplicationStreamConsumer:this.internals.platform==="native"&&t?.nativeHostProtocols===true?"host":"runtime",coordinationAvenueOverride:e.avenue,coordinationGateway:{endpoint:(this.internals.endpoints??a).gateway,environment:"production",grantProvider:e.grantProvider,testingAllowInsecureLoopback:this.internals.testingAllowInsecureLoopback},transports:{iroh:i?{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:t?.webrtc===true?i?{privacyMode:true,useTurn:true,useDefaultIceServers:false}:true:false,ble:t?.ble??false,moq:t?.moq??false},transportPriority:t?.priority}}async activate(e){let t=await this.controlPlane(),i={relay:this.options.transports?.relay===true,moq:this.options.transports?.moq===true,ble:this.options.transports?.ble===true,advancedFanout:e.advancedFanout===true,durableMembership:e.durableMembership===true},n=e.source,a=null,s=()=>({userId:e.principalId,token:n.token,tokenProvider:async()=>n.token,expiresAtMs:n.expiresAtMs}),o=this.runtimeOptions({avenue:e.source.avenue,grantProvider:t.grantProvider(e.source,{maxPeers:e.maxPeers,features:i,deviceProfile:e.deviceName&&e.devicePlatform?{name:e.deviceName,platform:e.devicePlatform}:void 0,onSourceRenewed:async l=>{n={...n,...l},await a?.setAuth(s());}}),deviceId:e.deviceId,userId:e.principalId,deviceName:e.deviceName,devicePlatform:e.devicePlatform}),[c,{wrapAssembly:d}]=await Promise.all([this.internals.runtimeFactory(o),import('./OpenRTCShared-LDKG5RPN.js')]);a=d(c,this.internals.platform==="native"?"native":"web"),await a.setAuth(s()),this.channels.attach(a,e.defaultDelivery??"reliable");try{this.usage.assertCanSpend("coordination.connection.open"),await a.devices.startSession({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(l){throw this.channels.detach(a),await a.advanced.runtime.shutdown().catch(()=>{}),l}return this.usage.record("coordination.connection.open"),a}async startDevices(e={}){this.assertOpen();let t=e.auth??this.options.auth;if(!t)throw new Error("[OpenRTC] devices.start() requires an auth provider.");let i=await this.deviceId(),{resolveDeviceProfile:n}=await import('./deviceProfile-3BEQZLJF.js'),a=n(e.profile,this.internals.platform==="native"?"native":"web"),s=await this.controlPlane(),o=await s.deviceCertificate(t,i,void 0,a),c=await this.activate({kind:"devices",id:o.principalId,source:o.source,principalId:o.principalId,deviceId:i,maxPeers:e.maxPeers,autoConnect:e.autoConnect!=="none",advancedFanout:e.advancedFanout,deviceName:a.name,devicePlatform:a.platform,deviceMetadata:a.metadata}),d;try{d=await s.listEnrolledDevices(t,i);}catch(h){throw this.channels.detach(c),await c.advanced.runtime.shutdown().catch(()=>{}),h}let{AuthenticatedDeviceRoster:l}=await import('./deviceRoster-VZA3TQOR.js'),p;return p=new f(o.principalId,c,()=>{this.channels.detach(c),this.onClosed(p);},new l(d)),this.handles.add(p),p}async joinSpace(e,t={}){this.assertOpen();let i=C(e),n=await(await this.controlPlane()).capability("space",i,t.maxPeers,t.advancedFanout),a=String(b$1(n.token).principalId),s=await this.activate({kind:"space",id:i,source:n,principalId:a,deviceId:b(n),maxPeers:t.maxPeers,autoConnect:true,defaultDelivery:t.payload??"reliable",advancedFanout:t.advancedFanout}),o;return o=new S(i,s,()=>{this.channels.detach(s),this.onClosed(o);},t.payload??"reliable"),this.handles.add(o),o}async joinRoom(e,t={}){this.assertOpen();let i=C(e),n=t.membership??"ephemeral",a=t.access??"capability";if(n==="durable"&&a!=="authenticated")throw new Error("[OpenRTC] Durable room membership requires access: authenticated.");if(a==="authenticated"){let l=t.auth??this.options.auth;if(!l)throw new Error("[OpenRTC] Authenticated rooms require an auth provider.");let p=await this.deviceId(),h=await this.controlPlane(),u=await h.deviceCertificate(l,p,{kind:"room",id:i});n==="durable"&&await h.durableRoomMembership(u.source,i,"join");let y;try{y=await this.activate({kind:"room",id:i,source:u.source,principalId:u.principalId,deviceId:p,maxPeers:t.maxPeers,autoConnect:!0,durableMembership:n==="durable",advancedFanout:t.advancedFanout});}catch(v){throw n==="durable"&&await h.durableRoomMembership(u.source,i,"leave").catch(()=>{}),v}let m;return m=new w(i,y,()=>{this.channels.detach(y),this.onClosed(m);},n,n==="durable"?async()=>{await h.durableRoomMembership(u.source,i,"leave");}:void 0),this.handles.add(m),m}let s=await(await this.controlPlane()).capability("room",i,t.maxPeers,t.advancedFanout),o=String(b$1(s.token).principalId),c=await this.activate({kind:"room",id:i,source:s,principalId:o,deviceId:b(s),maxPeers:t.maxPeers,autoConnect:true,advancedFanout:t.advancedFanout}),d;return d=new w(i,c,()=>{this.channels.detach(c),this.onClosed(d);},"ephemeral"),this.handles.add(d),d}async issueTicket(e,t={}){this.assertOpen();let i=C(e),n=await(await this.controlPlane()).capability("ticket",i,t.maxPeers,t.advancedFanout),a=String(b$1(n.token).principalId),s=await this.activate({kind:"ticket",id:i,source:n,principalId:a,deviceId:b(n),maxPeers:t.maxPeers,autoConnect:false,advancedFanout:t.advancedFanout}),o;return o=new k(i,s,()=>{this.channels.detach(s),this.onClosed(o);},n.token),this.handles.add(o),o}async close(){if(!this.closed){this.closed=true;try{await Promise.all([...this.handles].map(e=>e.close()));}finally{await this.controlPlanePromise?.then(e=>e.dispose(),()=>{}),this.activations.clear();}}}};function q(r,e){return new A(r,e)}export{$ as a,q as b};
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import {a}from'./chunk-7FPG3MFF.js';import'./chunk-VBUDERMM.js';import {d}from'./chunk-Z2WVSXPW.js';import {b}from'./chunk-EFSW5KA6.js';import'./chunk-XPL7PUBW.js';export{a as OPENRTC_ERROR_CODES,b as OpenRtcError,e as classifyOpenRtcFailure,d as openRtcError,c as projectOpenRtcErrorFields}from'./chunk-CWGKLGJZ.js';function i(p){return b(p,{platform:"web",runtimeFactory:async e=>{let{createWasmClient:t}=await import('./factories-3THBB2II.js');return t(e)}})}i.native=function(p,e=d()){return b(p,{platform:"native",deviceKeyProvider:a(e),deviceIdProvider:async()=>{let t=await e.invoke("get_rtc_local_device_info");return String(t?.deviceId??"")},runtimeFactory:async t=>{let{createIpcClient:c}=await import('./ipcFactory-DLS6OHDL.js');return c(t,e)}})};export{i as OpenRTC};
1
+ import {a}from'./chunk-7FPG3MFF.js';import'./chunk-VBUDERMM.js';import {d}from'./chunk-Z2WVSXPW.js';import {b}from'./chunk-655QSPCO.js';import'./chunk-XPL7PUBW.js';export{a as OPENRTC_ERROR_CODES,b as OpenRtcError,e as classifyOpenRtcFailure,d as openRtcError,c as projectOpenRtcErrorFields}from'./chunk-CWGKLGJZ.js';function i(p){return b(p,{platform:"web",runtimeFactory:async e=>{let{createWasmClient:t}=await import('./factories-3THBB2II.js');return t(e)}})}i.native=function(p,e=d()){return b(p,{platform:"native",deviceKeyProvider:a(e),deviceIdProvider:async()=>{let t=await e.invoke("get_rtc_local_device_info");return String(t?.deviceId??"")},runtimeFactory:async t=>{let{createIpcClient:c}=await import('./ipcFactory-DLS6OHDL.js');return c(t,e)}})};export{i as OpenRTC};
package/dist/native.js CHANGED
@@ -1 +1 @@
1
- import {a}from'./chunk-7FPG3MFF.js';import'./chunk-VBUDERMM.js';export{a as classifyNativeIpcFailure,b as isNativeIpcCommandUnavailable}from'./chunk-Z2WVSXPW.js';import {b}from'./chunk-EFSW5KA6.js';import'./chunk-XPL7PUBW.js';function m(n,e){return b(n,{platform:"native",deviceKeyProvider:a(e),deviceIdProvider:async()=>{let t=await e.invoke("get_rtc_local_device_info");return String(t?.deviceId??"")},runtimeFactory:async t=>{let{createIpcClient:o}=await import('./ipcFactory-DLS6OHDL.js');return o(t,e)}})}export{m as createNativeOpenRTC};
1
+ import {a}from'./chunk-7FPG3MFF.js';import'./chunk-VBUDERMM.js';export{a as classifyNativeIpcFailure,b as isNativeIpcCommandUnavailable}from'./chunk-Z2WVSXPW.js';import {b}from'./chunk-655QSPCO.js';import'./chunk-XPL7PUBW.js';function m(n,e){return b(n,{platform:"native",deviceKeyProvider:a(e),deviceIdProvider:async()=>{let t=await e.invoke("get_rtc_local_device_info");return String(t?.deviceId??"")},runtimeFactory:async t=>{let{createIpcClient:o}=await import('./ipcFactory-DLS6OHDL.js');return o(t,e)}})}export{m as createNativeOpenRTC};
Binary file
@@ -1 +1 @@
1
- export{b as Connection,u as IpcRuntimeAdapter,t as RuntimeClient,c as RuntimeConnectionController,g as ScopedConnectionActorError,j as ScopedConnectionActorHandle,k as ScopedConnectionActorRegistry,f as clog,r as concatRuntimeBytes,e as correlationForDriveGrantScope,q as createRuntimeJsonFrameDecoder,m as createRuntimeU32BEFrameDecoder,o as decodeRuntimeJsonPayload,p as encodeRuntimeJsonFrame,n as encodeRuntimeJsonPayload,l as encodeRuntimeU32BEFrame,s as readRuntimeU32BE,d as renderCorrelationFields,h as scopedConnectionKey,i as scopedConnectionKeyToString}from'../chunk-PWYWK7XV.js';export{a as classifyNativeIpcFailure,b as isNativeIpcCommandUnavailable}from'../chunk-Z2WVSXPW.js';export{a as runtimeFromCapability}from'../chunk-EFSW5KA6.js';import'../chunk-XPL7PUBW.js';export{a as isRuntimeDeviceActive,c as isRuntimeDeviceConnectable,b as isRuntimeDeviceRoutable}from'../chunk-CK6WQV7J.js';import'../chunk-HVYXEY7F.js';export{s as BROWSER_WASM_RUNTIME_CAPABILITIES,t as NATIVE_IPC_RUNTIME_CAPABILITIES,q as OPENRTC_RUNTIME_POLICY,u as cloneRuntimeCapabilities,r as getRuntimePolicy,i as logOpenRtcTeardownTrace,v as runtimeCapabilitiesForBrowserHost,w as runtimeCapabilitiesFromNativeStatus,x as runtimeCapabilityProfile}from'../chunk-VXMQ3AWK.js';import'../chunk-QHSM5NFZ.js';import'../chunk-RRMBD5OL.js';export{b as openRtcDebug,a as openRtcDebugEnabled,c as openRtcDebugInfo,d as openRtcDebugLog}from'../chunk-PQK5SJ47.js';import'../chunk-C7YN5MSV.js';import'../chunk-CWGKLGJZ.js';
1
+ export{b as Connection,u as IpcRuntimeAdapter,t as RuntimeClient,c as RuntimeConnectionController,g as ScopedConnectionActorError,j as ScopedConnectionActorHandle,k as ScopedConnectionActorRegistry,f as clog,r as concatRuntimeBytes,e as correlationForDriveGrantScope,q as createRuntimeJsonFrameDecoder,m as createRuntimeU32BEFrameDecoder,o as decodeRuntimeJsonPayload,p as encodeRuntimeJsonFrame,n as encodeRuntimeJsonPayload,l as encodeRuntimeU32BEFrame,s as readRuntimeU32BE,d as renderCorrelationFields,h as scopedConnectionKey,i as scopedConnectionKeyToString}from'../chunk-PWYWK7XV.js';export{a as classifyNativeIpcFailure,b as isNativeIpcCommandUnavailable}from'../chunk-Z2WVSXPW.js';export{a as runtimeFromCapability}from'../chunk-655QSPCO.js';import'../chunk-XPL7PUBW.js';export{a as isRuntimeDeviceActive,c as isRuntimeDeviceConnectable,b as isRuntimeDeviceRoutable}from'../chunk-CK6WQV7J.js';import'../chunk-HVYXEY7F.js';export{s as BROWSER_WASM_RUNTIME_CAPABILITIES,t as NATIVE_IPC_RUNTIME_CAPABILITIES,q as OPENRTC_RUNTIME_POLICY,u as cloneRuntimeCapabilities,r as getRuntimePolicy,i as logOpenRtcTeardownTrace,v as runtimeCapabilitiesForBrowserHost,w as runtimeCapabilitiesFromNativeStatus,x as runtimeCapabilityProfile}from'../chunk-VXMQ3AWK.js';import'../chunk-QHSM5NFZ.js';import'../chunk-RRMBD5OL.js';export{b as openRtcDebug,a as openRtcDebugEnabled,c as openRtcDebugInfo,d as openRtcDebugLog}from'../chunk-PQK5SJ47.js';import'../chunk-C7YN5MSV.js';import'../chunk-CWGKLGJZ.js';
package/dist/testing.js CHANGED
@@ -1 +1 @@
1
- import {a}from'./chunk-7FPG3MFF.js';import'./chunk-VBUDERMM.js';import {b}from'./chunk-EFSW5KA6.js';import'./chunk-XPL7PUBW.js';function l(r,n,e={}){return b(r,{endpoints:n,testingAllowInsecureLoopback:true,platform:"web",...e.deviceId?{deviceIdProvider:async()=>e.deviceId}:{},...e.irohTestRelayUrl?{irohTestRelayUrl:e.irohTestRelayUrl}:{},runtimeFactory:async t=>{let{createWasmClient:i}=await import('./factories-3THBB2II.js');return i(t)}})}function s(r,n,e){return b(r,{endpoints:n,testingAllowInsecureLoopback:true,platform:"native",deviceKeyProvider:a(e),deviceIdProvider:async()=>{let t=await e.invoke("get_rtc_local_device_info");return String(t?.deviceId??"")},runtimeFactory:async t=>{let{createIpcClient:i}=await import('./ipcFactory-DLS6OHDL.js');return i(t,e)}})}export{s as createTestingNativeOpenRTC,l as createTestingOpenRTC};
1
+ import {a}from'./chunk-7FPG3MFF.js';import'./chunk-VBUDERMM.js';import {b}from'./chunk-655QSPCO.js';import'./chunk-XPL7PUBW.js';function l(r,n,e={}){return b(r,{endpoints:n,testingAllowInsecureLoopback:true,platform:"web",...e.deviceId?{deviceIdProvider:async()=>e.deviceId}:{},...e.irohTestRelayUrl?{irohTestRelayUrl:e.irohTestRelayUrl}:{},runtimeFactory:async t=>{let{createWasmClient:i}=await import('./factories-3THBB2II.js');return i(t)}})}function s(r,n,e){return b(r,{endpoints:n,testingAllowInsecureLoopback:true,platform:"native",deviceKeyProvider:a(e),deviceIdProvider:async()=>{let t=await e.invoke("get_rtc_local_device_info");return String(t?.deviceId??"")},runtimeFactory:async t=>{let{createIpcClient:i}=await import('./ipcFactory-DLS6OHDL.js');return i(t,e)}})}export{s as createTestingNativeOpenRTC,l as createTestingOpenRTC};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openrtc",
3
- "version": "2.0.0-rc.26",
3
+ "version": "2.0.0-rc.27",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -1 +0,0 @@
1
- import {a,b as b$1}from'./chunk-XPL7PUBW.js';var x={"identity.assertion.exchange":25692e-8,"identity.monthly-active-principal":110352e-9,"capability.issue":212346e-9,"device.enroll":218946e-9,"gateway.grant.issue":202146e-9,"gateway.grant.refresh":200346e-9,"security.attestation.verify":29694e-8,"room.create":388056e-9,"room.join":209946e-9,"room.leave":200346e-9,"coordination.connection.open":299532e-9,"coordination.credential.refresh":259662e-9,"coordination.presence.offline":253638e-9,"coordination.signal.send":259638e-9,"coordination.session.put":259638e-9,"coordination.session.delete":253638e-9,"coordination.usage.ingest":197088e-9};var R=new WeakMap;function $(s){let e=R.get(s);if(!e)throw new Error("[OpenRTC] Capability runtime is unavailable or already closed.");return e}function F(s){let e=s?.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 C(s){let e=s?.trim()??"";if(!e||e.length>160||!/^[A-Za-z0-9_.:@-]+$/.test(e))throw new Error("[OpenRTC] Capability id is invalid.");return e}var _=/^[A-Za-z0-9_.:@-]{1,160}$/,N=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function U(s){let e=typeof s=="string"?s.trim():"";if(!_.test(e))return null;let t=e.startsWith("device_")?e.slice(7):"";return N.test(t)?t:e}function M(s,e){try{let t=s.getItem(`pluto_rtc_web_device_identity_${e}`);if(!t)return null;let i=JSON.parse(t);return U(i?.deviceId)}catch{return null}}function H(s){let e=`openrtc:v2:device-id:${s}`,t=`pluto_rtc_web_device_identity_${s}`,i,n=(()=>{try{return i=globalThis.localStorage,i&&M(i,s)||U(i?.getItem(e))||crypto.randomUUID()}catch{return crypto.randomUUID()}})();try{i?.setItem(e,n),i?.setItem(t,JSON.stringify({deviceId:n}));}catch{}return n}function E(s){let e=typeof s=="string"?s.trim():"";if(!_.test(e))throw new Error("[OpenRTC] The native host returned an invalid durable device ID.");return e}function b(s){let e=b$1(s.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 I=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);}},D=class{constructor(e){this.options=e;this.total=0;this.warned=false;}get sessionCreditsUsd(){return this.total}estimate(e){let t=Math.max(0,Math.floor(e.units??1));return {creditsUsd:(x[e.operation]??0)*t,estimated:true}}assertCanSpend(e,t=1){let i=this.options?.maxSessionCreditsUsd;if(i===void 0||this.total+this.estimate({operation:e,units:t}).creditsUsd<=i)return;let a={sessionCreditsUsd:this.total,operation:e,estimated:true,thresholdCreditsUsd:i,kind:"session-limit"};throw this.options?.onWarning?.(a),new Error("[OpenRTC] The client-side session credit limit was reached.")}record(e,t=1){let i=this.estimate({operation:e,units:t}).creditsUsd;this.total+=i;let n={sessionCreditsUsd:this.total,operation:e,estimated:true};this.options?.onUsage?.(n);let a=this.options?.warnAtSessionCreditsUsd;!this.warned&&a!==void 0&&this.total>=a&&(this.warned=true,this.options?.onWarning?.({...n,thresholdCreditsUsd:a,kind:"warning"}));}},O=class{constructor(e,t,i,n){this.kind=e;this.id=t;this.client=i;this.onClosed=n;this.closed=false;R.set(this,i);}get peers(){return this.client.peers}get channels(){return this.client.channels}get diagnostics(){return this.client.diagnostics}async retireDeviceIfPresent(e){(await this.client.devices.list()).some(i=>i.deviceId===e)&&await this.client.devices.delete(e);}async retireAllOtherDevices(e){let t=await this.client.devices.list();for(let i of t)i.deviceId!==e&&await this.client.devices.delete(i.deviceId);}async close(){if(!this.closed){this.closed=true;try{await this.client.advanced.runtime.shutdown();}finally{R.delete(this),this.onClosed();}}}},f=class extends O{constructor(t,i,n,a){super("devices",t,i,n);this.roster=a;this.kind="devices";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=t=>this.client.devices.watch(i=>t(this.roster.mergeDevices(i)));this.connect=this.client.devices.connect;this.disconnect=this.client.devices.disconnect;let r=i.devices.list,o=i.devices.listWithStatus,c=i.devices.watch,d=i.devices.watchWithStatus,l=v=>(this.roster.reconcileLiveSnapshot(v),v),p=async()=>this.roster.mergeDevices(l(await r())),h=async()=>this.roster.mergeStatus(await o()),u=v=>c(T=>v(this.roster.mergeDevices(l(T)))),y=v=>d(T=>v(this.roster.mergeStatus(T))),m=Object.create(i);Object.defineProperties(m,{listDevices:{value:p,enumerable:false},listDevicesWithStatus:{value:h,enumerable:false},watchDevices:{value:u,enumerable:false},watchDevicesWithStatus:{value:y,enumerable:false},devices:{value:{...i.devices,list:p,listWithStatus:h,watch:u,watchWithStatus:y},enumerable:true}}),R.set(this,m),this.stopRosterSync=c(l);}replaceEnrolledDevices(t){this.roster.replace(t);}removeEnrolledDevice(t){this.roster.remove(t);}retainCurrentEnrolledDevice(t){this.roster.retain(t);}async close(){this.stopRosterSync(),await super.close();}},S=class extends O{constructor(t,i,n,a){super("space",t,i,n);this.delivery=a;this.kind="space";this.leave=()=>this.close();}},w=class extends O{constructor(t,i,n,a,r){super("room",t,i,n);this.membership=a;this.onLeave=r;this.kind="room";this.left=false;}async leave(){this.left||(this.left=true,await this.onLeave?.()),await this.close();}},k=class extends O{constructor(t,i,n,a){super("ticket",t,i,n);this.token=a;this.kind="ticket";}},A=class{constructor(e,t){this.options=e;this.internals=t;this.channels=new I;this.handles=new Set;this.activations=new Map;this.closed=false;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",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());for(let n of this.handles)n instanceof f&&n.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=E(e),a=await this.deviceId();await(await this.controlPlane()).revokeDevice(i,a,n),await Promise.allSettled([...this.handles].map(r=>r.retireDeviceIfPresent(n)));for(let r of this.handles)r instanceof f&&r.removeEnrolledDevice(n);n===a&&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();for(let n of this.handles)n instanceof f&&n.retainCurrentEnrolledDevice(i);await Promise.allSettled([...this.handles].map(n=>n.retireAllOtherDevices(i)));}e.exceptCurrent!==true&&this.retireAuthCapabilities(t);}};this.spaces={join:(e,t={})=>this.activateOnce(`space:${C(e)}`,JSON.stringify({payload:t.payload??"reliable",maxPeers:t.maxPeers??null,advancedFanout:t.advancedFanout===true}),void 0,()=>this.joinSpace(e,t))};this.rooms={join:(e,t={})=>{let i=t.access??"capability";return this.activateOnce(`room:${C(e)}`,JSON.stringify({access:i,membership:t.membership??"ephemeral",maxPeers:t.maxPeers??null,advancedFanout:t.advancedFanout===true}),i==="authenticated"?t.auth??this.options.auth:void 0,()=>this.joinRoom(e,t))}};this.tickets={issue:(e,t={})=>this.activateOnce(`ticket:${C(e)}`,JSON.stringify({maxPeers:t.maxPeers??null,advancedFanout:t.advancedFanout===true}),void 0,()=>this.issueTicket(e,t))};this.onClosed=e=>{this.handles.delete(e);for(let[t,i]of this.activations)i.handle===e&&this.activations.delete(t);};this.apiKey=F(e.apiKey),this.appTag=`app_${this.apiKey.slice(-16)}`,this.usage=new D(e.usage);}controlPlane(){return this.controlPlanePromise??(this.controlPlanePromise=Promise.all([import('./controlPlane-HW224SPX.js'),this.internals.deviceKeyProvider?Promise.resolve(this.internals.deviceKeyProvider):import('./deviceKey-SBNKLVYF.js').then(({browserDeviceKeyProvider:e})=>e)]).then(([{OpenRTCV2ControlPlane:e},t])=>new e(this.apiKey,this.internals.endpoints??a,t,this.options.trust?.attestation,{beforeLogicalOperation:i=>this.usage.assertCanSpend(i),onLogicalOperation:i=>this.usage.record(i),onAuthEpochChanged:i=>this.retireAuthCapabilities(i)},this.options.trust?.botVerification)))}assertOpen(){if(this.closed)throw new Error("[OpenRTC] Client is closed.")}activateOnce(e,t,i,n){this.assertOpen();let a=this.activations.get(e);if(a){if(a.fingerprint!==t||a.auth!==i)throw new Error(`[OpenRTC] ${e} is already active with different options.`);return a.promise}let r={fingerprint:t,auth:i},o=n().then(c=>(r.handle=c,c)).catch(c=>{throw this.activations.get(e)===r&&this.activations.delete(e),c});return r.promise=o,this.activations.set(e,r),o}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):H(this.appTag);return E(e)}runtimeOptions(e){let t=this.options.transports,i=t?.privacy==="relay-only";if(i&&t?.relay!==true)throw new Error("[OpenRTC] transports.privacy: relay-only requires transports.relay: true.");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,nativeApplicationStreamConsumer:this.internals.platform==="native"&&t?.nativeHostProtocols===true?"host":"runtime",coordinationAvenueOverride:e.avenue,coordinationGateway:{endpoint:(this.internals.endpoints??a).gateway,environment:"production",grantProvider:e.grantProvider,testingAllowInsecureLoopback:this.internals.testingAllowInsecureLoopback},transports:{iroh:i?{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:t?.webrtc===true?i?{privacyMode:true,useTurn:true,useDefaultIceServers:false}:true:false,ble:t?.ble??false,moq:t?.moq??false},transportPriority:t?.priority}}async activate(e){let t=await this.controlPlane(),i={relay:this.options.transports?.relay===true,moq:this.options.transports?.moq===true,ble:this.options.transports?.ble===true,advancedFanout:e.advancedFanout===true,durableMembership:e.durableMembership===true},n=e.source,a=null,r=()=>({userId:e.principalId,token:n.token,tokenProvider:async()=>n.token,expiresAtMs:n.expiresAtMs}),o=this.runtimeOptions({avenue:e.source.avenue,grantProvider:t.grantProvider(e.source,{maxPeers:e.maxPeers,features:i,deviceProfile:e.deviceName&&e.devicePlatform?{name:e.deviceName,platform:e.devicePlatform}:void 0,onSourceRenewed:async l=>{n={...n,...l},await a?.setAuth(r());}}),deviceId:e.deviceId,userId:e.principalId,deviceName:e.deviceName,devicePlatform:e.devicePlatform}),[c,{wrapAssembly:d}]=await Promise.all([this.internals.runtimeFactory(o),import('./OpenRTCShared-LDKG5RPN.js')]);a=d(c,this.internals.platform==="native"?"native":"web"),await a.setAuth(r()),this.channels.attach(a,e.defaultDelivery??"reliable");try{this.usage.assertCanSpend("coordination.connection.open"),await a.devices.startSession({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(l){throw this.channels.detach(a),await a.advanced.runtime.shutdown().catch(()=>{}),l}return this.usage.record("coordination.connection.open"),a}async startDevices(e={}){this.assertOpen();let t=e.auth??this.options.auth;if(!t)throw new Error("[OpenRTC] devices.start() requires an auth provider.");let i=await this.deviceId(),{resolveDeviceProfile:n}=await import('./deviceProfile-3BEQZLJF.js'),a=n(e.profile,this.internals.platform==="native"?"native":"web"),r=await this.controlPlane(),o=await r.deviceCertificate(t,i,void 0,a),c=await this.activate({kind:"devices",id:o.principalId,source:o.source,principalId:o.principalId,deviceId:i,maxPeers:e.maxPeers,autoConnect:e.autoConnect!=="none",advancedFanout:e.advancedFanout,deviceName:a.name,devicePlatform:a.platform,deviceMetadata:a.metadata}),d;try{d=await r.listEnrolledDevices(t,i);}catch(h){throw this.channels.detach(c),await c.advanced.runtime.shutdown().catch(()=>{}),h}let{AuthenticatedDeviceRoster:l}=await import('./deviceRoster-VZA3TQOR.js'),p;return p=new f(o.principalId,c,()=>{this.channels.detach(c),this.onClosed(p);},new l(d)),this.handles.add(p),p}async joinSpace(e,t={}){this.assertOpen();let i=C(e),n=await(await this.controlPlane()).capability("space",i,t.maxPeers,t.advancedFanout),a=String(b$1(n.token).principalId),r=await this.activate({kind:"space",id:i,source:n,principalId:a,deviceId:b(n),maxPeers:t.maxPeers,autoConnect:true,defaultDelivery:t.payload??"reliable",advancedFanout:t.advancedFanout}),o;return o=new S(i,r,()=>{this.channels.detach(r),this.onClosed(o);},t.payload??"reliable"),this.handles.add(o),o}async joinRoom(e,t={}){this.assertOpen();let i=C(e),n=t.membership??"ephemeral",a=t.access??"capability";if(n==="durable"&&a!=="authenticated")throw new Error("[OpenRTC] Durable room membership requires access: authenticated.");if(a==="authenticated"){let l=t.auth??this.options.auth;if(!l)throw new Error("[OpenRTC] Authenticated rooms require an auth provider.");let p=await this.deviceId(),h=await this.controlPlane(),u=await h.deviceCertificate(l,p,{kind:"room",id:i});n==="durable"&&await h.durableRoomMembership(u.source,i,"join");let y;try{y=await this.activate({kind:"room",id:i,source:u.source,principalId:u.principalId,deviceId:p,maxPeers:t.maxPeers,autoConnect:!0,durableMembership:n==="durable",advancedFanout:t.advancedFanout});}catch(v){throw n==="durable"&&await h.durableRoomMembership(u.source,i,"leave").catch(()=>{}),v}let m;return m=new w(i,y,()=>{this.channels.detach(y),this.onClosed(m);},n,n==="durable"?async()=>{await h.durableRoomMembership(u.source,i,"leave");}:void 0),this.handles.add(m),m}let r=await(await this.controlPlane()).capability("room",i,t.maxPeers,t.advancedFanout),o=String(b$1(r.token).principalId),c=await this.activate({kind:"room",id:i,source:r,principalId:o,deviceId:b(r),maxPeers:t.maxPeers,autoConnect:true,advancedFanout:t.advancedFanout}),d;return d=new w(i,c,()=>{this.channels.detach(c),this.onClosed(d);},"ephemeral"),this.handles.add(d),d}async issueTicket(e,t={}){this.assertOpen();let i=C(e),n=await(await this.controlPlane()).capability("ticket",i,t.maxPeers,t.advancedFanout),a=String(b$1(n.token).principalId),r=await this.activate({kind:"ticket",id:i,source:n,principalId:a,deviceId:b(n),maxPeers:t.maxPeers,autoConnect:false,advancedFanout:t.advancedFanout}),o;return o=new k(i,r,()=>{this.channels.detach(r),this.onClosed(o);},n.token),this.handles.add(o),o}async close(){if(!this.closed){this.closed=true;try{await Promise.all([...this.handles].map(e=>e.close()));}finally{await this.controlPlanePromise?.then(e=>e.dispose(),()=>{}),this.activations.clear();}}}};function q(s,e){return new A(s,e)}export{$ as a,q as b};