@byloth/core 2.0.0-rc.1 → 2.0.0-rc.10

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.
Files changed (43) hide show
  1. package/dist/core.js +1379 -894
  2. package/dist/core.js.map +1 -1
  3. package/dist/core.umd.cjs +3 -3
  4. package/dist/core.umd.cjs.map +1 -1
  5. package/package.json +8 -10
  6. package/src/helpers.ts +7 -0
  7. package/src/index.ts +19 -14
  8. package/src/models/aggregators/aggregated-async-iterator.ts +129 -81
  9. package/src/models/aggregators/aggregated-iterator.ts +128 -82
  10. package/src/models/aggregators/index.ts +1 -3
  11. package/src/models/aggregators/reduced-iterator.ts +118 -30
  12. package/src/models/aggregators/types.ts +15 -10
  13. package/src/models/callbacks/callable-object.ts +23 -0
  14. package/src/models/callbacks/index.ts +5 -0
  15. package/src/models/callbacks/publisher.ts +45 -0
  16. package/src/models/callbacks/switchable-callback.ts +108 -0
  17. package/src/models/callbacks/types.ts +1 -0
  18. package/src/models/exceptions/core.ts +3 -3
  19. package/src/models/exceptions/index.ts +13 -13
  20. package/src/models/game-loop.ts +9 -9
  21. package/src/models/index.ts +3 -6
  22. package/src/models/iterators/smart-async-iterator.ts +109 -23
  23. package/src/models/iterators/smart-iterator.ts +105 -12
  24. package/src/models/iterators/types.ts +17 -7
  25. package/src/models/json/json-storage.ts +2 -3
  26. package/src/models/json/types.ts +3 -1
  27. package/src/models/promises/deferred-promise.ts +1 -1
  28. package/src/models/promises/index.ts +3 -1
  29. package/src/models/promises/long-running-task.ts +294 -0
  30. package/src/models/promises/smart-promise.ts +6 -1
  31. package/src/models/promises/thenable.ts +97 -0
  32. package/src/models/promises/timed-promise.ts +1 -1
  33. package/src/models/promises/types.ts +2 -0
  34. package/src/models/timers/clock.ts +29 -7
  35. package/src/models/timers/countdown.ts +56 -20
  36. package/src/models/types.ts +12 -10
  37. package/src/utils/async.ts +9 -4
  38. package/src/utils/date.ts +3 -0
  39. package/src/utils/index.ts +1 -1
  40. package/src/utils/random.ts +4 -3
  41. package/src/models/aggregators/aggregator.ts +0 -46
  42. package/src/models/aggregators/async-aggregator.ts +0 -56
  43. package/src/models/publisher.ts +0 -39
@@ -1,8 +1,8 @@
1
1
  import { SmartIterator } from "../iterators/index.js";
2
- import type { GeneratorFunction } from "../iterators/types.js";
2
+ import type { GeneratorFunction, IteratorLike } from "../iterators/types.js";
3
3
 
4
4
  import ReducedIterator from "./reduced-iterator.js";
5
- import type { KeyIteratee, KeyTypeGuardIteratee, KeyReducer } from "./types.js";
5
+ import type { KeyedIteratee, KeyedTypeGuardIteratee, KeyedReducer } from "./types.js";
6
6
 
7
7
  export default class AggregatedIterator<K extends PropertyKey, T>
