@softsky/utils 2.5.2 → 2.5.3

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 CHANGED
@@ -36,32 +36,32 @@ export function newStuff() {}
36
36
  ## Arrays
37
37
  Everything array related.
38
38
 
39
- ${\textsf{\color{CornflowerBlue}function}}$ randomFromArray - Returns random element from non-empty array
39
+ __function__ `randomFromArray` - Returns random element from non-empty array
40
40
 
41
41
  ---
42
- ${\textsf{\color{CornflowerBlue}function}}$ shuffleArray - Create new shuffled array
42
+ __function__ `shuffleArray` - Create new shuffled array
43
43
 
44
44
  ---
45
- ${\textsf{\color{CornflowerBlue}function}}$ swap - Swap two elements in array
45
+ __function__ `swap` - Swap two elements in array
46
46
 
47
47
  ---
48
- ${\textsf{\color{CornflowerBlue}function}}$ binarySearch - Binary search in sorted array.
48
+ __function__ `binarySearch` - Binary search in sorted array.
49
49
  Compare function should compare your needed value with value on index passed to it.
50
50
  If compare returns 0 it means we found target.
51
51
  If compare returns > 0 it means we have to cut out bigger side of array.
52
52
  If compare returns < 0 it means we have to cut out smaller side of array.
53
53
 
54
54
  ---
55
- ${\textsf{\color{CornflowerBlue}function}}$ chunk - Split array into sub arrays of spicified size
55
+ __function__ `chunk` - Split array into sub arrays of spicified size
56
56
 
57
57
  ---
58
- ${\textsf{\color{CornflowerBlue}function}}$ combinations - Return all combinations of items in array
58
+ __function__ `combinations` - Return all combinations of items in array
59
59
 
60
60
  ---
61
- ${\textsf{\color{CornflowerBlue}function}}$ permutations - Return all permutations of items in array
61
+ __function__ `permutations` - Return all permutations of items in array
62
62
 
63
63
  ---
64
- ${\textsf{\color{CornflowerBlue}function}}$ pushToSorted - Push data to sorted array. Array will always be kept sorted.
64
+ __function__ `pushToSorted` - Push data to sorted array. Array will always be kept sorted.
65
65
 
66
66
  Compare function should compare your needed value with value on index passed to it.
67
67
  If compare returns 0 it means we found target.
