stinky-moq-js 0.1.12 → 0.1.17
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/broadcast-mgr.d.ts +19 -0
- package/dist/broadcast-mgr.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +309 -346
- package/dist/index.mjs.map +1 -1
- package/dist/session.d.ts +30 -58
- package/dist/session.d.ts.map +1 -1
- package/dist/subscription-mgr.d.ts +25 -0
- package/dist/subscription-mgr.d.ts.map +1 -0
- package/dist/typed-emitter.d.ts +59 -0
- package/dist/typed-emitter.d.ts.map +1 -0
- package/dist/types.d.ts +12 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -2
- package/dist/broadcast.d.ts +0 -21
- package/dist/broadcast.d.ts.map +0 -1
- package/dist/event-emitter.d.ts +0 -8
- package/dist/event-emitter.d.ts.map +0 -1
- package/dist/subscription.d.ts +0 -27
- package/dist/subscription.d.ts.map +0 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Connection } from '@kixelated/moq';
|
|
2
|
+
import { BroadcastConfig, BroadcastEvents } from './types';
|
|
3
|
+
import { TypedEmitter } from './typed-emitter';
|
|
4
|
+
import { Valid } from '@kixelated/moq/path';
|
|
5
|
+
export declare class MoQBroadcastManager extends TypedEmitter<BroadcastEvents> {
|
|
6
|
+
private connection;
|
|
7
|
+
private broadcast;
|
|
8
|
+
private broadcasts;
|
|
9
|
+
private catalogTrack?;
|
|
10
|
+
constructor(namespace: Valid, connection: Connection.Established);
|
|
11
|
+
dispose(): void;
|
|
12
|
+
updateBroadcasts(configs: BroadcastConfig[]): void;
|
|
13
|
+
private addBroadcast;
|
|
14
|
+
private removeBroadcast;
|
|
15
|
+
private runTrackRequests;
|
|
16
|
+
private updateCatalog;
|
|
17
|
+
send(trackName: string, data: Uint8Array, newGroup: boolean): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=broadcast-mgr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broadcast-mgr.d.ts","sourceRoot":"","sources":["../src/broadcast-mgr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAgB,MAAM,gBAAgB,CAAC;AACrE,OAAO,EACL,eAAe,EACf,eAAe,EAEhB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAmC5C,qBAAa,mBAAoB,SAAQ,YAAY,CAAC,eAAe,CAAC;IACpE,OAAO,CAAC,UAAU,CAAyB;IAC3C,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,UAAU,CAA0C;IAC5D,OAAO,CAAC,YAAY,CAAC,CAAQ;gBAEjB,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,CAAC,WAAW;IAWzD,OAAO,IAAI,IAAI;IASf,gBAAgB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI;IAmCzD,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,eAAe;YAQT,gBAAgB;IAkB9B,OAAO,CAAC,aAAa;IAWf,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAIlF"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const p=require("@kixelated/moq");class m{constructor(){this.listeners=new Map}on(t,s){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(s)}off(t,s){const e=this.listeners.get(t);e&&e.delete(s)}emit(t,...s){const e=this.listeners.get(t);e&&e.forEach(a=>{try{a(...s)}catch(c){console.error("Error in event listener:",c)}})}removeAllListeners(t){t?this.listeners.delete(t):this.listeners.clear()}}var n=(r=>(r.DISCONNECTED="disconnected",r.CONNECTING="connecting",r.CONNECTED="connected",r.RECONNECTING="reconnecting",r.FAILED="failed",r))(n||{}),d=(r=>(r.IDLE="idle",r.BROADCASTING="broadcasting",r.ERROR="error",r))(d||{}),u=(r=>(r.PENDING="pending",r.SUBSCRIBED="subscribed",r.RETRYING="retrying",r.FAILED="failed",r))(u||{});class f extends m{constructor(t){super(),this.state=d.IDLE,this.bytesSent=0,this._config=t}get status(){return{state:this.state,trackName:this._config.trackName,bytesSent:this.bytesSent,lastError:this.lastError}}get config(){return{...this._config}}updateTrack(t){this.track=t,t&&this.setState(d.BROADCASTING)}async send(t,s){if(this.state!==d.BROADCASTING||!this.track)throw new Error("Broadcast is not active");try{(s||!this.group)&&(this.group&&this.group.close(),this.group=this.track.appendGroup()),await this.group.writeFrame(t),this.bytesSent+=t.length}catch(e){throw this.handleError(e),e}}async stop(){if(this.track){try{this.track.close()}catch(t){console.warn("Error closing track:",t)}this.track=void 0}this.setState(d.IDLE)}setState(t){this.state!==t&&(this.state=t,this.emit("stateChange",this.status))}handleError(t){this.lastError=t,this.setState(d.ERROR),this.emit("error",t)}dispose(){this.stop().catch(console.error),this.removeAllListeners()}}class b extends m{constructor(t){super(),this.state=u.PENDING,this.bytesReceived=0,this.retryAttempts=0,this._config=t}get status(){return{state:this.state,trackName:this._config.trackName,bytesReceived:this.bytesReceived,retryAttempts:this.retryAttempts,lastError:this.lastError}}get config(){return{...this._config}}async start(t,s){this.connection=t,this.namespace=s;try{await this.subscribe(t,s)}catch(e){this.handleError(e),this.scheduleRetry(t,s)}}async subscribe(t,s){this.setState(u.PENDING);const e=p.Path.from(s);this.broadcast=t.consume(e),this.subscription=this.broadcast.subscribe(this._config.trackName,this._config.priority||0),this.setState(u.SUBSCRIBED),this.retryAttempts=0,this.readFrames()}async readFrames(){if(this.subscription)try{for(;;){let t=0;const s=await this.subscription.nextGroup();if(!s)break;for(;;){const e=await s.readFrame();if(!e)break;t++,this.bytesReceived+=e.length;const a={trackName:this._config.trackName,data:e,timestamp:Date.now(),frameIndex:t};this.emit("data",a)}}}catch(t){this.handleError(t),this.connection&&this.namespace&&this.scheduleRetry(this.connection,this.namespace)}}scheduleRetry(t,s){var a;const e=((a=this._config.retry)==null?void 0:a.delay)||2e3;this.setState(u.RETRYING),this.retryAttempts++,this.retryTimer=setTimeout(async()=>{try{await this.subscribe(t,s)}catch(c){this.handleError(c),this.scheduleRetry(t,s)}},e)}async stop(){if(this.connection=void 0,this.namespace=void 0,this.retryTimer&&(clearTimeout(this.retryTimer),this.retryTimer=void 0),this.subscription){try{this.subscription.close()}catch(t){console.warn("Error closing subscription:",t)}this.subscription=void 0}if(this.broadcast){try{this.broadcast.close()}catch(t){console.warn("Error closing broadcast:",t)}this.broadcast=void 0}this.setState(u.PENDING)}setState(t){this.state!==t&&(this.state=t,this.emit("stateChange",this.status))}handleError(t){this.lastError=t,this.emit("error",t)}dispose(){this.stop().catch(t=>{console.warn("Error during dispose:",t)}),this.removeAllListeners()}}class E extends m{constructor(t){var s;super(),this.state=n.DISCONNECTED,this.reconnectAttempts=0,this.broadcasts=new Map,this.subscriptions=new Map,this.announcedBroadcasts=new Set,this.doReconnect=!0,this.disposed=!1,this.config={...t,reconnection:{delay:Math.max(((s=t.reconnection)==null?void 0:s.delay)||1e3,1e3)},connectionTimeout:t.connectionTimeout||1e4},this.url=new URL(this.config.relayUrl)}get status(){return{state:this.state,reconnectAttempts:this.reconnectAttempts,lastError:this.lastError,connectedAt:this.connectedAt}}async connect(){if(this.disposed)throw new Error("Cannot connect a disposed session");if(!(this.state===n.CONNECTING||this.state===n.CONNECTED)){this.setState(n.CONNECTING);try{this.doReconnect=!0,this.connection=await p.Connection.connect(this.url,{websocket:{enabled:!1}}),this.setState(n.CONNECTED),this.connectedAt=new Date,this.reconnectAttempts=0,this.connection.closed.then(()=>{!this.disposed&&this.state===n.CONNECTED&&this.handleDisconnection()}),this.startAnnouncementDiscovery(),await this.restartBroadcasts(),await this.restartSubscriptions()}catch(t){const s=new Error(`Failed to connect to relay: ${t.message}`);throw this.handleError(s),this.scheduleReconnect(),s}}}async disconnect(){if(this.doReconnect=!1,this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),await this.stopAllBroadcasts(),await this.stopAllSubscriptions(),this.connection){try{this.connection.close()}catch(t){console.warn("Error closing connection:",t)}this.connection=void 0}this.setState(n.DISCONNECTED),this.connectedAt=void 0}getAllBroadcastTrackNames(){return Array.from(this.broadcasts.keys())}getAllSubscriptionTrackNames(){return Array.from(this.subscriptions.keys())}updateBroadcasts(t){const s=t.map(i=>i.trackName),e=new Set(s);if(s.length!==e.size){const i=s.filter((h,o)=>s.indexOf(h)!==o);throw new Error(`Duplicate broadcast track name: ${i[0]}`)}const a=new Set(t.map(i=>i.trackName)),c=new Set(this.broadcasts.keys());for(const i of c)a.has(i)||this._removeBroadcast(i);for(const i of t){const h=this.broadcasts.get(i.trackName);h?h.config.priority!==i.priority&&(this._removeBroadcast(i.trackName),this._createBroadcast(i)):this._createBroadcast(i)}}updateSubscriptions(t){var i,h;const s=t.map(o=>o.trackName),e=new Set(s);if(s.length!==e.size){const o=s.filter((l,y)=>s.indexOf(l)!==y);throw new Error(`Duplicate subscription track name: ${o[0]}`)}const a=new Set(t.map(o=>o.trackName)),c=new Set(this.subscriptions.keys());for(const o of c)a.has(o)||this._removeSubscription(o);for(const o of t){const l=this.subscriptions.get(o.trackName);l?(l.config.priority!==o.priority||((i=l.config.retry)==null?void 0:i.delay)!==((h=o.retry)==null?void 0:h.delay))&&(this._removeSubscription(o.trackName),this._createSubscription(o)):this._createSubscription(o)}}getAnnouncedBroadcasts(){return Array.from(this.announcedBroadcasts)}async send(t,s,e){const a=this.broadcasts.get(t);if(!a)throw new Error(`No broadcast found for track: ${t}`);await a.send(s,e)}getBroadcastStatus(t){const s=this.broadcasts.get(t);return s==null?void 0:s.status}getSubscriptionStatus(t){const s=this.subscriptions.get(t);return s==null?void 0:s.status}_createBroadcast(t){const s=new f(t);return this.broadcasts.set(t.trackName,s),s.on("stateChange",e=>{this.emit("broadcastStateChange",t.trackName,e)}),s.on("error",e=>{this.emit("broadcastError",t.trackName,e)}),this.initBroadcasting(),s}_createSubscription(t){const s=new b(t);return this.subscriptions.set(t.trackName,s),s.on("data",e=>{this.emit("data",e.trackName,e.data,e.frameIndex)}),s.on("stateChange",e=>{this.emit("subscriptionStateChange",t.trackName,e)}),s.on("error",e=>{this.emit("subscriptionError",t.trackName,e)}),this.state===n.CONNECTED&&this.connection&&s.start(this.connection,this.config.namespace).catch(e=>{console.error("Failed to start subscription:",e)}),s}_removeBroadcast(t){const s=this.broadcasts.get(t);s&&(s.stop().catch(e=>{console.warn("Error stopping broadcast:",e)}),this.broadcasts.delete(t))}_removeSubscription(t){const s=this.subscriptions.get(t);s&&(s.stop().catch(e=>{console.warn("Error stopping subscription:",e)}),this.subscriptions.delete(t))}async startAnnouncementDiscovery(){if(this.connection)try{const t=p.Path.from(this.config.namespace),s=this.connection.announced(t);this.processAnnouncements(s)}catch(t){console.error("Failed to start announcement discovery:",t)}}async processAnnouncements(t){try{for(;!this.disposed;){const s=await t.next();if(!s||this.disposed)break;s.active?(this.announcedBroadcasts.add(s.path),this.emit("broadcastAnnounced",{path:s.path,active:!0})):(this.announcedBroadcasts.delete(s.path),this.emit("broadcastAnnounced",{path:s.path,active:!1}))}}catch(s){this.disposed||console.error("Error processing announcements:",s)}}async restartBroadcasts(){await this.stopAllBroadcasts(),this.initBroadcasting()}initBroadcasting(){this.broadcast||this.broadcasts.size!==0&&(this.broadcast=new p.Broadcast,this.connection&&(this.connection.publish(p.Path.from(this.config.namespace),this.broadcast),this.handleTrackRequests().catch(t=>{console.error("Error handling track requests:",t)})))}async handleTrackRequests(){if(this.broadcast)try{for(;;){const t=await this.broadcast.requested();if(!t)return;const s=this.broadcasts.get(t.track.name);s&&(s.updateTrack(t.track),this.emit("trackRequested",t.track.name))}}catch(t){console.warn("Error handling track requests:",t),this.handleError(t)}}async restartSubscriptions(){if(!this.connection)return;const t=Array.from(this.subscriptions.values()).map(s=>s.start(this.connection,this.config.namespace).catch(e=>{console.error("Failed to restart subscription:",e)}));await Promise.allSettled(t)}async stopAllBroadcasts(){var s;(s=this.broadcast)==null||s.close(),this.broadcast=void 0;const t=Array.from(this.broadcasts.values()).map(e=>e.stop().catch(a=>{console.warn("Error stopping broadcast:",a)}));await Promise.allSettled(t)}async stopAllSubscriptions(){const t=Array.from(this.subscriptions.values()).map(s=>s.stop().catch(e=>{console.warn("Error stopping subscription:",e)}));await Promise.allSettled(t)}handleDisconnection(){this.disposed||(this.setState(n.DISCONNECTED),this.scheduleReconnect())}scheduleReconnect(){var s;if(this.disposed||!this.config.reconnection||!this.doReconnect)return;const t=((s=this.config.reconnection)==null?void 0:s.delay)||1e3;this.setState(n.RECONNECTING),this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>{this.disposed||!this.doReconnect||this.state===n.RECONNECTING&&this.connect().catch(e=>{console.error("Reconnection failed:",e)})},t)}setState(t){this.disposed||this.state!==t&&(this.state=t,this.emit("stateChange",this.status))}handleError(t){this.disposed||(this.lastError=t,this.emit("error",t))}dispose(){this.disposed=!0,this.doReconnect=!1,this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.disconnect().catch(t=>{console.warn("Error during session disconnect:",t)}),this.removeAllListeners(),this.subscriptions.forEach(t=>t.dispose()),this.broadcasts.forEach(t=>t.dispose()),this.subscriptions.clear(),this.broadcasts.clear()}}exports.BroadcastState=d;exports.MoQBroadcast=f;exports.MoQSession=E;exports.MoQSubscription=b;exports.SessionState=n;exports.SubscriptionState=u;exports.default=E;
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const h=require("@kixelated/moq");class d{constructor(){this.listeners=new Map}emit(t,...e){const s=this.listeners.get(t);if(!s||s.size===0)return!1;for(const n of s)try{n(...e)}catch(r){console.error("Error in event listener:",r)}return!0}on(t,e){return this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e),this}once(t,e){const s=(...n)=>{this.off(t,s),e(...n)};return this.on(t,s)}off(t,e){const s=this.listeners.get(t);return s&&(s.delete(e),s.size===0&&this.listeners.delete(t)),this}removeListener(t,e){return this.off(t,e)}addListener(t,e){return this.on(t,e)}removeAllListeners(t){return t===void 0?this.listeners.clear():this.listeners.delete(t),this}listenerCount(t){var e;return((e=this.listeners.get(t))==null?void 0:e.size)||0}eventNames(){return Array.from(this.listeners.keys())}}class m{constructor(t,e){this.bytesSent=0,this.track=t,this.config=e}send(t,e){var s;try{(e||!this.group)&&((s=this.group)==null||s.close(),this.group=this.track.appendGroup()),this.group.writeFrame(t),this.bytesSent+=t.byteLength}catch{}}updateTrack(t){this.track=t}dispose(){var t;(t=this.group)==null||t.close(),this.track.close()}}class k extends d{constructor(t,e){super(),this.broadcasts=new Map,this.connection=e,this.broadcast=new h.Broadcast,this.connection.publish(t,this.broadcast),this.runTrackRequests().catch(s=>{this.emit("error",s)})}dispose(){this.removeAllListeners();for(const t of this.broadcasts.values())t.dispose();this.broadcasts.clear(),this.broadcast.close()}updateBroadcasts(t){let e=!1;const s=t.map(a=>a.trackName),n=new Set(s);if(s.length!==n.size){const a=s.filter((l,g)=>s.indexOf(l)!==g);throw new Error(`Duplicate broadcast track name: ${a[0]}`)}const r=new Set(t.map(a=>a.trackName)),c=new Set(this.broadcasts.keys());for(const a of c)r.has(a)||(this.removeBroadcast(a),e=!0);for(const a of t)this.broadcasts.get(a.trackName)||(this.addBroadcast(a),e=!0);e&&this.updateCatalog()}addBroadcast(t){const e=new m(new h.Track(t.trackName),t);this.broadcasts.set(t.trackName,e)}removeBroadcast(t){const e=this.broadcasts.get(t);e&&(e.dispose(),this.broadcasts.delete(t))}async runTrackRequests(){for(;;){const t=await this.broadcast.requested();if(!t)return;if(t.track.name==="catalog.json"){this.catalogTrack=t.track,this.updateCatalog();continue}const e=this.broadcasts.get(t.track.name);e&&(e.updateTrack(t.track),this.emit("trackRequested",t.track.name))}}updateCatalog(){var e;const t={tracks:[]};t.tracks=[...this.broadcasts.values()].map(s=>({trackName:s.config.trackName,type:s.config.type,priority:s.config.priority||0})),(e=this.catalogTrack)==null||e.writeJson(t)}async send(t,e,s){const n=this.broadcasts.get(t);return n==null?void 0:n.send(e,s)}}class E extends d{constructor(t,e){super(),this.catalog={tracks:[]},this.enabled_=!1,this.requestedSubscriptions=new Map,this.subscriptions=new Map,this.connection=e,this.namespace=t,this.broadcast=this.connection.consume(this.namespace)}set enabled(t){this.enabled_!==t&&(this.enabled_=t,t&&this.runCatalog().catch(e=>{this.emit("error",e)}))}get enabled(){return this.enabled_}async runCatalog(){if(this.catalogTrack=await this.broadcast.subscribe("catalog.json",0),!this.catalogTrack)throw new Error("Failed to subscribe to catalog track");for(;;){const t=await this.catalogTrack.readJson();if(t)console.log("Received catalog update:",t),this.updateCatalog(t);else return}}updateCatalog(t){this.catalog=t,this.checkSubscriptions()}dispose(){var t,e;this.removeAllListeners();for(const s of this.subscriptions.values())s.track.close();(t=this.catalogTrack)==null||t.close(),(e=this.broadcast)==null||e.close()}updateSubscriptions(t){this.requestedSubscriptions.clear();for(const e of t)this.requestedSubscriptions.set(e.trackName,e);this.checkSubscriptions()}checkSubscriptions(){const t=new Set(this.requestedSubscriptions.keys()),e=new Set(this.subscriptions.keys()),s=this.catalog.tracks.map(n=>n.trackName);for(const n of e)(!t.has(n)||!s.includes(n))&&this.removeSubscription(n);for(const n of t)if(!e.has(n)&&s.includes(n)){const r=this.requestedSubscriptions.get(n);this.addSubscription(n,r).catch(c=>{this.emit("error",c)})}}removeSubscription(t){const e=this.subscriptions.get(t);e&&(e.track.close(),this.subscriptions.delete(t),this.emit("unsubscribed",t))}async addSubscription(t,e){const s=this.broadcast.subscribe(t,e.priority??0);let n=-1;if(s)for(this.subscriptions.set(t,{track:s,config:e}),this.emit("subscribed",t);;){const r=await s.nextGroup();if(!r)return;try{if(r.sequence<=n){console.log(`Skipping out-of-order group on track "${t}": ${r.sequence} <= ${n}`),r.close();continue}for(;;){const c=await r.readFrame();if(!c)break;n=r.sequence,this.emit("data",{data:c,frameIndex:0,trackName:t,timestamp:Date.now()})}}catch{console.log("Error processing group on track:",t)}finally{r.close()}}}}var o=(i=>(i.DISCONNECTED="disconnected",i.CONNECTING="connecting",i.CONNECTED="connected",i.RECONNECTING="reconnecting",i.FAILED="failed",i))(o||{}),p=(i=>(i.IDLE="idle",i.BROADCASTING="broadcasting",i.ERROR="error",i))(p||{}),f=(i=>(i.IDLE="idle",i.SUBSCRIBED="subscribed",i.FAILED="failed",i))(f||{});class u extends d{constructor(t){var e;super(),this.reconnectAttempts=0,this.doReconnect=!0,this.disposed=!1,this.state=o.DISCONNECTED,this.announcedBroadcasts=new Set,this.config={...t,reconnection:{delay:Math.max(((e=t.reconnection)==null?void 0:e.delay)||1e3,1e3)},connectionTimeout:t.connectionTimeout||1e4},this.url=new URL(this.config.relayUrl)}get status(){return{state:this.state,reconnectAttempts:this.reconnectAttempts,lastError:this.lastError,connectedAt:this.connectedAt}}async connect(){if(this.disposed)throw new Error("Cannot connect a disposed session");if(!(this.state===o.CONNECTING||this.state===o.CONNECTED)){this.setState(o.CONNECTING);try{this.doReconnect=!0,this.connection=await h.Connection.connect(this.url,{websocket:{enabled:!1}}),this.setState(o.CONNECTED),this.connectedAt=new Date,this.reconnectAttempts=0,this.connection.closed.then(()=>{this.handleDisconnected()}),this.startAnnouncementDiscovery(),this.handleConnected()}catch(t){const e=new Error(`Failed to connect to relay: ${t.message}`);throw this.handleError(e),this.scheduleReconnect(),e}}}disconnect(){if(this.state!==o.DISCONNECTED){if(this.doReconnect=!1,this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.connection){try{this.connection.close()}catch(t){console.warn("Error closing connection:",t)}this.connection=void 0}this.setState(o.DISCONNECTED),this.connectedAt=void 0}}getAnnouncedBroadcasts(){return Array.from(this.announcedBroadcasts)}async startAnnouncementDiscovery(){if(this.connection)try{const t=h.Path.from(this.config.namespace),e=this.connection.announced(t);console.log("announced: ",e),this.processAnnouncements(e)}catch(t){console.error("Failed to start announcement discovery:",t)}}async processAnnouncements(t){try{for(;!this.disposed;){const e=await t.next();if(!e||this.disposed)break;e.active?this.announcedBroadcasts.add(e.path):this.announcedBroadcasts.delete(e.path),this.handleAnnounceUpdate(),console.log(this.announcedBroadcasts)}}catch{}}handleDisconnected(){this.disposed||(this.setState(o.DISCONNECTED),this.scheduleReconnect())}scheduleReconnect(){var e;if(this.disposed||!this.config.reconnection||!this.doReconnect)return;const t=((e=this.config.reconnection)==null?void 0:e.delay)||1e3;this.setState(o.RECONNECTING),this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>{this.disposed||!this.doReconnect||this.state===o.RECONNECTING&&this.connect().catch(s=>{console.error("Reconnection failed:",s)})},t)}setState(t){this.disposed||this.state!==t&&(this.state=t,this.emit("stateChange",this.status))}handleError(t){this.disposed||(this.lastError=t,this.emit("error",t))}dispose(){this.disposed=!0,this.doReconnect=!1,this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0);try{this.disconnect()}catch(t){console.warn("Error during disconnect in dispose:",t)}this.removeAllListeners()}}class T extends u{constructor(){super(...arguments),this.lastEnabledState=!1}dispose(){var t;super.dispose(),(t=this.subscriptionManager)==null||t.dispose()}handleConnected(){var t;(t=this.subscriptionManager)==null||t.dispose(),this.subscriptionManager=new E(h.Path.from(this.config.namespace),this.connection),this.subscriptionManager.on("data",e=>this.emit("data",e.trackName,e.data)),this.subscriptionManager.on("error",e=>this.emit("error",e))}handleDisconnected(){var t;super.handleDisconnected(),(t=this.subscriptionManager)==null||t.dispose()}updateSubscriptions(t){this.subscriptionManager.updateSubscriptions(t)}handleAnnounceUpdate(){const t=h.Path.from(this.config.namespace);let e=!1;for(const s of this.announcedBroadcasts)if(s.startsWith(t)){e=!0;break}e!==this.lastEnabledState&&(this.lastEnabledState=e,this.subscriptionManager&&(this.subscriptionManager.enabled=e))}}class b extends u{dispose(){var t;super.dispose(),(t=this.broadcastManager)==null||t.dispose()}updateBroadcasts(t){this.broadcastManager.updateBroadcasts(t)}handleConnected(){var t;(t=this.broadcastManager)==null||t.dispose(),this.broadcastManager=new k(h.Path.from(this.config.namespace),this.connection)}handleDisconnected(){var t;super.handleDisconnected(),(t=this.broadcastManager)==null||t.dispose()}handleAnnounceUpdate(){}send(t,e,s){if(!this.broadcastManager)throw new Error("Broadcast manager not initialized");if(this.state!==o.CONNECTED)throw new Error("Cannot send data when session is not connected");this.broadcastManager.send(t,e,s)}}exports.BroadcastState=p;exports.MoQSession=u;exports.MoqSessionBroadcaster=b;exports.MoqSessionSubscriber=T;exports.SessionState=o;exports.SubscriptionState=f;exports.default=b;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/event-emitter.ts","../src/types.ts","../src/broadcast.ts","../src/subscription.ts","../src/session.ts"],"sourcesContent":["// Simple event emitter for type-safe events\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class EventEmitter<T extends Record<string, (...args: any[]) => void>> {\n private listeners = new Map<keyof T, Set<T[keyof T]>>();\n\n on<K extends keyof T>(event: K, listener: T[K]): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n }\n\n off<K extends keyof T>(event: K, listener: T[K]): void {\n const eventListeners = this.listeners.get(event);\n if (eventListeners) {\n eventListeners.delete(listener);\n }\n }\n\n emit<K extends keyof T>(event: K, ...args: Parameters<T[K]>): void {\n const eventListeners = this.listeners.get(event);\n if (eventListeners) {\n eventListeners.forEach(listener => {\n try {\n listener(...args);\n } catch (error) {\n console.error('Error in event listener:', error);\n }\n });\n }\n }\n\n removeAllListeners<K extends keyof T>(event?: K): void {\n if (event) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n}","// Types for the library\nexport interface MoQSessionConfig {\n /** URL of the MoQ relay server */\n relayUrl: string;\n /** MoQ namespace (broadcast name) */\n namespace: string;\n /** Reconnection configuration */\n reconnection?: {\n /** Delay between reconnection attempts in ms (minimum: 1000) */\n delay?: number;\n };\n /** Connection timeout in ms (default: 10000) */\n connectionTimeout?: number;\n}\n\nexport interface BroadcastConfig {\n /** Track name for the broadcast */\n trackName: string;\n /** Priority for the track (default: 0) */\n priority?: number;\n}\n\nexport interface SubscriptionConfig {\n /** Track name to subscribe to */\n trackName: string;\n /** Priority for the subscription (default: 0) */\n priority?: number;\n /** Retry configuration for failed subscriptions */\n retry?: {\n /** Delay between retry attempts in ms (default: 2000) */\n delay?: number;\n };\n}\n\nexport enum SessionState {\n DISCONNECTED = 'disconnected',\n CONNECTING = 'connecting',\n CONNECTED = 'connected',\n RECONNECTING = 'reconnecting',\n FAILED = 'failed'\n}\n\nexport enum BroadcastState {\n IDLE = 'idle',\n BROADCASTING = 'broadcasting',\n ERROR = 'error'\n}\n\nexport enum SubscriptionState {\n PENDING = 'pending',\n SUBSCRIBED = 'subscribed',\n RETRYING = 'retrying',\n FAILED = 'failed'\n}\n\nexport interface SessionStatus {\n state: SessionState;\n reconnectAttempts: number;\n lastError?: Error;\n connectedAt?: Date;\n}\n\nexport interface BroadcastStatus {\n state: BroadcastState;\n trackName: string;\n bytesSent: number;\n lastError?: Error;\n}\n\nexport interface SubscriptionStatus {\n state: SubscriptionState;\n trackName: string;\n bytesReceived: number;\n retryAttempts: number;\n lastError?: Error;\n}\n\nexport interface DataReceived {\n trackName: string;\n data: Uint8Array;\n timestamp: number;\n frameIndex: number;\n}\n\n// Event types\nexport interface BroadcastAnnouncement {\n path: string;\n active: boolean;\n}\n\nexport interface SessionEvents {\n stateChange: (status: SessionStatus) => void;\n error: (error: Error) => void;\n broadcastAnnounced: (announcement: BroadcastAnnouncement) => void;\n data: (trackName: string, data: Uint8Array, frameIndex: number) => void;\n broadcastStateChange: (trackName: string, status: BroadcastStatus) => void;\n subscriptionStateChange: (trackName: string, status: SubscriptionStatus) => void;\n broadcastError: (trackName: string, error: Error) => void;\n subscriptionError: (trackName: string, error: Error) => void;\n trackRequested: (trackName: string) => void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: (...args: any[]) => void;\n}\n\nexport interface BroadcastEvents {\n stateChange: (status: BroadcastStatus) => void;\n error: (error: Error) => void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: (...args: any[]) => void;\n}\n\nexport interface SubscriptionEvents {\n stateChange: (status: SubscriptionStatus) => void;\n data: (data: DataReceived) => void;\n error: (error: Error) => void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: (...args: any[]) => void;\n}","import { Group, Track } from '@kixelated/moq';\nimport { EventEmitter } from './event-emitter';\nimport {\n BroadcastConfig,\n BroadcastState,\n BroadcastStatus,\n BroadcastEvents\n} from './types';\n\nexport class MoQBroadcast extends EventEmitter<BroadcastEvents> {\n private _config: BroadcastConfig;\n private state: BroadcastState = BroadcastState.IDLE;\n private bytesSent = 0;\n private lastError?: Error;\n private track?: Track;\n private group?: Group;\n\n constructor(config: BroadcastConfig) {\n super();\n this._config = config;\n }\n\n get status(): BroadcastStatus {\n return {\n state: this.state,\n trackName: this._config.trackName,\n bytesSent: this.bytesSent,\n lastError: this.lastError\n };\n }\n\n get config(): BroadcastConfig {\n return { ...this._config };\n }\n\n updateTrack(track: Track): void {\n this.track = track;\n if (track) {\n this.setState(BroadcastState.BROADCASTING);\n }\n }\n\n async send(data: Uint8Array, newGroup: boolean): Promise<void> {\n if (this.state !== BroadcastState.BROADCASTING || !this.track) {\n throw new Error('Broadcast is not active');\n }\n\n try {\n if (newGroup || !this.group) {\n if (this.group) {\n this.group.close();\n }\n this.group = this.track.appendGroup();\n }\n await this.group.writeFrame(data);\n this.bytesSent += data.length;\n } catch (error) {\n this.handleError(error as Error);\n throw error;\n }\n }\n\n async stop(): Promise<void> {\n if (this.track) {\n try {\n this.track.close();\n } catch (error) {\n console.warn('Error closing track:', error);\n }\n this.track = undefined;\n }\n \n this.setState(BroadcastState.IDLE);\n }\n\n private setState(newState: BroadcastState): void {\n if (this.state !== newState) {\n this.state = newState;\n this.emit('stateChange', this.status);\n }\n }\n\n private handleError(error: Error): void {\n this.lastError = error;\n this.setState(BroadcastState.ERROR);\n this.emit('error', error);\n }\n\n public dispose(): void {\n this.stop().catch(console.error);\n this.removeAllListeners();\n }\n}","import { Broadcast, Track, Connection, Path } from '@kixelated/moq';\nimport { EventEmitter } from './event-emitter';\nimport {\n SubscriptionConfig,\n SubscriptionState,\n SubscriptionStatus,\n SubscriptionEvents,\n DataReceived\n} from './types';\n\nexport class MoQSubscription extends EventEmitter<SubscriptionEvents> {\n private _config: SubscriptionConfig;\n private state: SubscriptionState = SubscriptionState.PENDING;\n private bytesReceived = 0;\n private retryAttempts = 0;\n private lastError?: Error;\n private subscription?: Track;\n private broadcast?: Broadcast;\n private retryTimer?: ReturnType<typeof setTimeout>;\n private connection?: Connection.Established;\n private namespace?: string;\n\n constructor(config: SubscriptionConfig) {\n super();\n this._config = config;\n }\n\n get status(): SubscriptionStatus {\n return {\n state: this.state,\n trackName: this._config.trackName,\n bytesReceived: this.bytesReceived,\n retryAttempts: this.retryAttempts,\n lastError: this.lastError\n };\n }\n\n get config(): SubscriptionConfig {\n return { ...this._config };\n }\n\n async start(connection: Connection.Established, namespace: string): Promise<void> {\n this.connection = connection;\n this.namespace = namespace;\n try {\n await this.subscribe(connection, namespace);\n } catch (error) {\n this.handleError(error as Error);\n this.scheduleRetry(connection, namespace);\n }\n }\n\n private async subscribe(connection: Connection.Established, namespace: string): Promise<void> {\n this.setState(SubscriptionState.PENDING);\n\n const broadcastPath = Path.from(namespace);\n this.broadcast = connection.consume(broadcastPath);\n\n // Subscribe to the specific track within the broadcast\n this.subscription = this.broadcast.subscribe(this._config.trackName, this._config.priority || 0);\n this.setState(SubscriptionState.SUBSCRIBED);\n this.retryAttempts = 0;\n\n // Set up data reception\n this.readFrames();\n }\n\n private async readFrames(): Promise<void> {\n if (!this.subscription) return;\n\n try {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n let framesInGroup = 0;\n const group = await this.subscription.nextGroup();\n if (!group) break; // Track is closed\n\n // Read all frames from the group\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const frame = await group.readFrame();\n if (!frame) break; // Group is finished\n framesInGroup++;\n\n this.bytesReceived += frame.length;\n const receivedData: DataReceived = {\n trackName: this._config.trackName,\n data: frame,\n timestamp: Date.now(),\n frameIndex: framesInGroup,\n };\n this.emit('data', receivedData);\n }\n }\n } catch (error) {\n this.handleError(error as Error);\n // Trigger retry when stream gets reset/closed\n if (this.connection && this.namespace) {\n this.scheduleRetry(this.connection, this.namespace);\n }\n }\n }\n \n private scheduleRetry(connection: Connection.Established, namespace: string): void {\n const delay = this._config.retry?.delay || 2000;\n\n this.setState(SubscriptionState.RETRYING);\n this.retryAttempts++;\n\n this.retryTimer = setTimeout(async () => {\n try {\n await this.subscribe(connection, namespace);\n } catch (error) {\n this.handleError(error as Error);\n this.scheduleRetry(connection, namespace);\n }\n }, delay);\n }\n\n async stop(): Promise<void> {\n this.connection = undefined;\n this.namespace = undefined;\n \n if (this.retryTimer) {\n clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n\n if (this.subscription) {\n try {\n this.subscription.close();\n } catch (error) {\n console.warn('Error closing subscription:', error);\n }\n this.subscription = undefined;\n }\n\n if (this.broadcast) {\n try {\n this.broadcast.close();\n } catch (error) {\n console.warn('Error closing broadcast:', error);\n }\n this.broadcast = undefined;\n }\n\n this.setState(SubscriptionState.PENDING);\n }\n\n private setState(newState: SubscriptionState): void {\n if (this.state !== newState) {\n this.state = newState;\n this.emit('stateChange', this.status);\n }\n }\n\n private handleError(error: Error): void {\n this.lastError = error;\n this.emit('error', error);\n }\n\n dispose(): void {\n this.stop().catch((error) => {\n console.warn('Error during dispose:', error);\n });\n this.removeAllListeners();\n }\n}","import { Broadcast, Connection, Path } from '@kixelated/moq';\nimport { EventEmitter } from './event-emitter';\nimport { MoQBroadcast } from './broadcast';\nimport { MoQSubscription } from './subscription';\nimport {\n MoQSessionConfig,\n SessionState,\n SessionStatus,\n SessionEvents,\n BroadcastConfig,\n SubscriptionConfig\n} from './types';\n\nexport class MoQSession extends EventEmitter<SessionEvents> {\n private config: MoQSessionConfig;\n private url: URL;\n private state: SessionState = SessionState.DISCONNECTED;\n private connection?: Connection.Established;\n private reconnectAttempts = 0;\n private lastError?: Error;\n private connectedAt?: Date;\n private reconnectTimer?: ReturnType<typeof setTimeout>;\n private broadcasts = new Map<string, MoQBroadcast>();\n private subscriptions = new Map<string, MoQSubscription>();\n private announcedBroadcasts = new Set<string>();\n private doReconnect = true;\n private broadcast?: Broadcast;\n private disposed = false;\n\n constructor(config: MoQSessionConfig) {\n super();\n this.config = {\n ...config,\n reconnection: {\n delay: Math.max(config.reconnection?.delay || 1000, 1000), // Enforce minimum 1 second\n },\n connectionTimeout: config.connectionTimeout || 10000\n };\n\n this.url = new URL(this.config.relayUrl);\n }\n\n get status(): SessionStatus {\n return {\n state: this.state,\n reconnectAttempts: this.reconnectAttempts,\n lastError: this.lastError,\n connectedAt: this.connectedAt\n };\n }\n\n async connect(): Promise<void> {\n if (this.disposed) {\n throw new Error('Cannot connect a disposed session');\n }\n \n if (this.state === SessionState.CONNECTING || this.state === SessionState.CONNECTED) {\n return;\n }\n\n this.setState(SessionState.CONNECTING);\n\n try {\n this.doReconnect = true;\n this.connection = await Connection.connect(this.url, {\n websocket: {\n enabled: false\n }\n });\n\n this.setState(SessionState.CONNECTED);\n this.connectedAt = new Date();\n this.reconnectAttempts = 0;\n\n // Set up connection close handling\n this.connection.closed.then(() => {\n // Only handle disconnection if not disposed\n if (!this.disposed && this.state === SessionState.CONNECTED) {\n this.handleDisconnection();\n }\n });\n\n // Start discovering announced broadcasts\n this.startAnnouncementDiscovery();\n\n // Restart all broadcasts and subscriptions\n await this.restartBroadcasts();\n await this.restartSubscriptions();\n\n } catch (error) {\n const err = new Error(`Failed to connect to relay: ${(error as Error).message}`);\n this.handleError(err);\n this.scheduleReconnect();\n throw err;\n }\n }\n\n async disconnect(): Promise<void> {\n this.doReconnect = false;\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n\n // Stop all broadcasts and subscriptions\n await this.stopAllBroadcasts();\n await this.stopAllSubscriptions();\n\n if (this.connection) {\n try {\n this.connection.close();\n } catch (error) {\n console.warn('Error closing connection:', error);\n }\n this.connection = undefined;\n }\n\n this.setState(SessionState.DISCONNECTED);\n this.connectedAt = undefined;\n }\n\n /**\n * Get all active broadcast track names\n */\n getAllBroadcastTrackNames(): string[] {\n return Array.from(this.broadcasts.keys());\n }\n\n /**\n * Get all active subscription track names\n */\n getAllSubscriptionTrackNames(): string[] {\n return Array.from(this.subscriptions.keys());\n }\n\n /**\n * Declaratively update broadcasts - add, remove, or update broadcasts to match the desired state.\n * \n * @param configs Array of broadcast configurations representing the desired state\n */\n updateBroadcasts(configs: BroadcastConfig[]): void {\n // Check for duplicate track names in the input\n const trackNames = configs.map(config => config.trackName);\n const uniqueTrackNames = new Set(trackNames);\n if (trackNames.length !== uniqueTrackNames.size) {\n const duplicates = trackNames.filter((name, index) => trackNames.indexOf(name) !== index);\n throw new Error(`Duplicate broadcast track name: ${duplicates[0]}`);\n }\n\n const desiredTracks = new Set(configs.map(config => config.trackName));\n const currentTracks = new Set(this.broadcasts.keys());\n\n // Remove broadcasts that are no longer needed\n for (const trackName of currentTracks) {\n if (!desiredTracks.has(trackName)) {\n this._removeBroadcast(trackName);\n }\n }\n\n // Add new broadcasts or update existing ones\n for (const config of configs) {\n const existing = this.broadcasts.get(config.trackName);\n if (!existing) {\n // Create new broadcast\n this._createBroadcast(config);\n } else {\n // Update existing broadcast config if needed\n if (existing.config.priority !== config.priority) {\n // For now, we recreate if priority changed\n // In future, we could support dynamic priority updates\n this._removeBroadcast(config.trackName);\n this._createBroadcast(config);\n }\n }\n }\n }\n\n /**\n * Declaratively update subscriptions - add, remove, or update subscriptions to match the desired state.\n * \n * @param configs Array of subscription configurations representing the desired state\n */\n updateSubscriptions(configs: SubscriptionConfig[]): void {\n // Check for duplicate track names in the input\n const trackNames = configs.map(config => config.trackName);\n const uniqueTrackNames = new Set(trackNames);\n if (trackNames.length !== uniqueTrackNames.size) {\n const duplicates = trackNames.filter((name, index) => trackNames.indexOf(name) !== index);\n throw new Error(`Duplicate subscription track name: ${duplicates[0]}`);\n }\n\n const desiredTracks = new Set(configs.map(config => config.trackName));\n const currentTracks = new Set(this.subscriptions.keys());\n\n // Remove subscriptions that are no longer needed\n for (const trackName of currentTracks) {\n if (!desiredTracks.has(trackName)) {\n this._removeSubscription(trackName);\n }\n }\n\n // Add new subscriptions or update existing ones\n for (const config of configs) {\n const existing = this.subscriptions.get(config.trackName);\n if (!existing) {\n // Create new subscription\n this._createSubscription(config);\n } else {\n // Update existing subscription config if needed\n if (existing.config.priority !== config.priority || \n existing.config.retry?.delay !== config.retry?.delay) {\n // For now, we recreate if config changed\n // In future, we could support dynamic config updates\n this._removeSubscription(config.trackName);\n this._createSubscription(config);\n }\n }\n }\n }\n\n getAnnouncedBroadcasts(): string[] {\n return Array.from(this.announcedBroadcasts);\n }\n\n /**\n * Send data to a broadcast track\n * @param trackName Name of the track to send data to\n * @param data Binary data to send\n */\n async send(trackName: string, data: Uint8Array, newGroup: boolean): Promise<void> {\n const broadcast = this.broadcasts.get(trackName);\n if (!broadcast) {\n throw new Error(`No broadcast found for track: ${trackName}`);\n }\n await broadcast.send(data, newGroup);\n }\n\n /**\n * Get the status of a specific broadcast track\n * @param trackName Name of the track\n */\n getBroadcastStatus(trackName: string) {\n const broadcast = this.broadcasts.get(trackName);\n return broadcast?.status;\n }\n\n /**\n * Get the status of a specific subscription track\n * @param trackName Name of the track\n */\n getSubscriptionStatus(trackName: string) {\n const subscription = this.subscriptions.get(trackName);\n return subscription?.status;\n }\n\n private _createBroadcast(config: BroadcastConfig): MoQBroadcast {\n const broadcast = new MoQBroadcast(config);\n this.broadcasts.set(config.trackName, broadcast);\n\n // Forward broadcast events to session\n broadcast.on('stateChange', (status) => {\n this.emit('broadcastStateChange', config.trackName, status);\n });\n\n broadcast.on('error', (error) => {\n this.emit('broadcastError', config.trackName, error);\n });\n\n this.initBroadcasting();\n\n return broadcast;\n }\n\n private _createSubscription(config: SubscriptionConfig): MoQSubscription {\n const subscription = new MoQSubscription(config);\n this.subscriptions.set(config.trackName, subscription);\n\n // Forward subscription events to session\n subscription.on('data', (received) => {\n this.emit('data', received.trackName, received.data, received.frameIndex);\n });\n\n subscription.on('stateChange', (status) => {\n this.emit('subscriptionStateChange', config.trackName, status);\n });\n\n subscription.on('error', (error) => {\n this.emit('subscriptionError', config.trackName, error);\n });\n\n // Start subscription if we're connected\n if (this.state === SessionState.CONNECTED && this.connection) {\n subscription.start(this.connection, this.config.namespace).catch(error => {\n console.error('Failed to start subscription:', error);\n });\n }\n\n return subscription;\n }\n\n private _removeBroadcast(trackName: string): void {\n const broadcast = this.broadcasts.get(trackName);\n if (broadcast) {\n broadcast.stop().catch(error => {\n console.warn('Error stopping broadcast:', error);\n });\n this.broadcasts.delete(trackName);\n }\n }\n\n private _removeSubscription(trackName: string): void {\n const subscription = this.subscriptions.get(trackName);\n if (subscription) {\n subscription.stop().catch(error => {\n console.warn('Error stopping subscription:', error);\n });\n this.subscriptions.delete(trackName);\n }\n }\n\n private async startAnnouncementDiscovery(): Promise<void> {\n if (!this.connection) return;\n\n try {\n // Listen for announcements with our namespace as prefix\n const namespacePath = Path.from(this.config.namespace);\n const announced = this.connection.announced(namespacePath);\n \n // Process announcements in the background\n this.processAnnouncements(announced);\n \n } catch (error) {\n console.error('Failed to start announcement discovery:', error);\n }\n }\n\n private async processAnnouncements(announced: ReturnType<Connection.Established['announced']>): Promise<void> {\n try {\n for (;;) {\n // Stop processing if session is disposed\n if (this.disposed) break;\n \n const announcement = await announced.next();\n if (!announcement) break; // Announcements closed\n \n // Don't emit events if disposed\n if (this.disposed) break;\n \n if (announcement.active) {\n this.announcedBroadcasts.add(announcement.path);\n this.emit('broadcastAnnounced', {\n path: announcement.path,\n active: true\n });\n } else {\n this.announcedBroadcasts.delete(announcement.path);\n this.emit('broadcastAnnounced', {\n path: announcement.path,\n active: false\n });\n }\n }\n } catch (error) {\n // Don't log errors if session is disposed\n if (!this.disposed) {\n console.error('Error processing announcements:', error);\n }\n }\n }\n\n private async restartBroadcasts(): Promise<void> {\n await this.stopAllBroadcasts();\n this.initBroadcasting();\n }\n\n private initBroadcasting(): void {\n if (this.broadcast) return;\n if (this.broadcasts.size === 0) return;\n\n this.broadcast = new Broadcast();\n if (this.connection) {\n this.connection.publish(Path.from(this.config.namespace), this.broadcast);\n this.handleTrackRequests().catch(error => {\n console.error('Error handling track requests:', error);\n });\n }\n }\n\n private async handleTrackRequests(): Promise<void> {\n if (!this.broadcast) return;\n \n try {\n for (;;) {\n const request = await this.broadcast.requested();\n if (!request) return; // No more requests, broadcast closed;\n const broadcast = this.broadcasts.get(request.track.name);\n if (broadcast) {\n broadcast.updateTrack(request.track);\n this.emit('trackRequested', request.track.name);\n }\n }\n\n } catch (error) {\n console.warn('Error handling track requests:', error);\n this.handleError(error as Error);\n }\n}\n\n private async restartSubscriptions(): Promise<void> {\n if (!this.connection) return;\n\n const promises = Array.from(this.subscriptions.values()).map(subscription => \n subscription.start(this.connection!, this.config.namespace).catch(error => {\n console.error('Failed to restart subscription:', error);\n })\n );\n\n await Promise.allSettled(promises);\n }\n\n private async stopAllBroadcasts(): Promise<void> {\n this.broadcast?.close();\n this.broadcast = undefined;\n const promises = Array.from(this.broadcasts.values()).map(broadcast => \n broadcast.stop().catch(error => {\n console.warn('Error stopping broadcast:', error);\n })\n );\n\n await Promise.allSettled(promises);\n }\n\n private async stopAllSubscriptions(): Promise<void> {\n const promises = Array.from(this.subscriptions.values()).map(subscription => \n subscription.stop().catch(error => {\n console.warn('Error stopping subscription:', error);\n })\n );\n\n await Promise.allSettled(promises);\n }\n\n private handleDisconnection(): void {\n if (this.disposed) return; // Don't reconnect if disposed\n this.setState(SessionState.DISCONNECTED);\n this.scheduleReconnect();\n }\n\n private scheduleReconnect(): void {\n if (this.disposed || !this.config.reconnection || !this.doReconnect) return;\n\n const delay = this.config.reconnection?.delay || 1000;\n\n this.setState(SessionState.RECONNECTING);\n this.reconnectAttempts++;\n\n this.reconnectTimer = setTimeout(() => {\n if (this.disposed || !this.doReconnect) return;\n if (this.state !== SessionState.RECONNECTING) return;\n this.connect().catch(error => {\n console.error('Reconnection failed:', error);\n });\n }, delay);\n }\n\n private setState(newState: SessionState): void {\n if (this.disposed) return; // Don't change state if disposed\n if (this.state !== newState) {\n this.state = newState;\n this.emit('stateChange', this.status);\n }\n }\n\n private handleError(error: Error): void {\n if (this.disposed) return; // Don't emit errors if disposed\n this.lastError = error;\n this.emit('error', error);\n }\n\n public dispose(): void {\n // Mark as disposed to prevent any further operations\n this.disposed = true;\n \n // Immediately stop reconnection attempts\n this.doReconnect = false;\n \n // Clear any pending reconnect timer immediately\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n \n // Disconnect (but don't await to keep dispose synchronous)\n this.disconnect().catch((error) => {\n console.warn('Error during session disconnect:', error);\n });\n this.removeAllListeners();\n\n this.subscriptions.forEach(sub => sub.dispose());\n this.broadcasts.forEach(bc => bc.dispose());\n this.subscriptions.clear();\n this.broadcasts.clear();\n }\n}"],"names":["EventEmitter","event","listener","eventListeners","args","error","SessionState","BroadcastState","SubscriptionState","MoQBroadcast","config","track","data","newGroup","newState","MoQSubscription","connection","namespace","broadcastPath","Path","framesInGroup","group","frame","receivedData","delay","_a","MoQSession","Connection","err","configs","trackNames","uniqueTrackNames","duplicates","name","index","desiredTracks","currentTracks","trackName","existing","_b","broadcast","subscription","status","received","namespacePath","announced","announcement","Broadcast","request","promises","sub","bc"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/typed-emitter.ts","../src/broadcast-mgr.ts","../src/subscription-mgr.ts","../src/types.ts","../src/session.ts"],"sourcesContent":["/**\n * A lightweight typed event emitter for browser environments.\n * \n * @template T - An interface where each key is an event name and each value is the event handler signature\n * \n * @example\n * ```typescript\n * interface MyEvents {\n * data: (value: string) => void;\n * error: (error: Error) => void;\n * }\n * \n * class MyEmitter extends TypedEmitter<MyEvents> {\n * sendData() {\n * this.emit('data', 'hello'); // Type-safe!\n * }\n * }\n * ```\n */\nexport class TypedEmitter<T extends Record<string, (...args: unknown[]) => void>> {\n private listeners: Map<keyof T, Set<(...args: unknown[]) => void>> = new Map();\n\n /**\n * Emit a typed event\n */\n emit<K extends keyof T>(event: K, ...args: Parameters<T[K]>): boolean {\n const eventListeners = this.listeners.get(event);\n if (!eventListeners || eventListeners.size === 0) {\n return false;\n }\n\n for (const listener of eventListeners) {\n try {\n listener(...args);\n } catch (error) {\n console.error('Error in event listener:', error);\n }\n }\n\n return true;\n }\n\n /**\n * Add a typed event listener\n */\n on<K extends keyof T>(event: K, listener: T[K]): this {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener as (...args: unknown[]) => void);\n return this;\n }\n\n /**\n * Add a one-time typed event listener\n */\n once<K extends keyof T>(event: K, listener: T[K]): this {\n const onceWrapper = ((...args: unknown[]) => {\n this.off(event, onceWrapper as T[K]);\n (listener as (...args: unknown[]) => void)(...args);\n }) as T[K];\n\n return this.on(event, onceWrapper);\n }\n\n /**\n * Remove a typed event listener\n */\n off<K extends keyof T>(event: K, listener: T[K]): this {\n const eventListeners = this.listeners.get(event);\n if (eventListeners) {\n eventListeners.delete(listener as (...args: unknown[]) => void);\n if (eventListeners.size === 0) {\n this.listeners.delete(event);\n }\n }\n return this;\n }\n\n /**\n * Remove a typed event listener (alias for off)\n */\n removeListener<K extends keyof T>(event: K, listener: T[K]): this {\n return this.off(event, listener);\n }\n\n /**\n * Add a typed event listener (alias for on)\n */\n addListener<K extends keyof T>(event: K, listener: T[K]): this {\n return this.on(event, listener);\n }\n\n /**\n * Remove all listeners for a specific event, or all listeners if no event is specified\n */\n removeAllListeners<K extends keyof T>(event?: K): this {\n if (event === undefined) {\n this.listeners.clear();\n } else {\n this.listeners.delete(event);\n }\n return this;\n }\n\n /**\n * Get the number of listeners for a specific event\n */\n listenerCount<K extends keyof T>(event: K): number {\n return this.listeners.get(event)?.size || 0;\n }\n\n /**\n * Get all event names that have listeners\n */\n eventNames(): Array<keyof T> {\n return Array.from(this.listeners.keys());\n }\n}\n","import { Broadcast, Connection, Group, Track } from '@kixelated/moq';\nimport {\n BroadcastConfig,\n BroadcastEvents,\n ICatalog\n} from './types';\nimport { TypedEmitter } from './typed-emitter';\nimport { Valid } from '@kixelated/moq/path';\n\nclass BroadcastTrack {\n private group?: Group;\n public track: Track;\n public bytesSent: number = 0;\n public config: BroadcastConfig;\n \n constructor(track: Track, config: BroadcastConfig) {\n this.track = track;\n this.config = config;\n }\n public send(data: Uint8Array, newGroup: boolean) {\n try {\n if (newGroup || !this.group) {\n this.group?.close();\n this.group = this.track.appendGroup();\n }\n this.group.writeFrame(data);\n this.bytesSent += data.byteLength;\n } catch (_) {\n //\n }\n }\n\n public updateTrack(newTrack: Track) {\n this.track = newTrack;\n }\n\n public dispose() {\n this.group?.close();\n this.track.close();\n }\n}\n\nexport class MoQBroadcastManager extends TypedEmitter<BroadcastEvents> {\n private connection: Connection.Established;\n private broadcast: Broadcast;\n private broadcasts: Map<string, BroadcastTrack> = new Map();\n private catalogTrack?: Track;\n\n constructor(namespace: Valid, connection: Connection.Established) {\n super();\n this.connection = connection;\n\n this.broadcast = new Broadcast();\n this.connection.publish(namespace, this.broadcast);\n this.runTrackRequests().catch((err: Error) => {\n this.emit('error', err);\n });\n }\n\n public dispose(): void {\n this.removeAllListeners();\n for (const broadcast of this.broadcasts.values()) {\n broadcast.dispose();\n }\n this.broadcasts.clear();\n this.broadcast.close();\n }\n\n public updateBroadcasts(configs: BroadcastConfig[]): void {\n let changed = false;\n // Check for duplicate track names in the input\n const trackNames = configs.map(config => config.trackName);\n const uniqueTrackNames = new Set(trackNames);\n if (trackNames.length !== uniqueTrackNames.size) {\n const duplicates = trackNames.filter((name, index) => trackNames.indexOf(name) !== index);\n throw new Error(`Duplicate broadcast track name: ${duplicates[0]}`);\n }\n\n const desiredTracks = new Set(configs.map(config => config.trackName));\n const currentTracks = new Set(this.broadcasts.keys());\n\n // Remove broadcasts that are no longer needed\n for (const trackName of currentTracks) {\n if (!desiredTracks.has(trackName)) {\n this.removeBroadcast(trackName);\n changed = true;\n }\n }\n\n // Add new broadcasts or update existing ones\n for (const config of configs) {\n const existing = this.broadcasts.get(config.trackName);\n if (!existing) {\n // Create new broadcast\n this.addBroadcast(config);\n changed = true;\n }\n }\n if (changed) {\n this.updateCatalog();\n }\n }\n\n private addBroadcast(config: BroadcastConfig): void {\n const track = new BroadcastTrack(new Track(config.trackName), config);\n this.broadcasts.set(config.trackName, track);\n }\n\n private removeBroadcast(trackName: string): void {\n const broadcast = this.broadcasts.get(trackName);\n if (broadcast) {\n broadcast.dispose();\n this.broadcasts.delete(trackName);\n }\n }\n\n private async runTrackRequests(): Promise<void> {\n for (;;) {\n const request = await this.broadcast.requested();\n if (!request) return;\n if (request.track.name === 'catalog.json') {\n this.catalogTrack = request.track;\n this.updateCatalog();\n continue;\n }\n\n const broadcast = this.broadcasts.get(request.track.name);\n if (broadcast) {\n broadcast.updateTrack(request.track);\n this.emit('trackRequested', request.track.name);\n }\n }\n }\n\n private updateCatalog() {\n const data: ICatalog = { tracks: [] };\n data.tracks = [...this.broadcasts.values()].map(b => ({\n trackName: b.config.trackName,\n type: b.config.type,\n priority: b.config.priority || 0\n }));\n\n this.catalogTrack?.writeJson(data);\n }\n\n async send(trackName: string, data: Uint8Array, newGroup: boolean): Promise<void> {\n const broadcast = this.broadcasts.get(trackName);\n return broadcast?.send(data, newGroup);\n }\n}\n","import { Broadcast, Connection, Track } from '@kixelated/moq';\nimport {\n ICatalog,\n SubscriptionConfig,\n SubscriptionEvents,\n} from './types';\n\nimport { TypedEmitter } from './typed-emitter';\nimport { Valid } from '@kixelated/moq/path';\n\nexport class MoQSubscriptionsManager extends TypedEmitter<SubscriptionEvents> {\n private connection: Connection.Established;\n private broadcast: Broadcast;\n private namespace: Valid;\n private catalogTrack?: Track;\n private catalog: ICatalog = { tracks: [] };\n private enabled_: boolean = false;\n private requestedSubscriptions: Map<string, SubscriptionConfig> = new Map();\n private subscriptions: Map<string, { track: Track; config: SubscriptionConfig }> = new Map();\n\n public set enabled(enabled: boolean) {\n if (this.enabled_ === enabled) {\n return;\n }\n\n this.enabled_ = enabled;\n \n if (enabled) {\n this.runCatalog().catch((err) => {\n this.emit('error', err);\n });\n }\n }\n\n public get enabled(): boolean {\n return this.enabled_;\n }\n\n constructor(namespace: Valid, connection: Connection.Established) {\n super();\n this.connection = connection;\n this.namespace = namespace;\n\n this.broadcast = this.connection.consume(this.namespace);\n }\n\n public async runCatalog(): Promise<void> {\n this.catalogTrack = await this.broadcast.subscribe('catalog.json', 0);\n if (!this.catalogTrack) {\n throw new Error('Failed to subscribe to catalog track');\n }\n\n for(;;) {\n const data = await this.catalogTrack.readJson();\n if (data) {\n console.log('Received catalog update:', data);\n this.updateCatalog(data as ICatalog);\n } else {\n return;\n }\n }\n }\n\n private updateCatalog(catalogData: ICatalog): void {\n this.catalog = catalogData;\n this.checkSubscriptions();\n }\n\n public dispose(): void {\n this.removeAllListeners();\n for (const sub of this.subscriptions.values()) {\n sub.track.close();\n }\n this.catalogTrack?.close();\n this.broadcast?.close();\n }\n\n public updateSubscriptions(configs: SubscriptionConfig[]): void {\n this.requestedSubscriptions.clear();\n for (const config of configs) {\n this.requestedSubscriptions.set(config.trackName, config);\n }\n\n this.checkSubscriptions();\n }\n\n private checkSubscriptions(): void {\n const desiredTracks = new Set(this.requestedSubscriptions.keys());\n const currentTracks = new Set(this.subscriptions.keys());\n const availableTracks = this.catalog.tracks.map(t => t.trackName);\n\n // Remove subscriptions that are no longer needed\n for (const trackName of currentTracks) {\n if (!desiredTracks.has(trackName) || !availableTracks.includes(trackName)) {\n this.removeSubscription(trackName);\n }\n }\n\n // Add new subscriptions\n for (const trackName of desiredTracks) {\n if (!currentTracks.has(trackName) && availableTracks.includes(trackName)) {\n const config = this.requestedSubscriptions.get(trackName)!;\n this.addSubscription(trackName, config).catch((err) => {\n this.emit('error', err);\n });\n }\n }\n }\n\n private removeSubscription(trackName: string): void {\n const existing = this.subscriptions.get(trackName);\n if (existing) {\n existing.track.close();\n this.subscriptions.delete(trackName);\n this.emit('unsubscribed', trackName);\n }\n }\n\n private async addSubscription(trackName: string, config: SubscriptionConfig): Promise<void> {\n const track = this.broadcast.subscribe(trackName, config.priority ?? 0);\n let lastSequence = -1;\n\n if (track) {\n this.subscriptions.set(trackName, { track, config });\n this.emit('subscribed', trackName);\n\n for (;;) {\n const group = await track.nextGroup();\n if (!group) {\n return;\n }\n try {\n if (group.sequence <= lastSequence) {\n console.log(`Skipping out-of-order group on track \"${trackName}\": ${group.sequence} <= ${lastSequence}`);\n group.close();\n continue;\n }\n\n for (;;) {\n const frame = await group.readFrame();\n if (!frame) {\n break;\n }\n lastSequence = group.sequence;\n this.emit('data', { data: frame, frameIndex: 0, trackName, timestamp: Date.now()});\n }\n } catch (_) {\n console.log('Error processing group on track:', trackName);\n } finally {\n group.close();\n }\n }\n }\n }\n}","// Types for the library\nexport interface MoQSessionConfig {\n /** URL of the MoQ relay server */\n relayUrl: string;\n /** MoQ namespace (broadcast name) */\n namespace: string;\n /** Reconnection configuration */\n reconnection?: {\n /** Delay between reconnection attempts in ms (minimum: 1000) */\n delay?: number;\n };\n /** Connection timeout in ms (default: 10000) */\n connectionTimeout?: number;\n}\n\nexport type MoQSessionType = 'broadcaster' | 'subscriber';\n\nexport interface BroadcastConfig {\n trackName: string;\n priority?: number;\n type: 'video' | 'audio' | 'data';\n}\n\nexport interface SubscriptionConfig {\n /** Track name to subscribe to */\n trackName: string;\n /** Priority for the subscription (default: 0) */\n priority?: number;\n /** Retry configuration for failed subscriptions */\n retry?: {\n /** Delay between retry attempts in ms (default: 2000) */\n delay?: number;\n };\n}\n\nexport interface ICatalog {\n tracks: ICatalogTrack[];\n}\n\nexport interface ICatalogTrack {\n type: 'video' | 'audio' | 'data';\n trackName: string;\n priority: number;\n}\n\nexport enum SessionState {\n DISCONNECTED = 'disconnected',\n CONNECTING = 'connecting',\n CONNECTED = 'connected',\n RECONNECTING = 'reconnecting',\n FAILED = 'failed'\n}\n\nexport enum BroadcastState {\n IDLE = 'idle',\n BROADCASTING = 'broadcasting',\n ERROR = 'error'\n}\n\nexport enum SubscriptionState {\n IDLE = 'idle',\n SUBSCRIBED = 'subscribed',\n FAILED = 'failed'\n}\n\nexport interface SessionStatus {\n state: SessionState;\n reconnectAttempts: number;\n lastError?: Error;\n connectedAt?: Date;\n}\n\nexport interface BroadcastStatus {\n state: BroadcastState;\n trackName: string;\n bytesSent: number;\n lastError?: Error;\n}\n\nexport interface SubscriptionStatus {\n state: SubscriptionState;\n trackName: string;\n bytesReceived: number;\n lastError?: Error;\n}\n\nexport interface DataReceived {\n trackName: string;\n data: Uint8Array;\n timestamp: number;\n frameIndex: number;\n}\n\n// Event types\nexport interface BroadcastAnnouncement {\n path: string;\n active: boolean;\n}\n\nexport interface SessionEvents {\n stateChange: (status: SessionStatus) => void;\n error: (error: Error) => void;\n broadcastAnnounced: (announcement: BroadcastAnnouncement) => void;\n data: (trackName: string, data: Uint8Array) => void;\n broadcastStateChange: (trackName: string, status: BroadcastStatus) => void;\n subscriptionStateChange: (trackName: string, status: SubscriptionStatus) => void;\n broadcastError: (trackName: string, error: Error) => void;\n subscriptionError: (trackName: string, error: Error) => void;\n trackRequested: (trackName: string) => void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: (...args: any[]) => void;\n}\n\nexport interface BroadcastEvents {\n stateChange: (status: BroadcastStatus) => void;\n error: (error: Error) => void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: (...args: any[]) => void;\n}\n\nexport interface SubscriptionEvents {\n stateChange: (status: SubscriptionStatus) => void;\n data: (data: DataReceived) => void;\n error: (error: Error) => void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: (...args: any[]) => void;\n}","import { Connection, Path } from '@kixelated/moq';\nimport { MoQBroadcastManager } from './broadcast-mgr';\nimport { MoQSubscriptionsManager } from './subscription-mgr';\nimport { TypedEmitter } from './typed-emitter';\nimport {\n MoQSessionConfig,\n SessionState,\n SessionStatus,\n SessionEvents,\n BroadcastConfig,\n SubscriptionConfig,\n} from './types';\n\nexport abstract class MoQSession extends TypedEmitter<SessionEvents> {\n private url: URL;\n private reconnectAttempts = 0;\n private lastError?: Error;\n private connectedAt?: Date;\n private reconnectTimer?: ReturnType<typeof setTimeout>;\n private doReconnect = true;\n private disposed = false;\n\n protected state: SessionState = SessionState.DISCONNECTED;\n protected connection?: Connection.Established;\n protected config: MoQSessionConfig;\n protected announcedBroadcasts = new Set<string>();\n\n constructor(config: MoQSessionConfig) {\n super();\n\n this.config = {\n ...config,\n reconnection: {\n delay: Math.max(config.reconnection?.delay || 1000, 1000), // Enforce minimum 1 second\n },\n connectionTimeout: config.connectionTimeout || 10000\n };\n\n this.url = new URL(this.config.relayUrl);\n }\n\n get status(): SessionStatus {\n return {\n state: this.state,\n reconnectAttempts: this.reconnectAttempts,\n lastError: this.lastError,\n connectedAt: this.connectedAt\n };\n }\n\n async connect(): Promise<void> {\n if (this.disposed) {\n throw new Error('Cannot connect a disposed session');\n }\n \n if (this.state === SessionState.CONNECTING || this.state === SessionState.CONNECTED) {\n return;\n }\n\n this.setState(SessionState.CONNECTING);\n\n try {\n this.doReconnect = true;\n this.connection = await Connection.connect(this.url, {\n websocket: {\n enabled: false\n }\n });\n\n this.setState(SessionState.CONNECTED);\n this.connectedAt = new Date();\n this.reconnectAttempts = 0;\n\n // Set up connection close handling\n this.connection.closed.then(() => {\n this.handleDisconnected();\n });\n\n // Start discovering announced broadcasts\n this.startAnnouncementDiscovery();\n\n this.handleConnected();\n } catch (error) {\n const err = new Error(`Failed to connect to relay: ${(error as Error).message}`);\n this.handleError(err);\n this.scheduleReconnect();\n throw err;\n }\n }\n\n disconnect() {\n if (this.state === SessionState.DISCONNECTED) {\n return;\n }\n\n this.doReconnect = false;\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n\n if (this.connection) {\n try {\n this.connection.close();\n } catch (error) {\n console.warn('Error closing connection:', error);\n }\n this.connection = undefined;\n }\n\n this.setState(SessionState.DISCONNECTED);\n this.connectedAt = undefined;\n }\n\n getAnnouncedBroadcasts(): string[] {\n return Array.from(this.announcedBroadcasts);\n }\n\n private async startAnnouncementDiscovery(): Promise<void> {\n if (!this.connection) return;\n\n try {\n // Listen for announcements with our namespace as prefix\n const namespacePath = Path.from(this.config.namespace);\n const announced = this.connection.announced(namespacePath);\n \n console.log('announced: ', announced);\n // Process announcements in the background\n this.processAnnouncements(announced);\n \n } catch (error) {\n console.error('Failed to start announcement discovery:', error);\n }\n }\n\n private async processAnnouncements(announced: ReturnType<Connection.Established['announced']>): Promise<void> {\n try {\n for (;;) {\n // Stop processing if session is disposed\n if (this.disposed) break;\n \n const announcement = await announced.next();\n if (!announcement) break;\n \n // Don't emit events if disposed\n if (this.disposed) break;\n \n if (announcement.active) {\n this.announcedBroadcasts.add(announcement.path);\n } else {\n this.announcedBroadcasts.delete(announcement.path);\n }\n\n this.handleAnnounceUpdate();\n\n console.log(this.announcedBroadcasts);\n }\n } catch (error) {\n //\n }\n }\n\n protected abstract handleAnnounceUpdate(): void;\n\n protected handleDisconnected(): void {\n if (this.disposed) return;\n this.setState(SessionState.DISCONNECTED);\n this.scheduleReconnect();\n }\n\n protected abstract handleConnected(): void;\n\n private scheduleReconnect(): void {\n if (this.disposed || !this.config.reconnection || !this.doReconnect) return;\n\n const delay = this.config.reconnection?.delay || 1000;\n\n this.setState(SessionState.RECONNECTING);\n this.reconnectAttempts++;\n\n this.reconnectTimer = setTimeout(() => {\n if (this.disposed || !this.doReconnect) return;\n if (this.state !== SessionState.RECONNECTING) return;\n this.connect().catch(error => {\n console.error('Reconnection failed:', error);\n });\n }, delay);\n }\n\n private setState(newState: SessionState): void {\n if (this.disposed) return; // Don't change state if disposed\n if (this.state !== newState) {\n this.state = newState;\n this.emit('stateChange', this.status);\n }\n }\n\n private handleError(error: Error): void {\n if (this.disposed) return; // Don't emit errors if disposed\n this.lastError = error;\n this.emit('error', error);\n }\n\n public dispose(): void {\n // Mark as disposed to prevent any further operations\n this.disposed = true;\n \n // Immediately stop reconnection attempts\n this.doReconnect = false;\n \n // Clear any pending reconnect timer immediately\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n \n // Disconnect (but don't await to keep dispose synchronous)\n try {\n this.disconnect();\n } catch (error) {\n console.warn('Error during disconnect in dispose:', error);\n }\n this.removeAllListeners();\n }\n}\n\nexport class MoqSessionSubscriber extends MoQSession {\n private subscriptionManager?: MoQSubscriptionsManager;\n private lastEnabledState: boolean = false;\n\n public dispose(): void {\n super.dispose();\n this.subscriptionManager?.dispose();\n }\n\n protected handleConnected(): void {\n this.subscriptionManager?.dispose();\n this.subscriptionManager = new MoQSubscriptionsManager(Path.from(this.config.namespace), this.connection!);\n this.subscriptionManager.on('data', (data) => this.emit('data', data.trackName, data.data));\n this.subscriptionManager.on('error', (err) => this.emit('error', err));\n }\n\n protected handleDisconnected(): void {\n super.handleDisconnected();\n this.subscriptionManager?.dispose();\n }\n\n public updateSubscriptions(configs: SubscriptionConfig[]): void {\n this.subscriptionManager!.updateSubscriptions(configs);\n }\n\n protected handleAnnounceUpdate(): void {\n // Check if any announced broadcast matches our namespace\n const namespace = Path.from(this.config.namespace);\n let hasMatchingBroadcast = false;\n \n for (const path of this.announcedBroadcasts) {\n if (path.startsWith(namespace)) {\n hasMatchingBroadcast = true;\n break;\n }\n }\n \n // Only update if the state has changed to prevent infinite loops\n if (hasMatchingBroadcast !== this.lastEnabledState) {\n this.lastEnabledState = hasMatchingBroadcast;\n \n if (this.subscriptionManager) {\n this.subscriptionManager.enabled = hasMatchingBroadcast;\n }\n }\n }\n}\n\nexport class MoqSessionBroadcaster extends MoQSession {\n private broadcastManager?: MoQBroadcastManager;\n\n public dispose(): void {\n super.dispose();\n this.broadcastManager?.dispose();\n }\n\n public updateBroadcasts(configs: BroadcastConfig[]): void {\n this.broadcastManager!.updateBroadcasts(configs);\n }\n\n protected handleConnected(): void {\n this.broadcastManager?.dispose();\n this.broadcastManager = new MoQBroadcastManager(Path.from(this.config.namespace), this.connection!);\n }\n\n protected handleDisconnected(): void {\n super.handleDisconnected();\n this.broadcastManager?.dispose();\n }\n\n protected handleAnnounceUpdate(): void {\n // No-op for broadcaster\n }\n\n public send(trackName: string, data: Uint8Array, newGroup: boolean): void {\n if (!this.broadcastManager) {\n throw new Error('Broadcast manager not initialized');\n }\n if (this.state !== SessionState.CONNECTED) {\n throw new Error('Cannot send data when session is not connected');\n }\n this.broadcastManager.send(trackName, data, newGroup);\n }\n}"],"names":["TypedEmitter","event","args","eventListeners","listener","error","onceWrapper","_a","BroadcastTrack","track","config","data","newGroup","newTrack","MoQBroadcastManager","namespace","connection","Broadcast","err","broadcast","configs","changed","trackNames","uniqueTrackNames","duplicates","name","index","desiredTracks","currentTracks","trackName","Track","request","b","MoQSubscriptionsManager","enabled","catalogData","sub","_b","availableTracks","t","existing","lastSequence","group","frame","SessionState","BroadcastState","SubscriptionState","MoQSession","Connection","namespacePath","Path","announced","announcement","delay","newState","MoqSessionSubscriber","hasMatchingBroadcast","path","MoqSessionBroadcaster"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
export { MoQSession } from './session';
|
|
2
|
-
export { MoQBroadcast } from './broadcast';
|
|
3
|
-
export { MoQSubscription } from './subscription';
|
|
1
|
+
export { MoQSession, MoqSessionBroadcaster, MoqSessionSubscriber } from './session';
|
|
4
2
|
export type { MoQSessionConfig, BroadcastConfig, SubscriptionConfig, SessionStatus, BroadcastStatus, SubscriptionStatus, DataReceived, SessionEvents, BroadcastEvents, SubscriptionEvents } from './types';
|
|
5
3
|
export { SessionState, BroadcastState, SubscriptionState } from './types';
|
|
6
|
-
export {
|
|
4
|
+
export { MoqSessionBroadcaster as default } from './session';
|
|
7
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAGpF,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,qBAAqB,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC"}
|