8
8
  {
@@ -11,58 +11,52 @@ export default class AggregatedIterator<K extends PropertyKey, T>
11
11
  public constructor(iterable: Iterable<[K, T]>);
12
12
  public constructor(iterator: Iterator<[K, T]>);
13
13
  public constructor(generatorFn: GeneratorFunction<[K, T]>);
14
- public constructor(argument: Iterable<[K, T]> | Iterator<[K, T]> | GeneratorFunction<[K, T]>);
15
- public constructor(argument: Iterable<[K, T]> | Iterator<[K, T]> | GeneratorFunction<[K, T]>)
14
+ public constructor(argument: IteratorLike<[K, T]> | GeneratorFunction<[K, T]>);
15
+ public constructor(argument: IteratorLike<[K, T]> | GeneratorFunction<[K, T]>)
16
16
  {
17
17
  this._elements = new SmartIterator(argument);
18
18
  }
19
19
 
20
- public every(predicate: KeyIteratee<K, T, boolean>): ReducedIterator<K, boolean>
20
+ public every(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, boolean>
21
21
  {
22
- const indexes = new Map<K, [number, boolean]>();
22
+ const values = new Map<K, [number, boolean]>();
23
23
 
24
24
  for (const [key, element] of this._elements)
25
25
  {
26
- const [index, result] = indexes.get(key) ?? [0, true];
26
+ const [index, result] = values.get(key) ?? [0, true];
27
27
 
28
28
  if (!(result)) { continue; }
29
29
 
30
- indexes.set(key, [index + 1, predicate(key, element, index)]);
30
+ values.set(key, [index + 1, predicate(key, element, index)]);
31
31
  }
32
32
 
33
33
  return new ReducedIterator(function* ()
34
34
  {
35
- for (const [key, [_, result]] of indexes)
36
- {
37
- yield [key, result];
38
- }
35
+ for (const [key, [_, result]] of values) { yield [key, result]; }
39
36
  });
40
37
  }
41
- public some(predicate: KeyIteratee<K, T, boolean>): ReducedIterator<K, boolean>
38
+ public some(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, boolean>
42
39
  {
43
- const indexes = new Map<K, [number, boolean]>();
40
+ const values = new Map<K, [number, boolean]>();
44
41
 
45
42
  for (const [key, element] of this._elements)
46
43
  {
47
- const [index, result] = indexes.get(key) ?? [0, false];
44
+ const [index, result] = values.get(key) ?? [0, false];
48
45
 
49
46
  if (result) { continue; }
50
47
 
51
- indexes.set(key, [index + 1, predicate(key, element, index)]);
48
+ values.set(key, [index + 1, predicate(key, element, index)]);
52
49
  }
53
50
 
54
51
  return new ReducedIterator(function* ()
55
52
  {
56
- for (const [key, [_, result]] of indexes)
57
- {
58
- yield [key, result];
59
- }
53
+ for (const [key, [_, result]] of values) { yield [key, result]; }
60
54
  });
61
55
  }
62
56
 
63
- public filter(predicate: KeyIteratee<K, T, boolean>): AggregatedIterator<K, T>;
64
- public filter<S extends T>(predicate: KeyTypeGuardIteratee<K, T, S>): AggregatedIterator<K, S>;
65
- public filter(predicate: KeyIteratee<K, T, boolean>): AggregatedIterator<K, T>
57
+ public filter(predicate: KeyedIteratee<K, T, boolean>): AggregatedIterator<K, T>;
58
+ public filter<S extends T>(predicate: KeyedTypeGuardIteratee<K, T, S>): AggregatedIterator<K, S>;
59
+ public filter(predicate: KeyedIteratee<K, T, boolean>): AggregatedIterator<K, T>
66
60
  {
67
61
  const elements = this._elements;
68
62
 
@@ -74,13 +68,13 @@ export default class AggregatedIterator<K extends PropertyKey, T>
74
68
  {
75
69
  const index = indexes.get(key) ?? 0;
76
70
 
77
- indexes.set(key, index + 1);
78
-
79
71
  if (predicate(key, element, index)) { yield [key, element]; }
72
+
73
+ indexes.set(key, index + 1);
80
74
  }
81
75
  });
82
76
  }
83
- public map<V>(iteratee: KeyIteratee<K, T, V>): AggregatedIterator<K, V>
77
+ public map<V>(iteratee: KeyedIteratee<K, T, V>): AggregatedIterator<K, V>
84
78
  {
85
79
  const elements = this._elements;
86
80
 
@@ -92,29 +86,24 @@ export default class AggregatedIterator<K extends PropertyKey, T>
92
86
  {
93
87
  const index = indexes.get(key) ?? 0;
94
88
 
95
- indexes.set(key, index + 1);
96
-
97
89
  yield [key, iteratee(key, element, index)];
90
+
91
+ indexes.set(key, index + 1);
98
92
  }
99
93
  });