@@ -73,13 +73,13 @@ pushToSorted(numArray, 10, x => x - 10);
73
73
  ```
74
74
 
75
75
  ---
76
- ${\textsf{\color{CornflowerBlue}function}}$ removeFromArray - Delete value from array.
76
+ __function__ `removeFromArray` - Delete value from array.
77
77
  Only deletes first encountered.
78
78
 
79
79
  Returns index of deleted value.
80
80
 
81
81
  ---
82
- ${\textsf{\color{CornflowerBlue}function}}$ removeLastFromArray - Delete value from array.
82
+ __function__ `removeLastFromArray` - Delete value from array.
83
83
  Only deletes last encountered.
84
84
 
85
85
  Returns index of deleted value.
@@ -90,16 +90,16 @@ Returns index of deleted value.
90
90
  ## Consts
91
91
  Some useful consts. That's it.
92
92
 
93
- ${\textsf{\color{ForestGreen}const}}$ DAY_MS - Milliseconds in a full day
93
+ __const__ `DAY_MS` - Milliseconds in a full day
94
94
 
95
95
  ---
96
- ${\textsf{\color{ForestGreen}const}}$ HOUR_MS - Milliseconds in a hour
96
+ __const__ `HOUR_MS` - Milliseconds in a hour
97
97
 
98
98
  ---
99
- ${\textsf{\color{ForestGreen}const}}$ MIN_MS - Milliseconds in a minute
99
+ __const__ `MIN_MS` - Milliseconds in a minute
100
100
 
101
101
  ---
102
- ${\textsf{\color{ForestGreen}const}}$ SEC_MS - Milliseconds in a second
102
+ __const__ `SEC_MS` - Milliseconds in a second
103
103
 
104
104
  ---
105
105
 
@@ -107,10 +107,10 @@ ${\textsf{\color{ForestGreen}const}}$ SEC_MS - Milliseconds in a second
107
107
  ## Control
108
108
  Utils related to code execution flow.
109
109
 
110
- ${\textsf{\color{ForestGreen}const}}$ SESSION_ID - Id generated only once per session
110
+ __const__ `SESSION_ID` - Id generated only once per session
111
111
 
112
112
  ---
113
- ${\textsf{\color{CornflowerBlue}function}}$ UUID - Get universally unique string id.
113
+ __function__ `UUID` - Get universally unique string id.
114
114
  You can get information then id was generated using extractUUIDDate(uuid)
115
115
  - 13 char - timestamp
116
116
  - 13 char - SESSION_ID
@@ -121,10 +121,10 @@ You can get information then id was generated using extractUUIDDate(uuid)
121
121
  USING CUSTOM TIMESTAMP MAY RESULT IN COLLISSIONS
122
122
 
123
123
  ---
124
- ${\textsf{\color{CornflowerBlue}function}}$ extractUUIDDate - Extract exact date of uuid generation
124
+ __function__ `extractUUIDDate` - Extract exact date of uuid generation
125
125
 
126
126
  ---
127
- ${\textsf{\color{CornflowerBlue}function}}$ createCashedFunction - Creates cached function. All arguments/results are cached.
127
+ __function__ `createCashedFunction` - Creates cached function. All arguments/results are cached.
128
128
  Returns [
129
129
  fn [cached function],
130
130
  delete [delete cached result for arguments]
@@ -132,7 +132,7 @@ hash
132
132
  ]
133
133
 
134
134
  ---
135
- ${\textsf{\color{CornflowerBlue}function}}$ createCashedAsyncFunction - Creates cached function. All arguments/results are cached. Will store in cache resolved data.
135
+ __function__ `createCashedAsyncFunction` - Creates cached function. All arguments/results are cached. Will store in cache resolved data.
136
136
  Returns [
137
137
  fn [cached function],
138
138
  delete [delete cached result for arguments]
@@ -140,29 +140,32 @@ hash
140
140
  ]
141
141
 
142
142
  ---
143
- ${\textsf{\color{CornflowerBlue}async function}}$ retry - Retry async function
143
+ __async function__ `retry` - Retry async function
144
144
 
145
145
  ---
146
- ${\textsf{\color{CornflowerBlue}function}}$ createDebouncedFunction - Create debounced function. Basically adds cooldown to function. Warning: throws!
146
+ __function__ `createDebouncedFunction` - Create debounced function. Basically adds cooldown to function. Warning: throws!
147
147
 
148
148
  ---
149
- ${\textsf{\color{CornflowerBlue}function}}$ createThrottledFunction - Create throttled function. Basically limits function calls in time period. Warning: throws!
149
+ __function__ `createThrottledFunction` - Create throttled function. Basically limits function calls in time period. Warning: throws!
150
150
 
151
151
  ---
152
- ${\textsf{\color{CornflowerBlue}function}}$ createDelayedFunction - Create debounced function. Basically create function that will be called with delay,
152
+ __function__ `createDelayedFunction` - Create debounced function. Basically create function that will be called with delay,
153
153
  but if another call comes in, we reset the timer.
154
154
 
155
155
  ---
156
- ${\textsf{\color{Orange}class}}$ ImmediatePromise - Promise that accepts no callback, but exposes `resolve` and `reject` methods
156
+ __class__ `ImmediatePromise` - Promise that accepts no callback, but exposes `resolve` and `reject` methods
157
157
 
158
158
  ---
159
- ${\textsf{\color{CornflowerBlue}function}}$ wait - setTimeout promisify
159
+ __function__ `wait` - setTimeout promisify
160
160
 
161
161
  ---
162
- ${\textsf{\color{CornflowerBlue}function}}$ noop - Empty function that does nothing
162
+ __function__ `noop` - Empty function that does nothing
163
163
 
164
164
  ---
165
- ${\textsf{\color{CornflowerBlue}async function}}$ concurrentRun - Run array of async tasks concurrently
165
+ __async function__ `concurrentRun` - Run array of async tasks concurrently
166
+
167
+ ---
168
+ __class__ `SimpleEventSource` - Create simple event source. Consider using `signal()` for reactive state managment.
166
169
 
167
170
  ---
168
171
 
@@ -170,10 +173,10 @@ ${\textsf{\color{CornflowerBlue}async function}}$ concurrentRun - Run array of a
170
173
  ## Errors
171
174
  Custom errors, finding errors and error handling.
172
175
 
173
- ${\textsf{\color{Orange}class}}$ ValidationError - Use as intended error. Basically 4** errors in HTTP
176
+ __class__ `ValidationError` - Use as intended error. Basically 4** errors in HTTP
174
177
 
175
178
  ---
176
- ${\textsf{\color{CornflowerBlue}function}}$ findErrorText - Find error inside anything recursively.
179
+ __function__ `findErrorText` - Find error inside anything recursively.
177
180
  Good for finding human-readable errors.
178
181
  Tries priority keys first.
179
182
  Parses JSON automatically.
@@ -185,37 +188,37 @@ Returns undefind if nothing found.
185
188
  ## Formatting
186
189
  Anything related to formatting and logging.
187
190
 
188
- ${\textsf{\color{Magenta}type}}$ FormatTimeRange - Type for formatTime ranges
191
+ __type__ `FormatTimeRange` - Type for formatTime ranges
189
192
 
190
193
  ---
191
- ${\textsf{\color{ForestGreen}const}}$ FORMAT_NUMBER_RANGES - Default time range
194
+ __const__ `FORMAT_NUMBER_RANGES` - Default time range
192
195
 
193
196
  ---
194
- ${\textsf{\color{ForestGreen}const}}$ FORMAT_NUMBER_RANGES_READABLE - Time range more suitable for readability
197
+ __const__ `FORMAT_NUMBER_RANGES_READABLE` - Time range more suitable for readability
195
198
 
196
199
  ---
197
- ${\textsf{\color{ForestGreen}const}}$ FORMAT_NUMBER_RANGES_BYTES - Bytes range
200
+ __const__ `FORMAT_NUMBER_RANGES_BYTES` - Bytes range
198
201
 
199
202
  ---
200
- ${\textsf{\color{CornflowerBlue}function}}$ formatNumber - Milliseconds to human readable time. Minimum accuracy, if set to 1000 will stop at seconds
203
+ __function__ `formatNumber` - Milliseconds to human readable time. Minimum accuracy, if set to 1000 will stop at seconds
201
204
 
202
205
  ---
203
- ${\textsf{\color{CornflowerBlue}function}}$ camelToSnakeCase - thisCase to this_case
206
+ __function__ `camelToSnakeCase` - thisCase to this_case
204
207
 
205
208
  ---
206
- ${\textsf{\color{CornflowerBlue}function}}$ snakeToCamelCase - this_case to thisCase
209
+ __function__ `snakeToCamelCase` - this_case to thisCase
207
210
 
208
211
  ---
209
- ${\textsf{\color{CornflowerBlue}function}}$ formatBytes - Bytes to KB,MB,GB,TB
212
+ __function__ `formatBytes` - Bytes to KB,MB,GB,TB
210
213
 
211
214
  ---
212
- ${\textsf{\color{CornflowerBlue}function}}$ log - Format logging
215
+ __function__ `log` - Format logging
213
216
 
214
217
  ---
215
- ${\textsf{\color{CornflowerBlue}function}}$ capitalizeFirstLetter - Capitalize first letter
218
+ __function__ `capitalizeFirstLetter` - Capitalize first letter
216
219
 
217
220
  ---
218
- ${\textsf{\color{CornflowerBlue}function}}$ pipe - pipe() can be called on one or more functions, each of which can take the return of previous value.
221
+ __function__ `pipe` - pipe() can be called on one or more functions, each of which can take the return of previous value.
219
222
 
220
223
  ```ts
