@zelgadis87/utils-core 4.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.
Files changed (134) hide show
  1. package/dist/Lazy.d.ts +21 -0
  2. package/dist/LazyAsync.d.ts +23 -0
  3. package/dist/Logger.d.ts +21 -0
  4. package/dist/Optional.d.ts +70 -0
  5. package/dist/async/CancelableDeferred.d.ts +17 -0
  6. package/dist/async/Deferred.d.ts +27 -0
  7. package/dist/async/RateThrottler.d.ts +12 -0
  8. package/dist/async/Semaphore.d.ts +10 -0
  9. package/dist/async/index.d.ts +4 -0
  10. package/dist/index.d.ts +11 -0
  11. package/dist/random/index.d.ts +2 -0
  12. package/dist/random/randomInterval.d.ts +1 -0
  13. package/dist/random/randomPercentage.d.ts +1 -0
  14. package/dist/sorting/ComparisonChain.d.ts +57 -0
  15. package/dist/sorting/Sorter.d.ts +100 -0
  16. package/dist/sorting/index.d.ts +4 -0
  17. package/dist/sorting/types.d.ts +5 -0
  18. package/dist/time/RandomTimeDuration.d.ts +9 -0
  19. package/dist/time/TimeBase.d.ts +38 -0
  20. package/dist/time/TimeDuration.d.ts +81 -0
  21. package/dist/time/TimeFrequency.d.ts +10 -0
  22. package/dist/time/TimeInstant.d.ts +137 -0
  23. package/dist/time/TimeInstantBuilder.d.ts +77 -0
  24. package/dist/time/TimeUnit.d.ts +17 -0
  25. package/dist/time/index.d.ts +6 -0
  26. package/dist/time/types.d.ts +26 -0
  27. package/dist/tsconfig.tsbuildinfo +1 -0
  28. package/dist/types/arrays.d.ts +33 -0
  29. package/dist/types/booleans.d.ts +2 -0
  30. package/dist/types/functions.d.ts +20 -0
  31. package/dist/types/index.d.ts +12 -0
  32. package/dist/types/json.d.ts +6 -0
  33. package/dist/types/nulls.d.ts +8 -0
  34. package/dist/types/numbers.d.ts +31 -0
  35. package/dist/types/promises.d.ts +6 -0
  36. package/dist/types/records.d.ts +14 -0
  37. package/dist/types/strings.d.ts +40 -0
  38. package/dist/upgrade/DataUpgrader.d.ts +22 -0
  39. package/dist/upgrade/errors.d.ts +12 -0
  40. package/dist/upgrade/getTransitionsPath.d.ts +3 -0
  41. package/dist/upgrade/index.d.ts +2 -0
  42. package/dist/upgrade/types.d.ts +31 -0
  43. package/dist/utils/asError.d.ts +1 -0
  44. package/dist/utils/bindThis.d.ts +1 -0
  45. package/dist/utils/constant.d.ts +8 -0
  46. package/dist/utils/entries.d.ts +4 -0
  47. package/dist/utils/groupBy.d.ts +7 -0
  48. package/dist/utils/iff.d.ts +8 -0
  49. package/dist/utils/index.d.ts +22 -0
  50. package/dist/utils/indexBy.d.ts +7 -0
  51. package/dist/utils/jsonCloneDeep.d.ts +2 -0
  52. package/dist/utils/math.d.ts +9 -0
  53. package/dist/utils/noop.d.ts +1 -0
  54. package/dist/utils/omit.d.ts +2 -0
  55. package/dist/utils/pad.d.ts +3 -0
  56. package/dist/utils/pluralize.d.ts +1 -0
  57. package/dist/utils/round.d.ts +8 -0
  58. package/dist/utils/sortBy.d.ts +7 -0
  59. package/dist/utils/throttle.d.ts +3 -0
  60. package/dist/utils/uniq.d.ts +1 -0
  61. package/dist/utils/uniqBy.d.ts +2 -0
  62. package/dist/utils/uniqByKey.d.ts +1 -0
  63. package/dist/utils/upsert.d.ts +0 -0
  64. package/dist/utils/withTryCatch.d.ts +2 -0
  65. package/dist/utils/withTryCatchAsync.d.ts +2 -0
  66. package/dist/utils/wrap.d.ts +1 -0
  67. package/esbuild/index.cjs +2670 -0
  68. package/esbuild/index.mjs +2518 -0
  69. package/package.json +159 -0
  70. package/src/Lazy.ts +77 -0
  71. package/src/LazyAsync.ts +100 -0
  72. package/src/Logger.ts +44 -0
  73. package/src/Optional.ts +172 -0
  74. package/src/async/CancelableDeferred.ts +36 -0
  75. package/src/async/Deferred.ts +84 -0
  76. package/src/async/RateThrottler.ts +46 -0
  77. package/src/async/Semaphore.ts +45 -0
  78. package/src/async/index.ts +6 -0
  79. package/src/index.ts +13 -0
  80. package/src/random/index.ts +3 -0
  81. package/src/random/randomInterval.ts +4 -0
  82. package/src/random/randomPercentage.ts +6 -0
  83. package/src/sorting/ComparisonChain.ts +209 -0
  84. package/src/sorting/Sorter.ts +357 -0
  85. package/src/sorting/index.ts +5 -0
  86. package/src/sorting/types.ts +7 -0
  87. package/src/time/RandomTimeDuration.ts +21 -0
  88. package/src/time/TimeBase.ts +113 -0
  89. package/src/time/TimeDuration.ts +296 -0
  90. package/src/time/TimeFrequency.ts +28 -0
  91. package/src/time/TimeInstant.ts +488 -0
  92. package/src/time/TimeInstantBuilder.ts +126 -0
  93. package/src/time/TimeUnit.ts +43 -0
  94. package/src/time/index.ts +8 -0
  95. package/src/time/types.ts +56 -0
  96. package/src/types/arrays.ts +89 -0
  97. package/src/types/booleans.ts +8 -0
  98. package/src/types/functions.ts +27 -0
  99. package/src/types/index.ts +18 -0
  100. package/src/types/json.ts +5 -0
  101. package/src/types/nulls.ts +33 -0
  102. package/src/types/numbers.ts +80 -0
  103. package/src/types/promises.ts +23 -0
  104. package/src/types/records.ts +21 -0
  105. package/src/types/strings.ts +143 -0
  106. package/src/upgrade/DataUpgrader.ts +100 -0
  107. package/src/upgrade/errors.ts +25 -0
  108. package/src/upgrade/getTransitionsPath.ts +89 -0
  109. package/src/upgrade/index.ts +4 -0
  110. package/src/upgrade/types.ts +36 -0
  111. package/src/utils/asError.ts +12 -0
  112. package/src/utils/bindThis.ts +4 -0
  113. package/src/utils/constant.ts +9 -0
  114. package/src/utils/entries.ts +13 -0
  115. package/src/utils/groupBy.ts +39 -0
  116. package/src/utils/iff.ts +26 -0
  117. package/src/utils/index.ts +24 -0
  118. package/src/utils/indexBy.ts +36 -0
  119. package/src/utils/jsonCloneDeep.ts +31 -0
  120. package/src/utils/math.ts +44 -0
  121. package/src/utils/noop.ts +2 -0
  122. package/src/utils/omit.ts +8 -0
  123. package/src/utils/pad.ts +20 -0
  124. package/src/utils/pluralize.ts +20 -0
  125. package/src/utils/round.ts +24 -0
  126. package/src/utils/sortBy.ts +27 -0
  127. package/src/utils/throttle.ts +10 -0
  128. package/src/utils/uniq.ts +6 -0
  129. package/src/utils/uniqBy.ts +15 -0
  130. package/src/utils/uniqByKey.ts +5 -0
  131. package/src/utils/upsert.ts +2 -0
  132. package/src/utils/withTryCatch.ts +10 -0
  133. package/src/utils/withTryCatchAsync.ts +6 -0
  134. package/src/utils/wrap.ts +4 -0
