@asaidimu/utils-events 1.1.0 → 1.2.0
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 +23 -5
- package/index.d.ts +23 -5
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +1 -1
package/index.d.mts
CHANGED
|
@@ -72,16 +72,18 @@ interface EventBus<TEventMap extends Record<string, any>> {
|
|
|
72
72
|
* Subscribes to a specific event by name.
|
|
73
73
|
* @param eventName - The name of the event to subscribe to.
|
|
74
74
|
* @param callback - The function to call when the event is emitted.
|
|
75
|
+
* @param options - Extra options to determine the behaviour of the
|
|
76
|
+
* subscription
|
|
75
77
|
* @returns A function to unsubscribe from the event.
|
|
76
78
|
*/
|
|
77
|
-
subscribe: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void) => () => void;
|
|
79
|
+
subscribe: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void, options?: SubscribeOptions) => () => void;
|
|
78
80
|
/**
|
|
79
81
|
* Subscribes to an event and automatically unsubscribes after it fires once.
|
|
80
82
|
* @param eventName - The name of the event to subscribe to.
|
|
81
83
|
* @param callback - The function to call when the event is emitted.
|
|
82
84
|
* @returns A function to cancel the one-shot subscription before it fires.
|
|
83
85
|
*/
|
|
84
|
-
once: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void) => () => void;
|
|
86
|
+
once: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void, options?: SubscribeOptions) => () => void;
|
|
85
87
|
/**
|
|
86
88
|
* Emits an event with a payload to all subscribed listeners.
|
|
87
89
|
* @param event - An object containing the event name and payload.
|
|
@@ -97,10 +99,18 @@ interface EventBus<TEventMap extends Record<string, any>> {
|
|
|
97
99
|
metrics: () => EventMetrics;
|
|
98
100
|
/**
|
|
99
101
|
* Clears all subscriptions and resets metrics.
|
|
100
|
-
*
|
|
102
|
+
*
|
|
103
|
+
* After calling `clear()`, the bus is fully reset and can be reused
|
|
101
104
|
* cross-tab communication is re-established if it was previously enabled.
|
|
105
|
+
*
|
|
106
|
+
* @param options - Optional configuration object.
|
|
107
|
+
* @param options.permanent - If `true`, the bus becomes permanently unusable after clearing.
|
|
108
|
+
* Defaults to `false`.
|
|
109
|
+
* @returns {void}
|
|
102
110
|
*/
|
|
103
|
-
clear: (
|
|
111
|
+
clear: (options?: {
|
|
112
|
+
permanent?: boolean;
|
|
113
|
+
}) => void;
|
|
104
114
|
}
|
|
105
115
|
/**
|
|
106
116
|
* Interface defining the metrics tracked by the EventBus.
|
|
@@ -125,6 +135,14 @@ interface EventError extends Error {
|
|
|
125
135
|
/** Optional payload that caused the error. */
|
|
126
136
|
payload?: unknown;
|
|
127
137
|
}
|
|
138
|
+
interface SubscribeOptions {
|
|
139
|
+
/**
|
|
140
|
+
* Debounce delay in milliseconds. When multiple events arrive in quick
|
|
141
|
+
* succession, the callback runs only after the quiet period ends, using the
|
|
142
|
+
* latest payload. Default = no debouncing.
|
|
143
|
+
*/
|
|
144
|
+
debounce?: number;
|
|
145
|
+
}
|
|
128
146
|
|
|
129
147
|
/**
|
|
130
148
|
* Creates a typed event bus.
|
|
@@ -172,4 +190,4 @@ declare class Events<TEventMap extends Record<string, any>> implements EventBus<
|
|
|
172
190
|
clear(): void;
|
|
173
191
|
}
|
|
174
192
|
|
|
175
|
-
export { type DebouncerResult, type EventBus, type EventBusOptions, type EventError, type EventMetrics, Events, createEventBus };
|
|
193
|
+
export { type DebouncerResult, type EventBus, type EventBusOptions, type EventError, type EventMetrics, Events, type SubscribeOptions, createEventBus };
|
package/index.d.ts
CHANGED
|
@@ -72,16 +72,18 @@ interface EventBus<TEventMap extends Record<string, any>> {
|
|
|
72
72
|
* Subscribes to a specific event by name.
|
|
73
73
|
* @param eventName - The name of the event to subscribe to.
|
|
74
74
|
* @param callback - The function to call when the event is emitted.
|
|
75
|
+
* @param options - Extra options to determine the behaviour of the
|
|
76
|
+
* subscription
|
|
75
77
|
* @returns A function to unsubscribe from the event.
|
|
76
78
|
*/
|
|
77
|
-
subscribe: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void) => () => void;
|
|
79
|
+
subscribe: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void, options?: SubscribeOptions) => () => void;
|
|
78
80
|
/**
|
|
79
81
|
* Subscribes to an event and automatically unsubscribes after it fires once.
|
|
80
82
|
* @param eventName - The name of the event to subscribe to.
|
|
81
83
|
* @param callback - The function to call when the event is emitted.
|
|
82
84
|
* @returns A function to cancel the one-shot subscription before it fires.
|
|
83
85
|
*/
|
|
84
|
-
once: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void) => () => void;
|
|
86
|
+
once: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void, options?: SubscribeOptions) => () => void;
|
|
85
87
|
/**
|
|
86
88
|
* Emits an event with a payload to all subscribed listeners.
|
|
87
89
|
* @param event - An object containing the event name and payload.
|
|
@@ -97,10 +99,18 @@ interface EventBus<TEventMap extends Record<string, any>> {
|
|
|
97
99
|
metrics: () => EventMetrics;
|
|
98
100
|
/**
|
|
99
101
|
* Clears all subscriptions and resets metrics.
|
|
100
|
-
*
|
|
102
|
+
*
|
|
103
|
+
* After calling `clear()`, the bus is fully reset and can be reused
|
|
101
104
|
* cross-tab communication is re-established if it was previously enabled.
|
|
105
|
+
*
|
|
106
|
+
* @param options - Optional configuration object.
|
|
107
|
+
* @param options.permanent - If `true`, the bus becomes permanently unusable after clearing.
|
|
108
|
+
* Defaults to `false`.
|
|
109
|
+
* @returns {void}
|
|
102
110
|
*/
|
|
103
|
-
clear: (
|
|
111
|
+
clear: (options?: {
|
|
112
|
+
permanent?: boolean;
|
|
113
|
+
}) => void;
|
|
104
114
|
}
|
|
105
115
|
/**
|
|
106
116
|
* Interface defining the metrics tracked by the EventBus.
|
|
@@ -125,6 +135,14 @@ interface EventError extends Error {
|
|
|
125
135
|
/** Optional payload that caused the error. */
|
|
126
136
|
payload?: unknown;
|
|
127
137
|
}
|
|
138
|
+
interface SubscribeOptions {
|
|
139
|
+
/**
|
|
140
|
+
* Debounce delay in milliseconds. When multiple events arrive in quick
|
|
141
|
+
* succession, the callback runs only after the quiet period ends, using the
|
|
142
|
+
* latest payload. Default = no debouncing.
|
|
143
|
+
*/
|
|
144
|
+
debounce?: number;
|
|
145
|
+
}
|
|
128
146
|
|
|
129
147
|
/**
|
|
130
148
|
* Creates a typed event bus.
|
|
@@ -172,4 +190,4 @@ declare class Events<TEventMap extends Record<string, any>> implements EventBus<
|
|
|
172
190
|
clear(): void;
|
|
173
191
|
}
|
|
174
192
|
|
|
175
|
-
export { type DebouncerResult, type EventBus, type EventBusOptions, type EventError, type EventMetrics, Events, createEventBus };
|
|
193
|
+
export { type DebouncerResult, type EventBus, type EventBusOptions, type EventError, type EventMetrics, Events, type SubscribeOptions, createEventBus };
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
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??{},
|
|
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??{},s=n.errorHandler??(e=>console.error("EventBus Error:",e)),i=null!=n.batch?.size,r=n.batch?.size,a=n.batch?.delay??16;if(i&&(r<=0||!Number.isFinite(r)))throw new Error(`EventBus: batch.size must be a positive finite number, got ${r}.`);if(i&&(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=i?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;b(t,n)},e};let f=p();const g=(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{callback:i}of Array.from(n.values()))try{i(t)}catch(n){const i=n instanceof Error?n:Object.assign(new Error(String(n)),{cause:n}),r=Object.assign(i,{eventName:e,payload:t});s(r)}},v=(t,n,s)=>{l.has(t)||l.set(t,new Map);const i=l.get(t);let r,a;return void 0!==s&&s>0?(a=new e({delay:s,leading:!1}),r=e=>{a.fire((()=>{n(e)}))}):r=n,i.set(n,{callback:r,debouncer:a}),()=>{const e=i.get(n);e&&(e.debouncer?.cancel(),i.delete(n),0===i.size&&l.delete(t))}},y=()=>{const e=u;u=[];for(const{name:t,payload:n}of e){const e=performance.now();b(t,n),g(t,performance.now()-e)}};return{subscribe:(e,t,n)=>v(e,t,n?.debounce),once:(e,t,n)=>{let s;return s=v(e,(e=>{s(),t(e)}),n?.debounce),s},emit:({name:e,payload:t})=>{if(i)return u.push({name:e,payload:t}),u.length>=r?(d.cancel(),void y()):(d.fire((()=>y())),void f?.postMessage({name:e,payload:t}));const n=performance.now();b(e,t),g(e,performance.now()-n),f?.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:e=>{d?.cancel(),u=[];for(const e of l.values())for(const{debouncer:t}of e.values())t?.cancel();l.clear(),h=0,m=0,_.clear(),f?.close(),f=e?.permanent?null: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=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((
|
|
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((n=>{this._enqueue(e,n)}))}fire(e){this._enqueue(e,void 0)}_enqueue(e,n){if(this._pendingFn=e,n&&this._pendingResolvers.push(n),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 n of e)n({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,n=this._pendingResolvers.splice(0);let t;this._pendingFn=void 0;try{t={status:"ok",value:await e()}}catch(e){t={status:"error",error:e}}for(const e of n)e(t);return t}};function n(n){const t=n??{},i=t.errorHandler??(e=>console.error("EventBus Error:",e)),s=null!=t.batch?.size,r=t.batch?.size,a=t.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=t.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,f=()=>{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:n,payload:t}=e.data;b(n,t)},e};let g=f();const p=(e,n)=>{h++,m+=n,_.set(e,(_.get(e)??0)+1)},b=(e,n)=>{const t=l.get(e);if(t&&0!==t.size)for(const{callback:s}of Array.from(t.values()))try{s(n)}catch(t){const s=t instanceof Error?t:Object.assign(new Error(String(t)),{cause:t}),r=Object.assign(s,{eventName:e,payload:n});i(r)}},v=(n,t,i)=>{l.has(n)||l.set(n,new Map);const s=l.get(n);let r,a;return void 0!==i&&i>0?(a=new e({delay:i,leading:!1}),r=e=>{a.fire((()=>{t(e)}))}):r=t,s.set(t,{callback:r,debouncer:a}),()=>{const e=s.get(t);e&&(e.debouncer?.cancel(),s.delete(t),0===s.size&&l.delete(n))}},y=()=>{const e=u;u=[];for(const{name:n,payload:t}of e){const e=performance.now();b(n,t),p(n,performance.now()-e)}};return{subscribe:(e,n,t)=>v(e,n,t?.debounce),once:(e,n,t)=>{let i;return i=v(e,(e=>{i(),n(e)}),t?.debounce),i},emit:({name:e,payload:n})=>{if(s)return u.push({name:e,payload:n}),u.length>=r?(d.cancel(),void y()):(d.fire((()=>y())),void g?.postMessage({name:e,payload:n}));const t=performance.now();b(e,n),p(e,performance.now()-t),g?.postMessage({name:e,payload:n})},metrics:()=>({totalEvents:h,activeSubscriptions:Array.from(l.values()).reduce(((e,n)=>e+n.size),0),eventCounts:new Map(_),averageEmitDuration:h>0?m/h:0}),clear:e=>{d?.cancel(),u=[];for(const e of l.values())for(const{debouncer:n}of e.values())n?.cancel();l.clear(),h=0,m=0,_.clear(),g?.close(),g=e?.permanent?null:f()}}}var t=class{bus;constructor(e){this.bus=n(e)}subscribe(e,n){return this.bus.subscribe(e,n)}once(e,n){return this.bus.once(e,n)}emit(e){return this.bus.emit(e)}metrics(){return this.bus.metrics()}clear(){return this.bus.clear()}};export{t as Events,n as createEventBus};
|