221
224
  // Takes string, converts to int, calc sqrt, convert and return date
@@ -232,21 +235,21 @@ pipe(
232
235
  ## Graphs
233
236
  Pos
234
237
 
235
- ${\textsf{\color{CornflowerBlue}function}}$ unfoldPathfindingResult - Unfold pathfinding result to path array.
238
+ __function__ `unfoldPathfindingResult` - Unfold pathfinding result to path array.
236
239
 
237
240
  ---
238
- ${\textsf{\color{CornflowerBlue}function}}$ aStar - Pathfind using aStar.
241
+ __function__ `aStar` - Pathfind using aStar.
239
242
  Returns a target and map of parents.
240
243
  You can use `unfoldPathfindingResult()` to get array of nodes.
241
244
 
242
245
  ---
243
- ${\textsf{\color{CornflowerBlue}function}}$ bfs - Breadth-first search. Slower than dfs.
246
+ __function__ `bfs` - Breadth-first search. Slower than dfs.
244
247
  If isTarget is omitted becomes floodfill.
245
248
  Returns a target and map of parents.
246
249
  You can use `unfoldPathfindingResult()` to get array of nodes.
247
250
 
248
251
  ---
249
- ${\textsf{\color{CornflowerBlue}function}}$ dfs - Depth-first search. Faster than bfs.
252
+ __function__ `dfs` - Depth-first search. Faster than bfs.
250
253
  If isTarget is omitted becomes floodfill.
251
254
  Returns a target and map of parents.
252
255
  You can use `unfoldPathfindingResult()` to get array of nodes.
@@ -257,19 +260,19 @@ You can use `unfoldPathfindingResult()` to get array of nodes.
257
260
  ## Numbers
258
261
  Numbers, math, etc.
259
262
 
260
- ${\textsf{\color{CornflowerBlue}function}}$ random - Random number between min and max. May enable float
263
+ __function__ `random` - Random number between min and max. May enable float
261
264
 
262
265
  ---
263
- ${\textsf{\color{CornflowerBlue}function}}$ parseInt - Same as Number.parseInt but throws if NaN or not safe
266
+ __function__ `parseInt` - Same as Number.parseInt but throws if NaN or not safe
264
267
 
265
268
  ---
266
- ${\textsf{\color{CornflowerBlue}function}}$ parseFloat - Same as Number.parseFloat but throws if NaN or Infinity
269
+ __function__ `parseFloat` - Same as Number.parseFloat but throws if NaN or Infinity
267
270
 
268
271
  ---
269
- ${\textsf{\color{CornflowerBlue}function}}$ factorial - Factorial
272
+ __function__ `factorial` - Factorial
270
273
 
271
274
  ---
272
- ${\textsf{\color{CornflowerBlue}function}}$ fib - Fibonacci
275
+ __function__ `fib` - Fibonacci
273
276
 
274
277
  ---
275
278
 
@@ -277,19 +280,19 @@ ${\textsf{\color{CornflowerBlue}function}}$ fib - Fibonacci
277
280
  ## Objects
278
281
  [object Object]
279
282
 
280
- ${\textsf{\color{CornflowerBlue}function}}$ getPropertyNames - Get all prorerty names, including in prototype
283
+ __function__ `getPropertyNames` - Get all prorerty names, including in prototype
281
284
 
282
285
  ---
283
- ${\textsf{\color{CornflowerBlue}function}}$ objectMap - Map function like for arrays, but for objects
286
+ __function__ `objectMap` - Map function like for arrays, but for objects
284
287
 
285
288
  ---
286
- ${\textsf{\color{CornflowerBlue}function}}$ objectFilter - Filter function like for arrays, but for objects
289
+ __function__ `objectFilter` - Filter function like for arrays, but for objects
287
290
 
288
291
  ---
289
- ${\textsf{\color{CornflowerBlue}function}}$ addPrefixToObject - Adds prefix to every key in object
292
+ __function__ `addPrefixToObject` - Adds prefix to every key in object
290
293
 
291
294
  ---
292
- ${\textsf{\color{CornflowerBlue}function}}$ deepEquals - Check if objects are deep equal
295
+ __function__ `deepEquals` - Check if objects are deep equal
293
296
 
294
297
  **Supports:**
295
298
  - All primitives (String, Number, BigNumber, Null, undefined, Symbol)
@@ -307,10 +310,10 @@ Behavior with types above are not defined, but
307
310
  it will still check them by reference.
308
311
 
309
312
  ---
310
- ${\textsf{\color{CornflowerBlue}function}}$ pick - Pick keys from object
313
+ __function__ `pick` - Pick keys from object
311
314
 
312
315
  ---
313
- ${\textsf{\color{Orange}class}}$ Base - Base class that helps to manage ids and subclasses.
316
+ __class__ `Base` - Base class that helps to manage ids and subclasses.
314
317
 
315
318
  Include next lines when extending this class:
316
319
  ```js
@@ -325,7 +328,7 @@ this.registerSubclass()
325
328
  ## Signals
326
329
  Reactive signals
327
330
 
328
- ${\textsf{\color{CornflowerBlue}function}}$ signal - __SIGNALS SYSTEM__
331
+ __function__ `signal` - __SIGNALS SYSTEM__
329
332
 
330
333
  Signal can hold any data (except functions),
331
334
  when this data has changed any effects containing
@@ -343,7 +346,7 @@ console.log($mySignal())
343
346
  ```
344
347
 
345
348
  ---
346
- ${\textsf{\color{CornflowerBlue}function}}$ effect - __SIGNALS SYSTEM__
349
+ __function__ `effect` - __SIGNALS SYSTEM__
347
350
 
348
351
  Effects are simplest way to react to signal changes.
349
352
  Returned data from handler function will be passed to it on next signal change.
@@ -362,7 +365,7 @@ return mySignal;
362
365
  })
