@asaidimu/utils-events 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.mts CHANGED
@@ -126,18 +126,17 @@ interface EventError extends Error {
126
126
  payload?: unknown;
127
127
  }
128
128
 
129
- declare const createEventBus: <TEventMap extends Record<string, any>>(options?: {
130
- batch: boolean;
131
- batchSize: number;
132
- batchDelay: number;
133
- errorHandler: (error: EventError) => void;
134
- crossTab: boolean;
135
- channelName: string;
136
- }) => EventBus<TEventMap>;
129
+ /**
130
+ * Creates a typed event bus.
131
+ *
132
+ * Options are validated eagerly so misconfiguration surfaces at construction
133
+ * time rather than silently producing wrong behaviour at runtime.
134
+ */
135
+ declare function createEventBus<TEventMap extends Record<string, any>>(options?: EventBusOptions): EventBus<TEventMap>;
137
136
 
138
137
  declare class Events<TEventMap extends Record<string, any>> implements EventBus<TEventMap> {
139
138
  private bus;
140
- constructor(options?: any);
139
+ constructor(options?: EventBusOptions);
141
140
  /**
142
141
  * Subscribes to a specific event by name.
143
142
  * @param eventName - The name of the event to subscribe to.
package/index.d.ts CHANGED
@@ -126,18 +126,17 @@ interface EventError extends Error {
126
126
  payload?: unknown;
127
127
  }
128
128
 
129
- declare const createEventBus: <TEventMap extends Record<string, any>>(options?: {
130
- batch: boolean;
131
- batchSize: number;
132
- batchDelay: number;
133
- errorHandler: (error: EventError) => void;
134
- crossTab: boolean;
135
- channelName: string;
136
- }) => EventBus<TEventMap>;
129
+ /**
130
+ * Creates a typed event bus.
131
+ *
132
+ * Options are validated eagerly so misconfiguration surfaces at construction
133
+ * time rather than silently producing wrong behaviour at runtime.
134
+ */
135
+ declare function createEventBus<TEventMap extends Record<string, any>>(options?: EventBusOptions): EventBus<TEventMap>;
137
136
 
138
137
  declare class Events<TEventMap extends Record<string, any>> implements EventBus<TEventMap> {
139
138
  private bus;
140
- constructor(options?: any);
139
+ constructor(options?: EventBusOptions);
141
140
  /**
142
141
  * Subscribes to a specific event by name.
143
142
  * @param eventName - The name of the event to subscribe to.
package/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e=(e={batch:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let a=[],r=0,s=0;const n=new Map,o=new Map;let c=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?c=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const l=(e,t)=>{r++,s+=t,n.set(e,(n.get(e)||0)+1)},i=()=>{const t=a;a=[],t.forEach((({name:t,payload:a})=>{const r=performance.now();try{(o.get(t)||[]).forEach((e=>e(a)))}catch(r){e.errorHandler({...r,eventName:t,payload:a})}l(t,performance.now()-r)}))},u=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(i,e.batchDelay)}})(),d=e=>{const a=t.get(e);a?o.set(e,Array.from(a)):o.delete(e)};return c&&(c.onmessage=e=>{const{name:t,payload:a}=e.data;(o.get(t)||[]).forEach((e=>e(a)))}),{once:(e,a)=>{let r;const s=e=>{r(),a(e)};return r=(()=>{t.has(e)||t.set(e,new Set);const a=t.get(e);return a.add(s),()=>{a.delete(s),0===a.size&&t.delete(e)}})(),r},subscribe:(e,a)=>{t.has(e)||t.set(e,new Set);const r=t.get(e);return r.add(a),d(e),()=>{r.delete(a),0===r.size?(t.delete(e),o.delete(e)):d(e)}},emit:({name:t,payload:r})=>{if(e.batch)return a.push({name:t,payload:r}),a.length>=e.batchSize?i():u(),void(c&&c.postMessage({name:t,payload:r}));const s=performance.now();try{(o.get(t)||[]).forEach((e=>e(r))),c&&c.postMessage({name:t,payload:r})}catch(a){e.errorHandler({...a,eventName:t,payload:r})}l(t,performance.now()-s)},metrics:()=>({totalEvents:r,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:n,averageEmitDuration:r>0?s/r:0}),clear:()=>{t.clear(),o.clear(),a=[],r=0,s=0,n.clear(),c&&(c.close(),c=null)}}};exports.Events=class{bus;constructor(t){this.bus=e(t)}subscribe(e,t){return this.bus.subscribe(e,t)}once(e,t){return this.bus.once(e,t)}emit(e){return this.bus.emit(e)}metrics(){return this.bus.metrics()}clear(){return this.bus.clear()}},exports.createEventBus=e;
1
+ "use strict";var e=class{_delay;_leading;_timer;_pendingFn;_pendingResolvers=[];_leadingFired=!1;constructor(e){this._delay=e?.delay??300,this._leading=e?.leading??!1}do(e){return new Promise((t=>{this._enqueue(e,t)}))}fire(e){this._enqueue(e,void 0)}_enqueue(e,t){if(this._pendingFn=e,t&&this._pendingResolvers.push(t),this._leading&&!this._leadingFired)return this._leadingFired=!0,this._fire(),clearTimeout(this._timer),void(this._timer=setTimeout((()=>{this._leadingFired=!1,void 0!==this._pendingFn&&this._fire()}),this._delay));clearTimeout(this._timer),this._timer=setTimeout((()=>{this._leadingFired=!1,this._fire()}),this._delay)}cancel(){clearTimeout(this._timer),this._timer=void 0,this._pendingFn=void 0,this._leadingFired=!1;const e=this._pendingResolvers.splice(0);for(const t of e)t({status:"cancelled"})}async flush(){return this._pendingFn?(clearTimeout(this._timer),this._timer=void 0,this._leadingFired=!1,this._fire()):null}pending(){return void 0!==this._pendingFn}async _fire(){const e=this._pendingFn,t=this._pendingResolvers.splice(0);let n;this._pendingFn=void 0;try{n={status:"ok",value:await e()}}catch(e){n={status:"error",error:e}}for(const e of t)e(n);return n}};function t(t){const n=t??{},i=n.errorHandler??(e=>console.error("EventBus Error:",e)),s=null!=n.batch?.size,r=n.batch?.size,a=n.batch?.delay??16;if(s&&(r<=0||!Number.isFinite(r)))throw new Error(`EventBus: batch.size must be a positive finite number, got ${r}.`);if(s&&(a<0||!Number.isFinite(a)))throw new Error(`EventBus: batch.delay must be a non-negative finite number, got ${a}.`);const o=n.broadcast?.channel,c=null!=o&&o.length>0,l=new Map;let u=[];const d=s?new e({delay:a}):null;let h=0,m=0;const _=new Map,p=()=>{if(!c)return null;if("undefined"==typeof BroadcastChannel)return console.warn("EventBus: BroadcastChannel is not supported in this environment. Cross-tab notifications are disabled."),null;const e=new BroadcastChannel(o);return e.onmessage=e=>{const{name:t,payload:n}=e.data;v(t,n)},e};let g=p();const f=(e,t)=>{h++,m+=t,_.set(e,(_.get(e)??0)+1)},v=(e,t)=>{const n=l.get(e);if(n&&0!==n.size)for(const s of Array.from(n))try{s(t)}catch(n){const s=n instanceof Error?n:Object.assign(new Error(String(n)),{cause:n}),r=Object.assign(s,{eventName:e,payload:t});i(r)}},b=(e,t)=>{l.has(e)||l.set(e,new Set);const n=l.get(e);return n.add(t),()=>{n.delete(t),0===n.size&&l.delete(e)}},y=()=>{const e=u;u=[];for(const{name:t,payload:n}of e){const e=performance.now();v(t,n),f(t,performance.now()-e)}};return{subscribe:(e,t)=>b(e,t),once:(e,t)=>{let n;return n=b(e,(e=>{n(),t(e)})),n},emit:({name:e,payload:t})=>{if(s)return u.push({name:e,payload:t}),u.length>=r?(d.cancel(),void y()):(d.fire((()=>y())),void g?.postMessage({name:e,payload:t}));const n=performance.now();v(e,t),f(e,performance.now()-n),g?.postMessage({name:e,payload:t})},metrics:()=>({totalEvents:h,activeSubscriptions:Array.from(l.values()).reduce(((e,t)=>e+t.size),0),eventCounts:new Map(_),averageEmitDuration:h>0?m/h:0}),clear:()=>{d?.cancel(),u=[],l.clear(),h=0,m=0,_.clear(),g?.close(),g=p()}}}exports.Events=class{bus;constructor(e){this.bus=t(e)}subscribe(e,t){return this.bus.subscribe(e,t)}once(e,t){return this.bus.once(e,t)}emit(e){return this.bus.emit(e)}metrics(){return this.bus.metrics()}clear(){return this.bus.clear()}},exports.createEventBus=t;
package/index.mjs CHANGED
@@ -1 +1 @@
1
- var e=(e={batch:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let a=[],r=0,n=0;const s=new Map,o=new Map;let c=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?c=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const l=(e,t)=>{r++,n+=t,s.set(e,(s.get(e)||0)+1)},i=()=>{const t=a;a=[],t.forEach((({name:t,payload:a})=>{const r=performance.now();try{(o.get(t)||[]).forEach((e=>e(a)))}catch(r){e.errorHandler({...r,eventName:t,payload:a})}l(t,performance.now()-r)}))},u=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(i,e.batchDelay)}})(),d=e=>{const a=t.get(e);a?o.set(e,Array.from(a)):o.delete(e)};return c&&(c.onmessage=e=>{const{name:t,payload:a}=e.data;(o.get(t)||[]).forEach((e=>e(a)))}),{once:(e,a)=>{let r;const n=e=>{r(),a(e)};return r=(()=>{t.has(e)||t.set(e,new Set);const a=t.get(e);return a.add(n),()=>{a.delete(n),0===a.size&&t.delete(e)}})(),r},subscribe:(e,a)=>{t.has(e)||t.set(e,new Set);const r=t.get(e);return r.add(a),d(e),()=>{r.delete(a),0===r.size?(t.delete(e),o.delete(e)):d(e)}},emit:({name:t,payload:r})=>{if(e.batch)return a.push({name:t,payload:r}),a.length>=e.batchSize?i():u(),void(c&&c.postMessage({name:t,payload:r}));const n=performance.now();try{(o.get(t)||[]).forEach((e=>e(r))),c&&c.postMessage({name:t,payload:r})}catch(a){e.errorHandler({...a,eventName:t,payload:r})}l(t,performance.now()-n)},metrics:()=>({totalEvents:r,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:s,averageEmitDuration:r>0?n/r:0}),clear:()=>{t.clear(),o.clear(),a=[],r=0,n=0,s.clear(),c&&(c.close(),c=null)}}},t=class{bus;constructor(t){this.bus=e(t)}subscribe(e,t){return this.bus.subscribe(e,t)}once(e,t){return this.bus.once(e,t)}emit(e){return this.bus.emit(e)}metrics(){return this.bus.metrics()}clear(){return this.bus.clear()}};export{t as Events,e as createEventBus};
1
+ var e=class{_delay;_leading;_timer;_pendingFn;_pendingResolvers=[];_leadingFired=!1;constructor(e){this._delay=e?.delay??300,this._leading=e?.leading??!1}do(e){return new Promise((t=>{this._enqueue(e,t)}))}fire(e){this._enqueue(e,void 0)}_enqueue(e,t){if(this._pendingFn=e,t&&this._pendingResolvers.push(t),this._leading&&!this._leadingFired)return this._leadingFired=!0,this._fire(),clearTimeout(this._timer),void(this._timer=setTimeout((()=>{this._leadingFired=!1,void 0!==this._pendingFn&&this._fire()}),this._delay));clearTimeout(this._timer),this._timer=setTimeout((()=>{this._leadingFired=!1,this._fire()}),this._delay)}cancel(){clearTimeout(this._timer),this._timer=void 0,this._pendingFn=void 0,this._leadingFired=!1;const e=this._pendingResolvers.splice(0);for(const t of e)t({status:"cancelled"})}async flush(){return this._pendingFn?(clearTimeout(this._timer),this._timer=void 0,this._leadingFired=!1,this._fire()):null}pending(){return void 0!==this._pendingFn}async _fire(){const e=this._pendingFn,t=this._pendingResolvers.splice(0);let n;this._pendingFn=void 0;try{n={status:"ok",value:await e()}}catch(e){n={status:"error",error:e}}for(const e of t)e(n);return n}};function t(t){const n=t??{},i=n.errorHandler??(e=>console.error("EventBus Error:",e)),s=null!=n.batch?.size,r=n.batch?.size,a=n.batch?.delay??16;if(s&&(r<=0||!Number.isFinite(r)))throw new Error(`EventBus: batch.size must be a positive finite number, got ${r}.`);if(s&&(a<0||!Number.isFinite(a)))throw new Error(`EventBus: batch.delay must be a non-negative finite number, got ${a}.`);const o=n.broadcast?.channel,c=null!=o&&o.length>0,l=new Map;let d=[];const u=s?new e({delay:a}):null;let h=0,m=0;const _=new Map,g=()=>{if(!c)return null;if("undefined"==typeof BroadcastChannel)return console.warn("EventBus: BroadcastChannel is not supported in this environment. Cross-tab notifications are disabled."),null;const e=new BroadcastChannel(o);return e.onmessage=e=>{const{name:t,payload:n}=e.data;b(t,n)},e};let p=g();const f=(e,t)=>{h++,m+=t,_.set(e,(_.get(e)??0)+1)},b=(e,t)=>{const n=l.get(e);if(n&&0!==n.size)for(const s of Array.from(n))try{s(t)}catch(n){const s=n instanceof Error?n:Object.assign(new Error(String(n)),{cause:n}),r=Object.assign(s,{eventName:e,payload:t});i(r)}},v=(e,t)=>{l.has(e)||l.set(e,new Set);const n=l.get(e);return n.add(t),()=>{n.delete(t),0===n.size&&l.delete(e)}},y=()=>{const e=d;d=[];for(const{name:t,payload:n}of e){const e=performance.now();b(t,n),f(t,performance.now()-e)}};return{subscribe:(e,t)=>v(e,t),once:(e,t)=>{let n;return n=v(e,(e=>{n(),t(e)})),n},emit:({name:e,payload:t})=>{if(s)return d.push({name:e,payload:t}),d.length>=r?(u.cancel(),void y()):(u.fire((()=>y())),void p?.postMessage({name:e,payload:t}));const n=performance.now();b(e,t),f(e,performance.now()-n),p?.postMessage({name:e,payload:t})},metrics:()=>({totalEvents:h,activeSubscriptions:Array.from(l.values()).reduce(((e,t)=>e+t.size),0),eventCounts:new Map(_),averageEmitDuration:h>0?m/h:0}),clear:()=>{u?.cancel(),d=[],l.clear(),h=0,m=0,_.clear(),p?.close(),p=g()}}}var n=class{bus;constructor(e){this.bus=t(e)}subscribe(e,t){return this.bus.subscribe(e,t)}once(e,t){return this.bus.once(e,t)}emit(e){return this.bus.emit(e)}metrics(){return this.bus.metrics()}clear(){return this.bus.clear()}};export{n as Events,t as createEventBus};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asaidimu/utils-events",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "A lightweight, type-safe event bus implementation for TypeScript applications.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",