@urun-sh/core 0.1.36 → 0.1.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{a as M,b as v,c as k}from"./chunk-FTLHEH7Y.mjs";var H="session-api.prod.cloud.urun.sh",K=["https://session-api.use2.prod.cloud.urun.sh","https://session-api.usw2.prod.cloud.urun.sh"];function b(n){return n.trim().replace(/\/+$/,"")}function C(n,e){let t=[],r=s=>{if(!s)return;let o=b(s);o&&!t.includes(o)&&t.push(o)};r(n);for(let s of e??[])r(s);for(let s of ee(n))r(s);return t}var q=120,V=1e3,W=3;function Y(n){if(!n)return null;try{let e=new URL(n),t=e.pathname.replace(/\/api\/sessions\/create\/?$/,"");return b(`${e.origin}${t}`)}catch{return null}}async function D(n){let e=C(n.baseUrl,n.fallbackUrls),t=null,r=e.length>1;for(let s of e)try{return await z(s,n,{pollAttempts:q,retryAfterLimitMs:r?V:void 0})}catch(o){if(t=o instanceof Error?o:new Error(String(o)),t instanceof w)throw t}throw t??new Error("[urun] session allocation failed")}async function z(n,e,t){let r,s,o,i=n,l=0,h=new Set;for(let p=0;p<t.pollAttempts;p++){s=o??await E(e),o=void 0;let d=r?await fetch(`${i}/api/session-requests/${encodeURIComponent(r)}`,{headers:A(e,s)}):await fetch(`${i}/api/sessions/create`,{method:"POST",redirect:"manual",headers:{...A(e,s),"Content-Type":"application/json","Idempotency-Key":e.idempotencyKey},body:JSON.stringify(X(e))});if(!r&&(d.status===307||d.status===308)){let u=Y(d.headers.get("location"));if(u&&u!==i&&l<W){l+=1,i=u;continue}throw new Error(`[urun] session create redirected from ${i} without a usable target`)}let a=await j(d);if(d.ok&&(a.status==="allocated"||!a.status&&!!a.session_id)&&!!a.session_id){let u=a.session_id;if(!a.ws_url)throw new w(`[urun] gateway allocated session ${u} without ws_url`);if(!$(a.ws_url))throw new w(`[urun] gateway allocated session ${u} with non-absolute ws_url`);return{baseUrl:i,sessionId:u,wsUrl:a.ws_url,response:a}}if(d.status===202||a.status==="pending"||a.status==="queued"||a.queued){if(r=a.request_id||r,!r)throw new Error("[urun] gateway queued session without request_id");await Z(Q(d,a,t.retryAfterLimitMs));continue}if((d.status===401||d.status===403)&&e.getAccessToken){let u=s??"";h.add(u);let _=await E(e,{forceRefresh:!0,reason:"unauthorized"});if(_&&!h.has(_)){o=_,r=void 0;continue}}let m=a.error_message||a.error_code||`HTTP ${d.status}`;throw new Error(`[urun] session allocation failed at ${i}: ${m}`)}throw new Error(`[urun] timed out waiting for session allocation at ${i}`)}function A(n,e){let t={"X-Tenant-Id":n.orgId,"X-Auth-Provider":n.authProvider||"default","X-User-Id":"anonymous"};return e&&(t.Authorization=`Bearer ${e}`),t}async function E(n,e){return n.getAccessToken?await n.getAccessToken(e)??void 0:n.jwt}function X(n){return{app:n.app,function:n.functionName,gpus:1,idempotency_key:n.idempotencyKey}}async function L(n){let e=C(n.baseUrl,n.fallbackUrls),t=null;for(let r of e)try{let s={baseUrl:r,app:"",functionName:"",orgId:n.orgId,jwt:n.jwt,getAccessToken:n.getAccessToken,authProvider:n.authProvider,idempotencyKey:""},o=await E(s),i=await fetch(`${b(r)}/api/sessions/${encodeURIComponent(n.sessionId)}/viewer-connect`,{headers:A(s,o)});if(!i.ok)throw new Error(`[urun] viewer-connect for ${n.sessionId} failed: HTTP ${i.status}`);let l=await j(i);if(!l.ws_url||!$(l.ws_url))throw new w(`[urun] viewer-connect returned no usable ws_url for ${n.sessionId}`);return{baseUrl:b(r),sessionId:n.sessionId,wsUrl:l.ws_url,response:l}}catch(s){if(t=s instanceof Error?s:new Error(String(s)),t instanceof w)throw t}throw t??new Error("[urun] viewer-connect failed")}async function j(n){try{let e=await n.json();return e&&typeof e=="object"?e:{}}catch{return{}}}function Q(n,e,t){let r=Number(n.headers.get("Retry-After")||""),s=Number(e.retry_after_seconds??r),o=t??1e4;return Number.isFinite(s)&&s>0?Math.min(s*1e3,o):1e3}function Z(n){return new Promise(e=>setTimeout(e,n))}var w=class extends Error{};function $(n){try{let e=new URL(n);return e.protocol==="ws:"||e.protocol==="wss:"}catch{return!1}}function ee(n){try{return new URL(n).hostname!==H?[]:K}catch{return[]}}import*as g from"yjs";var N=Symbol("urun:doc:remote"),te=Symbol("urun:doc:local");function R(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function P(n,e){let t={...n};for(let r of Object.keys(e)){let s=e[r],o=t[r];R(s)&&R(o)?t[r]=P(o,s):t[r]=s}return t}function re(n,e){let t=e.split("."),r=n;for(let s of t){if(r==null||typeof r!="object")return;r=r[s]}return r}function B(n){return n===void 0?n:JSON.parse(JSON.stringify(n))}var I=class{_doc=new g.Doc;_root=this._doc.getMap("session");_listeners=new Set;_key;_sessionId;_transport;_transportUnsubs=[];_synced;_pendingPatches=[];_observer=()=>this.notify();_updateHandler=(e,t)=>{t!==N&&this._transport?.sendDocSync(e)};constructor(e,t,r){this._key=e,this._sessionId=t,this._transport=r??null,this._synced=this._transport===null,this._root.observeDeep(this._observer),this._doc.on("update",this._updateHandler),this._transport&&(this._transportUnsubs.push(this._transport.onDocSync(s=>this.applyRemote(s)),this._transport.onDocSyncReady(()=>this.sendHello())),this._transport.isOpen&&this.sendHello())}setSessionId(e){this._sessionId=e}set(e){if(!this._synced){this._pendingPatches.push(B(e)),this.notify();return}this.applyPatch(e)}get(e,t){let r=this.snapshot();return e?re(r,e)??t:r}on(e,t){return this._listeners.add(t),()=>this._listeners.delete(t)}dispose(){this._root.unobserveDeep(this._observer),this._doc.off("update",this._updateHandler);for(let e of this._transportUnsubs)e();this._transportUnsubs=[],this._transport=null,this._listeners.clear(),this._doc.destroy()}sendHello(){this._transport&&this._transport.sendDocSync(g.encodeStateAsUpdate(this._doc))}applyRemote(e){if(g.applyUpdate(this._doc,e,N),!this._synced){this._synced=!0;let t=this._pendingPatches.splice(0);for(let r of t)this.applyPatch(r)}}applyPatch(e){this._doc.transact(()=>{let t=this._root.toJSON();for(let[r,s]of Object.entries(e)){let o=t[r],i=R(s)&&R(o)?P(o,s):B(s);JSON.stringify(i)!==JSON.stringify(o)&&this._root.set(r,i)}},te)}snapshot(){let e=this._root.toJSON();for(let t of this._pendingPatches)e=P(e,t);return e}notify(){let e=this.snapshot();for(let t of this._listeners)t(e)}};var ne=new Set(["control"]),O=class{constructor(e,t){this._name=e;this._transport=t;this._track=this._transport.getTrackByName(this._name)??null,this._unsubscribeTransport=this._transport.on("track",()=>{let r=this._transport.getTrackByName(this._name)??null;r!==this._track&&this._setTrack(r)})}_name;_transport;_track=null;_handlers=new Map;_unsubscribeTransport=null;get track(){let e=this._transport.getTrackByName(this._name)??this._track;return e!==this._track&&this._setTrack(e),this._track}async attach(e){await this._transport.addTrack(e)}async detach(){this._transport.removeTrack()}async seek(e){if(e!=="live"&&(!Number.isFinite(e)||e<0))throw new Error('[urun] stream.seek target must be "live" or a non-negative number of seconds');this._transport.seekStream(this._name,e)}on(e,t){let r=this._handlers.get(e);return r||(r=new Set,this._handlers.set(e,r)),r.add(t),()=>{r?.delete(t),r?.size===0&&this._handlers.delete(e)}}dispose(){this._unsubscribeTransport?.(),this._unsubscribeTransport=null,this._handlers.clear()}_setTrack(e){this._track=e,e&&e.addEventListener("ended",()=>{this._track===e&&this._setTrack(null)},{once:!0});let t=this._handlers.get("track");if(t)for(let r of t)r(e)}},S=class n{_sessionId;_multiplexer;_transport;_docs=new Map;_streams=new Map;constructor(e,t,r){this._sessionId=e,this._multiplexer=t,this._transport=r,this._wireControlDocIncarnation()}_wireControlDocIncarnation(){let e=this.doc("control");this._transport.applyControlDocState(e.get()),e.on("change",t=>{this._transport.applyControlDocState(t)})}static async attach(e,t){let r=await L({baseUrl:t.baseUrl,fallbackUrls:t.fallbackUrls,sessionId:e,orgId:t.orgId,jwt:t.jwt,getAccessToken:t.getAccessToken,authProvider:t.authProvider}),s=t.getAccessToken?await t.getAccessToken()??void 0:t.jwt,o=new v,i=new k({url:r.wsUrl,orgId:t.orgId,jwt:s,authProvider:t.authProvider,sessionId:e}),l=new n(e,o,i);return i.on("connected",()=>{i.multiplexer&&o.setTarget(i.multiplexer)}),i.setConnection({url:r.wsUrl,sessionId:e}),await i.connect({role:"viewer"}),l}get id(){return this._sessionId}get phase(){return this._transport.phase}onPhase(e){return e(this._transport.phase),this._transport.on("phase",e)}setSessionId(e){if(e===this._sessionId)return;this._multiplexer.rewriteSessionChannels?.call(this._multiplexer,this._sessionId,e),this._sessionId=e;for(let r of this._docs.values())r.setSessionId(e)}stream(e){let t=this._streams.get(e);return t||(t=new O(e,this._transport),this._streams.set(e,t)),t}doc(e){let t=this._docs.get(e);return t||(t=new I(e,this._sessionId,ne.has(e)?this._transport:null),this._docs.set(e,t)),t}disconnect(){for(let e of this._docs.values())e.dispose();this._docs.clear();for(let e of this._streams.values())e.dispose();this._streams.clear(),this._transport.disconnect()}};var se=new Set(["then","catch","finally","toJSON",Symbol.toPrimitive]);function oe(n,e){return new Proxy({},{get(t,r){if(!(se.has(r)||typeof r!="string"))return s=>{let o=s??{},i=()=>`s_${Date.now()}_${Math.random().toString(36).slice(2)}`,l=i(),h=new v,p=new k({url:"",orgId:e.orgId,jwt:e.jwt,authProvider:e.authProvider,sessionId:l}),d=new S(l,h,p),a=async c=>{let m=await D({baseUrl:e.baseUrl,fallbackUrls:e.fallbackUrls,app:n,functionName:r,orgId:e.orgId,jwt:e.jwt,getAccessToken:e.getAccessToken,authProvider:e.authProvider,idempotencyKey:c}),u=e.getAccessToken?await e.getAccessToken()??void 0:e.jwt;return d.setSessionId(m.sessionId),{url:m.wsUrl,sessionId:m.sessionId,jwt:u}};return p.setConnectionResolver(()=>a(i())),p.on("connected",()=>{p.multiplexer&&h.setTarget(p.multiplexer)}),(async()=>{let c=await a(l);p.setAuth({jwt:c.jwt,authProvider:e.authProvider,orgId:e.orgId}),p.setConnection({url:c.url,sessionId:c.sessionId}),await p.connect({app:n,functionName:r,args:o})})().catch(c=>{console.error(`[urun] Failed to connect session for ${r}:`,c)}),d}}})}var G=3e4,F="stream:",x=class{_ws;_multiplexer;_pendingRpc=new Map;_rpcId=0;constructor(e,t){this._ws=e,this._multiplexer=t,this._ws.addEventListener("message",r=>{let s;try{s=JSON.parse(typeof r.data=="string"?r.data:"")}catch{return}if(s.rpcId&&this._pendingRpc.has(s.rpcId)){let o=this._pendingRpc.get(s.rpcId);this._pendingRpc.delete(s.rpcId),clearTimeout(o.timer),s.error?o.reject(new Error(s.error)):o.resolve(s.result)}})}async get(e){return this._sendRpc("store.get",{key:e})}async has(e){return await this._sendRpc("store.has",{key:e})}on(e,t){let r=`${F}${e}`;return this._multiplexer.on(r,s=>{t(s)})}emit(e,t){let r=`${F}${e}`,s=typeof t=="object"&&t!==null&&!Array.isArray(t)?t:{data:t};this._multiplexer.emit(r,s)}_getInternals(){return{multiplexer:this._multiplexer,ws:this._ws}}_sendRpc(e,t){return new Promise((r,s)=>{if(!this._ws||this._ws.readyState!==WebSocket.OPEN){s(new Error("WebSocket not open"));return}let o=String(++this._rpcId),i=setTimeout(()=>{this._pendingRpc.has(o)&&(this._pendingRpc.delete(o),s(new Error(`RPC request "${e}" timed out after ${G}ms`)))},G);this._pendingRpc.set(o,{resolve:r,reject:s,timer:i}),this._ws.send(JSON.stringify({rpcId:o,type:e,...t}))})}};function ie(n){let r=`${n.baseUrl.replace(/\/$/,"").replace(/^http/,"ws")}/store/${encodeURIComponent(n.orgId)}`,s=new WebSocket(r);(n.jwt||n.apiKey)&&s.addEventListener("open",()=>{s.send(JSON.stringify({type:"auth",orgId:n.orgId,jwt:n.jwt,authProvider:n.authProvider,apiKey:n.apiKey}))});let o=new M(s);return new x(s,o)}var ae='video/mp4; codecs="avc1.42E01E"';function ce(n,e){let t=e?.codec??ae,r=document.createElement("video");r.muted=!0,r.playsInline=!0;let s=new MediaSource,o=URL.createObjectURL(s);r.src=o,s.addEventListener("sourceopen",()=>{let c;try{c=s.addSourceBuffer(t)}catch(f){throw f instanceof DOMException&&f.name==="NotSupportedError"?new Error(`Codec not supported: "${t}". Ensure the codec string matches the fMP4 container format. Common values: video/mp4; codecs="avc1.42E01E" (H.264 Baseline), video/mp4; codecs="avc1.4D401F" (H.264 Main).`):f}let m=n.getReader();function u(){return c.updating?new Promise(f=>{c.addEventListener("updateend",()=>f(),{once:!0})}):Promise.resolve()}async function _(){try{for(;;){let{done:f,value:U}=await m.read();if(f){await u(),s.readyState==="open"&&s.endOfStream();return}await u();try{c.appendBuffer(U)}catch(y){if(y instanceof DOMException&&y.name==="QuotaExceededError"){let T=c.buffered;if(T.length>0){let J=T.start(T.length-1);c.remove(0,J),await u(),c.appendBuffer(U)}else throw y}else throw y}}}catch{if(s.readyState==="open")try{s.endOfStream("decode")}catch{}}}_()}),r.play().catch(()=>{});let i=r,l=i.captureStream??i.mozCaptureStream;if(!l)throw new Error("captureStream() is not supported in this browser. videoStream() requires HTMLMediaElement.captureStream() support.");let h=l.call(r),p=h.getTracks(),d=0,a=p.length;if(a===0)r.addEventListener("emptied",()=>{URL.revokeObjectURL(o)},{once:!0});else for(let c of p)c.addEventListener("ended",()=>{d++,d>=a&&URL.revokeObjectURL(o)});return h}export{oe as App,S as Session,ie as createStore,ce as videoStream};
1
+ import{a as F,b as P,e as O}from"./chunk-FPOLGUA2.mjs";var re="session-api.prod.cloud.urun.sh",ne=["https://session-api.use2.prod.cloud.urun.sh","https://session-api.usw2.prod.cloud.urun.sh"];function U(n){return n.trim().replace(/\/+$/,"")}function G(n,e){let t=[],r=s=>{if(!s)return;let o=U(s);o&&!t.includes(o)&&t.push(o)};r(n);for(let s of e??[])r(s);for(let s of pe(n))r(s);return t}var se=120,oe=1e3,ie=3;function ae(n){if(!n)return null;try{let e=new URL(n),t=e.pathname.replace(/\/api\/sessions\/create\/?$/,"");return U(`${e.origin}${t}`)}catch{return null}}async function J(n){let e=G(n.baseUrl,n.fallbackUrls),t=null,r=e.length>1;for(let s of e)try{return await ce(s,n,{pollAttempts:se,retryAfterLimitMs:r?oe:void 0})}catch(o){if(t=o instanceof Error?o:new Error(String(o)),t instanceof b)throw t}throw t??new Error("[urun] session allocation failed")}async function ce(n,e,t){let r,s,o,i=n,a=0,f=new Set;for(let p=0;p<t.pollAttempts;p++){s=o??await L(e),o=void 0;let d=r?await fetch(`${i}/api/session-requests/${encodeURIComponent(r)}`,{headers:D(e,s)}):await fetch(`${i}/api/sessions/create`,{method:"POST",redirect:"manual",headers:{...D(e,s),"Content-Type":"application/json","Idempotency-Key":e.idempotencyKey},body:JSON.stringify(ue(e))});if(!r&&(d.status===307||d.status===308)){let h=ae(d.headers.get("location"));if(h&&h!==i&&a<ie){a+=1,i=h;continue}throw new Error(`[urun] session create redirected from ${i} without a usable target`)}let c=await H(d);if(d.ok&&(c.status==="allocated"||!c.status&&!!c.session_id)&&!!c.session_id){let h=c.session_id;if(!c.ws_url)throw new b(`[urun] gateway allocated session ${h} without ws_url`);if(!Y(c.ws_url))throw new b(`[urun] gateway allocated session ${h} with non-absolute ws_url`);return{baseUrl:i,sessionId:h,wsUrl:c.ws_url,response:c}}if(d.status===202||c.status==="pending"||c.status==="queued"||c.queued){if(r=c.request_id||r,!r)throw new Error("[urun] gateway queued session without request_id");await de(le(d,c,t.retryAfterLimitMs));continue}if((d.status===401||d.status===403)&&e.getAccessToken){let h=s??"";f.add(h);let g=await L(e,{forceRefresh:!0,reason:"unauthorized"});if(g&&!f.has(g)){o=g,r=void 0;continue}}let m=c.error_message||c.error_code||`HTTP ${d.status}`;throw new Error(`[urun] session allocation failed at ${i}: ${m}`)}throw new Error(`[urun] timed out waiting for session allocation at ${i}`)}function D(n,e){let t={"X-Tenant-Id":n.orgId,"X-Auth-Provider":n.authProvider||"default","X-User-Id":"anonymous"};return e&&(t.Authorization=`Bearer ${e}`),t}async function L(n,e){return n.getAccessToken?await n.getAccessToken(e)??void 0:n.jwt}function ue(n){return{app:n.app,function:n.functionName,gpus:1,idempotency_key:n.idempotencyKey}}async function K(n){let e=G(n.baseUrl,n.fallbackUrls),t=null;for(let r of e)try{let s={baseUrl:r,app:"",functionName:"",orgId:n.orgId,jwt:n.jwt,getAccessToken:n.getAccessToken,authProvider:n.authProvider,idempotencyKey:""},o=await L(s),i=await fetch(`${U(r)}/api/sessions/${encodeURIComponent(n.sessionId)}/viewer-connect`,{headers:D(s,o)});if(!i.ok)throw new Error(`[urun] viewer-connect for ${n.sessionId} failed: HTTP ${i.status}`);let a=await H(i);if(!a.ws_url||!Y(a.ws_url))throw new b(`[urun] viewer-connect returned no usable ws_url for ${n.sessionId}`);return{baseUrl:U(r),sessionId:n.sessionId,wsUrl:a.ws_url,response:a}}catch(s){if(t=s instanceof Error?s:new Error(String(s)),t instanceof b)throw t}throw t??new Error("[urun] viewer-connect failed")}async function H(n){try{let e=await n.json();return e&&typeof e=="object"?e:{}}catch{return{}}}function le(n,e,t){let r=Number(n.headers.get("Retry-After")||""),s=Number(e.retry_after_seconds??r),o=t??1e4;return Number.isFinite(s)&&s>0?Math.min(s*1e3,o):1e3}function de(n){return new Promise(e=>setTimeout(e,n))}var b=class extends Error{};function Y(n){try{let e=new URL(n);return e.protocol==="ws:"||e.protocol==="wss:"}catch{return!1}}function pe(n){try{return new URL(n).hostname!==re?[]:ne}catch{return[]}}import*as R from"yjs";var V=Symbol("urun:doc:remote"),he=Symbol("urun:doc:local");function M(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function j(n,e){let t={...n};for(let r of Object.keys(e)){let s=e[r],o=t[r];M(s)&&M(o)?t[r]=j(o,s):t[r]=s}return t}function fe(n,e){let t=e.split("."),r=n;for(let s of t){if(r==null||typeof r!="object")return;r=r[s]}return r}function W(n){return n===void 0?n:JSON.parse(JSON.stringify(n))}var q=class{_doc=new R.Doc;_root=this._doc.getMap("session");_listeners=new Set;_key;_sessionId;_transport;_transportUnsubs=[];_synced;_pendingPatches=[];_texts=new Map;_observer=()=>this.notify();_updateHandler=(e,t)=>{t!==V&&this._transport?.sendDocSync(this._key,e)};constructor(e,t,r){this._key=e,this._sessionId=t,this._transport=r??null,this._synced=this._transport===null,this._root.observeDeep(this._observer),this._doc.on("update",this._updateHandler),this._transport&&(this._transportUnsubs.push(this._transport.onDocSync(this._key,s=>this.applyRemote(s)),this._transport.onDocSyncReady(()=>this.sendHello())),this._transport.isOpen&&this.sendHello())}setSessionId(e){this._sessionId=e}set(e){if(!this._synced){this._pendingPatches.push(W(e)),this.notify();return}this.applyPatch(e)}get(e,t){let r=this.snapshot();return e?fe(r,e)??t:r}on(e,t){return this._listeners.add(t),()=>this._listeners.delete(t)}text(e){let t=this._texts.get(e);return t||(t=new $(this._doc.getText(`text:${e}`)),this._texts.set(e,t)),t}dispose(){this._root.unobserveDeep(this._observer),this._doc.off("update",this._updateHandler);for(let e of this._transportUnsubs)e();this._transportUnsubs=[],this._transport=null,this._listeners.clear();for(let e of this._texts.values())e.dispose();this._texts.clear(),this._doc.destroy()}sendHello(){this._transport&&this._transport.sendDocSync(this._key,R.encodeStateAsUpdate(this._doc))}applyRemote(e){if(R.applyUpdate(this._doc,e,V),!this._synced){this._synced=!0;let t=this._pendingPatches.splice(0);for(let r of t)this.applyPatch(r)}}applyPatch(e){this._doc.transact(()=>{let t=this._root.toJSON();for(let[r,s]of Object.entries(e)){let o=t[r],i=M(s)&&M(o)?j(o,s):W(s);JSON.stringify(i)!==JSON.stringify(o)&&this._root.set(r,i)}},he)}snapshot(){let e=this._root.toJSON();for(let t of this._pendingPatches)e=j(e,t);return e}notify(){let e=this.snapshot();for(let t of this._listeners)t(e)}},$=class{constructor(e){this._ytext=e;this._observer=t=>{for(let r of t.delta)if(typeof r.insert=="string"&&r.insert.length>0){let s=r.insert;for(let o of this._delta)o(s)}},this._ytext.observe(this._observer)}_ytext;_delta=new Set;_observer;append(e){e.length!==0&&this._ytext.insert(this._ytext.length,e)}toString(){return this._ytext.toString()}get length(){return this._ytext.length}on(e,t){return this._delta.add(t),()=>this._delta.delete(t)}dispose(){this._ytext.unobserve(this._observer),this._delta.clear()}};var y=class extends Error{requestId;code;constructor(e,t){super(e),this.name="RequestError",this.requestId=t?.requestId,this.code=t?.code,t?.cause!==void 0&&(this.cause=t.cause),Object.setPrototypeOf(this,new.target.prototype)}},T=class extends y{timeoutMs;constructor(e,t){super(`[urun] request timed out after ${e}ms`,{requestId:t}),this.name="RequestTimeoutError",this.timeoutMs=e,Object.setPrototypeOf(this,new.target.prototype)}},k=class extends y{constructor(e){super("[urun] request aborted",{requestId:e}),this.name="RequestAbortError",Object.setPrototypeOf(this,new.target.prototype)}},x=class extends y{constructor(e){super("[urun] request cancelled: session disconnected",{requestId:e}),this.name="RequestCancelledError",Object.setPrototypeOf(this,new.target.prototype)}};var ge=new Set,z="rpc";function X(){let n=globalThis.crypto;return n?.randomUUID?n.randomUUID():`req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`}function me(n,e,t,r,s){return{[Symbol.asyncIterator](){let o=[],i=null,a=!1,f=null,p=!1,d=n.text(e),c=null,u=null,m=null,h=()=>{c?.(),c=null,u?.(),u=null,m?.(),m=null,r?.removeEventListener("abort",S),p&&n.set({requests:{[e]:null}})},g=()=>{if(i){if(o.length>0){let l=i;i=null,l.resolve({value:o.shift(),done:!1})}else if(f!==null){let l=i;i=null,l.reject(f)}else if(a){let l=i;i=null,l.resolve({value:void 0,done:!0})}}},_=l=>{a||(o.push(l),g())},v=l=>{a||(f=l,a=!0,h(),g())},w=()=>{a||(a=!0,h(),g())},S=()=>v(new k(e)),E=l=>{if(l)if(l.error!==void 0&&l.error!==null){let I=typeof l.error=="string"?l.error:JSON.stringify(l.error);v(new y(I,{requestId:e,code:l.code}))}else l.done&&w()},ee=()=>{if(p)return;if(p=!0,r){if(r.aborted){v(new k(e));return}r.addEventListener("abort",S,{once:!0})}m=s?.(C=>v(C))??null,c=d.on("delta",_),u=n.on("change",C=>{if(a)return;let te=C.responses;E(te?.[e])}),n.set({requests:{[e]:{payload:t,stream:!0}}});let l=d.toString();l.length>0&&o.push(l);let I=n.get();E(I.responses?.[e])};return{next(){if(ee(),o.length>0)return Promise.resolve({value:o.shift(),done:!1});if(f!==null){let l=f;return f=null,Promise.reject(l)}return a?Promise.resolve({value:void 0,done:!0}):new Promise((l,I)=>{i={resolve:l,reject:I}})},return(){return a||(a=!0,h()),Promise.resolve({value:void 0,done:!0})},throw(l){return a||(a=!0,h()),Promise.reject(l)}}}}}var N=class{constructor(e,t){this._name=e;this._transport=t;this._track=this._transport.getTrackByName(this._name)??null,this._unsubscribeTransport=this._transport.on("track",()=>{let r=this._transport.getTrackByName(this._name)??null;r!==this._track&&this._setTrack(r)})}_name;_transport;_track=null;_handlers=new Map;_unsubscribeTransport=null;get track(){let e=this._transport.getTrackByName(this._name)??this._track;return e!==this._track&&this._setTrack(e),this._track}async attach(e){await this._transport.addTrack(e)}async detach(){this._transport.removeTrack()}async seek(e){if(e!=="live"&&(!Number.isFinite(e)||e<0))throw new Error('[urun] stream.seek target must be "live" or a non-negative number of seconds');this._transport.seekStream(this._name,e)}on(e,t){let r=this._handlers.get(e);return r||(r=new Set,this._handlers.set(e,r)),r.add(t),()=>{r?.delete(t),r?.size===0&&this._handlers.delete(e)}}dispose(){this._unsubscribeTransport?.(),this._unsubscribeTransport=null,this._handlers.clear()}_setTrack(e){this._track=e,e&&e.addEventListener("ended",()=>{this._track===e&&this._setTrack(null)},{once:!0});let t=this._handlers.get("track");if(t)for(let r of t)r(e)}},A=class n{_sessionId;_multiplexer;_transport;_docs=new Map;_streams=new Map;_activeRequests=new Set;constructor(e,t,r){this._sessionId=e,this._multiplexer=t,this._transport=r,this._wireControlDocIncarnation()}_wireControlDocIncarnation(){let e=this.doc("control");this._transport.applyControlDocState(e.get()),e.on("change",t=>{this._transport.applyControlDocState(t)})}static async attach(e,t){let r=await K({baseUrl:t.baseUrl,fallbackUrls:t.fallbackUrls,sessionId:e,orgId:t.orgId,jwt:t.jwt,getAccessToken:t.getAccessToken,authProvider:t.authProvider}),s=t.getAccessToken?await t.getAccessToken()??void 0:t.jwt,o=new P,i=new O({url:r.wsUrl,orgId:t.orgId,jwt:s,authProvider:t.authProvider,sessionId:e}),a=new n(e,o,i);return i.on("connected",()=>{i.multiplexer&&o.setTarget(i.multiplexer)}),i.setConnection({url:r.wsUrl,sessionId:e}),await i.connect({role:"viewer"}),a}get id(){return this._sessionId}get phase(){return this._transport.phase}onPhase(e){return e(this._transport.phase),this._transport.on("phase",e)}setSessionId(e){if(e===this._sessionId)return;this._multiplexer.rewriteSessionChannels?.call(this._multiplexer,this._sessionId,e),this._sessionId=e;for(let r of this._docs.values())r.setSessionId(e)}stream(e){let t=this._streams.get(e);return t||(t=new N(e,this._transport),this._streams.set(e,t)),t}doc(e){let t=this._docs.get(e);return t||(t=new q(e,this._sessionId,ge.has(e)?null:this._transport),this._docs.set(e,t)),t}request(e,t={}){let r=this.doc(z),s=X();return new Promise((o,i)=>{let a=!1,f=null,p=null,d=null,c=()=>{p&&(clearTimeout(p),p=null),f&&(f(),f=null),d&&(this._activeRequests.delete(d),d=null),t.signal?.removeEventListener("abort",m),r.set({requests:{[s]:null}})},u=g=>{a||(a=!0,c(),g())},m=()=>u(()=>i(new k(s)));if(t.signal){if(t.signal.aborted){a=!0,i(new k(s));return}t.signal.addEventListener("abort",m,{once:!0})}let h=g=>{let v=g.responses?.[s];if(v==null)return;let w=v;if(w.error!==void 0&&w.error!==null){let S=typeof w.error=="string"?w.error:JSON.stringify(w.error);u(()=>i(new y(S,{requestId:s,code:w.code})))}else u(()=>o(w.result))};f=r.on("change",h),d=g=>u(()=>i(g)),this._activeRequests.add(d),typeof t.timeout=="number"&&t.timeout>=0&&(p=setTimeout(()=>u(()=>i(new T(t.timeout,s))),t.timeout)),r.set({requests:{[s]:{payload:e}}}),h(r.get())})}requestStream(e,t={}){let r=this.doc(z),s=X();return me(r,s,e,t.signal,o=>(this._activeRequests.add(o),()=>this._activeRequests.delete(o)))}disconnect(){let e=Array.from(this._activeRequests);this._activeRequests.clear();for(let t of e)try{t(new x)}catch{}for(let t of this._docs.values())t.dispose();this._docs.clear();for(let t of this._streams.values())t.dispose();this._streams.clear(),this._transport.disconnect()}};var we=new Set(["then","catch","finally","toJSON",Symbol.toPrimitive]);function _e(n,e){return new Proxy({},{get(t,r){if(!(we.has(r)||typeof r!="string"))return s=>{let o=s??{},i=()=>`s_${Date.now()}_${Math.random().toString(36).slice(2)}`,a=i(),f=new P,p=new O({url:"",orgId:e.orgId,jwt:e.jwt,authProvider:e.authProvider,sessionId:a}),d=new A(a,f,p),c=async u=>{let m=await J({baseUrl:e.baseUrl,fallbackUrls:e.fallbackUrls,app:n,functionName:r,orgId:e.orgId,jwt:e.jwt,getAccessToken:e.getAccessToken,authProvider:e.authProvider,idempotencyKey:u}),h=e.getAccessToken?await e.getAccessToken()??void 0:e.jwt;return d.setSessionId(m.sessionId),{url:m.wsUrl,sessionId:m.sessionId,jwt:h}};return p.setConnectionResolver(()=>c(i())),p.on("connected",()=>{p.multiplexer&&f.setTarget(p.multiplexer)}),(async()=>{let u=await c(a);p.setAuth({jwt:u.jwt,authProvider:e.authProvider,orgId:e.orgId}),p.setConnection({url:u.url,sessionId:u.sessionId}),await p.connect({app:n,functionName:r,args:o})})().catch(u=>{console.error(`[urun] Failed to connect session for ${r}:`,u)}),d}}})}var Q=3e4,Z="stream:",B=class{_ws;_multiplexer;_pendingRpc=new Map;_rpcId=0;constructor(e,t){this._ws=e,this._multiplexer=t,this._ws.addEventListener("message",r=>{let s;try{s=JSON.parse(typeof r.data=="string"?r.data:"")}catch{return}if(s.rpcId&&this._pendingRpc.has(s.rpcId)){let o=this._pendingRpc.get(s.rpcId);this._pendingRpc.delete(s.rpcId),clearTimeout(o.timer),s.error?o.reject(new Error(s.error)):o.resolve(s.result)}})}async get(e){return this._sendRpc("store.get",{key:e})}async has(e){return await this._sendRpc("store.has",{key:e})}on(e,t){let r=`${Z}${e}`;return this._multiplexer.on(r,s=>{t(s)})}emit(e,t){let r=`${Z}${e}`,s=typeof t=="object"&&t!==null&&!Array.isArray(t)?t:{data:t};this._multiplexer.emit(r,s)}_getInternals(){return{multiplexer:this._multiplexer,ws:this._ws}}_sendRpc(e,t){return new Promise((r,s)=>{if(!this._ws||this._ws.readyState!==WebSocket.OPEN){s(new Error("WebSocket not open"));return}let o=String(++this._rpcId),i=setTimeout(()=>{this._pendingRpc.has(o)&&(this._pendingRpc.delete(o),s(new Error(`RPC request "${e}" timed out after ${Q}ms`)))},Q);this._pendingRpc.set(o,{resolve:r,reject:s,timer:i}),this._ws.send(JSON.stringify({rpcId:o,type:e,...t}))})}};function ve(n){let r=`${n.baseUrl.replace(/\/$/,"").replace(/^http/,"ws")}/store/${encodeURIComponent(n.orgId)}`,s=new WebSocket(r);(n.jwt||n.apiKey)&&s.addEventListener("open",()=>{s.send(JSON.stringify({type:"auth",orgId:n.orgId,jwt:n.jwt,authProvider:n.authProvider,apiKey:n.apiKey}))});let o=new F(s);return new B(s,o)}var ye='video/mp4; codecs="avc1.42E01E"';function Se(n,e){let t=e?.codec??ye,r=document.createElement("video");r.muted=!0,r.playsInline=!0;let s=new MediaSource,o=URL.createObjectURL(s);r.src=o,s.addEventListener("sourceopen",()=>{let u;try{u=s.addSourceBuffer(t)}catch(_){throw _ instanceof DOMException&&_.name==="NotSupportedError"?new Error(`Codec not supported: "${t}". Ensure the codec string matches the fMP4 container format. Common values: video/mp4; codecs="avc1.42E01E" (H.264 Baseline), video/mp4; codecs="avc1.4D401F" (H.264 Main).`):_}let m=n.getReader();function h(){return u.updating?new Promise(_=>{u.addEventListener("updateend",()=>_(),{once:!0})}):Promise.resolve()}async function g(){try{for(;;){let{done:_,value:v}=await m.read();if(_){await h(),s.readyState==="open"&&s.endOfStream();return}await h();try{u.appendBuffer(v)}catch(w){if(w instanceof DOMException&&w.name==="QuotaExceededError"){let S=u.buffered;if(S.length>0){let E=S.start(S.length-1);u.remove(0,E),await h(),u.appendBuffer(v)}else throw w}else throw w}}}catch{if(s.readyState==="open")try{s.endOfStream("decode")}catch{}}}g()}),r.play().catch(()=>{});let i=r,a=i.captureStream??i.mozCaptureStream;if(!a)throw new Error("captureStream() is not supported in this browser. videoStream() requires HTMLMediaElement.captureStream() support.");let f=a.call(r),p=f.getTracks(),d=0,c=p.length;if(c===0)r.addEventListener("emptied",()=>{URL.revokeObjectURL(o)},{once:!0});else for(let u of p)u.addEventListener("ended",()=>{d++,d>=c&&URL.revokeObjectURL(o)});return f}export{_e as App,k as RequestAbortError,x as RequestCancelledError,y as RequestError,T as RequestTimeoutError,A as Session,ve as createStore,Se as videoStream};
@@ -148,6 +148,17 @@ interface Store {
148
148
  emit(name: string, data: unknown): void;
149
149
  }
150
150
 
151
+ interface SessionText {
152
+
153
+ append(text: string): void;
154
+
155
+ toString(): string;
156
+
157
+ readonly length: number;
158
+
159
+ on(event: 'delta', handler: (inserted: string) => void): () => void;
160
+ }
161
+
151
162
  interface SessionDocument {
152
163
 
153
164
  set(patch: Record<string, unknown>): void;
@@ -155,6 +166,8 @@ interface SessionDocument {
155
166
  get(path?: string, defaultValue?: unknown): unknown;
156
167
 
157
168
  on(event: 'change', handler: (snapshot: Record<string, unknown>) => void): () => void;
169
+
170
+ text(field: string): SessionText;
158
171
  }
159
172
 
160
173
  interface SessionStream {
@@ -170,6 +183,18 @@ interface SessionStream {
170
183
  on(event: 'track', handler: (track: MediaStreamTrack | null) => void): () => void;
171
184
  }
172
185
 
186
+ interface RequestOptions {
187
+
188
+ timeout?: number;
189
+
190
+ signal?: AbortSignal;
191
+ }
192
+
193
+ interface RequestStreamOptions {
194
+
195
+ signal?: AbortSignal;
196
+ }
197
+
173
198
  interface Session {
174
199
 
175
200
  readonly id: string;
@@ -180,6 +205,10 @@ interface Session {
180
205
 
181
206
  doc(key: string): SessionDocument;
182
207
 
208
+ request(payload: unknown, options?: RequestOptions): Promise<unknown>;
209
+
210
+ requestStream(payload: unknown, options?: RequestStreamOptions): AsyncIterable<string>;
211
+
183
212
  onPhase(handler: (phase: SessionPhase) => void): () => void;
184
213
 
185
214
  disconnect(): void;
@@ -251,6 +280,13 @@ interface TransportConnection {
251
280
  sessionId: string;
252
281
  jwt?: string;
253
282
  }
283
+
284
+ declare function encodeDocSyncFrame(docKey: string, payload: Uint8Array): Uint8Array;
285
+
286
+ declare function decodeDocSyncFrame(frame: Uint8Array): {
287
+ docKey: string;
288
+ payload: Uint8Array;
289
+ } | null;
254
290
  interface TransportEvents {
255
291
  connected: () => void;
256
292
  disconnected: () => void;
@@ -259,7 +295,7 @@ interface TransportEvents {
259
295
  started: () => void;
260
296
  audioTransportReady: () => void;
261
297
 
262
- docSync: (payload: Uint8Array) => void;
298
+ docSync: (docKey: string, payload: Uint8Array) => void;
263
299
 
264
300
  docSyncReady: () => void;
265
301
 
@@ -351,11 +387,13 @@ declare class TransportSession {
351
387
  on<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): () => void;
352
388
  sendInput(data: Record<string, unknown>, sequence?: number): void;
353
389
 
354
- sendDocSync(payload: Uint8Array): void;
390
+ sendDocSync(docKey: string, payload: Uint8Array): void;
355
391
 
356
- onDocSync(handler: (payload: Uint8Array) => void): () => void;
392
+ onDocSync(docKey: string, handler: (payload: Uint8Array) => void): () => void;
357
393
 
358
394
  onDocSyncReady(handler: () => void): () => void;
395
+
396
+ private _emitDocSyncFrame;
359
397
  addTrack(track: MediaStreamTrack): Promise<void>;
360
398
  removeTrack(): void;
361
399
  requestDiagnostics(): void;
@@ -397,4 +435,4 @@ declare class TransportSession {
397
435
  private _emitError;
398
436
  }
399
437
 
400
- export { type App as A, type ChannelEndpoint as C, type Layer as L, type SceneContext as S, TransportSession as T, type AppOptions as a, type AttachOptions as b, type ChannelMessage as c, ChannelMultiplexer as d, type ChannelName as e, type LayoutConfig as f, type LayoutContext as g, type SceneGraph as h, type Session as i, type SessionDocument as j, type SessionPhase as k, type SessionPhaseName as l, type SessionStartOptions as m, type SessionStream as n, type Store as o, type StoreOptions as p, type TransportSessionOptions as q, type TransportState as r };
438
+ export { type App as A, type ChannelEndpoint as C, type Layer as L, type RequestOptions as R, type SceneContext as S, TransportSession as T, type AppOptions as a, type AttachOptions as b, type ChannelMessage as c, ChannelMultiplexer as d, type ChannelName as e, type LayoutConfig as f, type LayoutContext as g, type RequestStreamOptions as h, type SceneGraph as i, type Session as j, type SessionDocument as k, type SessionPhase as l, type SessionPhaseName as m, type SessionStartOptions as n, type SessionStream as o, type SessionText as p, type Store as q, type StoreOptions as r, type TransportSessionOptions as s, type TransportState as t, decodeDocSyncFrame as u, encodeDocSyncFrame as v };
@@ -148,6 +148,17 @@ interface Store {
148
148
  emit(name: string, data: unknown): void;
149
149
  }
150
150
 
151
+ interface SessionText {
152
+
153
+ append(text: string): void;
154
+
155
+ toString(): string;
156
+
157
+ readonly length: number;
158
+
159
+ on(event: 'delta', handler: (inserted: string) => void): () => void;
160
+ }
161
+
151
162
  interface SessionDocument {
152
163
 
153
164
  set(patch: Record<string, unknown>): void;
@@ -155,6 +166,8 @@ interface SessionDocument {
155
166
  get(path?: string, defaultValue?: unknown): unknown;
156
167
 
157
168
  on(event: 'change', handler: (snapshot: Record<string, unknown>) => void): () => void;
169
+
170
+ text(field: string): SessionText;
158
171
  }
159
172
 
160
173
  interface SessionStream {
@@ -170,6 +183,18 @@ interface SessionStream {
170
183
  on(event: 'track', handler: (track: MediaStreamTrack | null) => void): () => void;
171
184
  }
172
185
 
186
+ interface RequestOptions {
187
+
188
+ timeout?: number;
189
+
190
+ signal?: AbortSignal;
191
+ }
192
+
193
+ interface RequestStreamOptions {
194
+
195
+ signal?: AbortSignal;
196
+ }
197
+
173
198
  interface Session {
174
199
 
175
200
  readonly id: string;
@@ -180,6 +205,10 @@ interface Session {
180
205
 
181
206
  doc(key: string): SessionDocument;
182
207
 
208
+ request(payload: unknown, options?: RequestOptions): Promise<unknown>;
209
+
210
+ requestStream(payload: unknown, options?: RequestStreamOptions): AsyncIterable<string>;
211
+
183
212
  onPhase(handler: (phase: SessionPhase) => void): () => void;
184
213
 
185
214
  disconnect(): void;
@@ -251,6 +280,13 @@ interface TransportConnection {
251
280
  sessionId: string;
252
281
  jwt?: string;
253
282
  }
283
+
284
+ declare function encodeDocSyncFrame(docKey: string, payload: Uint8Array): Uint8Array;
285
+
286
+ declare function decodeDocSyncFrame(frame: Uint8Array): {
287
+ docKey: string;
288
+ payload: Uint8Array;
289
+ } | null;
254
290
  interface TransportEvents {
255
291
  connected: () => void;
256
292
  disconnected: () => void;
@@ -259,7 +295,7 @@ interface TransportEvents {
259
295
  started: () => void;
260
296
  audioTransportReady: () => void;
261
297
 
262
- docSync: (payload: Uint8Array) => void;
298
+ docSync: (docKey: string, payload: Uint8Array) => void;
263
299
 
264
300
  docSyncReady: () => void;
265
301
 
@@ -351,11 +387,13 @@ declare class TransportSession {
351
387
  on<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): () => void;
352
388
  sendInput(data: Record<string, unknown>, sequence?: number): void;
353
389
 
354
- sendDocSync(payload: Uint8Array): void;
390
+ sendDocSync(docKey: string, payload: Uint8Array): void;
355
391
 
356
- onDocSync(handler: (payload: Uint8Array) => void): () => void;
392
+ onDocSync(docKey: string, handler: (payload: Uint8Array) => void): () => void;
357
393
 
358
394
  onDocSyncReady(handler: () => void): () => void;
395
+
396
+ private _emitDocSyncFrame;
359
397
  addTrack(track: MediaStreamTrack): Promise<void>;
360
398
  removeTrack(): void;
361
399
  requestDiagnostics(): void;
@@ -397,4 +435,4 @@ declare class TransportSession {
397
435
  private _emitError;
398
436
  }
399
437
 
400
- export { type App as A, type ChannelEndpoint as C, type Layer as L, type SceneContext as S, TransportSession as T, type AppOptions as a, type AttachOptions as b, type ChannelMessage as c, ChannelMultiplexer as d, type ChannelName as e, type LayoutConfig as f, type LayoutContext as g, type SceneGraph as h, type Session as i, type SessionDocument as j, type SessionPhase as k, type SessionPhaseName as l, type SessionStartOptions as m, type SessionStream as n, type Store as o, type StoreOptions as p, type TransportSessionOptions as q, type TransportState as r };
438
+ export { type App as A, type ChannelEndpoint as C, type Layer as L, type RequestOptions as R, type SceneContext as S, TransportSession as T, type AppOptions as a, type AttachOptions as b, type ChannelMessage as c, ChannelMultiplexer as d, type ChannelName as e, type LayoutConfig as f, type LayoutContext as g, type RequestStreamOptions as h, type SceneGraph as i, type Session as j, type SessionDocument as k, type SessionPhase as l, type SessionPhaseName as m, type SessionStartOptions as n, type SessionStream as o, type SessionText as p, type Store as q, type StoreOptions as r, type TransportSessionOptions as s, type TransportState as t, decodeDocSyncFrame as u, encodeDocSyncFrame as v };
@@ -1 +1 @@
1
- export { c as ChannelMessage, d as ChannelMultiplexer, e as ChannelName, m as SessionStartOptions, T as TransportSession, q as TransportSessionOptions } from './internal-BYsSyqG4.mjs';
1
+ export { c as ChannelMessage, d as ChannelMultiplexer, e as ChannelName, n as SessionStartOptions, T as TransportSession, s as TransportSessionOptions, u as decodeDocSyncFrame, v as encodeDocSyncFrame } from './internal-B7GoThNN.mjs';
@@ -1 +1 @@
1
- export { c as ChannelMessage, d as ChannelMultiplexer, e as ChannelName, m as SessionStartOptions, T as TransportSession, q as TransportSessionOptions } from './internal-BYsSyqG4.js';
1
+ export { c as ChannelMessage, d as ChannelMultiplexer, e as ChannelName, n as SessionStartOptions, T as TransportSession, s as TransportSessionOptions, u as decodeDocSyncFrame, v as encodeDocSyncFrame } from './internal-B7GoThNN.js';