363
366
 
364
367
  ---
365
- ${\textsf{\color{CornflowerBlue}function}}$ untrack - __SIGNALS SYSTEM__
368
+ __function__ `untrack` - __SIGNALS SYSTEM__
366
369
 
367
370
  Untrack helps to not react to changes in effects.
368
371
  ```ts
@@ -375,7 +378,7 @@ console.log(untrack($a)+$b())
375
378
  ```
376
379
 
377
380
  ---
378
- ${\textsf{\color{CornflowerBlue}function}}$ derived - __SIGNALS SYSTEM__
381
+ __function__ `derived` - __SIGNALS SYSTEM__
379
382
 
380
383
  Creates a derived reactive memoized signal.
381
384
 
@@ -385,7 +388,7 @@ const { signal: $sumOfTwo, clear: clearSum } = derived((value) => value + $a(),
385
388
  ```
386
389
 
387
390
  ---
388
- ${\textsf{\color{CornflowerBlue}function}}$ batch - __SIGNALS SYSTEM__
391
+ __function__ `batch` - __SIGNALS SYSTEM__
389
392
 
390
393
  Batches multiple edits, so they don't call same effects multiple times
391
394
 
@@ -405,7 +408,7 @@ $b(5);
405
408
  ```
406
409
 
407
410
  ---
408
- ${\textsf{\color{CornflowerBlue}function}}$ when - __SIGNALS SYSTEM__
411
+ __function__ `when` - __SIGNALS SYSTEM__
409
412
 
410
413
  Returns ImmediatePromise that is resolved when check function returns truthy value.
411
414
  If you want to, you can resolve or reject promise beforehand.
@@ -424,15 +427,15 @@ primise.then(() => clearTimeout(timeout))
424
427
  ## Time
425
428
  Timers, CRON, etc.
426
429
 
427
- ${\textsf{\color{CornflowerBlue}function}}$ measurePerformance - Measure performance of a function
430
+ __function__ `measurePerformance` - Measure performance of a function
428
431
 
429
432
  ---
430
- ${\textsf{\color{CornflowerBlue}function}}$ cronInterval - Like setInterval but with cron.
433
+ __function__ `cronInterval` - Like setInterval but with cron.
431
434
  Returns clear function.
432
435
  For cron string syntax check __getNextCron()__ description
433
436
 
434
437
  ---
435
- ${\textsf{\color{CornflowerBlue}function}}$ getNextCron - Find next cron date after passed date.
438
+ __function__ `getNextCron` - Find next cron date after passed date.
436
439
 
437
440
  This function __DOES NOT__ implement regular CRON 1 to 1.
438
441
 
@@ -442,7 +445,7 @@ Main differences:
442
445
  - Second and millisecond support: __* * * * * 30 999__ - executes every 30 seconds at the end of a second
443
446
 
444
447
  ---
445
- ${\textsf{\color{Orange}class}}$ SpeedCalculator - Object that calculates speed, ETA and percent of any measurable task.
448
+ __class__ `SpeedCalculator` - Object that calculates speed, ETA and percent of any measurable task.
446
449
 
447
450
  `push()` chunks into speed calculator and then read `stats` for results.
448
451
  `size` - a target then task is finished. Without it only speed is calculated.
@@ -454,45 +457,45 @@ ${\textsf{\color{Orange}class}}$ SpeedCalculator - Object that calculates speed,
454
457
  ## Types
455
458
  Damn, I **love** TypeScript.
456
459
 
457
- ${\textsf{\color{Magenta}type}}$ Primitive - Values that are copied by value, not by reference
460
+ __type__ `Primitive` - Values that are copied by value, not by reference
458
461
 
459
462
  ---
460
- ${\textsf{\color{Magenta}type}}$ AnyFunction - Function with any arguments or return type
463
+ __type__ `AnyFunction` - Function with any arguments or return type
461
464
 
462
465
  ---
463
- ${\textsf{\color{Magenta}type}}$ Falsy - Values that convert to false
466
+ __type__ `Falsy` - Values that convert to false
464
467
 
465
468
  ---
466
- ${\textsf{\color{Magenta}type}}$ Optional - Make keys in object optional
469
+ __type__ `Optional` - Make keys in object optional
467
470
 
468
471
  ---
469
- ${\textsf{\color{Magenta}type}}$ RequiredKey - Make keys in object required
472
+ __type__ `RequiredKey` - Make keys in object required
470
473
 
471
474
  ---
472
- ${\textsf{\color{Magenta}type}}$ Constructor - Get contructor type of an instance
475
+ __type__ `Constructor` - Get contructor type of an instance
473
476
 
474
477
  ---
475
- ${\textsf{\color{Magenta}type}}$ AwaitedObject - Recursively resolves promises in objects and arrays
478
+ __type__ `AwaitedObject` - Recursively resolves promises in objects and arrays
476
479
 
477
480
  ---
478
- ${\textsf{\color{Magenta}type}}$ JSONSerializable - Anything that can be serialized to JSON
481
+ __type__ `JSONSerializable` - Anything that can be serialized to JSON
479
482
 
480
483
  ---
481
- ${\textsf{\color{Magenta}type}}$ ObjectAddPrefix - Adds prefix to all keys in object
484
+ __type__ `ObjectAddPrefix` - Adds prefix to all keys in object
482
485
 
483
486
  ---
484
- ${\textsf{\color{Magenta}type}}$ CamelToSnakeCase - Convert type of thisCase to this_case
487
+ __type__ `CamelToSnakeCase` - Convert type of thisCase to this_case
485
488
 
486
489
  ---
487
- ${\textsf{\color{Magenta}type}}$ ObjectCamelToSnakeCase - Convert object keys of thisCase to this_case
490
+ __type__ `ObjectCamelToSnakeCase` - Convert object keys of thisCase to this_case
488
491
 
489
492
  ---
490
- ${\textsf{\color{Magenta}type}}$ SnakeToCamel - Convert type of this-case to thisCase
493
+ __type__ `SnakeToCamel` - Convert type of this-case to thisCase
491
494
 
492
495
  ---
493
- ${\textsf{\color{Magenta}type}}$ ObjectSnakeToCamel - Convert object keys of this-case to thisCase
496
+ __type__ `ObjectSnakeToCamel` - Convert object keys of this-case to thisCase
494
497
 
495
498
  ---
496
- ${\textsf{\color{Magenta}type}}$ Concat - Concat types of array or objects
499
+ __type__ `Concat` - Concat types of array or objects
497
500
 
498
501
  ---
package/dist/control.d.ts CHANGED
@@ -60,4 +60,19 @@ export declare function wait(time: number): Promise<unknown>;
60
60
  export declare function noop(): void;
61
61
  /** Run array of async tasks concurrently */
62
62
  export declare function concurrentRun<T>(tasks: (() => Promise<T>)[], concurrency?: number): Promise<T[]>;
63
+ /** Create simple event source. Consider using `signal()` for reactive state managment. */
64
+ export declare class SimpleEventSource<EVENTS extends Record<string, unknown>> {
65
+ protected handlers: Map<keyof EVENTS, ((data: EVENTS[keyof EVENTS]) => unknown)[]>;
66
+ /** Send event to all subscribers */
67
+ send<T extends keyof EVENTS>(name: T, data: EVENTS[T]): unknown[];
68
+ /** Subscribe. Returns function to unsubscribe. */
69
+ on<T extends keyof EVENTS>(name: T, handler: (data: EVENTS[T]) => unknown): () => void;
70
+ /** Unsubscribe. Alternatively use return function of `on()` */
71
+ off<T extends keyof EVENTS>(name: T, handler: (data: EVENTS[T]) => unknown): void;
72
+ /** Use this to hide send function */
73
+ get source(): {
74
+ on: <T extends keyof EVENTS>(name: T, handler: (data: EVENTS[T]) => unknown) => () => void;
75
+ off: <T extends keyof EVENTS>(name: T, handler: (data: EVENTS[T]) => unknown) => void;
76
+ };
77
+ }
63
78
  export {};
package/dist/control.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Utils related to code execution flow.
3
3
  */
4
+ import { removeFromArray } from './arrays';
4
5
  let lastIncId = Math.floor(Math.random() * 0x1_00_00);
5
6
  /** Id generated only once per session */
6
7
  export const SESSION_ID = Math.floor(Math.random() * 0x10_00_00_00_00_00_00)
@@ -200,3 +201,41 @@ export async function concurrentRun(tasks, concurrency = 4) {
200
201
  runNext();
201
202
  });