100
94
  }
101
- public reduce(reducer: KeyReducer<K, T, T>): ReducedIterator<K, T>;
102
- public reduce<A>(reducer: KeyReducer<K, T, A>, initialValue: (key: K) => A): ReducedIterator<K, A>;
103
- public reduce<A>(reducer: KeyReducer<K, T, A>, initialValue?: (key: K) => A): ReducedIterator<K, A>
95
+ public reduce(reducer: KeyedReducer<K, T, T>): ReducedIterator<K, T>;
96
+ public reduce<A>(reducer: KeyedReducer<K, T, A>, initialValue: (key: K) => A): ReducedIterator<K, A>;
97
+ public reduce<A>(reducer: KeyedReducer<K, T, A>, initialValue?: (key: K) => A): ReducedIterator<K, A>
104
98
  {
105
- const accumulators = new Map<K, [number, A]>();
99
+ const values = new Map<K, [number, A]>();
106
100
 
107
101
  for (const [key, element] of this._elements)
108
102
  {
109
103
  let index: number;
110
104
  let accumulator: A;
111
105
 
112
- if (accumulators.has(key))
113
- {
114
- [index, accumulator] = accumulators.get(key)!;
115
-
116
- index += 1;
117
- }
106
+ if (values.has(key)) { [index, accumulator] = values.get(key)!; }
118
107
  else if (initialValue !== undefined)
119
108
  {
120
109
  index = 0;
@@ -122,103 +111,161 @@ export default class AggregatedIterator<K extends PropertyKey, T>
122
111
  }
123
112
  else
124
113
  {
125
- accumulators.set(key, [0, (element as unknown) as A]);
114
+ values.set(key, [0, (element as unknown) as A]);
126
115
 
127
116
  continue;
128
117
  }
129
118
 
130
- accumulator = reducer(key, accumulator, element, index);
131
-
132
- accumulators.set(key, [index, accumulator]);
119
+ values.set(key, [index + 1, reducer(key, accumulator, element, index)]);
133
120
  }
134
121
 
135
122
  return new ReducedIterator(function* ()
136
123
  {
137
- for (const [key, [_, accumulator]] of accumulators)
138
- {
139
- yield [key, accumulator];
140
- }
124
+ for (const [key, [_, accumulator]] of values) { yield [key, accumulator]; }
141
125
  });
142
126
  }
143
127
 
144
- public unique(): AggregatedIterator<K, T>
128
+ public flatMap<V>(iteratee: KeyedIteratee<K, T, Iterable<V>>): AggregatedIterator<K, V>
145
129
  {
146
130
  const elements = this._elements;
147
131
 
148
132
  return new AggregatedIterator(function* ()
149
133
  {
150
- const keys = new Map<K, Set<T>>();
134
+ const indexes = new Map<K, number>();
151
135
 
152
136
  for (const [key, element] of elements)
153
137
  {
154
- const values = keys.get(key) ?? new Set<T>();
155
-
156
- if (values.has(element)) { continue; }
138
+ const index = indexes.get(key) ?? 0;
139
+ const values = iteratee(key, element, index);
157
140
 
158
- values.add(element);
159
- keys.set(key, values);
141
+ for (const value of values) { yield [key, value]; }
160
142
 
161
- yield [key, element];
143
+ indexes.set(key, index + 1);
162
144
  }
163
145
  });
164
146
  }
165
147
 
