@byloth/core 2.0.0-rc.8 → 2.0.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/dist/core.js +3372 -609
- package/dist/core.js.map +1 -1
- package/dist/core.umd.cjs +2 -2
- package/dist/core.umd.cjs.map +1 -1
- package/package.json +13 -10
- package/src/core/types.ts +41 -0
- package/src/helpers.ts +11 -2
- package/src/index.ts +12 -9
- package/src/models/aggregators/aggregated-async-iterator.ts +765 -21
- package/src/models/aggregators/aggregated-iterator.ts +698 -22
- package/src/models/aggregators/reduced-iterator.ts +699 -10
- package/src/models/aggregators/types.ts +153 -10
- package/src/models/callbacks/callable-object.ts +42 -6
- package/src/models/callbacks/index.ts +2 -2
- package/src/models/callbacks/publisher.ts +140 -5
- package/src/models/callbacks/switchable-callback.ts +143 -5
- package/src/models/callbacks/types.ts +16 -0
- package/src/models/exceptions/core.ts +112 -3
- package/src/models/exceptions/index.ts +340 -13
- package/src/models/index.ts +4 -8
- package/src/models/iterators/smart-async-iterator.ts +687 -22
- package/src/models/iterators/smart-iterator.ts +631 -21
- package/src/models/iterators/types.ts +268 -9
- package/src/models/json/json-storage.ts +388 -110
- package/src/models/json/types.ts +10 -1
- package/src/models/promises/deferred-promise.ts +75 -5
- package/src/models/promises/index.ts +1 -3
- package/src/models/promises/smart-promise.ts +232 -4
- package/src/models/promises/timed-promise.ts +38 -1
- package/src/models/promises/types.ts +84 -2
- package/src/models/timers/clock.ts +91 -19
- package/src/models/timers/countdown.ts +152 -22
- package/src/models/timers/game-loop.ts +243 -0
- package/src/models/timers/index.ts +2 -1
- package/src/models/types.ts +6 -5
- package/src/utils/async.ts +43 -0
- package/src/utils/curve.ts +75 -0
- package/src/utils/date.ts +204 -10
- package/src/utils/dom.ts +16 -2
- package/src/utils/index.ts +3 -2
- package/src/utils/iterator.ts +200 -17
- package/src/utils/math.ts +55 -3
- package/src/utils/random.ts +109 -2
- package/src/utils/string.ts +11 -0
- package/src/models/game-loop.ts +0 -83
- package/src/models/promises/long-running-task.ts +0 -294
- package/src/models/promises/thenable.ts +0 -97
package/src/utils/async.ts
CHANGED
|
@@ -1,13 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a promise that resolves after a certain number of milliseconds.
|
|
3
|
+
* It can be used to pause or delay the execution of an asynchronous function.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* doSomething();
|
|
7
|
+
* await delay(1_000);
|
|
8
|
+
* doSomethingElse();
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* @param milliseconds The number of milliseconds to wait before resolving the promise.
|
|
12
|
+
*
|
|
13
|
+
* @returns A {@link Promise} that resolves after the specified number of milliseconds.
|
|
14
|
+
*/
|
|
1
15
|
export function delay(milliseconds: number): Promise<void>
|
|
2
16
|
{
|
|
3
17
|
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
4
18
|
}
|
|
5
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Returns a promise that resolves on the next animation frame.
|
|
22
|
+
* It can be used to synchronize operations with the browser's rendering cycle.
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* const $el = document.querySelector(".element");
|
|
26
|
+
*
|
|
27
|
+
* $el.classList.add("animate");
|
|
28
|
+
* await nextAnimationFrame();
|
|
29
|
+
* $el.style.opacity = "1";
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @returns A {@link Promise} that resolves on the next animation frame.
|
|
33
|
+
*/
|
|
6
34
|
export function nextAnimationFrame(): Promise<void>
|
|
7
35
|
{
|
|
8
36
|
return new Promise((resolve) => requestAnimationFrame(() => resolve()));
|
|
9
37
|
}
|
|
10
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Returns a promise that resolves on the next microtask.
|
|
41
|
+
* It can be used to yield to the event loop in long-running operations to prevent blocking the main thread.
|
|
42
|
+
*
|
|
43
|
+
* ```ts
|
|
44
|
+
* for (let i = 0; i < 100_000_000; i += 1)
|
|
45
|
+
* {
|
|
46
|
+
* doSomething(i);
|
|
47
|
+
*
|
|
48
|
+
* if (i % 100 === 0) await yieldToEventLoop();
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @returns A {@link Promise} that resolves on the next microtask.
|
|
53
|
+
*/
|
|
11
54
|
export function yieldToEventLoop(): Promise<void>
|
|
12
55
|
{
|
|
13
56
|
return new Promise((resolve) => setTimeout(resolve));
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { SmartIterator, ValueException } from "../models/index.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A utility class that provides a set of methods to generate sequences of numbers following specific curves.
|
|
5
|
+
* It can be used to generate sequences of values that can be
|
|
6
|
+
* used in animations, transitions and other different scenarios.
|
|
7
|
+
*
|
|
8
|
+
* It cannot be instantiated directly.
|
|
9
|
+
*/
|
|
10
|
+
export default class Curve
|
|
11
|
+
{
|
|
12
|
+
/**
|
|
13
|
+
* Generates a given number of values following a linear curve.
|
|
14
|
+
* The values are equally spaced and normalized between 0 and 1.
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* for (const value of Curve.Linear(5))
|
|
18
|
+
* {
|
|
19
|
+
* console.log(value); // 0, 0.25, 0.5, 0.75, 1
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @param values The number of values to generate.
|
|
24
|
+
*
|
|
25
|
+
* @returns A {@link SmartIterator} object that generates the values following a linear curve.
|
|
26
|
+
*/
|
|
27
|
+
public static Linear(values: number): SmartIterator<number>
|
|
28
|
+
{
|
|
29
|
+
const steps = (values - 1);
|
|
30
|
+
|
|
31
|
+
return new SmartIterator<number>(function* ()
|
|
32
|
+
{
|
|
33
|
+
for (let index = 0; index < values; index += 1) { yield index / steps; }
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Generates a given number of values following an exponential curve.
|
|
39
|
+
* The values are equally spaced and normalized between 0 and 1.
|
|
40
|
+
*
|
|
41
|
+
* ```ts
|
|
42
|
+
* for (const value of Curve.Exponential(6))
|
|
43
|
+
* {
|
|
44
|
+
* console.log(value); // 0, 0.04, 0.16, 0.36, 0.64, 1
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @param values The number of values to generate.
|
|
49
|
+
* @param base
|
|
50
|
+
* The base of the exponential curve. Default is `2`.
|
|
51
|
+
*
|
|
52
|
+
* Also note that:
|
|
53
|
+
* - If it's equal to `1`, the curve will be linear.
|
|
54
|
+
* - If it's included between `0` and `1`, the curve will be logarithmic.
|
|
55
|
+
*
|
|
56
|
+
* The base cannot be negative. If so, a {@link ValueException} will be thrown.
|
|
57
|
+
*
|
|
58
|
+
* @returns A {@link SmartIterator} object that generates the values following an exponential curve.
|
|
59
|
+
*/
|
|
60
|
+
public static Exponential(values: number, base = 2): SmartIterator<number>
|
|
61
|
+
{
|
|
62
|
+
if (base < 0) { throw new ValueException("The base of the exponential curve cannot be negative."); }
|
|
63
|
+
|
|
64
|
+
const steps = (values - 1);
|
|
65
|
+
|
|
66
|
+
return new SmartIterator<number>(function* ()
|
|
67
|
+
{
|
|
68
|
+
for (let index = 0; index < values; index += 1) { yield Math.pow(index / steps, base); }
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private constructor() { /* ... */ }
|
|
73
|
+
|
|
74
|
+
public readonly [Symbol.toStringTag]: string = "Curve";
|
|
75
|
+
}
|
package/src/utils/date.ts
CHANGED
|
@@ -1,50 +1,244 @@
|
|
|
1
1
|
|
|
2
|
-
import { SmartIterator } from "../models/index.js";
|
|
2
|
+
import { RangeException, SmartIterator } from "../models/index.js";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* An enumeration that represents the time units and their conversion factors.
|
|
6
|
+
* It can be used as utility to express time values in a more
|
|
7
|
+
* readable way or to convert time values between different units.
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* setTimeout(() => { [...] }, 5 * TimeUnit.Minute);
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
4
13
|
export enum TimeUnit
|
|
5
14
|
{
|
|
6
15
|
/* eslint-disable @typescript-eslint/prefer-literal-enum-member */
|
|
7
16
|
|
|
17
|
+
/**
|
|
18
|
+
* A millisecond: the base time unit.
|
|
19
|
+
*/
|
|
8
20
|
Millisecond = 1,
|
|
9
|
-
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A second: 1000 milliseconds.
|
|
24
|
+
*/
|
|
25
|
+
Second = 1_000,
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A minute: 60 seconds.
|
|
29
|
+
*/
|
|
10
30
|
Minute = 60 * Second,
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* An hour: 60 minutes.
|
|
34
|
+
*/
|
|
11
35
|
Hour = 60 * Minute,
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A day: 24 hours.
|
|
39
|
+
*/
|
|
12
40
|
Day = 24 * Hour,
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A week: 7 days.
|
|
44
|
+
*/
|
|
13
45
|
Week = 7 * Day,
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* A month: 30 days.
|
|
49
|
+
*/
|
|
14
50
|
Month = 30 * Day,
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* A year: 365 days.
|
|
54
|
+
*/
|
|
15
55
|
Year = 365 * Day
|
|
16
56
|
}
|
|
17
57
|
|
|
58
|
+
/**
|
|
59
|
+
* An enumeration that represents the days of the week.
|
|
60
|
+
* It can be used as utility to identify the days of the week when working with dates.
|
|
61
|
+
*
|
|
62
|
+
* ```ts
|
|
63
|
+
* const today = new Date();
|
|
64
|
+
* if (today.getUTCDay() === WeekDay.Sunday)
|
|
65
|
+
* {
|
|
66
|
+
* // Today is Sunday. Do something...
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export enum WeekDay
|
|
71
|
+
{
|
|
72
|
+
/**
|
|
73
|
+
* Sunday
|
|
74
|
+
*/
|
|
75
|
+
Sunday = 0,
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Monday
|
|
79
|
+
*/
|
|
80
|
+
Monday = 1,
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Tuesday
|
|
84
|
+
*/
|
|
85
|
+
Tuesday = 2,
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Wednesday
|
|
89
|
+
*/
|
|
90
|
+
Wednesday = 3,
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Thursday
|
|
94
|
+
*/
|
|
95
|
+
Thursday = 4,
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Friday
|
|
99
|
+
*/
|
|
100
|
+
Friday = 5,
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Saturday
|
|
104
|
+
*/
|
|
105
|
+
Saturday = 6
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* An utility function that calculates the difference between two dates.
|
|
110
|
+
* The difference can be expressed in different time units.
|
|
111
|
+
*
|
|
112
|
+
* ```ts
|
|
113
|
+
* const start = new Date("2025-01-01");
|
|
114
|
+
* const end = new Date("2025-01-31");
|
|
115
|
+
*
|
|
116
|
+
* dateDifference(start, end, TimeUnit.Minute); // 43200
|
|
117
|
+
* ```
|
|
118
|
+
*
|
|
119
|
+
* @param start The start date.
|
|
120
|
+
* @param end The end date.
|
|
121
|
+
* @param unit The time unit to express the difference. `TimeUnit.Day` by default.
|
|
122
|
+
*
|
|
123
|
+
* @returns The difference between the two dates in the specified time unit.
|
|
124
|
+
*/
|
|
18
125
|
export function dateDifference(start: string | Date, end: string | Date, unit = TimeUnit.Day): number
|
|
19
126
|
{
|
|
127
|
+
let _round: (value: number) => number;
|
|
128
|
+
|
|
20
129
|
start = new Date(start);
|
|
21
130
|
end = new Date(end);
|
|
22
131
|
|
|
23
|
-
|
|
132
|
+
if (start < end) { _round = Math.floor; }
|
|
133
|
+
else { _round = Math.ceil; }
|
|
134
|
+
|
|
135
|
+
return _round((end.getTime() - start.getTime()) / unit);
|
|
24
136
|
}
|
|
25
137
|
|
|
26
|
-
|
|
138
|
+
/**
|
|
139
|
+
* An utility function that generates an iterator over a range of dates.
|
|
140
|
+
* The step between the dates can be expressed in different time units.
|
|
141
|
+
*
|
|
142
|
+
* ```ts
|
|
143
|
+
* const start = new Date("2025-01-01");
|
|
144
|
+
* const end = new Date("2025-01-31");
|
|
145
|
+
*
|
|
146
|
+
* for (const date of dateRange(start, end, TimeUnit.Week))
|
|
147
|
+
* {
|
|
148
|
+
* date.toISOString().slice(8, 10); // "01", "08", "15", "22", "29"
|
|
149
|
+
* }
|
|
150
|
+
* ```
|
|
151
|
+
*
|
|
152
|
+
* @param start The start date (included).
|
|
153
|
+
* @param end
|
|
154
|
+
* The end date (excluded).
|
|
155
|
+
*
|
|
156
|
+
* Must be greater than the start date. Otherwise, a {@link RangeException} will be thrown.
|
|
157
|
+
*
|
|
158
|
+
* @param step The time unit to express the step between the dates. `TimeUnit.Day` by default.
|
|
159
|
+
*
|
|
160
|
+
* @returns A {@link SmartIterator} object that generates the dates in the range.
|
|
161
|
+
*/
|
|
162
|
+
export function dateRange(start: string | Date, end: string | Date, step = TimeUnit.Day): SmartIterator<Date>
|
|
27
163
|
{
|
|
28
|
-
start
|
|
29
|
-
end = new Date(end);
|
|
164
|
+
if (start >= end) { throw new RangeException("The end date must be greater than the start date."); }
|
|
30
165
|
|
|
31
166
|
return new SmartIterator<Date>(function* ()
|
|
32
167
|
{
|
|
33
|
-
const endTime = end.getTime();
|
|
168
|
+
const endTime = new Date(end).getTime();
|
|
34
169
|
|
|
35
|
-
let unixTime: number = start.getTime();
|
|
170
|
+
let unixTime: number = new Date(start).getTime();
|
|
36
171
|
while (unixTime < endTime)
|
|
37
172
|
{
|
|
38
173
|
yield new Date(unixTime);
|
|
39
174
|
|
|
40
|
-
unixTime +=
|
|
175
|
+
unixTime += step;
|
|
41
176
|
}
|
|
42
177
|
});
|
|
43
178
|
}
|
|
44
179
|
|
|
180
|
+
/**
|
|
181
|
+
* An utility function that rounds a date to the nearest time unit.
|
|
182
|
+
* The rounding can be expressed in different time units.
|
|
183
|
+
*
|
|
184
|
+
* ```ts
|
|
185
|
+
* const date = new Date("2025-01-01T12:34:56.789Z");
|
|
186
|
+
*
|
|
187
|
+
* dateRound(date, TimeUnit.Hour); // 2025-01-01T12:00:00.000Z
|
|
188
|
+
* ```
|
|
189
|
+
*
|
|
190
|
+
* @param date The date to round.
|
|
191
|
+
* @param unit
|
|
192
|
+
* The time unit to express the rounding. `TimeUnit.Day` by default.
|
|
193
|
+
*
|
|
194
|
+
* Must be greater than a millisecond and less than or equal to a day.
|
|
195
|
+
* Otherwise, a {@link RangeException} will be thrown.
|
|
196
|
+
*
|
|
197
|
+
* @returns The rounded date.
|
|
198
|
+
*/
|
|
45
199
|
export function dateRound(date: string | Date, unit = TimeUnit.Day): Date
|
|
46
200
|
{
|
|
47
|
-
|
|
201
|
+
if (unit <= TimeUnit.Millisecond)
|
|
202
|
+
{
|
|
203
|
+
throw new RangeException(
|
|
204
|
+
"Rounding a timestamp by milliseconds or less makes no sense." +
|
|
205
|
+
"Use the timestamp value directly instead."
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
if (unit > TimeUnit.Day)
|
|
209
|
+
{
|
|
210
|
+
throw new RangeException(
|
|
211
|
+
"Rounding by more than a day leads to unexpected results. " +
|
|
212
|
+
"Consider using other methods to round dates by weeks, months or years."
|
|
213
|
+
);
|
|
214
|
+
}
|
|
48
215
|
|
|
216
|
+
date = new Date(date);
|
|
49
217
|
return new Date(Math.floor(date.getTime() / unit) * unit);
|
|
50
218
|
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* An utility function that gets the week of a date.
|
|
222
|
+
* The first day of the week can be optionally specified.
|
|
223
|
+
*
|
|
224
|
+
* ```ts
|
|
225
|
+
* const date = new Date("2025-01-01");
|
|
226
|
+
*
|
|
227
|
+
* getWeek(date, WeekDay.Monday); // 2024-12-30
|
|
228
|
+
* ```
|
|
229
|
+
*
|
|
230
|
+
* @param date The date to get the week of.
|
|
231
|
+
* @param firstDay The first day of the week. `WeekDay.Sunday` by default.
|
|
232
|
+
*
|
|
233
|
+
* @returns The first day of the week of the specified date.
|
|
234
|
+
*/
|
|
235
|
+
export function getWeek(date: string | Date, firstDay = WeekDay.Sunday): Date
|
|
236
|
+
{
|
|
237
|
+
date = new Date(date);
|
|
238
|
+
|
|
239
|
+
const startCorrector = 7 - firstDay;
|
|
240
|
+
const weekDayIndex = (date.getUTCDay() + startCorrector) % 7;
|
|
241
|
+
const firstDayTime = date.getTime() - (TimeUnit.Day * weekDayIndex);
|
|
242
|
+
|
|
243
|
+
return dateRound(new Date(firstDayTime));
|
|
244
|
+
}
|
package/src/utils/dom.ts
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Appends a script element to the document body.
|
|
3
|
+
* It can be used to load external scripts dynamically.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* await loadScript("https://analytics.service/script.js?id=0123456789");
|
|
7
|
+
* ```
|
|
8
|
+
*
|
|
9
|
+
* @param scriptUrl The URL of the script to load.
|
|
10
|
+
* @param scriptType The type of the script to load. Default is `"text/javascript"`.
|
|
11
|
+
*
|
|
12
|
+
* @returns
|
|
13
|
+
* A {@link Promise} that resolves when the script has been loaded successfully or rejects if an error occurs.
|
|
14
|
+
*/
|
|
1
15
|
export function loadScript(scriptUrl: string, scriptType = "text/javascript"): Promise<void>
|
|
2
16
|
{
|
|
3
17
|
return new Promise<void>((resolve, reject) =>
|
|
@@ -9,8 +23,8 @@ export function loadScript(scriptUrl: string, scriptType = "text/javascript"): P
|
|
|
9
23
|
script.src = scriptUrl;
|
|
10
24
|
script.type = scriptType;
|
|
11
25
|
|
|
12
|
-
script.onload = () => resolve();
|
|
13
|
-
script.onerror = () => reject();
|
|
26
|
+
script.onload = (evt) => resolve();
|
|
27
|
+
script.onerror = (reason) => reject(reason);
|
|
14
28
|
|
|
15
29
|
document.body.appendChild(script);
|
|
16
30
|
});
|
package/src/utils/index.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import Curve from "./curve.js";
|
|
1
2
|
import Random from "./random.js";
|
|
2
3
|
|
|
3
4
|
export { delay, nextAnimationFrame, yieldToEventLoop } from "./async.js";
|
|
4
|
-
export { dateDifference, dateRange, dateRound, TimeUnit } from "./date.js";
|
|
5
|
+
export { dateDifference, dateRange, dateRound, getWeek, TimeUnit, WeekDay } from "./date.js";
|
|
5
6
|
export { loadScript } from "./dom.js";
|
|
6
7
|
export { chain, count, enumerate, range, shuffle, unique, zip } from "./iterator.js";
|
|
7
8
|
export { average, hash, sum } from "./math.js";
|
|
8
9
|
export { capitalize } from "./string.js";
|
|
9
10
|
|
|
10
|
-
export { Random };
|
|
11
|
+
export { Curve, Random };
|