@softsky/utils 2.5.4 → 2.6.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 +89 -3
- package/dist/control.d.ts +55 -7
- package/dist/control.js +100 -51
- package/dist/errors.d.ts +11 -0
- package/dist/errors.js +15 -0
- package/dist/numbers.d.ts +18 -0
- package/dist/numbers.js +41 -2
- package/dist/objects.d.ts +27 -3
- package/dist/objects.js +38 -4
- package/dist/signals.d.ts +1 -2
- package/dist/signals.js +4 -5
- package/dist/time.d.ts +17 -2
- package/dist/time.js +49 -4
- package/dist/types.d.ts +21 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -150,7 +150,7 @@ __function__ `createThrottledFunction` - Create throttled function. Basically li
|
|
|
150
150
|
|
|
151
151
|
---
|
|
152
152
|
__function__ `createDelayedFunction` - Create debounced function. Basically create function that will be called with delay,
|
|
153
|
-
but if another call comes in, we reset the timer.
|
|
153
|
+
but if another call comes in, we reset the timer (previous function isn't called).
|
|
154
154
|
|
|
155
155
|
---
|
|
156
156
|
__class__ `ImmediatePromise` - Promise that accepts no callback, but exposes `resolve` and `reject` methods
|
|
@@ -158,6 +158,9 @@ __class__ `ImmediatePromise` - Promise that accepts no callback, but exposes `re
|
|
|
158
158
|
---
|
|
159
159
|
__function__ `wait` - setTimeout promisify
|
|
160
160
|
|
|
161
|
+
---
|
|
162
|
+
__function__ `timeout` - Reject after specified time
|
|
163
|
+
|
|
161
164
|
---
|
|
162
165
|
__function__ `noop` - Empty function that does nothing
|
|
163
166
|
|
|
@@ -167,6 +170,37 @@ __async function__ `concurrentRun` - Run array of async tasks concurrently
|
|
|
167
170
|
---
|
|
168
171
|
__class__ `SimpleEventSource` - Create simple event source. Consider using `signal()` for reactive state managment.
|
|
169
172
|
|
|
173
|
+
---
|
|
174
|
+
__class__ `Semaphore` - Semaphore is used to limit concurrent tasks by delaying promise.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
const semaphore = new Semaphore(2);
|
|
178
|
+
|
|
179
|
+
async function task() {
|
|
180
|
+
await semaphore.acquire();
|
|
181
|
+
try {
|
|
182
|
+
// This code can only be executed by two tasks at the same time
|
|
183
|
+
} finally {
|
|
184
|
+
semaphore.release();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
task();
|
|
188
|
+
task();
|
|
189
|
+
task(); // This task will wait until one of the previous tasks releases the semaphore.
|
|
190
|
+
|
|
191
|
+
// === SHORTHAND ===
|
|
192
|
+
semaphore.run(()=>{
|
|
193
|
+
// Your code
|
|
194
|
+
})
|
|
195
|
+
semaphore.run(()=>{
|
|
196
|
+
// Your code
|
|
197
|
+
})
|
|
198
|
+
// ...
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
__async function__ `withTimeout` - Add timeout to a promise
|
|
203
|
+
|
|
170
204
|
---
|
|
171
205
|
|
|
172
206
|
|
|
@@ -175,6 +209,9 @@ Custom errors, finding errors and error handling.
|
|
|
175
209
|
|
|
176
210
|
__class__ `ValidationError` - Use as intended error. Basically 4** errors in HTTP
|
|
177
211
|
|
|
212
|
+
---
|
|
213
|
+
__class__ `TimeoutError` - Use as intended error. Basically 4** errors in HTTP
|
|
214
|
+
|
|
178
215
|
---
|
|
179
216
|
__function__ `findErrorText` - Find error inside anything recursively.
|
|
180
217
|
Good for finding human-readable errors.
|
|
@@ -274,6 +311,27 @@ __function__ `factorial` - Factorial
|
|
|
274
311
|
---
|
|
275
312
|
__function__ `fib` - Fibonacci
|
|
276
313
|
|
|
314
|
+
---
|
|
315
|
+
__function__ `clamp` - Clamp numbers to max and min
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
__function__ `inRange` - Is number in range. Inclusive.
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
__function__ `mean` - Calucalate avarage from array of numbers
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
__function__ `round` - Round with precision.
|
|
325
|
+
|
|
326
|
+
```ts
|
|
327
|
+
round(1.2345); // 1
|
|
328
|
+
round(1.2345, 2); // 1.23
|
|
329
|
+
round(1.2345, 10); // 1.2345
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
__function__ `sum` - Sum of array of numbers
|
|
334
|
+
|
|
277
335
|
---
|
|
278
336
|
|
|
279
337
|
|
|
@@ -352,7 +410,7 @@ Effects are simplest way to react to signal changes.
|
|
|
352
410
|
Returned data from handler function will be passed to it on next signal change.
|
|
353
411
|
Returns a function that will clear the effect.
|
|
354
412
|
|
|
355
|
-
|
|
413
|
+
|
|
356
414
|
// Will print signal on change
|
|
357
415
|
effect(()=>{
|
|
358
416
|
console.log($mySignal())
|
|
@@ -363,7 +421,6 @@ const mySignal = $mySignal()
|
|
|
363
421
|
if(last>mySignal) console.log('Increment!')
|
|
364
422
|
return mySignal;
|
|
365
423
|
})
|
|
366
|
-
```
|
|
367
424
|
|
|
368
425
|
---
|
|
369
426
|
__function__ `untrack` - __SIGNALS SYSTEM__
|
|
@@ -430,6 +487,18 @@ Timers, CRON, etc.
|
|
|
430
487
|
|
|
431
488
|
__function__ `measurePerformance` - Measure performance of a function
|
|
432
489
|
|
|
490
|
+
---
|
|
491
|
+
__function__ `setSafeTimeout` - Original setTimeout and setIntval known for accumulating delay
|
|
492
|
+
and causing problem with timeouts bigger than 32bit integer.
|
|
493
|
+
|
|
494
|
+
This timeout wrapper fixes them. Returns clear function.
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
__function__ `setSafeInterval` - Original setTimeout and setIntval known for accumulating delay
|
|
498
|
+
and causing problem with timeouts bigger than 32bit integer.
|
|
499
|
+
|
|
500
|
+
This interval wrapper fixes them. Returns clear function.
|
|
501
|
+
|
|
433
502
|
---
|
|
434
503
|
__function__ `cronInterval` - Like setInterval but with cron.
|
|
435
504
|
Returns clear function.
|
|
@@ -500,3 +569,20 @@ __type__ `ObjectSnakeToCamel` - Convert object keys of this-case to thisCase
|
|
|
500
569
|
__type__ `Concat` - Concat types of array or objects
|
|
501
570
|
|
|
502
571
|
---
|
|
572
|
+
__type__ `Prettify` - Visual only overhaul. Shows final type result on hover.
|
|
573
|
+
|
|
574
|
+
```ts
|
|
575
|
+
type a = {a: '1'}
|
|
576
|
+
type b = Prettify<a & { b: 'b' }>
|
|
577
|
+
// On hovering b it will show
|
|
578
|
+
type b = {
|
|
579
|
+
a: "1";
|
|
580
|
+
b: "b";
|
|
581
|
+
}
|
|
582
|
+
// instead of
|
|
583
|
+
type b = a & {
|
|
584
|
+
b: "b";
|
|
585
|
+
}
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
---
|
package/dist/control.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export declare function extractUUIDDate(uuid: string): Date;
|
|
|
26
26
|
* hash
|
|
27
27
|
* ]
|
|
28
28
|
*/
|
|
29
|
-
export declare function createCashedFunction<T, V extends JSONSerializable[]>(
|
|
29
|
+
export declare function createCashedFunction<T, V extends JSONSerializable[]>(run: (...data: V) => T): readonly [(...data: V) => T, (...data: V) => boolean, Map<string, T>];
|
|
30
30
|
/**
|
|
31
31
|
* Creates cached function. All arguments/results are cached. Will store in cache resolved data.
|
|
32
32
|
* Returns [
|
|
@@ -35,16 +35,16 @@ export declare function createCashedFunction<T, V extends JSONSerializable[]>(fu
|
|
|
35
35
|
* hash
|
|
36
36
|
* ]
|
|
37
37
|
*/
|
|
38
|
-
export declare function createCashedAsyncFunction<T, V extends JSONSerializable[]>(
|
|
38
|
+
export declare function createCashedAsyncFunction<T, V extends JSONSerializable[]>(run: (...data: V) => Promise<T>): readonly [(...data: V) => Promise<T>, (...data: V) => boolean, Map<string, T>];
|
|
39
39
|
/** Retry async function */
|
|
40
|
-
export declare function retry<T>(
|
|
40
|
+
export declare function retry<T>(run: () => Promise<T>, retries?: number, interval?: number | number[], ignore?: (error: unknown) => boolean): Promise<T>;
|
|
41
41
|
/** Create debounced function. Basically adds cooldown to function. Warning: throws! */
|
|
42
|
-
export declare function createDebouncedFunction<T, V extends unknown[]>(
|
|
42
|
+
export declare function createDebouncedFunction<T, V extends unknown[]>(run: (...data: V) => T, time: number): (...data: V) => T;
|
|
43
43
|
/** Create throttled function. Basically limits function calls in time period. Warning: throws! */
|
|
44
|
-
export declare function createThrottledFunction<T, V extends unknown[]>(
|
|
44
|
+
export declare function createThrottledFunction<T, V extends unknown[]>(run: (...data: V) => T, calls: number, time: number): (...data: V) => T;
|
|
45
45
|
/** Create debounced function. Basically create function that will be called with delay,
|
|
46
|
-
* but if another call comes in, we reset the timer. */
|
|
47
|
-
export declare function createDelayedFunction<T, V extends unknown[]>(
|
|
46
|
+
* but if another call comes in, we reset the timer (previous function isn't called). */
|
|
47
|
+
export declare function createDelayedFunction<T, V extends unknown[]>(run: (...data: V) => T, time: number): (...data: V) => Promise<T>;
|
|
48
48
|
type ResolveFunction<T> = undefined extends T ? (value?: T | PromiseLike<T>) => void : (value: T | PromiseLike<T>) => void;
|
|
49
49
|
/** Promise that accepts no callback, but exposes `resolve` and `reject` methods */
|
|
50
50
|
export declare class ImmediatePromise<T> extends Promise<T> {
|
|
@@ -56,6 +56,8 @@ export declare class ImmediatePromise<T> extends Promise<T> {
|
|
|
56
56
|
export default function deepPromiseAll<T>(input: T): Promise<AwaitedObject<T>>;
|
|
57
57
|
/** setTimeout promisify */
|
|
58
58
|
export declare function wait(time: number): Promise<unknown>;
|
|
59
|
+
/** Reject after specified time */
|
|
60
|
+
export declare function timeout(time: number): Promise<never>;
|
|
59
61
|
/** Empty function that does nothing */
|
|
60
62
|
export declare function noop(): void;
|
|
61
63
|
/** Run array of async tasks concurrently */
|
|
@@ -75,4 +77,50 @@ export declare class SimpleEventSource<EVENTS extends Record<string, unknown>> {
|
|
|
75
77
|
off: <T extends keyof EVENTS>(name: T, handler: (data: EVENTS[T]) => unknown) => void;
|
|
76
78
|
};
|
|
77
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Semaphore is used to limit concurrent tasks by delaying promise.
|
|
82
|
+
*
|
|
83
|
+
* ```ts
|
|
84
|
+
* const semaphore = new Semaphore(2);
|
|
85
|
+
*
|
|
86
|
+
* async function task() {
|
|
87
|
+
* await semaphore.acquire();
|
|
88
|
+
* try {
|
|
89
|
+
* // This code can only be executed by two tasks at the same time
|
|
90
|
+
* } finally {
|
|
91
|
+
* semaphore.release();
|
|
92
|
+
* }
|
|
93
|
+
* }
|
|
94
|
+
* task();
|
|
95
|
+
* task();
|
|
96
|
+
* task(); // This task will wait until one of the previous tasks releases the semaphore.
|
|
97
|
+
*
|
|
98
|
+
* // === SHORTHAND ===
|
|
99
|
+
* semaphore.run(()=>{
|
|
100
|
+
* // Your code
|
|
101
|
+
* })
|
|
102
|
+
* semaphore.run(()=>{
|
|
103
|
+
* // Your code
|
|
104
|
+
* })
|
|
105
|
+
* // ...
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export declare class Semaphore {
|
|
109
|
+
/** The maximum number of concurrent operations allowed.*/
|
|
110
|
+
capacity: number;
|
|
111
|
+
/** Tasks running. */
|
|
112
|
+
running: number;
|
|
113
|
+
protected deferredTasks: (() => void)[];
|
|
114
|
+
constructor(
|
|
115
|
+
/** The maximum number of concurrent operations allowed.*/
|
|
116
|
+
capacity: number);
|
|
117
|
+
/** Acquires a semaphore, blocking if necessary until one is available. */
|
|
118
|
+
acquire(): Promise<void>;
|
|
119
|
+
/** Releases a semaphore, allowing one more operation to proceed. */
|
|
120
|
+
release(): void;
|
|
121
|
+
/** Shorthand for running functions */
|
|
122
|
+
run<T>(run: () => T): Promise<T>;
|
|
123
|
+
}
|
|
124
|
+
/** Add timeout to a promise */
|
|
125
|
+
export declare function withTimeout<T>(run: () => Promise<T>, ms: number): Promise<T>;
|
|
78
126
|
export {};
|
package/dist/control.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Utils related to code execution flow.
|
|
3
3
|
*/
|
|
4
4
|
import { removeFromArray } from './arrays';
|
|
5
|
+
import { DelayedError, TimeoutError } from './errors';
|
|
5
6
|
let lastIncId = Math.floor(Math.random() * 0x1_00_00);
|
|
6
7
|
/** Id generated only once per session */
|
|
7
8
|
export const SESSION_ID = Math.floor(Math.random() * 0x10_00_00_00_00_00_00)
|
|
@@ -38,19 +39,19 @@ export function extractUUIDDate(uuid) {
|
|
|
38
39
|
* hash
|
|
39
40
|
* ]
|
|
40
41
|
*/
|
|
41
|
-
export function createCashedFunction(
|
|
42
|
+
export function createCashedFunction(run) {
|
|
42
43
|
const hash = new Map();
|
|
43
44
|
return [
|
|
44
|
-
(...
|
|
45
|
-
const key = JSON.stringify(
|
|
45
|
+
(...data) => {
|
|
46
|
+
const key = JSON.stringify(data);
|
|
46
47
|
const value = hash.get(key);
|
|
47
48
|
if (value)
|
|
48
49
|
return value;
|
|
49
|
-
const newValue =
|
|
50
|
+
const newValue = run(...data);
|
|
50
51
|
hash.set(key, newValue);
|
|
51
52
|
return newValue;
|
|
52
53
|
},
|
|
53
|
-
(...
|
|
54
|
+
(...data) => hash.delete(JSON.stringify(data)),
|
|
54
55
|
hash,
|
|
55
56
|
];
|
|
56
57
|
}
|
|
@@ -62,26 +63,26 @@ export function createCashedFunction(function_) {
|
|
|
62
63
|
* hash
|
|
63
64
|
* ]
|
|
64
65
|
*/
|
|
65
|
-
export function createCashedAsyncFunction(
|
|
66
|
+
export function createCashedAsyncFunction(run) {
|
|
66
67
|
const hash = new Map();
|
|
67
68
|
return [
|
|
68
|
-
async (...
|
|
69
|
-
const key = JSON.stringify(
|
|
69
|
+
async (...data) => {
|
|
70
|
+
const key = JSON.stringify(data);
|
|
70
71
|
const value = hash.get(key);
|
|
71
72
|
if (value)
|
|
72
73
|
return value;
|
|
73
|
-
const newValue = await
|
|
74
|
+
const newValue = await run(...data);
|
|
74
75
|
hash.set(key, newValue);
|
|
75
76
|
return newValue;
|
|
76
77
|
},
|
|
77
|
-
(...
|
|
78
|
+
(...data) => hash.delete(JSON.stringify(data)),
|
|
78
79
|
hash,
|
|
79
80
|
];
|
|
80
81
|
}
|
|
81
82
|
/** Retry async function */
|
|
82
|
-
export async function retry(
|
|
83
|
+
export async function retry(run, retries = 5, interval = 0, ignore) {
|
|
83
84
|
try {
|
|
84
|
-
return await
|
|
85
|
+
return await run();
|
|
85
86
|
}
|
|
86
87
|
catch (error) {
|
|
87
88
|
if (retries === 0 || ignore?.(error))
|
|
@@ -89,46 +90,46 @@ export async function retry(function_, retries = 5, interval = 0, ignore) {
|
|
|
89
90
|
await wait(typeof interval === 'number'
|
|
90
91
|
? interval
|
|
91
92
|
: interval[interval.length - retries]);
|
|
92
|
-
return retry(
|
|
93
|
+
return retry(run, retries - 1, interval);
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
96
|
/** Create debounced function. Basically adds cooldown to function. Warning: throws! */
|
|
96
|
-
export function createDebouncedFunction(
|
|
97
|
+
export function createDebouncedFunction(run, time) {
|
|
97
98
|
let nextExec = 0;
|
|
98
|
-
return (...
|
|
99
|
+
return (...data) => {
|
|
99
100
|
const now = Date.now();
|
|
100
101
|
if (nextExec > now)
|
|
101
|
-
throw new
|
|
102
|
+
throw new DelayedError();
|
|
102
103
|
nextExec = now + time;
|
|
103
|
-
return
|
|
104
|
+
return run(...data);
|
|
104
105
|
};
|
|
105
106
|
}
|
|
106
107
|
/** Create throttled function. Basically limits function calls in time period. Warning: throws! */
|
|
107
|
-
export function createThrottledFunction(
|
|
108
|
+
export function createThrottledFunction(run, calls, time) {
|
|
108
109
|
let nextClear = 0;
|
|
109
110
|
let amount = 0;
|
|
110
|
-
return (...
|
|
111
|
+
return (...data) => {
|
|
111
112
|
const now = Date.now();
|
|
112
113
|
if (nextClear <= now) {
|
|
113
114
|
nextClear = now + time;
|
|
114
115
|
amount = 0;
|
|
115
116
|
}
|
|
116
117
|
if (amount === calls)
|
|
117
|
-
throw new
|
|
118
|
+
throw new DelayedError();
|
|
118
119
|
amount++;
|
|
119
|
-
return
|
|
120
|
+
return run(...data);
|
|
120
121
|
};
|
|
121
122
|
}
|
|
122
123
|
/** Create debounced function. Basically create function that will be called with delay,
|
|
123
|
-
* but if another call comes in, we reset the timer. */
|
|
124
|
-
export function createDelayedFunction(
|
|
124
|
+
* but if another call comes in, we reset the timer (previous function isn't called). */
|
|
125
|
+
export function createDelayedFunction(run, time) {
|
|
125
126
|
let timeout;
|
|
126
127
|
let activePromise;
|
|
127
|
-
return (...
|
|
128
|
+
return (...data) => {
|
|
128
129
|
activePromise ??= new ImmediatePromise();
|
|
129
130
|
clearTimeout(timeout);
|
|
130
131
|
timeout = setTimeout(() => {
|
|
131
|
-
activePromise?.resolve(
|
|
132
|
+
activePromise?.resolve(run(...data));
|
|
132
133
|
activePromise = undefined;
|
|
133
134
|
}, time);
|
|
134
135
|
return activePromise;
|
|
@@ -169,37 +170,19 @@ export default async function deepPromiseAll(input) {
|
|
|
169
170
|
export function wait(time) {
|
|
170
171
|
return new Promise((r) => setTimeout(r, time));
|
|
171
172
|
}
|
|
173
|
+
/** Reject after specified time */
|
|
174
|
+
export function timeout(time) {
|
|
175
|
+
return new Promise((_, reject) => setTimeout(() => {
|
|
176
|
+
reject(new TimeoutError());
|
|
177
|
+
}, time));
|
|
178
|
+
}
|
|
172
179
|
/** Empty function that does nothing */
|
|
173
180
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
174
181
|
export function noop() { }
|
|
175
182
|
/** Run array of async tasks concurrently */
|
|
176
183
|
export async function concurrentRun(tasks, concurrency = 4) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
let inProgress = 0;
|
|
180
|
-
let index = 0;
|
|
181
|
-
let completed = 0;
|
|
182
|
-
function runNext() {
|
|
183
|
-
if (completed === tasks.length) {
|
|
184
|
-
resolve(results);
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
while (inProgress < concurrency && index < tasks.length) {
|
|
188
|
-
const currentIndex = index++;
|
|
189
|
-
const task = tasks[currentIndex];
|
|
190
|
-
inProgress++;
|
|
191
|
-
task()
|
|
192
|
-
.then((result) => {
|
|
193
|
-
results[currentIndex] = result;
|
|
194
|
-
inProgress--;
|
|
195
|
-
completed++;
|
|
196
|
-
runNext();
|
|
197
|
-
})
|
|
198
|
-
.catch(reject);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
runNext();
|
|
202
|
-
});
|
|
184
|
+
const semaphore = new Semaphore(concurrency);
|
|
185
|
+
return Promise.all(tasks.map(semaphore.run.bind(semaphore)));
|
|
203
186
|
}
|
|
204
187
|
/** Create simple event source. Consider using `signal()` for reactive state managment. */
|
|
205
188
|
export class SimpleEventSource {
|
|
@@ -239,3 +222,69 @@ export class SimpleEventSource {
|
|
|
239
222
|
};
|
|
240
223
|
}
|
|
241
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* Semaphore is used to limit concurrent tasks by delaying promise.
|
|
227
|
+
*
|
|
228
|
+
* ```ts
|
|
229
|
+
* const semaphore = new Semaphore(2);
|
|
230
|
+
*
|
|
231
|
+
* async function task() {
|
|
232
|
+
* await semaphore.acquire();
|
|
233
|
+
* try {
|
|
234
|
+
* // This code can only be executed by two tasks at the same time
|
|
235
|
+
* } finally {
|
|
236
|
+
* semaphore.release();
|
|
237
|
+
* }
|
|
238
|
+
* }
|
|
239
|
+
* task();
|
|
240
|
+
* task();
|
|
241
|
+
* task(); // This task will wait until one of the previous tasks releases the semaphore.
|
|
242
|
+
*
|
|
243
|
+
* // === SHORTHAND ===
|
|
244
|
+
* semaphore.run(()=>{
|
|
245
|
+
* // Your code
|
|
246
|
+
* })
|
|
247
|
+
* semaphore.run(()=>{
|
|
248
|
+
* // Your code
|
|
249
|
+
* })
|
|
250
|
+
* // ...
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
export class Semaphore {
|
|
254
|
+
capacity;
|
|
255
|
+
/** Tasks running. */
|
|
256
|
+
running = 0;
|
|
257
|
+
deferredTasks = [];
|
|
258
|
+
constructor(
|
|
259
|
+
/** The maximum number of concurrent operations allowed.*/
|
|
260
|
+
capacity) {
|
|
261
|
+
this.capacity = capacity;
|
|
262
|
+
}
|
|
263
|
+
/** Acquires a semaphore, blocking if necessary until one is available. */
|
|
264
|
+
async acquire() {
|
|
265
|
+
if (this.running === this.capacity)
|
|
266
|
+
return new Promise((resolve) => {
|
|
267
|
+
this.deferredTasks.push(resolve);
|
|
268
|
+
});
|
|
269
|
+
this.running++;
|
|
270
|
+
}
|
|
271
|
+
/** Releases a semaphore, allowing one more operation to proceed. */
|
|
272
|
+
release() {
|
|
273
|
+
this.running--;
|
|
274
|
+
this.deferredTasks.shift()?.();
|
|
275
|
+
}
|
|
276
|
+
/** Shorthand for running functions */
|
|
277
|
+
async run(run) {
|
|
278
|
+
await this.acquire();
|
|
279
|
+
try {
|
|
280
|
+
return await run();
|
|
281
|
+
}
|
|
282
|
+
finally {
|
|
283
|
+
this.release();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/** Add timeout to a promise */
|
|
288
|
+
export async function withTimeout(run, ms) {
|
|
289
|
+
return Promise.race([run(), timeout(ms)]);
|
|
290
|
+
}
|
package/dist/errors.d.ts
CHANGED
|
@@ -7,6 +7,17 @@
|
|
|
7
7
|
export declare class ValidationError extends Error {
|
|
8
8
|
name: string;
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Use as intended error. Basically 4** errors in HTTP
|
|
12
|
+
*/
|
|
13
|
+
export declare class TimeoutError extends Error {
|
|
14
|
+
name: string;
|
|
15
|
+
constructor();
|
|
16
|
+
}
|
|
17
|
+
export declare class DelayedError extends Error {
|
|
18
|
+
name: string;
|
|
19
|
+
constructor();
|
|
20
|
+
}
|
|
10
21
|
/**
|
|
11
22
|
* Find error inside anything recursively.
|
|
12
23
|
* Good for finding human-readable errors.
|
package/dist/errors.js
CHANGED
|
@@ -8,6 +8,21 @@ import { getPropertyNames } from './objects';
|
|
|
8
8
|
export class ValidationError extends Error {
|
|
9
9
|
name = 'ValidationError';
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Use as intended error. Basically 4** errors in HTTP
|
|
13
|
+
*/
|
|
14
|
+
export class TimeoutError extends Error {
|
|
15
|
+
name = 'TimeoutError';
|
|
16
|
+
constructor() {
|
|
17
|
+
super('The operation has timed out');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class DelayedError extends Error {
|
|
21
|
+
name = 'DelayedError';
|
|
22
|
+
constructor() {
|
|
23
|
+
super('The operation is delayed and can not be executed now');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
11
26
|
const defaultPriorityErrorKeys = [
|
|
12
27
|
'message',
|
|
13
28
|
'messages',
|
package/dist/numbers.d.ts
CHANGED
|
@@ -8,3 +8,21 @@ export declare function parseFloat(parameter: unknown): number;
|
|
|
8
8
|
export declare function factorial(n: number): number;
|
|
9
9
|
/** Fibonacci */
|
|
10
10
|
export declare function fib(n: number): bigint;
|
|
11
|
+
/** Clamp numbers to max and min */
|
|
12
|
+
export declare function clamp(value: number, min?: number, max?: number): number;
|
|
13
|
+
/** Is number in range. Inclusive. */
|
|
14
|
+
export declare function inRange(value: number, min?: number, max?: number): boolean;
|
|
15
|
+
/** Calucalate avarage from array of numbers */
|
|
16
|
+
export declare function mean(array: number[]): number;
|
|
17
|
+
/**
|
|
18
|
+
* Round with precision.
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* round(1.2345); // 1
|
|
22
|
+
* round(1.2345, 2); // 1.23
|
|
23
|
+
* round(1.2345, 10); // 1.2345
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function round(value: number, precision?: number): number;
|
|
27
|
+
/** Sum of array of numbers */
|
|
28
|
+
export declare function sum(array: number[]): number;
|
package/dist/numbers.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
import { ValidationError } from './errors';
|
|
5
5
|
/** Random number between min and max. May enable float */
|
|
6
6
|
export function random(min, max, float) {
|
|
7
|
-
const
|
|
8
|
-
return float ?
|
|
7
|
+
const number = Math.random() * (max - min) + min;
|
|
8
|
+
return float ? number : Math.round(number);
|
|
9
9
|
}
|
|
10
10
|
/** Same as Number.parseInt but throws if NaN or not safe */
|
|
11
11
|
export function parseInt(parameter, radix) {
|
|
@@ -44,3 +44,42 @@ export function fib(n) {
|
|
|
44
44
|
}
|
|
45
45
|
return a;
|
|
46
46
|
}
|
|
47
|
+
/** Clamp numbers to max and min */
|
|
48
|
+
export function clamp(value, min = -Infinity, max = Infinity) {
|
|
49
|
+
if (value > max)
|
|
50
|
+
return max;
|
|
51
|
+
if (value < min)
|
|
52
|
+
return min;
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
/** Is number in range. Inclusive. */
|
|
56
|
+
export function inRange(value, min = -Infinity, max = Infinity) {
|
|
57
|
+
return value <= max && value >= min;
|
|
58
|
+
}
|
|
59
|
+
/** Calucalate avarage from array of numbers */
|
|
60
|
+
export function mean(array) {
|
|
61
|
+
let sum = 0;
|
|
62
|
+
for (let index = 0; index < array.length; index++)
|
|
63
|
+
sum += array[index];
|
|
64
|
+
return sum / array.length;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Round with precision.
|
|
68
|
+
*
|
|
69
|
+
* ```ts
|
|
70
|
+
* round(1.2345); // 1
|
|
71
|
+
* round(1.2345, 2); // 1.23
|
|
72
|
+
* round(1.2345, 10); // 1.2345
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export function round(value, precision = 0) {
|
|
76
|
+
const mult = 10 ** precision;
|
|
77
|
+
return Math.round(value * mult) / mult;
|
|
78
|
+
}
|
|
79
|
+
/** Sum of array of numbers */
|
|
80
|
+
export function sum(array) {
|
|
81
|
+
let result = 0;
|
|
82
|
+
for (let index = 0; index < array.length; index++)
|
|
83
|
+
result += array[index];
|
|
84
|
+
return result;
|
|
85
|
+
}
|
package/dist/objects.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* [object Object]
|
|
3
3
|
*/
|
|
4
|
-
import { Constructor, ObjectAddPrefix } from './types';
|
|
4
|
+
import { AnyFunction, Constructor, ObjectAddPrefix } from './types';
|
|
5
5
|
/** Get all prorerty names, including in prototype */
|
|
6
6
|
export declare function getPropertyNames(object: object, keys?: Set<unknown>): Set<unknown>;
|
|
7
7
|
/** Map function like for arrays, but for objects */
|
|
8
|
-
export declare function objectMap<T extends object>(object: T,
|
|
8
|
+
export declare function objectMap<T extends object>(object: T, run: (key: keyof T, value: T[keyof T]) => [string, unknown]): {
|
|
9
9
|
[k: string]: unknown;
|
|
10
10
|
};
|
|
11
11
|
/** Filter function like for arrays, but for objects */
|
|
12
|
-
export declare function objectFilter<T extends object>(object: T,
|
|
12
|
+
export declare function objectFilter<T extends object>(object: T, run: (key: keyof T, value: T[keyof T]) => unknown): {
|
|
13
13
|
[k: string]: any;
|
|
14
14
|
};
|
|
15
15
|
/** Adds prefix to every key in object */
|
|
@@ -45,12 +45,36 @@ export declare function pick<T extends object, K extends keyof T>(object: T, key
|
|
|
45
45
|
* ```
|
|
46
46
|
*/
|
|
47
47
|
export declare class Base {
|
|
48
|
+
/** Id of last AUTOMATICALLY created object id */
|
|
48
49
|
static lastId: number;
|
|
50
|
+
/** Map of class instances by they ids */
|
|
49
51
|
static idMap: Map<number, Base>;
|
|
52
|
+
/** Map of subclasses of base class by their name */
|
|
50
53
|
static subclasses: Map<string, Constructor<Base>>;
|
|
54
|
+
/** Functions in this array will be run on instance destroy */
|
|
55
|
+
runOnDestroy: AnyFunction[];
|
|
51
56
|
private _id;
|
|
52
57
|
get id(): number;
|
|
53
58
|
set id(value: number);
|
|
54
59
|
constructor(id?: number);
|
|
60
|
+
/**
|
|
61
|
+
* Include next lines when extending this class:
|
|
62
|
+
* ```js
|
|
63
|
+
* static {
|
|
64
|
+
* this.registerSubclass()
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
55
68
|
static registerSubclass(): void;
|
|
69
|
+
/**
|
|
70
|
+
* Destroy instance. Will run all `runOnDestroy` functions
|
|
71
|
+
* and remove istance from idMap.
|
|
72
|
+
* If class is garbage collected automatically runs this.
|
|
73
|
+
* */
|
|
74
|
+
destroy(): void;
|
|
75
|
+
/**
|
|
76
|
+
* Register autocleared event handler.
|
|
77
|
+
* If using classes methods don't forget to `bind(this)`
|
|
78
|
+
*/
|
|
79
|
+
protected registerEvent(target: EventTarget, type: string, listener: EventListener, options?: AddEventListenerOptions): void;
|
|
56
80
|
}
|
package/dist/objects.js
CHANGED
|
@@ -12,12 +12,12 @@ export function getPropertyNames(object, keys = new Set()) {
|
|
|
12
12
|
return keys;
|
|
13
13
|
}
|
|
14
14
|
/** Map function like for arrays, but for objects */
|
|
15
|
-
export function objectMap(object,
|
|
16
|
-
return Object.fromEntries(Object.entries(object).map(([key, value]) =>
|
|
15
|
+
export function objectMap(object, run) {
|
|
16
|
+
return Object.fromEntries(Object.entries(object).map(([key, value]) => run(key, value)));
|
|
17
17
|
}
|
|
18
18
|
/** Filter function like for arrays, but for objects */
|
|
19
|
-
export function objectFilter(object,
|
|
20
|
-
return Object.fromEntries(Object.entries(object).filter(([key, value]) =>
|
|
19
|
+
export function objectFilter(object, run) {
|
|
20
|
+
return Object.fromEntries(Object.entries(object).filter(([key, value]) => run(key, value)));
|
|
21
21
|
}
|
|
22
22
|
/** Adds prefix to every key in object */
|
|
23
23
|
export function addPrefixToObject(object, prefix) {
|
|
@@ -118,9 +118,14 @@ export function pick(object, keys) {
|
|
|
118
118
|
* ```
|
|
119
119
|
*/
|
|
120
120
|
export class Base {
|
|
121
|
+
/** Id of last AUTOMATICALLY created object id */
|
|
121
122
|
static lastId = 0;
|
|
123
|
+
/** Map of class instances by they ids */
|
|
122
124
|
static idMap = new Map();
|
|
125
|
+
/** Map of subclasses of base class by their name */
|
|
123
126
|
static subclasses = new Map();
|
|
127
|
+
/** Functions in this array will be run on instance destroy */
|
|
128
|
+
runOnDestroy = [];
|
|
124
129
|
_id;
|
|
125
130
|
get id() {
|
|
126
131
|
return this._id;
|
|
@@ -134,7 +139,36 @@ export class Base {
|
|
|
134
139
|
this._id = id;
|
|
135
140
|
Base.idMap.set(id, this);
|
|
136
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Include next lines when extending this class:
|
|
144
|
+
* ```js
|
|
145
|
+
* static {
|
|
146
|
+
* this.registerSubclass()
|
|
147
|
+
* }
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
137
150
|
static registerSubclass() {
|
|
138
151
|
Base.subclasses.set(this.name, this);
|
|
139
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Destroy instance. Will run all `runOnDestroy` functions
|
|
155
|
+
* and remove istance from idMap.
|
|
156
|
+
* If class is garbage collected automatically runs this.
|
|
157
|
+
* */
|
|
158
|
+
destroy() {
|
|
159
|
+
Base.idMap.delete(this._id);
|
|
160
|
+
for (let index = 0; index < this.runOnDestroy.length; index++)
|
|
161
|
+
this.runOnDestroy[index]();
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Register autocleared event handler.
|
|
165
|
+
* If using classes methods don't forget to `bind(this)`
|
|
166
|
+
*/
|
|
167
|
+
registerEvent(target, type, listener, options = {}) {
|
|
168
|
+
options.passive ??= true;
|
|
169
|
+
target.addEventListener(type, listener, options);
|
|
170
|
+
this.runOnDestroy.push(() => {
|
|
171
|
+
target.removeEventListener(type, listener);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
140
174
|
}
|
package/dist/signals.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export declare function signal<T>(value: T): Signal<T>;
|
|
|
31
31
|
* Returned data from handler function will be passed to it on next signal change.
|
|
32
32
|
* Returns a function that will clear the effect.
|
|
33
33
|
*
|
|
34
|
-
*
|
|
34
|
+
*
|
|
35
35
|
* // Will print signal on change
|
|
36
36
|
* effect(()=>{
|
|
37
37
|
* console.log($mySignal())
|
|
@@ -42,7 +42,6 @@ export declare function signal<T>(value: T): Signal<T>;
|
|
|
42
42
|
* if(last>mySignal) console.log('Increment!')
|
|
43
43
|
* return mySignal;
|
|
44
44
|
* })
|
|
45
|
-
* ```
|
|
46
45
|
*/
|
|
47
46
|
export declare function effect<T>(handler: (argument: T | undefined) => T, initialValue?: T): () => void;
|
|
48
47
|
/**
|
package/dist/signals.js
CHANGED
|
@@ -7,9 +7,9 @@ const effectsMap = new WeakMap();
|
|
|
7
7
|
let batchedEffects;
|
|
8
8
|
export function signal(value) {
|
|
9
9
|
const subscribers = new Set();
|
|
10
|
-
return (...
|
|
11
|
-
if (
|
|
12
|
-
const argument =
|
|
10
|
+
return (...data) => {
|
|
11
|
+
if (data.length === 1) {
|
|
12
|
+
const argument = data[0];
|
|
13
13
|
value =
|
|
14
14
|
typeof argument === 'function'
|
|
15
15
|
? argument(value)
|
|
@@ -47,7 +47,7 @@ function clearEffect(handler) {
|
|
|
47
47
|
* Returned data from handler function will be passed to it on next signal change.
|
|
48
48
|
* Returns a function that will clear the effect.
|
|
49
49
|
*
|
|
50
|
-
*
|
|
50
|
+
*
|
|
51
51
|
* // Will print signal on change
|
|
52
52
|
* effect(()=>{
|
|
53
53
|
* console.log($mySignal())
|
|
@@ -58,7 +58,6 @@ function clearEffect(handler) {
|
|
|
58
58
|
* if(last>mySignal) console.log('Increment!')
|
|
59
59
|
* return mySignal;
|
|
60
60
|
* })
|
|
61
|
-
* ```
|
|
62
61
|
*/
|
|
63
62
|
export function effect(handler, initialValue) {
|
|
64
63
|
let lastValue = initialValue;
|
package/dist/time.d.ts
CHANGED
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Timers, CRON, etc.
|
|
3
3
|
*/
|
|
4
|
+
import { AnyFunction } from './types';
|
|
4
5
|
/** Measure performance of a function */
|
|
5
|
-
export declare function measurePerformance(
|
|
6
|
+
export declare function measurePerformance(run: () => unknown, timeCheck?: number): number;
|
|
7
|
+
/**
|
|
8
|
+
* Original setTimeout and setIntval known for accumulating delay
|
|
9
|
+
* and causing problem with timeouts bigger than 32bit integer.
|
|
10
|
+
*
|
|
11
|
+
* This timeout wrapper fixes them. Returns clear function.
|
|
12
|
+
*/
|
|
13
|
+
export declare function setSafeTimeout(handler: AnyFunction, delay: number): () => void;
|
|
14
|
+
/**
|
|
15
|
+
* Original setTimeout and setIntval known for accumulating delay
|
|
16
|
+
* and causing problem with timeouts bigger than 32bit integer.
|
|
17
|
+
*
|
|
18
|
+
* This interval wrapper fixes them. Returns clear function.
|
|
19
|
+
*/
|
|
20
|
+
export declare function setSafeInterval(handler: AnyFunction, delay: number): () => void;
|
|
6
21
|
/** Like setInterval but with cron.
|
|
7
22
|
* Returns clear function.
|
|
8
23
|
* For cron string syntax check __getNextCron()__ description */
|
|
9
|
-
export declare function cronInterval(
|
|
24
|
+
export declare function cronInterval(run: () => unknown, cronString: string): () => void;
|
|
10
25
|
/** Find next cron date after passed date.
|
|
11
26
|
*
|
|
12
27
|
* This function __DOES NOT__ implement regular CRON 1 to 1.
|
package/dist/time.js
CHANGED
|
@@ -4,19 +4,64 @@
|
|
|
4
4
|
import { HOUR_MS } from './consts';
|
|
5
5
|
import { ValidationError } from './errors';
|
|
6
6
|
/** Measure performance of a function */
|
|
7
|
-
export function measurePerformance(
|
|
7
|
+
export function measurePerformance(run, timeCheck = 16.6) {
|
|
8
8
|
const endTime = performance.now() + timeCheck;
|
|
9
9
|
let executions = 0;
|
|
10
10
|
while (performance.now() < endTime) {
|
|
11
|
-
|
|
11
|
+
run();
|
|
12
12
|
executions++;
|
|
13
13
|
}
|
|
14
14
|
return executions;
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Original setTimeout and setIntval known for accumulating delay
|
|
18
|
+
* and causing problem with timeouts bigger than 32bit integer.
|
|
19
|
+
*
|
|
20
|
+
* This timeout wrapper fixes them. Returns clear function.
|
|
21
|
+
*/
|
|
22
|
+
export function setSafeTimeout(handler, delay) {
|
|
23
|
+
const end = Date.now() + delay;
|
|
24
|
+
let timeout;
|
|
25
|
+
function r() {
|
|
26
|
+
const timeLeft = end - Date.now();
|
|
27
|
+
if (timeLeft < 1)
|
|
28
|
+
handler();
|
|
29
|
+
else
|
|
30
|
+
timeout = setTimeout(r, Math.min(timeLeft, HOUR_MS));
|
|
31
|
+
}
|
|
32
|
+
r();
|
|
33
|
+
return () => {
|
|
34
|
+
clearTimeout(timeout);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Original setTimeout and setIntval known for accumulating delay
|
|
39
|
+
* and causing problem with timeouts bigger than 32bit integer.
|
|
40
|
+
*
|
|
41
|
+
* This interval wrapper fixes them. Returns clear function.
|
|
42
|
+
*/
|
|
43
|
+
export function setSafeInterval(handler, delay) {
|
|
44
|
+
let end = Date.now() + delay;
|
|
45
|
+
let timeout;
|
|
46
|
+
function r() {
|
|
47
|
+
const timeLeft = end - Date.now();
|
|
48
|
+
if (timeLeft < 1) {
|
|
49
|
+
end += delay;
|
|
50
|
+
handler();
|
|
51
|
+
r();
|
|
52
|
+
}
|
|
53
|
+
else
|
|
54
|
+
timeout = setTimeout(r, Math.min(timeLeft, HOUR_MS));
|
|
55
|
+
}
|
|
56
|
+
r();
|
|
57
|
+
return () => {
|
|
58
|
+
clearInterval(timeout);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
16
61
|
/** Like setInterval but with cron.
|
|
17
62
|
* Returns clear function.
|
|
18
63
|
* For cron string syntax check __getNextCron()__ description */
|
|
19
|
-
export function cronInterval(
|
|
64
|
+
export function cronInterval(run, cronString) {
|
|
20
65
|
let timeout;
|
|
21
66
|
let next = getNextCron(cronString).getTime();
|
|
22
67
|
const r = () => {
|
|
@@ -25,7 +70,7 @@ export function cronInterval(function_, cronString) {
|
|
|
25
70
|
if (d < 1) {
|
|
26
71
|
next = getNextCron(cronString).getTime();
|
|
27
72
|
d = next - now;
|
|
28
|
-
|
|
73
|
+
run();
|
|
29
74
|
}
|
|
30
75
|
timeout = setTimeout(r, Math.min(d, HOUR_MS));
|
|
31
76
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
/** Values that are copied by value, not by reference */
|
|
5
5
|
export type Primitive = string | number | bigint | boolean | symbol | null | undefined;
|
|
6
6
|
/** Function with any arguments or return type */
|
|
7
|
-
export type AnyFunction = (...
|
|
7
|
+
export type AnyFunction = (...data: any[]) => any;
|
|
8
8
|
/** Values that convert to false */
|
|
9
9
|
export type Falsy = false | '' | 0 | null | undefined;
|
|
10
10
|
/** Make keys in object optional */
|
|
@@ -39,3 +39,23 @@ export type ObjectSnakeToCamel<T> = {
|
|
|
39
39
|
};
|
|
40
40
|
/** Concat types of array or objects */
|
|
41
41
|
export type Concat<T, U> = T extends any[] ? U extends any[] ? [...T, ...U] : never : T & U;
|
|
42
|
+
/**
|
|
43
|
+
* Visual only overhaul. Shows final type result on hover.
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* type a = {a: '1'}
|
|
47
|
+
* type b = Prettify<a & { b: 'b' }>
|
|
48
|
+
* // On hovering b it will show
|
|
49
|
+
* type b = {
|
|
50
|
+
* a: "1";
|
|
51
|
+
* b: "b";
|
|
52
|
+
* }
|
|
53
|
+
* // instead of
|
|
54
|
+
* type b = a & {
|
|
55
|
+
* b: "b";
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
* */
|
|
59
|
+
export type Prettify<T extends object> = {
|
|
60
|
+
[k in keyof T]: T[k];
|
|
61
|
+
} & {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softsky/utils",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "JavaScript/TypeScript utilities",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
},
|
|
21
21
|
"homepage": "https://github.com/SoundOfTheSky/utils#readme",
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@softsky/configs": "^1.3.
|
|
24
|
-
"@types/bun": "^1.2.
|
|
23
|
+
"@softsky/configs": "^1.3.4",
|
|
24
|
+
"@types/bun": "^1.2.19"
|
|
25
25
|
},
|
|
26
26
|
"files": ["dist/**/*"]
|
|
27
27
|
}
|