166
- public count(): ReducedIterator<K, number>
148
+ public drop(count: number): AggregatedIterator<K, T>
167
149
  {
168
- const counters = new Map<K, number>();
150
+ const elements = this._elements;
169
151
 
170
- for (const [key] of this._elements)
152
+ return new AggregatedIterator(function* ()
171
153
  {
172
- const count = counters.get(key) ?? 0;
154
+ const indexes = new Map<K, number>();
173
155
 
174
- counters.set(key, count + 1);
175
- }
156
+ for (const [key, element] of elements)
157
+ {
158
+ const index = indexes.get(key) ?? 0;
159
+ if (index < count)
160
+ {
161
+ indexes.set(key, index + 1);
176
162
 
177
- return new ReducedIterator(function* ()
163
+ continue;
164
+ }
165
+
166
+ yield [key, element];
167
+ }
168
+ });
169
+ }
170
+ public take(limit: number): AggregatedIterator<K, T>
171
+ {
172
+ const elements = this._elements;
173
+
174
+ return new AggregatedIterator(function* ()
178
175
  {
179
- for (const [key, count] of counters)
176
+ const indexes = new Map<K, number>();
177
+
178
+ for (const [key, element] of elements)
180
179
  {
181
- yield [key, count];
180
+ const index = indexes.get(key) ?? 0;
181
+ if (index >= limit) { continue; }
182
+
183
+ yield [key, element];
184
+
185
+ indexes.set(key, index + 1);
182
186
  }
183
187
  });
184
188
  }
