@develia/commons 0.3.29 → 0.3.31

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.
@@ -1,59 +1,85 @@
1
- import {Deferred} from "./types";
2
- import {promisify} from "./utilities";
1
+ import {Supplier} from "./types";
2
+ import {delay} from "./utilities";
3
3
 
4
4
  export default class AsyncPoolExecutor {
5
+ private _checkIntervalMs: number;
5
6
 
6
- private readonly _maxConcurrency: number;
7
- private _taskQueue: Array<() => Deferred<any>> = [];
8
- private _activeTasks: number = 0;
7
+ get maxConcurrency(): number {
8
+ return this._maxConcurrency;
9
+ }
10
+
11
+ set maxConcurrency(value: number) {
12
+ this._maxConcurrency = value;
9
13
 
10
- constructor(maxConcurrency: number) {
11
- this._maxConcurrency = maxConcurrency;
12
14
  }
13
15
 
16
+ private _proccess: any;
17
+ private _maxConcurrency: number;
18
+ private _activeTasks: number;
19
+ private _taskQueue: Array<Supplier<any>> = [];
20
+
21
+
22
+ /**
23
+ * @param {number} maxConcurrency - The maximum number of concurrent tasks allowed.
24
+ * @param {number} [checkInterval=50] - The interval, in milliseconds, to check for capacity to run new tasks. Defaults to 50 ms.
25
+ */
26
+ constructor(maxConcurrency: number, checkInterval: number = 50) {
27
+ this._maxConcurrency = maxConcurrency;
28
+ this._checkIntervalMs = checkInterval;
29
+ this._activeTasks = 0;
30
+ }
14
31
 
15
32
  /**
16
33
  * Submits a deferred task to a queue for asynchronous execution and returns a Promise resolving to its result.
17
34
  * @template T
18
- * @param {Deferred<T>} task - The deferred task to be executed asynchronously.
19
- * @return {Promise<T>} A Promise that resolves with the result of the executed task, or rejects if an error occurs during execution.
35
+ * @param {Supplier<T>} task - The deferred task to be executed asynchronously.
20
36
  */
21
- public submit<T>(task: Deferred<T>): Promise<T> {
22
- return new Promise<T>((resolve, reject) => {
23
- this._taskQueue.push(async () => {
24
- try {
37
+ public submit(task: Supplier<any>): void {
38
+
39
+ this._taskQueue.push(task);
40
+
41
+ if (this._proccess != null)
42
+ return;
43
+
44
+ this._proccess = setTimeout(async () => {
45
+
46
+ while (this._taskQueue.length > 0) {
47
+
48
+ while (this._activeTasks >= this._maxConcurrency) {
49
+ await delay(this._checkIntervalMs);
50
+ }
51
+
52
+ const task = this._taskQueue.shift();
53
+ if (task) {
25
54
  this._activeTasks++;
26
- resolve(await promisify(task));
27
- } catch (error) {
28
- reject(error);
29
- } finally {
30
- this._activeTasks--;
31
- this._runNext(); // Intenta ejecutar la siguiente tarea
55
+ setTimeout(async () => {
56
+ try {
57
+ await task();
58
+ } finally {
59
+ this._activeTasks--;
60
+ }
61
+ });
32
62
  }
33
- });
34
- this._runNext();
35
- });
36
- }
37
63
 
38
64
 
39
- private _runNext(): void {
40
- while (this._activeTasks < this._maxConcurrency && this._taskQueue.length > 0) {
41
- const nextTask = this._taskQueue.shift();
42
- nextTask && nextTask();
43
- }
65
+ }
66
+
67
+ this._proccess = null;
68
+ }, 0);
69
+
70
+
44
71
  }
45
72
 
46
73
 
47
74
  /**
48
- * Gracefully shuts down the system by waiting for all queued and active tasks to complete.
49
- * The method ensures that no tasks remain in the queue and no tasks are actively running
50
- * before resolving the promise.
75
+ * Waits until all tasks (both queued and active) are completed.
76
+ * This method resolves only when there are no pending tasks.
51
77
  *
52
- * @return {Promise<void>} A promise that resolves when the shutdown process is complete.
78
+ * @return {Promise<void>} A promise that resolves when all tasks are complete.
53
79
  */
54
80
  public async shutdown(): Promise<void> {
55
81
  while (this._taskQueue.length > 0 || this._activeTasks > 0) {
56
- await new Promise((resolve) => setTimeout(resolve, 50));
82
+ await delay(this._checkIntervalMs);
57
83
  }
58
84
  }
59
- }
85
+ }
@@ -0,0 +1,24 @@
1
+ import {isFunction} from "./utilities";
2
+
3
+ export class LazyMap<K, V> extends Map<K, V> {
4
+
5
+ private readonly _factoryMethod: (key: K) => V;
6
+
7
+ constructor(factoryMethod: (key: K) => V, entries?: readonly (readonly [K, V])[] | null) {
8
+ super(entries);
9
+ if (!isFunction(factoryMethod)) {
10
+ throw new Error("factoryMethod is not a function");
11
+ }
12
+ this._factoryMethod = factoryMethod;
13
+ }
14
+
15
+ // Sobrescribir el método get
16
+ get(key: K): V {
17
+ if (!this.has(key)) {
18
+ const value = this._factoryMethod(key);
19
+ this.set(key, value);
20
+ return value;
21
+ }
22
+ return super.get(key) as V;
23
+ }
24
+ }
package/src/from.ts CHANGED
@@ -1,9 +1,9 @@
1
- import {Consumer, EqualityComparer, UnaryFunction, Predicate, Provider, Optional, Nullable} from "./types";
1
+ import {Consumer, EqualityComparer, UnaryFunction, Predicate, Supplier, Optional, Nullable} from "./types";
2
2
  import {toPairs} from "./utilities";
3
- import Pair from "./pair";
3
+ import KeyValuePair from "./key-value-pair";
4
4
 
5
5
 
6
- export default function from<T>(source: Iterable<T> | Provider<Iterable<T>>): From<T> | From<Pair<any, any>> {
6
+ export default function from<T>(source: Iterable<T> | Supplier<Iterable<T>>): From<T> | From<KeyValuePair<any, any>> {
7
7
  if (source == null)
8
8
  throw "Source is null.";
9
9
  if (typeof source === 'function')
@@ -19,8 +19,8 @@ export default function from<T>(source: Iterable<T> | Provider<Iterable<T>>): Fr
19
19
 
20
20
  export class From<T> implements Iterable<T> {
21
21
 
22
- public static object(obj: any): From<Pair<any, any>> {
23
- return new From<Pair<any, any>>(function () {
22
+ public static object(obj: any): From<KeyValuePair<any, any>> {
23
+ return new From<KeyValuePair<any, any>>(function () {
24
24
  return toPairs(obj);
25
25
  });
26
26
  }
@@ -42,13 +42,13 @@ export class From<T> implements Iterable<T> {
42
42
  return true;
43
43
  }
44
44
 
45
- private readonly _fn: Provider<Iterable<T>>
45
+ private readonly _fn: Supplier<Iterable<T>>
46
46
 
47
- protected constructor(fn: Provider<Iterable<T>>) {
47
+ protected constructor(fn: Supplier<Iterable<T>>) {
48
48
  this._fn = fn;
49
49
  }
50
50
 
51
- public static fn<T>(callable: Provider<Iterable<T>>): From<T> {
51
+ public static fn<T>(callable: Supplier<Iterable<T>>): From<T> {
52
52
  return new From<T>(callable);
53
53
  };
54
54
 
package/src/index.ts CHANGED
@@ -8,9 +8,10 @@ export {default as from, From} from './from';
8
8
  export {default as Timer} from './timer'
9
9
  export {default as TimeSpan} from './timespan'
10
10
  export {default as Lazy} from './lazy'
11
- export {default as Pair} from './pair'
11
+ export {default as KeyValuePair} from './key-value-pair'
12
12
  export {default as array, ArrayManipulator} from './array-manipulator';
13
13
  export {default as AsyncPoolExecutor} from './async-pool-executor';
14
+ export * from './array'
14
15
 
15
16
 
16
17
 
@@ -4,7 +4,7 @@
4
4
  * @template TKey The type of the key.
5
5
  * @template TValue The type of the value.
6
6
  */
7
- export default class Pair<TKey, TValue> {
7
+ export default class KeyValuePair<TKey, TValue> {
8
8
  get value(): TValue {
9
9
  return this._value;
10
10
  }
package/src/lazy.ts CHANGED
@@ -1,4 +1,4 @@
1
- import {Nullable, Provider} from "./types";
1
+ import {Nullable, Supplier} from "./types";
2
2
 
3
3
 
4
4
  /**
@@ -8,9 +8,9 @@ import {Nullable, Provider} from "./types";
8
8
  export default class Lazy<T> {
9
9
  private _valueCreated = false;
10
10
  private _value: Nullable<T> = null;
11
- private readonly _factoryMethod: Provider<T>;
11
+ private readonly _factoryMethod: Supplier<T>;
12
12
 
13
- constructor(getter: Provider<T>) {
13
+ constructor(getter: Supplier<T>) {
14
14
  this._factoryMethod = getter;
15
15
  }
16
16
 
package/src/types.ts CHANGED
@@ -6,12 +6,14 @@ export type Consumer<T> = (arg: T) => void
6
6
 
7
7
  export type Predicate<T> = (arg: T) => boolean;
8
8
 
9
- export type Provider<T> = () => T;
9
+ export type Supplier<T> = () => T;
10
10
 
11
11
  export type Nullable<T> = T | null;
12
12
 
13
13
  export type Optional<T> = T | undefined;
14
14
 
15
- export type Deferred<T> = Promise<T> | Provider<T>
15
+ export type Resolvable<T> = Promise<T> | Supplier<T>
16
+
17
+ export type PromiseExecutor = (resolve: Consumer<any>, reject: Consumer<any>) => any
16
18
 
17
19
 
package/src/utilities.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  // noinspection JSUnusedGlobalSymbols
2
2
 
3
3
 
4
- import Pair from "./pair";
5
- import {Deferred, Optional, Provider} from "./types";
4
+ import KeyValuePair from "./key-value-pair";
5
+ import {Optional, Resolvable, Supplier} from "./types";
6
6
  import {Type} from "./typing";
7
7
 
8
8
  /**
@@ -77,13 +77,68 @@ export function isFunction(value: any): value is Function {
77
77
  }
78
78
 
79
79
 
80
+ /**
81
+ * Compares two objects or arrays to check if they have the same fields and values,
82
+ * or the same elements if they are arrays.
83
+ *
84
+ * @param {any} a - The first object or array.
85
+ * @param {any} b - The second object or array.
86
+ * @return {boolean} - Returns true if the objects/arrays are equal, otherwise false.
87
+ */
88
+ export function deepEqual(a: any, b: any): boolean {
89
+ if (a === b) {
90
+ // If both values are strictly equal, return true
91
+ return true;
92
+ }
93
+
94
+ // If either value is null or their types differ, return false
95
+ if (a === null || b === null || typeof a !== typeof b) {
96
+ return false;
97
+ }
98
+
99
+ // Check if both values are arrays
100
+ if (Array.isArray(a) && Array.isArray(b)) {
101
+ // Compare lengths and elements recursively
102
+ if (a.length !== b.length) {
103
+ return false;
104
+ }
105
+ for (let i = 0; i < a.length; i++) {
106
+ if (!deepEqual(a[i], b[i])) {
107
+ return false;
108
+ }
109
+ }
110
+ return true;
111
+ }
112
+
113
+ // Check if both values are objects
114
+ if (typeof a === "object" && typeof b === "object") {
115
+ const keysA = Object.keys(a);
116
+ const keysB = Object.keys(b);
117
+
118
+ // Compare the keys length and check if all keys/values match
119
+ if (keysA.length !== keysB.length) {
120
+ return false;
121
+ }
122
+ for (const key of keysA) {
123
+ if (!keysB.includes(key) || !deepEqual(a[key], b[key])) {
124
+ return false;
125
+ }
126
+ }
127
+ return true;
128
+ }
129
+
130
+ // For all other data types (e.g., numbers, strings, booleans), use strict equality
131
+ return false;
132
+ }
133
+
134
+
80
135
  /**
81
136
  * Pauses the execution of an asynchronous function for a specified duration.
82
137
  *
83
138
  * @param {number} ms - The delay duration in milliseconds.
84
139
  * @return {Promise<void>} A promise that resolves after the specified delay.
85
140
  */
86
- export async function delay(ms: number): Promise<void>{
141
+ export async function delay(ms: number): Promise<void> {
87
142
  await new Promise(resolve => setTimeout(resolve, ms));
88
143
  }
89
144
 
@@ -118,6 +173,7 @@ export function isNull(value: any): value is null {
118
173
  return value === null;
119
174
  }
120
175
 
176
+
121
177
  /**
122
178
  * Determines whether the given value is of type bigint.
123
179
  * @param {any} value - The value to be checked.
@@ -200,13 +256,13 @@ export async function ajaxSubmit(selectorOrElement: HTMLFormElement | string): P
200
256
  * Converts an object into an array of key-value pairs.
201
257
  *
202
258
  * @param {Record<string, any>} obj - The object to convert.
203
- * @return {Pair<string, any>[]} - The array of key-value pairs.
259
+ * @return {KeyValuePair<string, any>[]} - The array of key-value pairs.
204
260
  */
205
- export function toPairs(obj: Record<string, any>): Pair<string, any>[] {
261
+ export function toPairs(obj: Record<string, any>): KeyValuePair<string, any>[] {
206
262
 
207
263
  let output = [];
208
264
  for (const key in obj) {
209
- output.push(new Pair(key, obj[key]));
265
+ output.push(new KeyValuePair(key, obj[key]));
210
266
  }
211
267
  return output;
212
268
 
@@ -218,7 +274,7 @@ export function toPairs(obj: Record<string, any>): Pair<string, any>[] {
218
274
  * @param {any} thing - The thing to be converted into a Promise.
219
275
  * @returns {Promise<T>} - A Promise representing the given thing.
220
276
  */
221
- export function promisify<T>(thing: Deferred<T>): Promise<T> {
277
+ export function promisify<T>(thing: Resolvable<T>): Promise<T> {
222
278
 
223
279
  if (thing instanceof Promise)
224
280
  return thing;
@@ -240,8 +296,8 @@ export function promisify<T>(thing: Deferred<T>): Promise<T> {
240
296
 
241
297
 
242
298
  export function ajaxSubmission(selectorOrElement: HTMLFormElement | string,
243
- onSuccess: Optional<Provider<any>> = undefined,
244
- onFailure: Optional<Provider<any>> = undefined) : void {
299
+ onSuccess: Optional<Supplier<any>> = undefined,
300
+ onFailure: Optional<Supplier<any>> = undefined): void {
245
301
 
246
302
  const form = typeof selectorOrElement === 'string'
247
303
  ? document.querySelector(selectorOrElement)