@byloth/core 1.5.3 → 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 (45) hide show
  1. package/dist/core.js +1468 -826
  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 +10 -0
  7. package/src/index.ts +33 -16
  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 +119 -31
  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 +6 -7
  19. package/src/models/exceptions/index.ts +50 -10
  20. package/src/models/game-loop.ts +83 -0
  21. package/src/models/index.ts +10 -7
  22. package/src/models/iterators/smart-async-iterator.ts +112 -24
  23. package/src/models/iterators/smart-iterator.ts +108 -13
  24. package/src/models/iterators/types.ts +17 -7
  25. package/src/models/json/index.ts +3 -0
  26. package/src/models/{json-storage.ts → json/json-storage.ts} +40 -28
  27. package/src/models/json/types.ts +5 -0
  28. package/src/models/promises/deferred-promise.ts +1 -1
  29. package/src/models/promises/index.ts +3 -1
  30. package/src/models/promises/long-running-task.ts +294 -0
  31. package/src/models/promises/smart-promise.ts +6 -1
  32. package/src/models/promises/thenable.ts +97 -0
  33. package/src/models/promises/timed-promise.ts +1 -1
  34. package/src/models/promises/types.ts +2 -0
  35. package/src/models/timers/clock.ts +69 -0
  36. package/src/models/timers/countdown.ts +117 -0
  37. package/src/models/timers/index.ts +4 -0
  38. package/src/models/types.ts +20 -9
  39. package/src/utils/async.ts +9 -4
  40. package/src/utils/date.ts +7 -4
  41. package/src/utils/index.ts +2 -2
  42. package/src/utils/random.ts +4 -3
  43. package/src/models/aggregators/aggregator.ts +0 -46
  44. package/src/models/aggregators/async-aggregator.ts +0 -56
  45. package/src/models/subscribers.ts +0 -35
@@ -1,4 +1,7 @@
1
- import type { GeneratorFunction, Iteratee, TypeGuardIteratee, Reducer, IterLike } from "./types.js";
1
+ import AggregatedIterator from "../aggregators/aggregated-iterator.js";
2
+ import { ValueException } from "../exceptions/index.js";
3
+
4
+ import type { GeneratorFunction, Iteratee, TypeGuardIteratee, Reducer, IteratorLike } from "./types.js";
2
5
 
3
6
  export default class SmartIterator<T, R = void, N = undefined> implements Iterator<T, R, N>
4
7
  {
@@ -7,11 +10,11 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
7
10
  public return?: (value?: R) => IteratorResult<T, R>;
8
11
  public throw?: (error?: unknown) => IteratorResult<T, R>;
9
12
 
10
- public constructor(iterable: Iterable<T>);
13
+ public constructor(iterable: Iterable<T, R, N>);
11
14
  public constructor(iterator: Iterator<T, R, N>);
12
15
  public constructor(generatorFn: GeneratorFunction<T, R, N>);
13
- public constructor(argument: IterLike<T, R, N>);
14
- public constructor(argument: IterLike<T, R, N>)
16
+ public constructor(argument: IteratorLike<T, R, N> | GeneratorFunction<T, R, N>);
17
+ public constructor(argument: IteratorLike<T, R, N> | GeneratorFunction<T, R, N>)
15
18
  {
16
19
  if (argument instanceof Function)
17
20
  {
@@ -26,15 +29,14 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
26
29
  this._iterator = argument;
27
30
  }
28
31
 
29
- if (this._iterator.return) { this.return = (value?: R) => this._iterator.return!(value); }
30
- if (this._iterator.throw) { this.throw = (error?: unknown) => this._iterator.throw!(error); }
32
+ if (this._iterator.return) { this.return = (value) => this._iterator.return!(value); }
33
+ if (this._iterator.throw) { this.throw = (error) => this._iterator.throw!(error); }
31
34
  }
32
35
 
33
36
  public every(predicate: Iteratee<T, boolean>): boolean
34
37
  {
35
38
  let index = 0;
36
39
 
37
- // eslint-disable-next-line no-constant-condition
38
40
  while (true)
39
41
  {
40
42
  const result = this._iterator.next();
@@ -49,7 +51,6 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
49
51
  {
50
52
  let index = 0;
51
53
 
52
- // eslint-disable-next-line no-constant-condition
53
54
  while (true)
54
55
  {
55
56
  const result = this._iterator.next();
@@ -110,13 +111,12 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
110
111
  if (accumulator === undefined)
111
112
  {
112
113
  const result = this._iterator.next();
113
- if (result.done) { throw new TypeError("Reduce of empty iterator with no initial value"); }
114
+ if (result.done) { throw new ValueException("Cannot reduce an empty iterator without an initial value."); }
114
115
 
115
116
  accumulator = (result.value as unknown) as A;
116
117
  index += 1;
117
118
  }
118
119
 
119
- // eslint-disable-next-line no-constant-condition
120
120
  while (true)
121
121
  {
122
122
  const result = this._iterator.next();
@@ -128,6 +128,92 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
128
128
  }
129
129
  }
130
130
 
131
+ public flatMap<V>(iteratee: Iteratee<T, Iterable<V>>): SmartIterator<V, R>
132
+ {
133
+ const iterator = this._iterator;
134
+
135
+ return new SmartIterator<V, R>(function* ()
136
+ {
137
+ let index = 0;
138
+
139
+ while (true)
140
+ {
141
+ const result = iterator.next();
142
+ if (result.done) { return result.value; }
143
+
144
+ const iterable = iteratee(result.value, index);
145
+ for (const value of iterable)
146
+ {
147
+ yield value;
148
+ }
149
+
150
+ index += 1;
151
+ }
152
+ });
153
+ }
154
+
155
+ public drop(count: number): SmartIterator<T, R | undefined>
156
+ {
157
+ const iterator = this._iterator;
158
+
159
+ return new SmartIterator<T, R | undefined>(function* ()
160
+ {
161
+ let index = 0;
162
+ while (index < count)
163
+ {
164
+ const result = iterator.next();
165
+ if (result.done) { return; }
166
+
167
+ index += 1;
168
+ }
169
+
170
+ while (true)
171
+ {
172
+ const result = iterator.next();
173
+ if (result.done) { return result.value; }
174
+
175
+ yield result.value;
176
+ }
177
+ });
178
+ }
179
+ public take(limit: number): SmartIterator<T, R | undefined>
180
+ {
181
+ const iterator = this._iterator;
182
+
183
+ return new SmartIterator<T, R | undefined>(function* ()
184
+ {
185
+ let index = 0;
186
+ while (index < limit)
187
+ {
188
+ const result = iterator.next();
189
+ if (result.done) { return result.value; }
190
+
191
+ yield result.value;
192
+
193
+ index += 1;
194
+ }
195
+
196
+ return;
197
+ });
198
+ }
199
+
200
+ public find(predicate: Iteratee<T, boolean>): T | undefined;
201
+ public find<S extends T>(predicate: TypeGuardIteratee<T, S>): S | undefined;
202
+ public find(predicate: Iteratee<T, boolean>): T | undefined
203
+ {
204
+ let index = 0;
205
+
206
+ while (true)
207
+ {
208
+ const result = this._iterator.next();
209
+
210
+ if (result.done) { return; }
211
+ if (predicate(result.value, index)) { return result.value; }
212
+
213
+ index += 1;
214
+ }
215
+ }
216
+
131
217
  public enumerate(): SmartIterator<[number, T], R>
132
218
  {
133
219
  return this.map((value, index) => [index, value]);
@@ -158,7 +244,6 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
158
244
  {
159
245
  let index = 0;
160
246
 
161
- // eslint-disable-next-line no-constant-condition
162
247
  while (true)
163
248
  {
164
249
  const result = this._iterator.next();
@@ -167,11 +252,11 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
167
252
  index += 1;
168
253
  }
169
254
  }
255
+
170
256
  public forEach(iteratee: Iteratee<T>): void
171
257
  {
172
258
  let index = 0;
173
259
 
174
- // eslint-disable-next-line no-constant-condition
175
260
  while (true)
176
261
  {
177
262
  const result = this._iterator.next();
@@ -188,12 +273,22 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
188
273
  return this._iterator.next(...values);
189
274
  }
190
275
 
276
+ public groupBy<K extends PropertyKey>(iteratee: Iteratee<T, K>): AggregatedIterator<K, T>
277
+ {
278
+ return new AggregatedIterator(this.map((element, index) =>
279
+ {
280
+ const key = iteratee(element, index);
281
+
282
+ return [key, element] as [K, T];
283
+ }));
284
+ }
285
+
191
286
  public toArray(): T[]
192
287
  {
193
288
  return Array.from(this as Iterable<T>);
194
289
  }
195
290
 
196
- public get [Symbol.toStringTag]() { return "SmartIterator"; }
291
+ public readonly [Symbol.toStringTag]: string = "SmartIterator";
197
292
 
198
293
  public [Symbol.iterator](): SmartIterator<T, R, N> { return this; }
199
294
  }
@@ -1,20 +1,30 @@
1
+
1
2
  import type { MaybePromise } from "../promises/types.js";
2
3
 
4
+ export type MaybeAsyncIterable<T, R = void, N = undefined> = Iterable<T, R, N> | AsyncIterable<T, R, N>;
5
+ export type MaybeAsyncIterator<T, R = void, N = undefined> = Iterator<T, R, N> | AsyncIterator<T, R, N>;
6
+ export type MaybeAsyncGenerator<T, R = void, N = undefined> = Generator<T, R, N> | AsyncGenerator<T, R, N>;
7
+
3
8
  export type GeneratorFunction<T, R = void, N = undefined> = () => Generator<T, R, N>;
4
9
  export type AsyncGeneratorFunction<T, R = void, N = undefined> = () => AsyncGenerator<T, R, N>;
10
+ export type MaybeAsyncGeneratorFunction<T, R = void, N = undefined> = () => MaybeAsyncGenerator<T, R, N>;
5
11
 
6
12
  export type Iteratee<T, R = void> = (value: T, index: number) => R;
13
+ export type AsyncIteratee<T, R = void> = (value: T, index: number) => Promise<R>;
7
14
  export type MaybeAsyncIteratee<T, R = void> = (value: T, index: number) => MaybePromise<R>;
8
15
 
9
16
  export type TypeGuardIteratee<T, R extends T> = (value: T, index: number) => value is R;
10
- export type MaybeAsyncTypeGuardIteratee<T, R extends T> = (value: MaybePromise<T>, index: number) =>
11
- value is MaybePromise<R>;
17
+
18
+ // @ts-expect-error - This is an asyncronous type guard iteratee that guarantees the return value is a promise.
19
+ export type AsyncTypeGuardIteratee<T, R extends T> = (value: T, index: number) => value is Promise<R>;
20
+
21
+ // @ts-expect-error - This may be an asyncronous type guard iteratee that guarantees the return value may be a promise.
22
+ export type MaybeAsyncTypeGuardIteratee<T, R extends T> = (value: T, index: number) => value is MaybePromise<R>;
12
23
 
13
24
  export type Reducer<T, A> = (accumulator: A, value: T, index: number) => A;
25
+ export type AsyncReducer<T, A> = (accumulator: A, value: T, index: number) => Promise<A>;
14
26
  export type MaybeAsyncReducer<T, A> = (accumulator: A, value: T, index: number) => MaybePromise<A>;
15
27
 
16
- export type IterLike<T, R = void, N = undefined> = Iterable<T> | Iterator<T, R, N> | GeneratorFunction<T, R, N>;
17
- export type AsyncIterLike<T, R = void, N = undefined> =
18
- AsyncIterable<T> | AsyncIterator<T, R, N> | AsyncGeneratorFunction<T, R, N>;
19
-
20
- export type MaybeAsyncIterLike<T, R = void, N = undefined> = IterLike<T, R, N> | AsyncIterLike<T, R, N>;
28
+ export type IteratorLike<T, R = void, N = undefined> = Iterable<T> | Iterator<T, R, N>;
29
+ export type AsyncIteratorLike<T, R = void, N = undefined> = AsyncIterable<T> | AsyncIterator<T, R, N>;
30
+ export type MaybeAsyncIteratorLike<T, R = void, N = undefined> = IteratorLike<T, R, N> | AsyncIteratorLike<T, R, N>;
@@ -0,0 +1,3 @@
1
+ import JSONStorage from "./json-storage.js";
2
+
3
+ export { JSONStorage };
@@ -1,4 +1,8 @@
1
- /* eslint-disable no-trailing-spaces */
1
+
2
+ import { isBrowser } from "../../helpers.js";
3
+ import { EnvironmentException } from "../exceptions/index.js";
4
+
5
+ import type { JSONValue } from "./types.js";
2
6
 
3
7
  /**
4
8
  * A wrapper around the `Storage` API to store and retrieve JSON values.
@@ -6,7 +10,7 @@
6
10
  * It allows to handle either the `sessionStorage` or the `localStorage`
7
11
  * storage at the same time, depending on the required use case.
8
12
  */
9
- export default class JsonStorage
13
+ export default class JSONStorage
10
14
  {
11
15
  protected _preferPersistence: boolean;
12
16
 
@@ -17,14 +21,21 @@ export default class JsonStorage
17
21
  {
18
22
  this._preferPersistence = preferPersistence;
19
23
 
24
+ if (!(isBrowser))
25
+ {
26
+ throw new EnvironmentException(
27
+ "The `JSONStorage` class can only be instantiated within a browser environment."
28
+ );
29
+ }
30
+
20
31
  this._volatile = window.sessionStorage;
21
32
  this._persistent = window.localStorage;
22
33
  }
23
34
 
24
- protected _get<T>(storage: Storage, propertyName: string): T | undefined;
25
- protected _get<T>(storage: Storage, propertyName: string, defaultValue: T): T;
26
- protected _get<T>(storage: Storage, propertyName: string, defaultValue?: T): T | undefined;
27
- protected _get<T>(storage: Storage, propertyName: string, defaultValue?: T): T | undefined
35
+ protected _get<T extends JSONValue>(storage: Storage, propertyName: string): T | undefined;
36
+ protected _get<T extends JSONValue>(storage: Storage, propertyName: string, defaultValue: T): T;
37
+ protected _get<T extends JSONValue>(storage: Storage, propertyName: string, defaultValue?: T): T | undefined;
38
+ protected _get<T extends JSONValue>(storage: Storage, propertyName: string, defaultValue?: T): T | undefined
28
39
  {
29
40
  const propertyValue = storage.getItem(propertyName);
30
41
  if (propertyValue)
@@ -33,7 +44,7 @@ export default class JsonStorage
33
44
  {
34
45
  return JSON.parse(propertyValue);
35
46
  }
36
- catch (error)
47
+ catch
37
48
  {
38
49
  // eslint-disable-next-line no-console
39
50
  console.warn(
@@ -46,7 +57,7 @@ export default class JsonStorage
46
57
 
47
58
  return defaultValue;
48
59
  }
49
- protected _set<T>(storage: Storage, propertyName: string, newValue?: T): void
60
+ protected _set<T extends JSONValue>(storage: Storage, propertyName: string, newValue?: T): void
50
61
  {
51
62
  const encodedValue = JSON.stringify(newValue);
52
63
  if (encodedValue)
@@ -68,10 +79,11 @@ export default class JsonStorage
68
79
  *
69
80
  * @returns The value of the property or the default value if the property does not exist.
70
81
  */
71
- public get<T>(propertyName: string, defaultValue: undefined, persistent?: boolean): T | undefined;
72
- public get<T>(propertyName: string, defaultValue: T, persistent?: boolean): T ;
73
- public get<T>(propertyName: string, defaultValue?: T, persistent?: boolean): T | undefined;
74
- public get<T>(propertyName: string, defaultValue?: T, persistent = this._preferPersistence): T | undefined
82
+ public get<T extends JSONValue>(propertyName: string, defaultValue: undefined, persistent?: boolean): T | undefined;
83
+ public get<T extends JSONValue>(propertyName: string, defaultValue: T, persistent?: boolean): T ;
84
+ public get<T extends JSONValue>(propertyName: string, defaultValue?: T, persistent?: boolean): T | undefined;
85
+ public get<T extends JSONValue>(propertyName: string, defaultValue?: T, persistent = this._preferPersistence)
86
+ : T | undefined
75
87
  {
76
88
  const storage = persistent ? this._persistent : this._volatile;
77
89
 
@@ -85,10 +97,10 @@ export default class JsonStorage
85
97
  *
86
98
  * @returns The value of the property or the default value if the property does not exist.
87
99
  */
88
- public recall<T>(propertyName: string): T | undefined;
89
- public recall<T>(propertyName: string, defaultValue: T): T;
90
- public recall<T>(propertyName: string, defaultValue?: T): T | undefined;
91
- public recall<T>(propertyName: string, defaultValue?: T): T | undefined
100
+ public recall<T extends JSONValue>(propertyName: string): T | undefined;
101
+ public recall<T extends JSONValue>(propertyName: string, defaultValue: T): T;
102
+ public recall<T extends JSONValue>(propertyName: string, defaultValue?: T): T | undefined;
103
+ public recall<T extends JSONValue>(propertyName: string, defaultValue?: T): T | undefined
92
104
  {
93
105
  return this._get<T>(this._volatile, propertyName, defaultValue);
94
106
  }
@@ -101,10 +113,10 @@ export default class JsonStorage
101
113
  *
102
114
  * @returns The value of the property or the default value if the property does not exist.
103
115
  */
104
- public retrieve<T>(propertyName: string): T | undefined;
105
- public retrieve<T>(propertyName: string, defaultValue: T): T;
106
- public retrieve<T>(propertyName: string, defaultValue?: T): T | undefined;
107
- public retrieve<T>(propertyName: string, defaultValue?: T): T | undefined
116
+ public retrieve<T extends JSONValue>(propertyName: string): T | undefined;
117
+ public retrieve<T extends JSONValue>(propertyName: string, defaultValue: T): T;
118
+ public retrieve<T extends JSONValue>(propertyName: string, defaultValue?: T): T | undefined;
119
+ public retrieve<T extends JSONValue>(propertyName: string, defaultValue?: T): T | undefined
108
120
  {
109
121
  return this.recall<T>(propertyName) ?? this.read<T>(propertyName, defaultValue);
110
122
  }
@@ -116,10 +128,10 @@ export default class JsonStorage
116
128
  *
117
129
  * @returns The value of the property or the default value if the property does not exist.
118
130
  */
119
- public read<T>(propertyName: string): T | undefined;
120
- public read<T>(propertyName: string, defaultValue: T): T;
121
- public read<T>(propertyName: string, defaultValue?: T): T | undefined;
122
- public read<T>(propertyName: string, defaultValue?: T): T | undefined
131
+ public read<T extends JSONValue>(propertyName: string): T | undefined;
132
+ public read<T extends JSONValue>(propertyName: string, defaultValue: T): T;
133
+ public read<T extends JSONValue>(propertyName: string, defaultValue?: T): T | undefined;
134
+ public read<T extends JSONValue>(propertyName: string, defaultValue?: T): T | undefined
123
135
  {
124
136
  return this._get<T>(this._persistent, propertyName, defaultValue);
125
137
  }
@@ -181,7 +193,7 @@ export default class JsonStorage
181
193
  * @param newValue The new value to set.
182
194
  * @param persistent Whether to use the persistent `localStorage` or the volatile `sessionStorage`.
183
195
  */
184
- public set<T>(propertyName: string, newValue?: T, persistent = this._preferPersistence): void
196
+ public set<T extends JSONValue>(propertyName: string, newValue?: T, persistent = this._preferPersistence): void
185
197
  {
186
198
  const storage = persistent ? this._persistent : this._volatile;
187
199
 
@@ -194,7 +206,7 @@ export default class JsonStorage
194
206
  * @param propertyName The name of the property to set.
195
207
  * @param newValue The new value to set.
196
208
  */
197
- public remember<T>(propertyName: string, newValue?: T): void
209
+ public remember<T extends JSONValue>(propertyName: string, newValue?: T): void
198
210
  {
199
211
  this._set<T>(this._volatile, propertyName, newValue);
200
212
  }
@@ -205,7 +217,7 @@ export default class JsonStorage
205
217
  * @param propertyName The name of the property to set.
206
218
  * @param newValue The new value to set.
207
219
  */
208
- public write<T>(propertyName: string, newValue?: T): void
220
+ public write<T extends JSONValue>(propertyName: string, newValue?: T): void
209
221
  {
210
222
  this._set<T>(this._persistent, propertyName, newValue);
211
223
  }
@@ -239,5 +251,5 @@ export default class JsonStorage
239
251
  this._persistent.removeItem(propertyName);
240
252
  }
241
253
 
242
- public get [Symbol.toStringTag]() { return "JsonStorage"; }
254
+ public readonly [Symbol.toStringTag]: string = "JSONStorage";
243
255
  }
@@ -0,0 +1,5 @@
1
+ export type JSONArray = JSONValue[];
2
+
3
+ // eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
4
+ export interface JSONObject { [key: string]: JSONValue }
5
+ export type JSONValue = boolean | number | string | null | JSONObject | JSONArray;
@@ -37,5 +37,5 @@ export default class DeferredPromise<T = void, F = T, R = never> extends SmartPr
37
37
  return this;
38
38
  }
39
39
 
40
- public get [Symbol.toStringTag]() { return "DeferredPromise"; }
40
+ public readonly [Symbol.toStringTag]: string = "DeferredPromise";
41
41
  }
@@ -1,5 +1,7 @@
1
1
  import DeferredPromise from "./deferred-promise.js";
2
+ import LongRunningTask from "./long-running-task.js";
2
3
  import SmartPromise from "./smart-promise.js";
4
+ import Thenable from "./thenable.js";
3
5
  import TimedPromise from "./timed-promise.js";
4
6
 
5
- export { DeferredPromise, SmartPromise, TimedPromise };
7
+ export { DeferredPromise, LongRunningTask, SmartPromise, Thenable, TimedPromise };