202
203
  }
204
+ /** Create simple event source. Consider using `signal()` for reactive state managment. */
205
+ export class SimpleEventSource {
206
+ handlers = new Map();
207
+ /** Send event to all subscribers */
208
+ send(name, data) {
209
+ return this.handlers.get(name)?.map((handler) => handler(data)) ?? [];
210
+ }
211
+ /** Subscribe. Returns function to unsubscribe. */
212
+ on(name, handler) {
213
+ let handlers = this.handlers.get(name);
214
+ if (!handlers) {
215
+ handlers = [];
216
+ this.handlers.set(name, handlers);
217
+ }
218
+ handlers.push(handler);
219
+ return () => {
220
+ removeFromArray(handlers, handler);
221
+ if (handlers.length === 0)
222
+ this.handlers.delete(name);
223
+ };
224
+ }
225
+ /** Unsubscribe. Alternatively use return function of `on()` */
226
+ off(name, handler) {
227
+ const handlers = this.handlers.get(name);
228
+ if (!handlers)
229
+ return;
230
+ removeFromArray(handlers, handler);
231
+ if (handlers.length === 0)
232
+ this.handlers.delete(name);
233
+ }
234
+ /** Use this to hide send function */
235
+ get source() {
236
+ return {
237
+ on: this.on.bind(this),
238
+ off: this.off.bind(this),
239
+ };
240
+ }
241
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softsky/utils",
3
- "version": "2.5.2",
3
+ "version": "2.5.3",
4
4
  "description": "JavaScript/TypeScript utilities",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {