evnty 5.0.0 → 5.1.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/README.md +28 -28
- package/build/async.cjs +101 -0
- package/build/async.cjs.map +1 -0
- package/build/async.d.ts +37 -0
- package/build/async.js +83 -0
- package/build/async.js.map +1 -0
- package/build/broadcast.cjs +205 -0
- package/build/broadcast.cjs.map +1 -0
- package/build/broadcast.d.ts +164 -0
- package/build/broadcast.js +184 -0
- package/build/broadcast.js.map +1 -0
- package/build/dispatch-result.cjs +154 -0
- package/build/dispatch-result.cjs.map +1 -0
- package/build/dispatch-result.d.ts +49 -0
- package/build/dispatch-result.js +127 -0
- package/build/dispatch-result.js.map +1 -0
- package/build/event.cjs +92 -127
- package/build/event.cjs.map +1 -1
- package/build/event.d.ts +92 -167
- package/build/event.js +90 -122
- package/build/event.js.map +1 -1
- package/build/index.cjs +3 -1
- package/build/index.cjs.map +1 -1
- package/build/index.d.ts +3 -1
- package/build/index.js +3 -1
- package/build/index.js.map +1 -1
- package/build/iterator.cjs +578 -91
- package/build/iterator.cjs.map +1 -1
- package/build/iterator.d.ts +178 -7
- package/build/iterator.js +579 -92
- package/build/iterator.js.map +1 -1
- package/build/listener-registry.cjs +114 -0
- package/build/listener-registry.cjs.map +1 -0
- package/build/listener-registry.d.ts +54 -0
- package/build/listener-registry.js +104 -0
- package/build/listener-registry.js.map +1 -0
- package/build/ring-buffer.cjs +171 -0
- package/build/ring-buffer.cjs.map +1 -0
- package/build/ring-buffer.d.ts +80 -0
- package/build/ring-buffer.js +161 -0
- package/build/ring-buffer.js.map +1 -0
- package/build/sequence.cjs +34 -35
- package/build/sequence.cjs.map +1 -1
- package/build/sequence.d.ts +38 -24
- package/build/sequence.js +34 -35
- package/build/sequence.js.map +1 -1
- package/build/signal.cjs +26 -35
- package/build/signal.cjs.map +1 -1
- package/build/signal.d.ts +36 -39
- package/build/signal.js +26 -35
- package/build/signal.js.map +1 -1
- package/build/types.cjs +0 -11
- package/build/types.cjs.map +1 -1
- package/build/types.d.ts +86 -9
- package/build/types.js +1 -5
- package/build/types.js.map +1 -1
- package/build/utils.cjs +202 -22
- package/build/utils.cjs.map +1 -1
- package/build/utils.d.ts +85 -26
- package/build/utils.js +181 -22
- package/build/utils.js.map +1 -1
- package/package.json +27 -25
- package/src/__tests__/example.js +19 -24
- package/src/index.ts +3 -1
- package/build/callable.cjs +0 -72
- package/build/callable.cjs.map +0 -1
- package/build/callable.d.ts +0 -34
- package/build/callable.js +0 -51
- package/build/callable.js.map +0 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { isThenable, noop } from "./utils.js";
|
|
2
|
+
const ERR_BRAND = Symbol.for('evnty.ResultError');
|
|
3
|
+
function ResultError(error) {
|
|
4
|
+
this.error = error;
|
|
5
|
+
}
|
|
6
|
+
ResultError.prototype[ERR_BRAND] = true;
|
|
7
|
+
export function err(error) {
|
|
8
|
+
return new ResultError(error);
|
|
9
|
+
}
|
|
10
|
+
export function isErr(result) {
|
|
11
|
+
return typeof result === 'object' && result !== null && result[ERR_BRAND] === true;
|
|
12
|
+
}
|
|
13
|
+
export function isOk(result) {
|
|
14
|
+
return typeof result !== 'object' || result === null || !result[ERR_BRAND];
|
|
15
|
+
}
|
|
16
|
+
export function unwrap(results) {
|
|
17
|
+
const len = results.length;
|
|
18
|
+
const unwrapped = new Array(len);
|
|
19
|
+
for(let i = 0; i < len; i++){
|
|
20
|
+
const r = results[i];
|
|
21
|
+
unwrapped[i] = isErr(r) ? Promise.reject(r.error) : r;
|
|
22
|
+
}
|
|
23
|
+
return unwrapped;
|
|
24
|
+
}
|
|
25
|
+
async function resolveMaybePromises(items, asyncIndices) {
|
|
26
|
+
const pending = new Array(asyncIndices.length);
|
|
27
|
+
for(let j = 0; j < asyncIndices.length; j++){
|
|
28
|
+
pending[j] = items[asyncIndices[j]];
|
|
29
|
+
}
|
|
30
|
+
const resolved = await Promise.all(pending);
|
|
31
|
+
for(let j = 0; j < asyncIndices.length; j++){
|
|
32
|
+
items[asyncIndices[j]] = resolved[j];
|
|
33
|
+
}
|
|
34
|
+
return items;
|
|
35
|
+
}
|
|
36
|
+
function resolveAll(results) {
|
|
37
|
+
const len = results.length;
|
|
38
|
+
if (len === 0) return results;
|
|
39
|
+
let firstError;
|
|
40
|
+
let hasError = false;
|
|
41
|
+
let asyncIndices = null;
|
|
42
|
+
for(let i = 0; i < len; i++){
|
|
43
|
+
const r = results[i];
|
|
44
|
+
if (isErr(r)) {
|
|
45
|
+
if (!hasError) {
|
|
46
|
+
hasError = true;
|
|
47
|
+
firstError = r.error;
|
|
48
|
+
}
|
|
49
|
+
} else try {
|
|
50
|
+
if (isThenable(r)) (asyncIndices ??= []).push(i);
|
|
51
|
+
} catch (e) {
|
|
52
|
+
if (!hasError) {
|
|
53
|
+
hasError = true;
|
|
54
|
+
firstError = e;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (hasError) {
|
|
59
|
+
if (asyncIndices !== null) {
|
|
60
|
+
for(let j = 0; j < asyncIndices.length; j++){
|
|
61
|
+
results[asyncIndices[j]].then(noop, noop);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return Promise.reject(firstError);
|
|
65
|
+
}
|
|
66
|
+
if (asyncIndices === null) return results;
|
|
67
|
+
return resolveMaybePromises(results, asyncIndices);
|
|
68
|
+
}
|
|
69
|
+
function settleAll(results) {
|
|
70
|
+
const len = results.length;
|
|
71
|
+
if (len === 0) return [];
|
|
72
|
+
let asyncIndices = null;
|
|
73
|
+
const settled = new Array(len);
|
|
74
|
+
for(let i = 0; i < len; i++){
|
|
75
|
+
const r = results[i];
|
|
76
|
+
if (isErr(r)) {
|
|
77
|
+
settled[i] = {
|
|
78
|
+
status: 'rejected',
|
|
79
|
+
reason: r.error
|
|
80
|
+
};
|
|
81
|
+
} else try {
|
|
82
|
+
if (isThenable(r)) {
|
|
83
|
+
const wrapped = r.then((value)=>({
|
|
84
|
+
status: 'fulfilled',
|
|
85
|
+
value
|
|
86
|
+
}), (reason)=>({
|
|
87
|
+
status: 'rejected',
|
|
88
|
+
reason
|
|
89
|
+
}));
|
|
90
|
+
(asyncIndices ??= []).push(i);
|
|
91
|
+
settled[i] = wrapped;
|
|
92
|
+
} else {
|
|
93
|
+
settled[i] = {
|
|
94
|
+
status: 'fulfilled',
|
|
95
|
+
value: r
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
} catch (e) {
|
|
99
|
+
settled[i] = {
|
|
100
|
+
status: 'rejected',
|
|
101
|
+
reason: e
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (asyncIndices === null) return settled;
|
|
106
|
+
return resolveMaybePromises(settled, asyncIndices);
|
|
107
|
+
}
|
|
108
|
+
export class DispatchResult {
|
|
109
|
+
#results;
|
|
110
|
+
[Symbol.toStringTag] = 'DispatchResult';
|
|
111
|
+
constructor(results){
|
|
112
|
+
this.#results = results;
|
|
113
|
+
}
|
|
114
|
+
then(onfulfilled, onrejected) {
|
|
115
|
+
const resolved = this.all();
|
|
116
|
+
if (resolved instanceof Promise) return resolved.then(onfulfilled, onrejected);
|
|
117
|
+
return Promise.resolve(resolved).then(onfulfilled, onrejected);
|
|
118
|
+
}
|
|
119
|
+
all() {
|
|
120
|
+
return resolveAll(this.#results);
|
|
121
|
+
}
|
|
122
|
+
settled() {
|
|
123
|
+
return settleAll(this.#results);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
//# sourceMappingURL=dispatch-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dispatch-result.ts"],"sourcesContent":["import { Fn, MaybePromise } from './types.js';\nimport { isThenable, noop } from './utils.js';\n\nconst ERR_BRAND = Symbol.for('evnty.ResultError');\n\n/**\n * @internal\n */\nexport interface ResultError<E = unknown> {\n readonly error: E;\n readonly [ERR_BRAND]: true;\n}\n\nfunction ResultError<E>(this: ResultError<E>, error: E): void {\n (this as { error: E }).error = error;\n}\n(ResultError.prototype as { [ERR_BRAND]: true })[ERR_BRAND] = true;\n\n/**\n * @internal\n */\nexport function err<E>(error: E): ResultError<E> {\n return new (ResultError as unknown as new (error: E) => ResultError<E>)(error);\n}\n\n/**\n * @internal\n */\nexport function isErr(result: unknown): result is ResultError<unknown> {\n return typeof result === 'object' && result !== null && (result as Record<symbol, boolean>)[ERR_BRAND] === true;\n}\n\n/**\n * @internal\n */\nexport function isOk(result: unknown): boolean {\n return typeof result !== 'object' || result === null || !(result as Record<symbol, boolean>)[ERR_BRAND];\n}\n\n/**\n * @internal\n */\nexport type DispatchResultItem<T> = MaybePromise<T> | ResultError;\n\n/**\n * @internal\n */\nexport function unwrap<T>(results: DispatchResultItem<T>[]): MaybePromise<T>[] {\n const len = results.length;\n const unwrapped = new Array<MaybePromise<T>>(len);\n for (let i = 0; i < len; i++) {\n const r = results[i];\n unwrapped[i] = isErr(r) ? Promise.reject(r.error) : r;\n }\n return unwrapped;\n}\n\nasync function resolveMaybePromises<T>(items: MaybePromise<T>[], asyncIndices: number[]): Promise<T[]> {\n const pending = new Array<PromiseLike<T>>(asyncIndices.length);\n for (let j = 0; j < asyncIndices.length; j++) {\n pending[j] = items[asyncIndices[j]] as PromiseLike<T>;\n }\n const resolved = await Promise.all(pending);\n for (let j = 0; j < asyncIndices.length; j++) {\n items[asyncIndices[j]] = resolved[j];\n }\n return items as T[];\n}\n\nfunction resolveAll<T>(results: DispatchResultItem<T>[]): T[] | Promise<T[]> {\n const len = results.length;\n if (len === 0) return results as T[];\n\n let firstError: unknown;\n let hasError = false;\n let asyncIndices: number[] | null = null;\n\n for (let i = 0; i < len; i++) {\n const r = results[i];\n if (isErr(r)) {\n if (!hasError) {\n hasError = true;\n firstError = r.error;\n }\n } else\n try {\n if (isThenable(r)) (asyncIndices ??= []).push(i);\n } catch (e) {\n if (!hasError) {\n hasError = true;\n firstError = e;\n }\n }\n }\n\n if (hasError) {\n if (asyncIndices !== null) {\n for (let j = 0; j < asyncIndices.length; j++) {\n (results[asyncIndices[j]] as PromiseLike<T>).then(noop, noop);\n }\n }\n return Promise.reject(firstError);\n }\n if (asyncIndices === null) return results as T[];\n\n return resolveMaybePromises(results as MaybePromise<T>[], asyncIndices);\n}\n\nfunction settleAll<T>(results: DispatchResultItem<T>[]): PromiseSettledResult<T>[] | Promise<PromiseSettledResult<T>[]> {\n const len = results.length;\n if (len === 0) return [] as PromiseSettledResult<T>[];\n\n let asyncIndices: number[] | null = null;\n const settled = new Array<MaybePromise<PromiseSettledResult<T>>>(len);\n\n for (let i = 0; i < len; i++) {\n const r = results[i];\n if (isErr(r)) {\n settled[i] = { status: 'rejected', reason: r.error };\n } else\n try {\n if (isThenable(r)) {\n const wrapped = r.then(\n (value: T): PromiseFulfilledResult<T> => ({ status: 'fulfilled', value }),\n (reason: unknown): PromiseRejectedResult => ({ status: 'rejected', reason }),\n );\n (asyncIndices ??= []).push(i);\n settled[i] = wrapped;\n } else {\n settled[i] = { status: 'fulfilled', value: r };\n }\n } catch (e) {\n settled[i] = { status: 'rejected', reason: e };\n }\n }\n\n if (asyncIndices === null) return settled as PromiseSettledResult<T>[];\n\n return resolveMaybePromises(settled, asyncIndices);\n}\n\n/**\n * Wraps an array of values or promises (typically listener results) and provides batch resolution.\n *\n * @template T\n */\nexport class DispatchResult<T> implements PromiseLike<T[]> {\n #results: DispatchResultItem<T>[];\n\n readonly [Symbol.toStringTag] = 'DispatchResult';\n\n constructor(results: DispatchResultItem<T>[]) {\n this.#results = results;\n }\n\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: Fn<[T[]], MaybePromise<TResult1>> | null,\n onrejected?: Fn<[any], MaybePromise<TResult2>> | null,\n ): PromiseLike<TResult1 | TResult2> {\n const resolved = this.all();\n if (resolved instanceof Promise) return resolved.then(onfulfilled, onrejected);\n return Promise.resolve(resolved).then(onfulfilled, onrejected);\n }\n\n /**\n * Resolves all listener results, rejecting if any promise rejects or any ResultError exists.\n */\n all(): T[] | Promise<T[]> {\n return resolveAll(this.#results);\n }\n\n /**\n * Waits for all listener results to settle, regardless of fulfillment or rejection.\n */\n settled(): PromiseSettledResult<T>[] | Promise<PromiseSettledResult<T>[]> {\n return settleAll(this.#results);\n }\n}\n"],"names":["isThenable","noop","ERR_BRAND","Symbol","for","ResultError","error","prototype","err","isErr","result","isOk","unwrap","results","len","length","unwrapped","Array","i","r","Promise","reject","resolveMaybePromises","items","asyncIndices","pending","j","resolved","all","resolveAll","firstError","hasError","push","e","then","settleAll","settled","status","reason","wrapped","value","DispatchResult","toStringTag","onfulfilled","onrejected","resolve"],"mappings":"AACA,SAASA,UAAU,EAAEC,IAAI,QAAQ,aAAa;AAE9C,MAAMC,YAAYC,OAAOC,GAAG,CAAC;AAU7B,SAASC,YAAqCC,KAAQ;IACpD,AAAC,IAAI,CAAkBA,KAAK,GAAGA;AACjC;AACCD,YAAYE,SAAS,AAA0B,CAACL,UAAU,GAAG;AAK9D,OAAO,SAASM,IAAOF,KAAQ;IAC7B,OAAO,IAAKD,YAA4DC;AAC1E;AAKA,OAAO,SAASG,MAAMC,MAAe;IACnC,OAAO,OAAOA,WAAW,YAAYA,WAAW,QAAQ,AAACA,MAAkC,CAACR,UAAU,KAAK;AAC7G;AAKA,OAAO,SAASS,KAAKD,MAAe;IAClC,OAAO,OAAOA,WAAW,YAAYA,WAAW,QAAQ,CAAC,AAACA,MAAkC,CAACR,UAAU;AACzG;AAUA,OAAO,SAASU,OAAUC,OAAgC;IACxD,MAAMC,MAAMD,QAAQE,MAAM;IAC1B,MAAMC,YAAY,IAAIC,MAAuBH;IAC7C,IAAK,IAAII,IAAI,GAAGA,IAAIJ,KAAKI,IAAK;QAC5B,MAAMC,IAAIN,OAAO,CAACK,EAAE;QACpBF,SAAS,CAACE,EAAE,GAAGT,MAAMU,KAAKC,QAAQC,MAAM,CAACF,EAAEb,KAAK,IAAIa;IACtD;IACA,OAAOH;AACT;AAEA,eAAeM,qBAAwBC,KAAwB,EAAEC,YAAsB;IACrF,MAAMC,UAAU,IAAIR,MAAsBO,aAAaT,MAAM;IAC7D,IAAK,IAAIW,IAAI,GAAGA,IAAIF,aAAaT,MAAM,EAAEW,IAAK;QAC5CD,OAAO,CAACC,EAAE,GAAGH,KAAK,CAACC,YAAY,CAACE,EAAE,CAAC;IACrC;IACA,MAAMC,WAAW,MAAMP,QAAQQ,GAAG,CAACH;IACnC,IAAK,IAAIC,IAAI,GAAGA,IAAIF,aAAaT,MAAM,EAAEW,IAAK;QAC5CH,KAAK,CAACC,YAAY,CAACE,EAAE,CAAC,GAAGC,QAAQ,CAACD,EAAE;IACtC;IACA,OAAOH;AACT;AAEA,SAASM,WAAchB,OAAgC;IACrD,MAAMC,MAAMD,QAAQE,MAAM;IAC1B,IAAID,QAAQ,GAAG,OAAOD;IAEtB,IAAIiB;IACJ,IAAIC,WAAW;IACf,IAAIP,eAAgC;IAEpC,IAAK,IAAIN,IAAI,GAAGA,IAAIJ,KAAKI,IAAK;QAC5B,MAAMC,IAAIN,OAAO,CAACK,EAAE;QACpB,IAAIT,MAAMU,IAAI;YACZ,IAAI,CAACY,UAAU;gBACbA,WAAW;gBACXD,aAAaX,EAAEb,KAAK;YACtB;QACF,OACE,IAAI;YACF,IAAIN,WAAWmB,IAAI,AAACK,CAAAA,iBAAiB,EAAE,AAAD,EAAGQ,IAAI,CAACd;QAChD,EAAE,OAAOe,GAAG;YACV,IAAI,CAACF,UAAU;gBACbA,WAAW;gBACXD,aAAaG;YACf;QACF;IACJ;IAEA,IAAIF,UAAU;QACZ,IAAIP,iBAAiB,MAAM;YACzB,IAAK,IAAIE,IAAI,GAAGA,IAAIF,aAAaT,MAAM,EAAEW,IAAK;gBAC3Cb,OAAO,CAACW,YAAY,CAACE,EAAE,CAAC,CAAoBQ,IAAI,CAACjC,MAAMA;YAC1D;QACF;QACA,OAAOmB,QAAQC,MAAM,CAACS;IACxB;IACA,IAAIN,iBAAiB,MAAM,OAAOX;IAElC,OAAOS,qBAAqBT,SAA8BW;AAC5D;AAEA,SAASW,UAAatB,OAAgC;IACpD,MAAMC,MAAMD,QAAQE,MAAM;IAC1B,IAAID,QAAQ,GAAG,OAAO,EAAE;IAExB,IAAIU,eAAgC;IACpC,MAAMY,UAAU,IAAInB,MAA6CH;IAEjE,IAAK,IAAII,IAAI,GAAGA,IAAIJ,KAAKI,IAAK;QAC5B,MAAMC,IAAIN,OAAO,CAACK,EAAE;QACpB,IAAIT,MAAMU,IAAI;YACZiB,OAAO,CAAClB,EAAE,GAAG;gBAAEmB,QAAQ;gBAAYC,QAAQnB,EAAEb,KAAK;YAAC;QACrD,OACE,IAAI;YACF,IAAIN,WAAWmB,IAAI;gBACjB,MAAMoB,UAAUpB,EAAEe,IAAI,CACpB,CAACM,QAAyC,CAAA;wBAAEH,QAAQ;wBAAaG;oBAAM,CAAA,GACvE,CAACF,SAA4C,CAAA;wBAAED,QAAQ;wBAAYC;oBAAO,CAAA;gBAE3Ed,CAAAA,iBAAiB,EAAE,AAAD,EAAGQ,IAAI,CAACd;gBAC3BkB,OAAO,CAAClB,EAAE,GAAGqB;YACf,OAAO;gBACLH,OAAO,CAAClB,EAAE,GAAG;oBAAEmB,QAAQ;oBAAaG,OAAOrB;gBAAE;YAC/C;QACF,EAAE,OAAOc,GAAG;YACVG,OAAO,CAAClB,EAAE,GAAG;gBAAEmB,QAAQ;gBAAYC,QAAQL;YAAE;QAC/C;IACJ;IAEA,IAAIT,iBAAiB,MAAM,OAAOY;IAElC,OAAOd,qBAAqBc,SAASZ;AACvC;AAOA,OAAO,MAAMiB;IACX,CAAA,OAAQ,CAA0B;IAEzB,CAACtC,OAAOuC,WAAW,CAAC,GAAG,iBAAiB;IAEjD,YAAY7B,OAAgC,CAAE;QAC5C,IAAI,CAAC,CAAA,OAAQ,GAAGA;IAClB;IAEAqB,KACES,WAAsD,EACtDC,UAAqD,EACnB;QAClC,MAAMjB,WAAW,IAAI,CAACC,GAAG;QACzB,IAAID,oBAAoBP,SAAS,OAAOO,SAASO,IAAI,CAACS,aAAaC;QACnE,OAAOxB,QAAQyB,OAAO,CAAClB,UAAUO,IAAI,CAACS,aAAaC;IACrD;IAKAhB,MAA0B;QACxB,OAAOC,WAAW,IAAI,CAAC,CAAA,OAAQ;IACjC;IAKAO,UAA0E;QACxE,OAAOD,UAAU,IAAI,CAAC,CAAA,OAAQ;IAChC;AACF"}
|
package/build/event.cjs
CHANGED
|
@@ -12,11 +12,8 @@ _export(exports, {
|
|
|
12
12
|
get Event () {
|
|
13
13
|
return Event;
|
|
14
14
|
},
|
|
15
|
-
get
|
|
16
|
-
return
|
|
17
|
-
},
|
|
18
|
-
get Unsubscribe () {
|
|
19
|
-
return Unsubscribe;
|
|
15
|
+
get EventIterator () {
|
|
16
|
+
return EventIterator;
|
|
20
17
|
},
|
|
21
18
|
get createEvent () {
|
|
22
19
|
return createEvent;
|
|
@@ -31,165 +28,133 @@ _export(exports, {
|
|
|
31
28
|
return merge;
|
|
32
29
|
}
|
|
33
30
|
});
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
class
|
|
39
|
-
|
|
40
|
-
constructor(
|
|
41
|
-
|
|
42
|
-
this._done = true;
|
|
43
|
-
await callback();
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
get done() {
|
|
47
|
-
return this._done;
|
|
48
|
-
}
|
|
49
|
-
pre(callback) {
|
|
50
|
-
return new Unsubscribe(async ()=>{
|
|
51
|
-
await callback();
|
|
52
|
-
await this();
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
post(callback) {
|
|
56
|
-
return new Unsubscribe(async ()=>{
|
|
57
|
-
await this();
|
|
58
|
-
await callback();
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
countdown(count) {
|
|
62
|
-
return new Unsubscribe(async ()=>{
|
|
63
|
-
if (!--count) {
|
|
64
|
-
await this();
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
class EventResult {
|
|
70
|
-
#results;
|
|
71
|
-
[Symbol.toStringTag] = 'EventResult';
|
|
72
|
-
constructor(results){
|
|
73
|
-
this.#results = results;
|
|
31
|
+
const _asynccjs = require("./async.cjs");
|
|
32
|
+
const _signalcjs = require("./signal.cjs");
|
|
33
|
+
const _listenerregistrycjs = require("./listener-registry.cjs");
|
|
34
|
+
const _dispatchresultcjs = require("./dispatch-result.cjs");
|
|
35
|
+
class EventIterator {
|
|
36
|
+
#signal;
|
|
37
|
+
constructor(signal){
|
|
38
|
+
this.#signal = signal;
|
|
74
39
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
40
|
+
async next() {
|
|
41
|
+
try {
|
|
42
|
+
const value = await this.#signal.receive();
|
|
43
|
+
return {
|
|
44
|
+
value,
|
|
45
|
+
done: false
|
|
46
|
+
};
|
|
47
|
+
} catch {
|
|
48
|
+
return {
|
|
49
|
+
value: undefined,
|
|
50
|
+
done: true
|
|
51
|
+
};
|
|
52
|
+
}
|
|
80
53
|
}
|
|
81
|
-
|
|
82
|
-
return
|
|
54
|
+
async return() {
|
|
55
|
+
return {
|
|
56
|
+
value: undefined,
|
|
57
|
+
done: true
|
|
58
|
+
};
|
|
83
59
|
}
|
|
84
60
|
}
|
|
85
|
-
class Event
|
|
86
|
-
listeners;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
61
|
+
class Event {
|
|
62
|
+
#listeners = new _listenerregistrycjs.ListenerRegistry();
|
|
63
|
+
#signal = new _signalcjs.Signal();
|
|
64
|
+
#disposer;
|
|
65
|
+
#onDispose;
|
|
66
|
+
#sink;
|
|
90
67
|
[Symbol.toStringTag] = 'Event';
|
|
91
|
-
constructor(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
void this.clear();
|
|
101
|
-
void dispose?.();
|
|
102
|
-
};
|
|
68
|
+
constructor(onDispose){
|
|
69
|
+
this.#onDispose = onDispose;
|
|
70
|
+
this.#disposer = new _asynccjs.Disposer(this);
|
|
71
|
+
}
|
|
72
|
+
get sink() {
|
|
73
|
+
return this.#sink ??= this.emit.bind(this);
|
|
74
|
+
}
|
|
75
|
+
handleEvent(event) {
|
|
76
|
+
this.emit(event);
|
|
103
77
|
}
|
|
104
78
|
get size() {
|
|
105
|
-
return this
|
|
79
|
+
return this.#listeners.size;
|
|
106
80
|
}
|
|
107
|
-
|
|
108
|
-
|
|
81
|
+
emit(value) {
|
|
82
|
+
this.#signal.emit(value);
|
|
83
|
+
return new _dispatchresultcjs.DispatchResult(this.#listeners.dispatch(value));
|
|
109
84
|
}
|
|
110
85
|
lacks(listener) {
|
|
111
|
-
return !this
|
|
86
|
+
return !this.#listeners.has(listener);
|
|
112
87
|
}
|
|
113
88
|
has(listener) {
|
|
114
|
-
return this
|
|
89
|
+
return this.#listeners.has(listener);
|
|
115
90
|
}
|
|
116
91
|
off(listener) {
|
|
117
|
-
|
|
118
|
-
[
|
|
119
|
-
...this.hooks
|
|
120
|
-
].forEach((hook)=>hook(listener, _typescjs.HookType.Remove));
|
|
121
|
-
}
|
|
92
|
+
this.#listeners.off(listener);
|
|
122
93
|
return this;
|
|
123
94
|
}
|
|
124
95
|
on(listener) {
|
|
125
|
-
this
|
|
126
|
-
|
|
127
|
-
[
|
|
128
|
-
...this.hooks
|
|
129
|
-
].forEach((hook)=>hook(listener, _typescjs.HookType.Add));
|
|
130
|
-
}
|
|
131
|
-
return new Unsubscribe(()=>{
|
|
132
|
-
void this.off(listener);
|
|
133
|
-
});
|
|
96
|
+
this.#listeners.on(listener);
|
|
97
|
+
return ()=>void this.off(listener);
|
|
134
98
|
}
|
|
135
99
|
once(listener) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return listener(event);
|
|
139
|
-
};
|
|
140
|
-
return this.on(oneTimeListener);
|
|
100
|
+
this.#listeners.once(listener);
|
|
101
|
+
return ()=>void this.off(listener);
|
|
141
102
|
}
|
|
142
103
|
clear() {
|
|
143
|
-
this
|
|
144
|
-
if (this.hooks.length) {
|
|
145
|
-
[
|
|
146
|
-
...this.hooks
|
|
147
|
-
].forEach((hook)=>hook(undefined, _typescjs.HookType.Remove));
|
|
148
|
-
}
|
|
104
|
+
this.#listeners.clear();
|
|
149
105
|
return this;
|
|
150
106
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
});
|
|
107
|
+
receive() {
|
|
108
|
+
return this.#signal.receive();
|
|
109
|
+
}
|
|
110
|
+
then(onfulfilled, onrejected) {
|
|
111
|
+
return this.receive().then(onfulfilled, onrejected);
|
|
157
112
|
}
|
|
158
|
-
|
|
159
|
-
return
|
|
160
|
-
|
|
161
|
-
|
|
113
|
+
catch(onrejected) {
|
|
114
|
+
return this.receive().catch(onrejected);
|
|
115
|
+
}
|
|
116
|
+
finally(onfinally) {
|
|
117
|
+
return this.receive().finally(onfinally);
|
|
118
|
+
}
|
|
119
|
+
settle() {
|
|
120
|
+
return this.receive().then((value)=>({
|
|
121
|
+
status: 'fulfilled',
|
|
122
|
+
value
|
|
123
|
+
}), (reason)=>({
|
|
124
|
+
status: 'rejected',
|
|
125
|
+
reason
|
|
126
|
+
}));
|
|
162
127
|
}
|
|
163
128
|
[Symbol.asyncIterator]() {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
};
|
|
169
|
-
this.listeners.push(emitEvent);
|
|
170
|
-
const hook = (target = emitEvent, action)=>{
|
|
171
|
-
if (target === emitEvent && action === _typescjs.HookType.Remove) {
|
|
172
|
-
ctrl.abort('done');
|
|
173
|
-
this.listeners.removeFirst(emitEvent);
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
this.hooks.push(hook);
|
|
177
|
-
return sequence[Symbol.asyncIterator]();
|
|
129
|
+
return new EventIterator(this.#signal);
|
|
130
|
+
}
|
|
131
|
+
dispose() {
|
|
132
|
+
this[Symbol.dispose]();
|
|
178
133
|
}
|
|
179
134
|
[Symbol.dispose]() {
|
|
180
|
-
|
|
135
|
+
if (this.#disposer[Symbol.dispose]()) {
|
|
136
|
+
this.#signal[Symbol.dispose]();
|
|
137
|
+
this.#listeners.clear();
|
|
138
|
+
void this.#onDispose?.();
|
|
139
|
+
}
|
|
181
140
|
}
|
|
182
141
|
}
|
|
183
142
|
const merge = (...events)=>{
|
|
184
|
-
const mergedEvent = new Event()
|
|
185
|
-
|
|
143
|
+
const mergedEvent = new Event(()=>{
|
|
144
|
+
for (const event of events){
|
|
145
|
+
event.off(mergedEvent.sink);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
for (const event of events){
|
|
149
|
+
event.on(mergedEvent.sink);
|
|
150
|
+
}
|
|
186
151
|
return mergedEvent;
|
|
187
152
|
};
|
|
188
153
|
const createInterval = (interval)=>{
|
|
189
154
|
let counter = 0;
|
|
190
155
|
const intervalEvent = new Event(()=>clearInterval(timerId));
|
|
191
156
|
const timerId = setInterval(()=>{
|
|
192
|
-
|
|
157
|
+
intervalEvent.emit(counter++);
|
|
193
158
|
}, interval);
|
|
194
159
|
return intervalEvent;
|
|
195
160
|
};
|
package/build/event.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/event.ts"],"sourcesContent":["import { RingBuffer } from 'fastds';\nimport { MaybePromise, Callback, Listener, HookListener, HookType, FilterFunction, Predicate, Mapper, Reducer } from './types.js';\nimport { Callable, CallableAsyncIterator } from './callable.js';\nimport { Sequence } from './sequence.js';\n\n/**\n * Represents an unsubscribe function that can be called to remove a listener.\n * Provides additional utilities for chaining and conditional unsubscription.\n *\n * @internal\n */\nexport class Unsubscribe extends Callable<[], MaybePromise<void>> {\n private _done = false;\n\n constructor(callback: Callback) {\n super(async () => {\n this._done = true;\n await callback();\n });\n }\n\n get done() {\n return this._done;\n }\n\n /**\n * Creates a new unsubscribe function that executes the given callback before this unsubscribe.\n *\n * @param callback - The callback to execute before unsubscribing.\n * @returns {Unsubscribe} A new Unsubscribe instance.\n */\n pre(callback: Callback): Unsubscribe {\n return new Unsubscribe(async () => {\n await callback();\n await this();\n });\n }\n\n /**\n * Creates a new unsubscribe function that executes the given callback after this unsubscribe.\n *\n * @param callback - The callback to execute after unsubscribing.\n * @returns {Unsubscribe} A new Unsubscribe instance.\n */\n post(callback: Callback): Unsubscribe {\n return new Unsubscribe(async () => {\n await this();\n await callback();\n });\n }\n\n /**\n * Creates a new unsubscribe function that only executes after being called a specified number of times.\n *\n * @param count - The number of times this must be called before actually unsubscribing.\n * @returns {Unsubscribe} A new Unsubscribe instance.\n */\n countdown(count: number): Unsubscribe {\n return new Unsubscribe(async () => {\n if (!--count) {\n await this();\n }\n });\n }\n}\n\n/**\n * Wraps an array of values or promises (typically listener results) and provides batch resolution.\n *\n * @template T\n */\nexport class EventResult<T> implements PromiseLike<T[]> {\n #results: MaybePromise<T>[];\n\n readonly [Symbol.toStringTag] = 'EventResult';\n /**\n * @param results - An array of values or Promise-returning listener calls.\n */\n constructor(results: MaybePromise<T>[]) {\n this.#results = results;\n }\n\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T[]) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,\n ): PromiseLike<TResult1 | TResult2> {\n return this.all().then(onfulfilled, onrejected);\n }\n\n /**\n * Resolves all listener results, rejecting if any promise rejects.\n *\n * @returns {Promise<T[]>} A promise that fulfills with an array of all resolved values.\n */\n all(): Promise<T[]> {\n return Promise.all(this.#results);\n }\n /**\n * Waits for all listener results to settle, regardless of fulfillment or rejection.\n *\n * @returns {Promise<PromiseSettledResult<T>[]>} A promise that fulfills with an array of each result's settled status and value/reason.\n */\n settled(): Promise<PromiseSettledResult<T>[]> {\n return Promise.allSettled(this.#results);\n }\n}\n\n/**\n * A class representing a multi-listener event emitter with async support.\n * Events allow multiple listeners to react to emitted values, with each listener\n * potentially returning a result. All listeners are called for each emission.\n *\n * Key characteristics:\n * - Multiple listeners - all are called for each emission\n * - Listeners can return values collected in EventResult\n * - Supports async listeners and async iteration\n * - Provides lifecycle hooks for listener management\n * - Memory efficient using RingBuffer for storage\n *\n * Differs from:\n * - Signal: Events have multiple persistent listeners vs Signal's one-time resolution per consumer\n * - Sequence: Events broadcast to all listeners vs Sequence's single consumer queue\n *\n * @template T - The type of value emitted to listeners (event payload)\n * @template R - The return type of listener functions\n */\nexport class Event<T = unknown, R = unknown> extends CallableAsyncIterator<T, EventResult<void | R>> {\n /**\n * The ring buffer containing all registered listeners for the event.\n */\n private listeners: RingBuffer<Listener<T, R>>;\n\n /**\n * The ring buffer containing hook listeners that respond to listener lifecycle events.\n */\n private hooks = new RingBuffer<HookListener<T, R>>();\n\n /**\n * Flag indicating whether this event has been disposed.\n */\n private _disposed = false;\n\n /**\n * A function that disposes of the event and its listeners.\n */\n readonly dispose: Callback;\n\n readonly [Symbol.toStringTag] = 'Event';\n /**\n * Creates a new event.\n *\n * @param dispose - A function to call on the event disposal.\n *\n * ```typescript\n * // Create a click event.\n * const clickEvent = new Event<[x: number, y: number], void>();\n * clickEvent.on(([x, y]) => console.log(`Clicked at ${x}, ${y}`));\n * ```\n */\n constructor(dispose?: Callback) {\n const listeners = new RingBuffer<Listener<T, R>>();\n super((value: T): EventResult<void | R> => {\n const results = listeners.toArray().map(async (listener) => listener(await value));\n return new EventResult(results);\n });\n\n this.listeners = listeners;\n\n this.dispose = () => {\n this._disposed = true;\n void this.clear();\n void dispose?.();\n };\n }\n\n /**\n * The number of listeners for the event.\n *\n * @readonly\n * @type {number}\n */\n get size(): number {\n return this.listeners.length;\n }\n\n /**\n * Checks if the event has been disposed.\n *\n * @returns {boolean} `true` if the event has been disposed; otherwise, `false`.\n */\n get disposed(): boolean {\n return this._disposed;\n }\n\n /**\n * Checks if the given listener is NOT registered for this event.\n *\n * @param listener - The listener function to check against the registered listeners.\n * @returns {boolean} `true` if the listener is not already registered; otherwise, `false`.\n *\n * ```typescript\n * // Check if a listener is not already added\n * if (event.lacks(myListener)) {\n * event.on(myListener);\n * }\n * ```\n */\n lacks(listener: Listener<T, R>): boolean {\n return !this.listeners.has(listener);\n }\n\n /**\n * Checks if the given listener is registered for this event.\n *\n * @param listener - The listener function to check.\n * @returns {boolean} `true` if the listener is currently registered; otherwise, `false`.\n *\n * ```typescript\n * // Verify if a listener is registered\n * if (event.has(myListener)) {\n * console.log('Listener is already registered');\n * }\n * ```\n */\n has(listener: Listener<T, R>): boolean {\n return this.listeners.has(listener);\n }\n\n /**\n * Removes a specific listener from this event.\n *\n * @param listener - The listener to remove.\n * @returns {this} The event instance, allowing for method chaining.\n *\n * ```typescript\n * // Remove a listener\n * event.off(myListener);\n * ```\n */\n off(listener: Listener<T, R>): this {\n if (this.listeners.compact((l) => l !== listener) && this.hooks.length) {\n [...this.hooks].forEach((hook) => hook(listener, HookType.Remove));\n }\n return this;\n }\n\n /**\n * Registers a listener that gets triggered whenever the event is emitted.\n * This is the primary method for adding event handlers that will react to the event being triggered.\n *\n * @param listener - The function to call when the event occurs.\n * @returns {Unsubscribe} An object that can be used to unsubscribe the listener, ensuring easy cleanup.\n *\n * ```typescript\n * // Add a listener to an event\n * const unsubscribe = event.on((data) => {\n * console.log('Event data:', data);\n * });\n * ```\n */\n on(listener: Listener<T, R>): Unsubscribe {\n this.listeners.push(listener);\n if (this.hooks.length) {\n [...this.hooks].forEach((hook) => hook(listener, HookType.Add));\n }\n return new Unsubscribe(() => {\n void this.off(listener);\n });\n }\n\n /**\n * Adds a listener that will be called only once the next time the event is emitted.\n * This method is useful for one-time notifications or single-trigger scenarios.\n *\n * @param listener - The listener to trigger once.\n * @returns {Unsubscribe} An object that can be used to remove the listener if the event has not yet occurred.\n *\n * ```typescript\n * // Register a one-time listener\n * const onceUnsubscribe = event.once((data) => {\n * console.log('Received data once:', data);\n * });\n * ```\n */\n once(listener: Listener<T, R>): Unsubscribe {\n const oneTimeListener = (event: T) => {\n void this.off(oneTimeListener);\n return listener(event);\n };\n return this.on(oneTimeListener);\n }\n\n /**\n * Removes all listeners from the event, effectively resetting it. This is useful when you need to\n * cleanly dispose of all event handlers to prevent memory leaks or unwanted triggers after certain conditions.\n *\n * @returns {this} The instance of the event, allowing for method chaining.\n *\n * ```typescript\n * const myEvent = new Event();\n * myEvent.on(data => console.log(data));\n * myEvent.clear(); // Clears all listeners\n * ```\n */\n clear(): this {\n this.listeners.clear();\n if (this.hooks.length) {\n [...this.hooks].forEach((hook) => hook(undefined, HookType.Remove));\n }\n return this;\n }\n\n /**\n * Waits for the next event emission and returns the emitted value.\n * This method allows the event to be used as a promise that resolves with the next emitted value.\n *\n * @returns {Promise<T>} A promise that resolves with the next emitted event value.\n */\n async next(): Promise<T> {\n const { promise, resolve } = Promise.withResolvers<T>();\n this.listeners.push(resolve);\n\n return promise.finally(() => {\n this.listeners.removeFirst(resolve);\n });\n }\n\n /**\n * Waits for the event to settle, returning a `PromiseSettledResult`.\n *\n * @returns {Promise<PromiseSettledResult<T>>} A promise that resolves with the settled result.\n *\n * @example\n * ```typescript\n * const result = await event.settle();\n * if (result.status === 'fulfilled') {\n * console.log('Event fulfilled with value:', result.value);\n * } else {\n * console.error('Event rejected with reason:', result.reason);\n * }\n * ```\n */\n async settle(): Promise<PromiseSettledResult<T>> {\n return await Promise.allSettled([this.next()]).then(([settled]) => settled);\n }\n\n /**\n * Makes this event iterable using `for await...of` loops.\n *\n * @returns {AsyncIterator<T>} An async iterator that yields values as they are emitted by this event.\n *\n * ```typescript\n * // Assuming an event that emits numbers\n * const numberEvent = new Event<number>();\n * (async () => {\n * for await (const num of numberEvent) {\n * console.log('Number:', num);\n * }\n * })();\n * await numberEvent(1);\n * await numberEvent(2);\n * await numberEvent(3);\n * ```\n */\n [Symbol.asyncIterator](): AsyncIterator<T> {\n const ctrl = new AbortController();\n const sequence = new Sequence<T>(ctrl.signal);\n const emitEvent = (value: T) => {\n sequence(value);\n };\n this.listeners.push(emitEvent);\n const hook: HookListener<T, R> = (target = emitEvent, action) => {\n if (target === emitEvent && action === HookType.Remove) {\n ctrl.abort('done');\n this.listeners.removeFirst(emitEvent);\n }\n };\n this.hooks.push(hook);\n return sequence[Symbol.asyncIterator]();\n }\n\n [Symbol.dispose](): void {\n void this.dispose();\n }\n}\n\nexport type EventParameters<T> = T extends Event<infer P, any> ? P : never;\n\nexport type EventReturn<T> = T extends Event<any, infer R> ? R : never;\n\nexport type AllEventsParameters<T extends Event<any, any>[]> = { [K in keyof T]: EventParameters<T[K]> }[number];\n\nexport type AllEventsResults<T extends Event<any, any>[]> = { [K in keyof T]: EventReturn<T[K]> }[number];\n\n/**\n * Merges multiple events into a single event. This function takes any number of `Event` instances\n * and returns a new `Event` that triggers whenever any of the input events trigger. The parameters\n * and results of the merged event are derived from the input events, providing a flexible way to\n * handle multiple sources of events in a unified manner.\n *\n * @template Events - An array of `Event` instances.\n * @param events - A rest parameter that takes multiple events to be merged.\n * @returns {Event<AllEventsParameters<Events>, AllEventsResults<Events>>} Returns a new `Event` instance\n * that triggers with the parameters and results of any of the merged input events.\n *\n * ```typescript\n * // Merging mouse and keyboard events into a single event\n * const mouseEvent = createEvent<MouseEvent>();\n * const keyboardEvent = createEvent<KeyboardEvent>();\n * const inputEvent = merge(mouseEvent, keyboardEvent);\n * inputEvent.on(event => console.log('Input event:', event));\n * ```\n */\nexport const merge = <Events extends Event<any, any>[]>(...events: Events): Event<AllEventsParameters<Events>, AllEventsResults<Events>> => {\n const mergedEvent = new Event<AllEventsParameters<Events>, AllEventsResults<Events>>();\n events.forEach((event) => event.on(mergedEvent));\n return mergedEvent;\n};\n\n/**\n * Creates a periodic event that triggers at a specified interval. The event will automatically emit\n * an incrementing counter value each time it triggers, starting from zero. This function is useful\n * for creating time-based triggers within an application, such as updating UI elements, polling,\n * or any other timed operation.\n *\n * @template R - The return type of the event handler function, defaulting to `void`.\n * @param interval - The interval in milliseconds at which the event should trigger.\n * @returns {Event<number, R>} An `Event` instance that triggers at the specified interval,\n * emitting an incrementing counter value.\n *\n * ```typescript\n * // Creating an interval event that logs a message every second\n * const tickEvent = createInterval(1000);\n * tickEvent.on(tickNumber => console.log('Tick:', tickNumber));\n * ```\n */\nexport const createInterval = <R = unknown>(interval: number): Event<number, R> => {\n let counter = 0;\n const intervalEvent = new Event<number, R>(() => clearInterval(timerId));\n const timerId: ReturnType<typeof setInterval> = setInterval(() => {\n void intervalEvent(counter++);\n }, interval);\n return intervalEvent;\n};\n\n/**\n * Creates a new Event instance for multi-listener event handling.\n * This is the primary way to create events in the library.\n *\n * @template T - The type of value emitted to listeners (event payload)\n * @template R - The return type of listener functions (collected in EventResult)\n * @returns {Event<T, R>} A new Event instance ready for listener registration\n *\n * ```typescript\n * // Create an event that accepts a string payload\n * const messageEvent = createEvent<string>();\n * messageEvent.on(msg => console.log('Received:', msg));\n * messageEvent('Hello'); // All listeners receive 'Hello'\n *\n * // Create an event where listeners return values\n * const validateEvent = createEvent<string, boolean>();\n * validateEvent.on(str => str.length > 0);\n * validateEvent.on(str => str.length < 100);\n * const results = await validateEvent('test'); // EventResult with [true, true]\n * ```\n */\nexport const createEvent = <T = unknown, R = unknown>(): Event<T, R> => new Event<T, R>();\n\nexport default createEvent;\n\n/**\n * Extracts the listener function type from an Event type.\n * Useful for type-safe listener definitions.\n *\n * @template E - The Event type to extract the listener type from\n *\n * @example\n * ```typescript\n * type MyEvent = Event<string, boolean>;\n * type MyListener = EventHandler<MyEvent>; // (value: string) => boolean | Promise<boolean>\n * ```\n */\nexport type EventHandler<E> = E extends Event<infer T, infer R> ? Listener<T, R> : never;\n\n/**\n * Extracts a filter function type for an Event's parameters.\n * Used for creating type-safe event filters.\n *\n * @template E - The Event type to create a filter for\n */\nexport type EventFilter<E> = FilterFunction<EventParameters<E>>;\n\n/**\n * Extracts a predicate function type for an Event's parameters.\n * Used for type narrowing with event values.\n *\n * @template E - The Event type to create a predicate for\n * @template P - The narrowed type that the predicate validates\n */\nexport type EventPredicate<E, P extends EventParameters<E>> = Predicate<EventParameters<E>, P>;\n\n/**\n * Extracts a mapper function type for transforming Event parameters.\n * Used for creating type-safe event value transformations.\n *\n * @template E - The Event type to create a mapper for\n * @template M - The target type to map event values to\n */\nexport type EventMapper<E, M> = Mapper<EventParameters<E>, M>;\n\n/**\n * Extracts a reducer function type for Event parameters.\n * Used for creating type-safe event value reducers.\n *\n * @template E - The Event type to create a reducer for\n * @template R - The accumulator type for the reduction\n */\nexport type EventReducer<E, R> = Reducer<EventParameters<E>, R>;\n"],"names":["Event","EventResult","Unsubscribe","createEvent","createInterval","merge","Callable","_done","callback","done","pre","post","countdown","count","Symbol","toStringTag","results","then","onfulfilled","onrejected","all","Promise","settled","allSettled","CallableAsyncIterator","listeners","hooks","RingBuffer","_disposed","dispose","value","toArray","map","listener","clear","size","length","disposed","lacks","has","off","compact","l","forEach","hook","HookType","Remove","on","push","Add","once","oneTimeListener","event","undefined","next","promise","resolve","withResolvers","finally","removeFirst","settle","asyncIterator","ctrl","AbortController","sequence","Sequence","signal","emitEvent","target","action","abort","events","mergedEvent","interval","counter","intervalEvent","clearInterval","timerId","setInterval"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/event.ts"],"sourcesContent":["import { Callback, Listener, FilterFunction, Predicate, Mapper, Reducer, Action, Fn, Emitter, MaybePromise, Promiseable } from './types.js';\nimport { Disposer } from './async.js';\nimport { Signal } from './signal.js';\nimport { ListenerRegistry } from './listener-registry.js';\nimport { DispatchResult } from './dispatch-result.js';\n\nexport type Unsubscribe = Action;\n\n/**\n * @internal\n */\nexport class EventIterator<T> implements AsyncIterator<T, void, void> {\n #signal: Signal<T>;\n\n constructor(signal: Signal<T>) {\n this.#signal = signal;\n }\n\n async next(): Promise<IteratorResult<T, void>> {\n try {\n const value = await this.#signal.receive();\n return { value, done: false };\n } catch {\n return { value: undefined, done: true };\n }\n }\n\n async return(): Promise<IteratorResult<T, void>> {\n return { value: undefined, done: true };\n }\n}\n\n/**\n * Multi-listener event emitter with async support.\n * All registered listeners are called for each emission, and their return\n * values are collected in a DispatchResult. Supports async iteration and\n * an `onDispose` callback for cleanup.\n *\n * Differs from:\n * - Signal: Event has persistent listeners; Signal is promise-based (receive per round)\n * - Sequence: Event broadcasts to all listeners; Sequence is a single-consumer queue\n *\n * @template T - The type of value emitted to listeners (event payload)\n * @template R - The return type of listener functions\n */\nexport class Event<T = unknown, R = unknown> implements Emitter<T, DispatchResult<void | R>>, Promiseable<T>, Promise<T>, Disposable, AsyncIterable<T> {\n #listeners = new ListenerRegistry<[T], R | void>();\n #signal = new Signal<T>();\n #disposer: Disposer;\n #onDispose?: Callback;\n #sink?: Fn<[T], DispatchResult<void | R>>;\n\n readonly [Symbol.toStringTag] = 'Event';\n\n /**\n * Creates a new event.\n *\n * @param onDispose - A function to call on the event disposal.\n *\n * @example\n * ```typescript\n * // Create a click event.\n * const clickEvent = new Event<[x: number, y: number], void>();\n * clickEvent.on(([x, y]) => console.log(`Clicked at ${x}, ${y}`));\n * clickEvent.emit([10, 20]);\n * ```\n */\n constructor(onDispose?: Callback) {\n this.#onDispose = onDispose;\n this.#disposer = new Disposer(this);\n }\n\n /**\n * Returns a bound emit function for use as a callback.\n * Useful for passing to other APIs that expect a function.\n *\n * @example\n * ```typescript\n * const event = new Event<string>();\n * someApi.onMessage(event.sink);\n * ```\n */\n get sink(): Fn<[T], DispatchResult<void | R>> {\n return (this.#sink ??= this.emit.bind(this));\n }\n\n /**\n * DOM EventListener interface compatibility.\n * Allows the event to be used directly with addEventListener.\n */\n handleEvent(event: T): void {\n this.emit(event);\n }\n\n /**\n * The number of listeners for the event.\n */\n get size(): number {\n return this.#listeners.size;\n }\n\n /**\n * Emits a value to all registered listeners.\n * Each listener is called with the value and their return values are collected.\n *\n * @param value - The value to emit to all listeners.\n * @returns A DispatchResult containing all listener return values.\n *\n * @example\n * ```typescript\n * const event = new Event<string, number>();\n * event.on(str => str.length);\n * const result = event.emit('hello');\n * await result.all(); // [5]\n * ```\n */\n emit(value: T): DispatchResult<void | R> {\n this.#signal.emit(value);\n return new DispatchResult(this.#listeners.dispatch(value));\n }\n\n /**\n * Checks if the given listener is NOT registered for this event.\n *\n * @param listener - The listener function to check against the registered listeners.\n * @returns `true` if the listener is not already registered; otherwise, `false`.\n *\n * @example\n * ```typescript\n * // Check if a listener is not already added\n * if (event.lacks(myListener)) {\n * event.on(myListener);\n * }\n * ```\n */\n lacks(listener: Listener<T, R>): boolean {\n return !this.#listeners.has(listener);\n }\n\n /**\n * Checks if the given listener is registered for this event.\n *\n * @param listener - The listener function to check.\n * @returns `true` if the listener is currently registered; otherwise, `false`.\n *\n * @example\n * ```typescript\n * // Verify if a listener is registered\n * if (event.has(myListener)) {\n * console.log('Listener is already registered');\n * }\n * ```\n */\n has(listener: Listener<T, R>): boolean {\n return this.#listeners.has(listener);\n }\n\n /**\n * Removes a specific listener from this event.\n *\n * @param listener - The listener to remove.\n * @returns The event instance for chaining.\n *\n * @example\n * ```typescript\n * // Remove a listener\n * event.off(myListener);\n * ```\n */\n off(listener: Listener<T, R>): this {\n this.#listeners.off(listener);\n return this;\n }\n\n /**\n * Registers a listener that is called on every emission.\n *\n * @param listener - The function to call when the event occurs.\n * @returns A function that removes this listener when called.\n *\n * @example\n * ```typescript\n * const unsubscribe = event.on((data) => {\n * console.log('Event data:', data);\n * });\n * ```\n */\n on(listener: Listener<T, R>): Unsubscribe {\n this.#listeners.on(listener);\n return () => void this.off(listener);\n }\n\n /**\n * Registers a listener that is called only once on the next emission, then auto-removed.\n *\n * @param listener - The listener to trigger once.\n * @returns A function that removes this listener when called (if it hasn't fired yet).\n *\n * @example\n * ```typescript\n * const cancel = event.once((data) => {\n * console.log('Received data once:', data);\n * });\n * ```\n */\n once(listener: Listener<T, R>): Unsubscribe {\n this.#listeners.once(listener);\n return () => void this.off(listener);\n }\n\n /**\n * Removes all listeners from the event.\n * Does not dispose the event - new listeners can still be added after clearing.\n *\n * @returns The event instance for chaining.\n */\n clear(): this {\n this.#listeners.clear();\n return this;\n }\n\n /**\n * Waits for the next emission and returns the emitted value.\n *\n * @returns A promise that resolves with the next emitted value.\n */\n receive(): Promise<T> {\n return this.#signal.receive();\n }\n\n then<OK = T, ERR = never>(onfulfilled?: Fn<[T], MaybePromise<OK>> | null, onrejected?: Fn<[unknown], MaybePromise<ERR>> | null): Promise<OK | ERR> {\n return this.receive().then(onfulfilled, onrejected);\n }\n\n catch<ERR = never>(onrejected?: Fn<[unknown], MaybePromise<ERR>> | null): Promise<T | ERR> {\n return this.receive().catch(onrejected);\n }\n\n finally(onfinally?: Action | null): Promise<T> {\n return this.receive().finally(onfinally);\n }\n\n /**\n * Waits for the next emission via `receive()` and wraps the outcome in a\n * `PromiseSettledResult` - always resolves, never rejects.\n *\n * @returns A promise that resolves with the settled result.\n *\n * @example\n * ```typescript\n * const result = await event.settle();\n * if (result.status === 'fulfilled') {\n * console.log('Value:', result.value);\n * } else {\n * console.error('Reason:', result.reason);\n * }\n * ```\n */\n settle(): Promise<PromiseSettledResult<T>> {\n return this.receive().then(\n (value) => ({ status: 'fulfilled', value }) as const,\n (reason: unknown) => ({ status: 'rejected', reason }) as const,\n );\n }\n\n [Symbol.asyncIterator](): AsyncIterator<T, void, void> {\n return new EventIterator(this.#signal);\n }\n\n dispose(): void {\n this[Symbol.dispose]();\n }\n\n [Symbol.dispose](): void {\n if (this.#disposer[Symbol.dispose]()) {\n this.#signal[Symbol.dispose]();\n this.#listeners.clear();\n void this.#onDispose?.();\n }\n }\n}\n\nexport type EventParameters<T> = T extends Event<infer P, any> ? P : never;\n\nexport type EventReturn<T> = T extends Event<any, infer R> ? R : never;\n\nexport type AllEventsParameters<T extends Event<any, any>[]> = { [K in keyof T]: EventParameters<T[K]> }[number];\n\nexport type AllEventsResults<T extends Event<any, any>[]> = { [K in keyof T]: EventReturn<T[K]> }[number];\n\n/**\n * Merges multiple events into a single event that triggers whenever any source triggers.\n * Disposing the merged event unsubscribes from all sources.\n *\n * @param events - The events to merge.\n * @returns A new Event that forwards emissions from all sources.\n *\n * @example\n * ```typescript\n * const mouseEvent = createEvent<MouseEvent>();\n * const keyboardEvent = createEvent<KeyboardEvent>();\n * const inputEvent = merge(mouseEvent, keyboardEvent);\n * inputEvent.on(event => console.log('Input event:', event));\n * ```\n */\nexport const merge = <Events extends Event<any, any>[]>(...events: Events): Event<AllEventsParameters<Events>, AllEventsResults<Events>> => {\n const mergedEvent = new Event<AllEventsParameters<Events>, AllEventsResults<Events>>(() => {\n for (const event of events) {\n event.off(mergedEvent.sink);\n }\n });\n\n for (const event of events) {\n event.on(mergedEvent.sink);\n }\n return mergedEvent;\n};\n\n/**\n * Creates a periodic event that emits an incrementing counter (starting from 0) at a fixed interval.\n * Disposing the event clears the interval.\n *\n * @param interval - The interval in milliseconds.\n * @returns An Event that triggers at the specified interval.\n *\n * @example\n * ```typescript\n * const tickEvent = createInterval(1000);\n * tickEvent.on(tickNumber => console.log('Tick:', tickNumber));\n * ```\n */\nexport const createInterval = <R = unknown>(interval: number): Event<number, R> => {\n let counter = 0;\n const intervalEvent = new Event<number, R>(() => clearInterval(timerId));\n const timerId: ReturnType<typeof setInterval> = setInterval(() => {\n intervalEvent.emit(counter++);\n }, interval);\n return intervalEvent;\n};\n\n/**\n * Creates a new Event instance for multi-listener event handling.\n *\n * @example\n * ```typescript\n * const messageEvent = createEvent<string>();\n * messageEvent.on(msg => console.log('Received:', msg));\n * messageEvent.emit('Hello'); // All listeners receive 'Hello'\n *\n * // Listeners can return values, collected via DispatchResult\n * const validateEvent = createEvent<string, boolean>();\n * validateEvent.on(str => str.length > 0);\n * validateEvent.on(str => str.length < 100);\n * const results = await validateEvent.emit('test').all(); // [true, true]\n * ```\n */\nexport const createEvent = <T = unknown, R = unknown>(): Event<T, R> => new Event<T, R>();\n\nexport default createEvent;\n\n/**\n * Extracts the listener function type from an Event type.\n * Useful for type-safe listener definitions.\n *\n * @template E - The Event type to extract the listener type from\n *\n * @example\n * ```typescript\n * type MyEvent = Event<string, boolean>;\n * type MyListener = EventHandler<MyEvent>; // (value: string) => boolean | Promise<boolean>\n * ```\n */\nexport type EventHandler<E> = E extends Event<infer T, infer R> ? Listener<T, R> : never;\n\n/**\n * Extracts a filter function type for an Event's parameters.\n * Used for creating type-safe event filters.\n *\n * @template E - The Event type to create a filter for\n */\nexport type EventFilter<E> = FilterFunction<EventParameters<E>>;\n\n/**\n * Extracts a predicate function type for an Event's parameters.\n * Used for type narrowing with event values.\n *\n * @template E - The Event type to create a predicate for\n * @template P - The narrowed type that the predicate validates\n */\nexport type EventPredicate<E, P extends EventParameters<E>> = Predicate<EventParameters<E>, P>;\n\n/**\n * Extracts a mapper function type for transforming Event parameters.\n * Used for creating type-safe event value transformations.\n *\n * @template E - The Event type to create a mapper for\n * @template M - The target type to map event values to\n */\nexport type EventMapper<E, M> = Mapper<EventParameters<E>, M>;\n\n/**\n * Extracts a reducer function type for Event parameters.\n * Used for creating type-safe event value reducers.\n *\n * @template E - The Event type to create a reducer for\n * @template R - The accumulator type for the reduction\n */\nexport type EventReducer<E, R> = Reducer<EventParameters<E>, R>;\n"],"names":["Event","EventIterator","createEvent","createInterval","merge","signal","next","value","receive","done","undefined","return","ListenerRegistry","Signal","Symbol","toStringTag","onDispose","Disposer","sink","emit","bind","handleEvent","event","size","DispatchResult","dispatch","lacks","listener","has","off","on","once","clear","then","onfulfilled","onrejected","catch","finally","onfinally","settle","status","reason","asyncIterator","dispose","events","mergedEvent","interval","counter","intervalEvent","clearInterval","timerId","setInterval"],"mappings":"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"}
|