185
- public first(): ReducedIterator<K, T>
189
+
190
+ public find(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, T | undefined>;
191
+ public find<S extends T>(predicate: KeyedTypeGuardIteratee<K, T, S>): ReducedIterator<K, S | undefined>;
192
+ public find(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, T | undefined>
186
193
  {
187
- const firsts = new Map<K, T>();
194
+ const values = new Map<K, [number, T | undefined]>();
188
195
 
189
196
  for (const [key, element] of this._elements)
190
197
  {
191
- if (firsts.has(key)) { continue; }
198
+ let [index, finding] = values.get(key) ?? [0, undefined];
192
199
 
193
- firsts.set(key, element);
200
+ if (finding !== undefined) { continue; }
201
+ if (predicate(key, element, index)) { finding = element; }
202
+
203
+ values.set(key, [index + 1, finding]);
194
204
  }
195
205
 
196
206
  return new ReducedIterator(function* ()
197
207
  {
198
- for (const [key, element] of firsts)
208
+ for (const [key, [_, finding]] of values) { yield [key, finding]; }
209
+ });
210
+ }
211
+
212
+ public enumerate(): AggregatedIterator<K, [number, T]>
213
+ {
214
+ return this.map((_, value, index) => [index, value]);
215
+ }
216
+ public unique(): AggregatedIterator<K, T>
217
+ {
218
+ const elements = this._elements;
219
+
220
+ return new AggregatedIterator(function* ()
221
+ {
222
+ const keys = new Map<K, Set<T>>();
223
+
224
+ for (const [key, element] of elements)
199
225
  {
226
+ const values = keys.get(key) ?? new Set<T>();
227
+
228
+ if (values.has(element)) { continue; }
229
+
230
+ values.add(element);
231
+ keys.set(key, values);
232
+
200
233
  yield [key, element];
201
234
  }
202
235
  });
203
236
  }
204
- public last(): ReducedIterator<K, T>
237
+
238
+ public count(): ReducedIterator<K, number>
205
239
  {
206
- const lasts = new Map<K, T>();
240
+ const counters = new Map<K, number>();
207
241
 
208
- for (const [key, element] of this._elements)
242
+ for (const [key] of this._elements)
209
243
  {
210
- lasts.set(key, element);
244
+ const count = counters.get(key) ?? 0;
245
+
246
+ counters.set(key, count + 1);
211
247
  }
212
248
 
213
249
  return new ReducedIterator(function* ()
214
250
  {
215
- for (const [key, element] of lasts)
216
- {
217
- yield [key, element];
218
- }
251
+ for (const [key, count] of counters) { yield [key, count]; }
219
252
  });
220
253
  }
221
254
 
255
+ public forEach(iteratee: KeyedIteratee<K, T>): void
256
+ {
257
+ const indexes = new Map<K, number>();
258
+
259
+ for (const [key, element] of this._elements)
260
+ {
261
+ const index = indexes.get(key) ?? 0;
262
+
263
+ iteratee(key, element, index);
264
+
265
+ indexes.set(key, index + 1);
266
+ }
267
+ }
268
+
222
269
  public keys(): SmartIterator<K>
223
270
  {
224
271
  const elements = this._elements;
@@ -246,16 +293,15 @@ export default class AggregatedIterator<K extends PropertyKey, T>
246
293
 
247
294
  return new SmartIterator<T>(function* ()
248
295
  {
249
- for (const [_, element] of elements)
250
- {
251
- yield element;
252
- }
296
+ for (const [_, element] of elements) { yield element; }
253
297
  });
254
298
  }
255
299
 
256
300
  public toArray(): T[][]
257
301
  {
258
- return Array.from(this.toMap().values());
302
+ const map = this.toMap();
303
+
304
+ return Array.from(map.values());
259
305
  }
260
306
  public toMap(): Map<K, T[]>
261
307
  {
@@ -286,5 +332,5 @@ export default class AggregatedIterator<K extends PropertyKey, T>
286
332
  return groups;
287
333
  }
288
334
 
289
- public get [Symbol.toStringTag]() { return "AggregatedIterator"; }
335
+ public readonly [Symbol.toStringTag]: string = "AggregatedIterator";
290
336
  }
@@ -1,7 +1,5 @@
1
- import Aggregator from "./aggregator.js";
2
- import AsyncAggregator from "./async-aggregator.js";
3
1
  import AggregatedIterator from "./aggregated-iterator.js";
4
2
  import AggregatedAsyncIterator from "./aggregated-async-iterator.js";
5
3
  import ReducedIterator from "./reduced-iterator.js";
6
4
 
7
- export { Aggregator, AsyncAggregator, AggregatedIterator, AggregatedAsyncIterator, ReducedIterator };
5
+ export { AggregatedIterator, AggregatedAsyncIterator, ReducedIterator };
@@ -2,7 +2,8 @@ import { ValueException } from "../exceptions/index.js";
2
2
  import { SmartIterator } from "../iterators/index.js";
3
3
  import type { GeneratorFunction } from "../iterators/types.js";
4
4
 
5
- import type { KeyIteratee, KeyReducer, KeyTypeGuardIteratee } from "./types.js";
5
+ import AggregatedIterator from "./aggregated-iterator.js";
6
+ import type { KeyedIteratee, KeyedReducer, KeyedTypeGuardIteratee } from "./types.js";
6
7
 
7
8
  export default class ReducedIterator<K extends PropertyKey, T>
8
9
  {
@@ -17,56 +18,64 @@ export default class ReducedIterator<K extends PropertyKey, T>
17
18
  this._elements = new SmartIterator(argument);
18
19
  }
19
20
 
20
- public filter(predicate: KeyIteratee<K, T, boolean>): ReducedIterator<K, T>;
21
- public filter<S extends T>(predicate: KeyTypeGuardIteratee<K, T, S>): ReducedIterator<K, S>;
22
- public filter(predicate: KeyIteratee<K, T, boolean>): ReducedIterator<K, T>
21
+ public every(predicate: KeyedIteratee<K, T, boolean>): boolean
23
22
  {
24
- const elements = this._elements;
23
+ for (const [index, [key, element]] of this._elements.enumerate())
24
+ {
25
+ if (!(predicate(key, element, index))) { return false; }
26
+ }
27
+
28
+ return true;
29
+ }
30
+ public some(predicate: KeyedIteratee<K, T, boolean>): boolean
31
+ {
32
+ for (const [index, [key, element]] of this._elements.enumerate())
33
+ {
34
+ if (predicate(key, element, index)) { return true; }
35
+ }
36
+
37
+ return false;
38
+ }
39
+
40
+ public filter(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, T>;
41
+ public filter<S extends T>(predicate: KeyedTypeGuardIteratee<K, T, S>): ReducedIterator<K, S>;
42
+ public filter(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, T>
43
+ {
44
+ const elements = this._elements.enumerate();
25
45
 
26
46
  return new ReducedIterator(function* ()
27
47
  {
28
- for (const [index, [key, element]] of elements.enumerate())
48
+ for (const [index, [key, element]] of elements)
29
49
  {
30
- if (predicate(key, element, index))
31
- {
32
- yield [key, element];
33
- }
50
+ if (predicate(key, element, index)) { yield [key, element]; }
34
51
  }
35
52
  });
36
53
  }
37
- public map<V>(iteratee: KeyIteratee<K, T, V>): ReducedIterator<K, V>
54
+ public map<V>(iteratee: KeyedIteratee<K, T, V>): ReducedIterator<K, V>
38
55
  {
39
- const elements = this._elements;
56
+ const elements = this._elements.enumerate();
40
57
 
41
58
  return new ReducedIterator(function* ()
42
59
  {
43
- for (const [index, [key, element]] of elements.enumerate())
60
+ for (const [index, [key, element]] of elements)
44
61
  {
45
62
  yield [key, iteratee(key, element, index)];
46
63
  }
47
64
  });
48
65
  }
49
- public reduce(reducer: KeyReducer<K, T, T>): T;
50
- public reduce<A>(reducer: KeyReducer<K, T, A>, initialValue: A): A;
51
- public reduce<A>(reducer: KeyReducer<K, T, A>, initialValue?: A): A
66
+ public reduce(reducer: KeyedReducer<K, T, T>): T;
67
+ public reduce<A>(reducer: KeyedReducer<K, T, A>, initialValue: A): A;
68
+ public reduce<A>(reducer: KeyedReducer<K, T, A>, initialValue?: A): A
52
69
  {
53
70
  let index = 0;
54
- let accumulator: A;
55
-
56
- if (initialValue !== undefined)
71
+ let accumulator = initialValue;
72
+ if (accumulator === undefined)
57
73
  {
58
- accumulator = initialValue;
59
- }
60
- else
61
- {
62
- const firstElement = this._elements.next();
63
- if (firstElement.done)
64
- {
65
- throw new ValueException("Cannot reduce an empty iterator without an initial value.");
66
- }
74
+ const result = this._elements.next();
75
+ if (result.done) { throw new ValueException("Cannot reduce an empty iterator without an initial value."); }
67
76
 
77
+ accumulator = (result.value[1] as unknown) as A;
68
78
  index += 1;
69
- accumulator = (firstElement.value[1] as unknown) as A;
70
79
  }
71
80
 
72
81
  for (const [key, element] of this._elements)
@@ -79,6 +88,85 @@ export default class ReducedIterator<K extends PropertyKey, T>
79
88
  return accumulator;
80
89
  }
81
90
 
91
+ public flatMap<V>(iteratee: KeyedIteratee<K, T, Iterable<V>>): AggregatedIterator<K, V>
92
+ {
93
+ const elements = this._elements.enumerate();
94
+
95
+ return new AggregatedIterator(function* ()
96
+ {
97
+ for (const [index, [key, element]] of elements)
98
+ {
99
+ for (const value of iteratee(key, element, index)) { yield [key, value]; }
100
+ }
101
+ });
102
+ }
103
+
104
+ public drop(count: number): ReducedIterator<K, T>
105
+ {
106
+ const elements = this._elements.enumerate();
107
+
108
+ return new ReducedIterator(function* ()
109
+ {
110
+ for (const [index, [key, element]] of elements)
111
+ {
112
+ if (index >= count) { yield [key, element]; }
113
+ }
114
+ });
115
+ }
116
+ public take(count: number): ReducedIterator<K, T>
117
+ {
118
+ const elements = this._elements.enumerate();
119
+
120
+ return new ReducedIterator(function* ()
121
+ {
122
+ for (const [index, [key, element]] of elements)
123
+ {
124
+ if (index >= count) { break; }
125
+
126
+ yield [key, element];
127
+ }
128
+ });
129
+ }
130
+
131
+ public enumerate(): ReducedIterator<K, [number, T]>
132
+ {
133
+ return this.map((_, element, index) => [index, element]);
134
+ }
135
+ public unique(): ReducedIterator<K, T>
136
+ {
137
+ const elements = this._elements;
138
+
139
+ return new ReducedIterator(function* ()
140
+ {
141
+ const values = new Set<T>();
142
+
143
+ for (const [key, element] of elements)
144
+ {
145
+ if (values.has(element)) { continue; }
146
+ values.add(element);
147
+
148
+ yield [key, element];
149
+ }
150
+ });
151
+ }
152
+
153
+ public count(): number
154
+ {
155
+ let index = 0;
156
+
157
+ for (const _ of this._elements) { index += 1; }
158
+
159
+ return index;
160
+ }
161
+
162
+ public forEach(iteratee: KeyedIteratee<K, T>): void
163
+ {
164
+ for (const [index, [key, element]] of this._elements.enumerate())
165
+ {
166
+ iteratee(key, element, index);
167
+ }
168
+ }
169
+
82
170
  public keys(): SmartIterator<K>
83
171
  {
84
172
  const elements = this._elements;
@@ -121,5 +209,5 @@ export default class ReducedIterator<K extends PropertyKey, T>
121
209
  return Object.fromEntries(this.items()) as Record<K, T>;
122
210
  }
123
211
 
124
- public get [Symbol.toStringTag]() { return "ReducedIterator"; }
212
+ public readonly [Symbol.toStringTag]: string = "ReducedIterator";
125
213
  }
@@ -1,14 +1,19 @@
1
+ /* eslint-disable max-len */
2
+
1
3
  import type { MaybePromise } from "../promises/types.js";
2
4
 
3
- export type KeyIteratee<K extends PropertyKey, T, R = void> = (key: K, value: T, index: number) => R;
4
- export type MaybeAsyncKeyIteratee<K extends PropertyKey, T, R = void> = (key: K, value: T, index: number) =>
5
- MaybePromise<R>;
5
+ export type KeyedIteratee<K extends PropertyKey, T, R = void> = (key: K, value: T, index: number) => R;
6
+ export type AsyncKeyedIteratee<K extends PropertyKey, T, R = void> = (key: K, value: T, index: number) => Promise<R>;
7
+ export type MaybeAsyncKeyedIteratee<K extends PropertyKey, T, R = void> = (key: K, value: T, index: number) => MaybePromise<R>;
8
+
9
+ export type KeyedTypeGuardIteratee<K extends PropertyKey, T, R extends T> = (key: K, value: T, index: number) => value is R;
10
+
11
+ // @ts-expect-error - This is an asyncronous type guard keyed-iteratee that guarantees the return value is a promise.
12
+ export type AsyncKeyedTypeGuardIteratee<K extends PropertyKey, T, R extends T> = (key: K, value: T, index: number) => value is Promise<R>;
6
13
 
7
- export type KeyTypeGuardIteratee<K extends PropertyKey, T, R extends T> =
8
- (key: K, value: T, index: number) => value is R;
9
- export type MaybeAsyncKeyTypeGuardIteratee<K extends PropertyKey, T, R extends T> =
10
- (key: K, value: MaybePromise<T>, index: number) => value is Awaited<R>;
14
+ // @ts-expect-error - This may be an asyncronous type guard keyed-iteratee that guarantees the return value may be a promise.
15
+ export type MaybeAsyncKeyedTypeGuardIteratee<K extends PropertyKey, T, R extends T> = (key: K, value: T, index: number) => value is MaybePromise<R>;
11
16
 
12
- export type KeyReducer<K extends PropertyKey, T, A> = (key: K, accumulator: A, value: T, index: number) => A;
13
- export type MaybeAsyncKeyReducer<K extends PropertyKey, T, A> =
14
- (key: K, accumulator: A, value: T, index: number) => MaybePromise<A>;
17
+ export type KeyedReducer<K extends PropertyKey, T, A> = (key: K, accumulator: A, value: T, index: number) => A;
18
+ export type AsyncKeyedReducer<K extends PropertyKey, T, A> = (key: K, accumulator: A, value: T, index: number) => Promise<A>;
19
+ export type MaybeAsyncKeyedReducer<K extends PropertyKey, T, A> = (key: K, accumulator: A, value: T, index: number) => MaybePromise<A>;
@@ -0,0 +1,23 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+
3
+ import type { Callback } from "./types.js";
4
+
5
+ export const SmartFunction = (Function as unknown) as
6
+ new<T extends Callback<any[], any> = () => void>(...args: string[]) =>
7
+ (...args: Parameters<T>) => ReturnType<T>;
8
+
9
+ export default abstract class CallableObject<T extends Callback<any[], any> = () => void>
10
+ extends SmartFunction<T>
11
+ {
12
+ public constructor()
13
+ {
14
+ super(`return this.invoke(...arguments);`);
15
+
16
+ const self = this.bind(this);
17
+ Object.setPrototypeOf(this, self);
18
+
19
+ return self as this;
20
+ }
21
+
22
+ public abstract invoke(...args: Parameters<T>): ReturnType<T>;
23
+ }
@@ -0,0 +1,5 @@
1
+ import CallableObject, { SmartFunction } from "./callable-object.js";
2
+ import Publisher from "./publisher.js";
3
+ import SwitchableCallback from "./switchable-callback.js";
4
+
5
+ export { CallableObject, Publisher, SmartFunction, SwitchableCallback };
@@ -0,0 +1,45 @@
1
+ import { ReferenceException } from "../exceptions/index.js";
2
+
3
+ import type { Callback } from "./types.js";
4
+
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ export default class Publisher<T extends { [K in keyof T]: Callback<any[], any> } = Record<string, Callback>>
7
+ {
8
+ protected _subscribers: Map<keyof T, Callback<unknown[], unknown>[]>;
9
+
10
+ public constructor()
11
+ {
12
+ this._subscribers = new Map();
13
+ }
14
+
15
+ public subscribe<K extends keyof T>(event: K, subscriber: T[K]): () => void
16
+ {
17
+ if (!(this._subscribers.has(event))) { this._subscribers.set(event, []); }
18
+
19
+ const subscribers = this._subscribers.get(event)!;
20
+ subscribers.push(subscriber);
21
+
22
+ return () =>
23
+ {
24
+ const index = subscribers.indexOf(subscriber);
25
+ if (index < 0)
26
+ {
27
+ throw new ReferenceException("Unable to unsubscribe the required subscriber. " +
28
+ "The subscription was already unsubscribed.");
29
+ }
30
+
31
+ subscribers.splice(index, 1);
32
+ };
33
+ }
34
+
35
+ public publish<K extends keyof T>(event: K, ...args: Parameters<T[K]>): ReturnType<T[K]>[]
36
+ {
37
+ const subscribers = this._subscribers.get(event);
38
+ if (!(subscribers)) { return []; }
39
+
40
+ return subscribers.slice()
41
+ .map((subscriber) => subscriber(...args)) as ReturnType<T[K]>[];
42
+ }
43
+
44
+ public readonly [Symbol.toStringTag]: string = "Publisher";
45
+ }