@@ -0,0 +1,296 @@
1
+ import Deferred, { ICancelablePromise } from "../async/Deferred.js";
2
+ import { randomInterval } from "../random";
3
+ import { TComparisonResult } from "../sorting/index.js";
4
+ import { TIntervalHandle, TMaybe, TTimeoutHandle, TVoidFunction, ensureNonNegativeNumber, ensurePositiveNumber } from "../types";
5
+ import { pad } from "../utils";
6
+ import TimeBase from "./TimeBase";
7
+ import TimeInstant from "./TimeInstant";
8
+ import TimeUnit from "./TimeUnit";
9
+
10
+ export class TimeDuration extends TimeBase<TimeDuration> {
11
+
12
+ protected constructor( value: number, unit: TimeUnit ) {
13
+ super( value, unit );
14
+ if ( value < 0 )
15
+ throw new Error( 'Duration cannot be less than 0' );
16
+ }
17
+
18
+ protected create( value: number, unit: TimeUnit ) {
19
+ return new TimeDuration( value, unit );
20
+ }
21
+
22
+ public addDuration( duration: TimeDuration ): TimeDuration {
23
+ return this.addUnits( duration.ms, TimeUnit.MILLISECONDS );
24
+ }
25
+
26
+ public removeDuration( duration: TimeDuration ): TimeDuration {
27
+ return this.removeUnits( duration.ms, TimeUnit.MILLISECONDS );
28
+ }
29
+
30
+ public override removeUnits( n: number, unit: TimeUnit ): TimeDuration {
31
+ const nn = Math.min( n, this.getUnit( unit ) ); // Avoid going negative.
32
+ return super.removeUnits( nn, unit );
33
+ }
34
+
35
+ /** @deprecated: Use multiplyBy instead **/
36
+ public multiply( times: number ) {
37
+ return this.multiplyBy( times );
38
+ }
39
+
40
+ public multiplyBy( times: number ): TimeDuration {
41
+ ensureNonNegativeNumber( times, "times" );
42
+ return TimeDuration.ms( this.ms * times );
43
+ }
44
+
45
+ public divideBy( times: number ): TimeDuration {
46
+ ensurePositiveNumber( times, "times" );
47
+ return TimeDuration.ms( this.ms / times );
48
+ }
49
+
50
+ /**
51
+ * Returns the current duration in a human readable format, prioritizing the most significant unit of time and excluding the rest.
52
+ * @todo[2023-06] Should allow more customization options
53
+ * @todo[2023-06] By default should show the secondary unit only when actually needed (eg, 1h 20m & 3h, instead of 1h 20m & 3h 28m)
54
+ * @todo[2023-06] Should not allow negative durations, as this is a duration and not an instant.
55
+ * @returns the duration, with only the most significant units displayed as a human readable string, eg: 1d 20h, 10m 30s.
56
+ */
57
+ public get formatted(): string {
58
+ const format = ( x: number, u1: string, y: number, u2: string ): string => `${x}${u1} ${pad( y.toString(), 2, '0' )}${u2}`;
59
+ const units = this.toUnits();
60
+
61
+ if ( units.days >= 1 )
62
+ return format( units.days, 'd', units.hours, 'h' );
63
+ else if ( units.hours >= 1 )
64
+ return format( units.hours, 'h', units.minutes, 'm' );
65
+ else if ( units.minutes >= 1 )
66
+ return format( units.minutes, 'm', units.seconds, 's' );
67
+ else if ( units.seconds >= 0 )
68
+ return units.seconds.toString() + 's';
69
+ else if ( units.seconds > -60 )
70
+ return 'A few moments ago';
71
+ else
72
+ return 'Some time ago';
73
+ }
74
+
75
+ /**
76
+ * @deprecated[2023-06] this method makes no sense, as durations are positive by default.
77
+ */
78
+ public absolute(): TimeDuration {
79
+ return this.ms < 0 ? new TimeDuration( -this.ms, TimeUnit.MILLISECONDS ) : this;
80
+ }
81
+
82
+ public interval( cb: () => unknown ): TIntervalHandle {
83
+ return setInterval( cb, this.ms );
84
+ }
85
+
86
+ public timeout( cb: () => unknown ): TTimeoutHandle {
87
+ return setTimeout( cb, this.ms );
88
+ }
89
+
90
+
91
+ public promise(): ICancelablePromise<void> {
92
+ const deferred = new Deferred<void>;
93
+ if ( this.isEmpty() ) {
94
+ deferred.resolve();
95
+ } else {
96
+ this.timeout( () => deferred.resolve() );
97
+ }
98
+ return deferred.asCancelablePromise;
99
+ }
100
+
101
+ public delay( cb: () => unknown ): { cancel: TVoidFunction } {
102
+ const deferred = this.promise();
103
+ void deferred.then( () => {
104
+ cb();
105
+ }, _err => {
106
+ return; // Do nothing on cancelation ( err is always an instance of DeferredCanceledError )
107
+ } );
108
+ return { cancel: () => deferred.cancel() };
109
+ }
110
+
111
+ public debounce<T>( fn: ( t: T ) => void ) {
112
+ let handle: TMaybe<TTimeoutHandle> = null;
113
+ return ( t: T ) => {
114
+ if ( handle )
115
+ clearTimeout( handle );
116
+ handle = this.timeout( () => {
117
+ handle = null;
118
+ fn( t );
119
+ } );
120
+ }
121
+ }
122
+
123
+ public toDigitalClock(): string {
124
+ const units = this.toUnits();
125
+ // data.hours += data.days * 24; // roll over days as hours.
126
+ return pad( units.hours.toString(), 2, '0' ) + ':' + pad( units.minutes.toString(), 2, '0' ) + ':' + pad( units.seconds.toString(), 2, '0' );
127
+ }
128
+
129
+ public get asSeconds(): string {
130
+ if ( this.ms < 0 )
131
+ return "0";
132
+ if ( this.ms < 1000 )
133
+ return ( this.ms / 1000 ).toFixed( 1 );
134
+ return Math.floor( this.seconds ).toString();
135
+ }
136
+
137
+ public fromNow(): TimeInstant {
138
+ return TimeInstant.now().addDuration( this );
139
+ }
140
+
141
+ public differenceFrom( other: TimeDuration ): TimeDuration {
142
+ return new TimeDuration( Math.abs( this.ms - other.ms ), TimeUnit.MILLISECONDS );
143
+ }
144
+
145
+ /** @deprecated: Use fromNow instead **/
146
+ public addCurrentTime() {
147
+ return this.fromNow();
148
+ }
149
+
150
+ public isGreaterThan( other: TimeDuration ): boolean {
151
+ return this.ms > other.ms;
152
+ }
153
+
154
+ public isLessThan( other: TimeDuration ): boolean {
155
+ return this.ms < other.ms;
156
+ }
157
+
158
+ public compareTo( other: TimeDuration ): TComparisonResult {
159
+ if ( this.ms === other.ms ) {
160
+ return 0;
161
+ } else if ( this.isLessThan( other ) ) {
162
+ return -1;
163
+ } else {
164
+ return 1;
165
+ }
166
+ }
167
+
168
+ public atLeast( other: TimeDuration ): TimeDuration {
169
+ if ( !this.isLessThan( other ) ) {
170
+ return this;
171
+ } else {
172
+ return other;
173
+ }
174
+ }
175
+
176
+ public atMost( other: TimeDuration ): TimeDuration {
177
+ if ( !this.isGreaterThan( other ) ) {
178
+ return this;
179
+ } else {
180
+ return other;
181
+ }
182
+ }
183
+
184
+ public isEmpty(): boolean {
185
+ return this.ms <= 0;
186
+ }
187
+
188
+ public isNotEmpty(): boolean {
189
+ return this.ms > 0;
190
+ }
191
+
192
+ /**
193
+ * This method is used to provide a better DX when inspecting a TimeInstant object in DevTools.
194
+ */
195
+ protected get _duration() {
196
+ return this.formatted;
197
+ }
198
+
199
+ public override toString() {
200
+ return `${this.constructor.name}[${this.formatted}]`;
201
+ }
202
+
203
+ public static parseHumanTime( humanTime: string ): TimeDuration {
204
+ const match = humanTime.trim().match( /^(?:([0-9]+)d|)\s*(?:([0-9]+)h|)\s*(?:([0-9]+)m|)\s*(?:([0-9]+)s|)$/ );
205
+ if ( match ) {
206
+ const [ _, days, hours, minutes, seconds ] = match;
207
+ return new TimeDuration( TimeBase.toMs( { days: Number( days ?? 0 ), hours: Number( hours ?? 0 ), minutes: Number( minutes ?? 0 ), seconds: Number( seconds ?? 0 ) } ), TimeUnit.MILLISECONDS );
208
+ }
209
+ throw new Error( 'Failed to parse time: ' + humanTime );
210
+ }
211
+
212
+ public static compare( a: TimeDuration, b: TimeDuration ): TComparisonResult {
213
+ return a.compareTo( b );
214
+ }
215
+
216
+ public static ms = durationConstructor( TimeUnit.MILLISECONDS );
217
+ public static seconds = durationConstructor( TimeUnit.SECONDS );
218
+ public static minutes = durationConstructor( TimeUnit.MINUTES );
219
+ public static hours = durationConstructor( TimeUnit.HOURS );
220
+ public static days = durationConstructor( TimeUnit.DAYS );
221
+
222
+ public static shamefulUnref = ( ms: TAllowedTimeDuration ): number => {
223
+ if ( ms instanceof TimeDuration ) {
224
+ return ms.ms;
225
+ }
226
+ return ms;
227
+ }
228
+ public static shamefulRef = ( ms: TAllowedTimeDuration ): TimeDuration => {
229
+ if ( ms instanceof TimeDuration ) {
230
+ return ms;
231
+ }
232
+ if ( ms < 0 ) {
233
+ ms = 0;
234
+ }
235
+ return TimeDuration.ms( ms );
236
+ }
237
+
238
+ public static unref = ( ms: TValidTimeDuration ): TPredefinedTimeDuration => {
239
+ return TimeDuration.shamefulUnref( ms ) as TPredefinedTimeDuration;
240
+ }
241
+
242
+ public static ref = ( ms: TValidTimeDuration ): TimeDuration => {
243
+ return TimeDuration.shamefulRef( ms );
244
+ }
245
+
246
+ public static fromMs( ms: number ) {
247
+ return new TimeDuration( ms, TimeUnit.MILLISECONDS );
248
+ }
249
+
250
+ public static distanceFromNow( instant: TimeInstant ): TimeDuration {
251
+ return TimeDuration.distance( TimeInstant.now(), instant );
252
+ }
253
+
254
+ public static distance( instant1: TimeInstant, instant2: TimeInstant ): TimeDuration {
255
+ return instant1.distanceFrom( instant2 );
256
+ }
257
+
258
+ public static greatest( duration1: TimeDuration, duration2: TimeDuration ): TimeDuration {
259
+ return duration1.isGreaterThan( duration2 ) ? duration1 : duration2;
260
+ }
261
+
262
+ public static lowest( duration1: TimeDuration, duration2: TimeDuration ): TimeDuration {
263
+ return duration1.isLessThan( duration2 ) ? duration1 : duration2;
264
+ }
265
+
266
+ public static ZERO = new TimeDuration( 0, TimeUnit.MILLISECONDS );
267
+
268
+ public static fromJSON( ms: number ) {
269
+ return TimeDuration.ms( ms );
270
+ }
271
+
272
+ }
273
+
274
+ interface IDurationConstructor {
275
+ ( a: number ): TimeDuration
276
+ /** @deprecated[2023-06] Use RandomTimeDuration instead */( a: number, b?: number ): TimeDuration
277
+ }
278
+
279
+ /** @deprecated[2023-06] Use RandomTimeDuration instead */
280
+ function durationConstructor( unit: TimeUnit ): IDurationConstructor {
281
+ return ( a: number, b?: number ) => {
282
+ const aMs = unit.toMs( a );
283
+ const bMs = b ? unit.toMs( b ) : aMs;
284
+ return TimeDuration.fromMs( randomInterval( aMs, bMs ) );
285
+ }
286
+ }
287
+
288
+ export type TPredefinedTimeDuration = 0 | 50 | 100 | 150 | 200 | 250 | 300 | 500 | 1000 | 1500 | 2000 | 2500 | 5000;
289
+ export type TValidTimeDuration = TimeDuration | TPredefinedTimeDuration;
290
+ type TAllowedTimeDuration = TValidTimeDuration | number; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents
291
+
292
+ export function isAllowedTimeDuration( t: unknown ): t is TAllowedTimeDuration {
293
+ return ( typeof t === "number" && t > 0 ) || t instanceof TimeDuration;
294
+ }
295
+
296
+ export default TimeDuration;
@@ -0,0 +1,28 @@
1
+ import { TPositiveNumber } from "../types";
2
+ import TimeDuration from "./TimeDuration";
3
+
4
+ export default class TimeFrequency {
5
+
6
+ public constructor(
7
+ public readonly times: TPositiveNumber,
8
+ public readonly period: TimeDuration,
9
+ ) {
10
+ if ( isNaN( times ) || times <= 0 )
11
+ throw new Error();
12
+ if ( period.isEmpty() )
13
+ throw new Error();
14
+ }
15
+
16
+ public get frequency() {
17
+ return this.period.divideBy( this.times );
18
+ }
19
+
20
+ public static onceEvery( period: TimeDuration ) {
21
+ return new TimeFrequency( 1, period );
22
+ }
23
+
24
+ public static twiceEvery( period: TimeDuration ) {
25
+ return new TimeFrequency( 2, period );
26
+ }
27
+
28
+ }