@develia/commons 0.4.15 → 0.4.18

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 (216) hide show
  1. package/dist/cjs/array.js +38 -2
  2. package/dist/cjs/array.js.map +1 -1
  3. package/dist/cjs/async-pool-executor.js +26 -11
  4. package/dist/cjs/async-pool-executor.js.map +1 -1
  5. package/dist/cjs/browser/form-utilities.js +35 -34
  6. package/dist/cjs/browser/form-utilities.js.map +1 -1
  7. package/dist/cjs/browser/geo-location.js +1 -1
  8. package/dist/cjs/browser/geo-location.js.map +1 -1
  9. package/dist/cjs/browser/native-bridge.js +3 -1
  10. package/dist/cjs/browser/native-bridge.js.map +1 -1
  11. package/dist/cjs/cancellable-promise.js +34 -13
  12. package/dist/cjs/cancellable-promise.js.map +1 -1
  13. package/dist/cjs/clean-url-search-params.js +26 -3
  14. package/dist/cjs/clean-url-search-params.js.map +1 -1
  15. package/dist/cjs/collections/cache-dictionary.js +3 -3
  16. package/dist/cjs/collections/cache-dictionary.js.map +1 -1
  17. package/dist/cjs/collections/default-map.js.map +1 -1
  18. package/dist/cjs/collections/default-weak-map.js.map +1 -1
  19. package/dist/cjs/collections/from.js +3 -3
  20. package/dist/cjs/collections/from.js.map +1 -1
  21. package/dist/cjs/collections/index.js.map +1 -1
  22. package/dist/cjs/draft.js +46 -11
  23. package/dist/cjs/draft.js.map +1 -1
  24. package/dist/cjs/event-bus.js +1 -1
  25. package/dist/cjs/event-bus.js.map +1 -1
  26. package/dist/cjs/functions.js +348 -0
  27. package/dist/cjs/functions.js.map +1 -0
  28. package/dist/cjs/index.js +4 -1
  29. package/dist/cjs/index.js.map +1 -1
  30. package/dist/cjs/key-value-pair.js.map +1 -1
  31. package/dist/cjs/lazy.js.map +1 -1
  32. package/dist/cjs/math.js +3 -0
  33. package/dist/cjs/math.js.map +1 -1
  34. package/dist/cjs/order.js.map +1 -1
  35. package/dist/cjs/parse.js +10 -1
  36. package/dist/cjs/parse.js.map +1 -1
  37. package/dist/cjs/patch.js.map +1 -1
  38. package/dist/cjs/range.js +154 -0
  39. package/dist/cjs/range.js.map +1 -0
  40. package/dist/cjs/stopwatch.js.map +1 -1
  41. package/dist/cjs/string.js +8 -5
  42. package/dist/cjs/string.js.map +1 -1
  43. package/dist/cjs/timer.js +1 -1
  44. package/dist/cjs/timer.js.map +1 -1
  45. package/dist/cjs/timespan.js +21 -8
  46. package/dist/cjs/timespan.js.map +1 -1
  47. package/dist/cjs/type-code.js.map +1 -1
  48. package/dist/cjs/type.js +20 -19
  49. package/dist/cjs/type.js.map +1 -1
  50. package/dist/cjs/types.js.map +1 -1
  51. package/dist/cjs/utilities.js +175 -39
  52. package/dist/cjs/utilities.js.map +1 -1
  53. package/dist/esm/array.js +36 -2
  54. package/dist/esm/array.js.map +1 -1
  55. package/dist/esm/async-pool-executor.js +26 -11
  56. package/dist/esm/async-pool-executor.js.map +1 -1
  57. package/dist/esm/browser/form-utilities.js +35 -34
  58. package/dist/esm/browser/form-utilities.js.map +1 -1
  59. package/dist/esm/browser/geo-location.js +1 -1
  60. package/dist/esm/browser/geo-location.js.map +1 -1
  61. package/dist/esm/browser/native-bridge.js +3 -1
  62. package/dist/esm/browser/native-bridge.js.map +1 -1
  63. package/dist/esm/cancellable-promise.js +34 -13
  64. package/dist/esm/cancellable-promise.js.map +1 -1
  65. package/dist/esm/clean-url-search-params.js +26 -3
  66. package/dist/esm/clean-url-search-params.js.map +1 -1
  67. package/dist/esm/collections/cache-dictionary.js +3 -3
  68. package/dist/esm/collections/cache-dictionary.js.map +1 -1
  69. package/dist/esm/collections/default-map.js.map +1 -1
  70. package/dist/esm/collections/default-weak-map.js.map +1 -1
  71. package/dist/esm/collections/from.js +3 -3
  72. package/dist/esm/collections/from.js.map +1 -1
  73. package/dist/esm/collections/index.js.map +1 -1
  74. package/dist/esm/draft.js +46 -11
  75. package/dist/esm/draft.js.map +1 -1
  76. package/dist/esm/event-bus.js +1 -1
  77. package/dist/esm/event-bus.js.map +1 -1
  78. package/dist/esm/functions.js +336 -0
  79. package/dist/esm/functions.js.map +1 -0
  80. package/dist/esm/index.js +2 -0
  81. package/dist/esm/index.js.map +1 -1
  82. package/dist/esm/key-value-pair.js.map +1 -1
  83. package/dist/esm/lazy.js.map +1 -1
  84. package/dist/esm/math.js +3 -0
  85. package/dist/esm/math.js.map +1 -1
  86. package/dist/esm/order.js.map +1 -1
  87. package/dist/esm/parse.js +10 -1
  88. package/dist/esm/parse.js.map +1 -1
  89. package/dist/esm/patch.js.map +1 -1
  90. package/dist/esm/range.js +151 -0
  91. package/dist/esm/range.js.map +1 -0
  92. package/dist/esm/stopwatch.js.map +1 -1
  93. package/dist/esm/string.js +8 -5
  94. package/dist/esm/string.js.map +1 -1
  95. package/dist/esm/timer.js +1 -1
  96. package/dist/esm/timer.js.map +1 -1
  97. package/dist/esm/timespan.js +21 -8
  98. package/dist/esm/timespan.js.map +1 -1
  99. package/dist/esm/type-code.js.map +1 -1
  100. package/dist/esm/type.js +20 -19
  101. package/dist/esm/type.js.map +1 -1
  102. package/dist/esm/types.js.map +1 -1
  103. package/dist/esm/utilities.js +174 -39
  104. package/dist/esm/utilities.js.map +1 -1
  105. package/dist/types/array.d.ts +29 -0
  106. package/dist/types/array.d.ts.map +1 -1
  107. package/dist/types/async-pool-executor.d.ts +2 -2
  108. package/dist/types/async-pool-executor.d.ts.map +1 -1
  109. package/dist/types/browser/form-utilities.d.ts.map +1 -1
  110. package/dist/types/browser/native-bridge.d.ts.map +1 -1
  111. package/dist/types/cancellable-promise.d.ts.map +1 -1
  112. package/dist/types/clean-url-search-params.d.ts +3 -1
  113. package/dist/types/clean-url-search-params.d.ts.map +1 -1
  114. package/dist/types/collections/from.d.ts +1 -1
  115. package/dist/types/draft.d.ts.map +1 -1
  116. package/dist/types/functions.d.ts +231 -0
  117. package/dist/types/functions.d.ts.map +1 -0
  118. package/dist/types/index.d.ts +2 -0
  119. package/dist/types/index.d.ts.map +1 -1
  120. package/dist/types/math.d.ts.map +1 -1
  121. package/dist/types/parse.d.ts.map +1 -1
  122. package/dist/types/range.d.ts +72 -0
  123. package/dist/types/range.d.ts.map +1 -0
  124. package/dist/types/string.d.ts.map +1 -1
  125. package/dist/types/timer.d.ts +1 -1
  126. package/dist/types/timespan.d.ts.map +1 -1
  127. package/dist/types/type.d.ts +2 -0
  128. package/dist/types/type.d.ts.map +1 -1
  129. package/dist/types/types.d.ts +1 -1
  130. package/dist/types/types.d.ts.map +1 -1
  131. package/dist/types/utilities.d.ts +21 -3
  132. package/dist/types/utilities.d.ts.map +1 -1
  133. package/dist/web/array.js +36 -2
  134. package/dist/web/array.js.map +1 -1
  135. package/dist/web/async-pool-executor.js +26 -11
  136. package/dist/web/async-pool-executor.js.map +1 -1
  137. package/dist/web/browser/form-utilities.js +35 -34
  138. package/dist/web/browser/form-utilities.js.map +1 -1
  139. package/dist/web/browser/geo-location.js +1 -1
  140. package/dist/web/browser/geo-location.js.map +1 -1
  141. package/dist/web/browser/native-bridge.js +3 -1
  142. package/dist/web/browser/native-bridge.js.map +1 -1
  143. package/dist/web/cancellable-promise.js +34 -13
  144. package/dist/web/cancellable-promise.js.map +1 -1
  145. package/dist/web/clean-url-search-params.js +26 -3
  146. package/dist/web/clean-url-search-params.js.map +1 -1
  147. package/dist/web/collections/cache-dictionary.js +3 -3
  148. package/dist/web/collections/cache-dictionary.js.map +1 -1
  149. package/dist/web/collections/default-map.js.map +1 -1
  150. package/dist/web/collections/default-weak-map.js.map +1 -1
  151. package/dist/web/collections/from.js +3 -3
  152. package/dist/web/collections/from.js.map +1 -1
  153. package/dist/web/collections/index.js.map +1 -1
  154. package/dist/web/draft.js +46 -11
  155. package/dist/web/draft.js.map +1 -1
  156. package/dist/web/event-bus.js +1 -1
  157. package/dist/web/event-bus.js.map +1 -1
  158. package/dist/web/functions.js +336 -0
  159. package/dist/web/functions.js.map +1 -0
  160. package/dist/web/index.js +2 -0
  161. package/dist/web/index.js.map +1 -1
  162. package/dist/web/key-value-pair.js.map +1 -1
  163. package/dist/web/lazy.js.map +1 -1
  164. package/dist/web/math.js +3 -0
  165. package/dist/web/math.js.map +1 -1
  166. package/dist/web/order.js.map +1 -1
  167. package/dist/web/parse.js +10 -1
  168. package/dist/web/parse.js.map +1 -1
  169. package/dist/web/patch.js.map +1 -1
  170. package/dist/web/range.js +151 -0
  171. package/dist/web/range.js.map +1 -0
  172. package/dist/web/stopwatch.js.map +1 -1
  173. package/dist/web/string.js +8 -5
  174. package/dist/web/string.js.map +1 -1
  175. package/dist/web/timer.js +1 -1
  176. package/dist/web/timer.js.map +1 -1
  177. package/dist/web/timespan.js +21 -8
  178. package/dist/web/timespan.js.map +1 -1
  179. package/dist/web/type-code.js.map +1 -1
  180. package/dist/web/type.js +20 -19
  181. package/dist/web/type.js.map +1 -1
  182. package/dist/web/types.js.map +1 -1
  183. package/dist/web/utilities.js +174 -39
  184. package/dist/web/utilities.js.map +1 -1
  185. package/package.json +66 -60
  186. package/src/array.ts +116 -68
  187. package/src/async-pool-executor.ts +107 -85
  188. package/src/browser/form-utilities.ts +32 -31
  189. package/src/browser/geo-location.ts +113 -113
  190. package/src/browser/native-bridge.ts +118 -116
  191. package/src/cancellable-promise.ts +102 -76
  192. package/src/clean-url-search-params.ts +36 -11
  193. package/src/collections/cache-dictionary.ts +115 -115
  194. package/src/collections/default-map.ts +48 -48
  195. package/src/collections/default-weak-map.ts +51 -51
  196. package/src/collections/from.ts +859 -859
  197. package/src/collections/index.ts +3 -3
  198. package/src/draft.ts +55 -16
  199. package/src/event-bus.ts +83 -83
  200. package/src/functions.ts +496 -0
  201. package/src/index.ts +44 -42
  202. package/src/key-value-pair.ts +24 -24
  203. package/src/lazy.ts +32 -32
  204. package/src/math.ts +33 -30
  205. package/src/order.ts +5 -5
  206. package/src/parse.ts +251 -240
  207. package/src/patch.ts +79 -79
  208. package/src/range.ts +165 -0
  209. package/src/stopwatch.ts +43 -43
  210. package/src/string.ts +8 -5
  211. package/src/timer.ts +67 -67
  212. package/src/timespan.ts +412 -398
  213. package/src/type-code.ts +15 -15
  214. package/src/type.ts +372 -371
  215. package/src/types.ts +30 -30
  216. package/src/utilities.ts +653 -480
package/src/array.ts CHANGED
@@ -1,69 +1,117 @@
1
- import type {Predicate} from "./types.js";
2
-
3
- /**
4
- * Removes all given values from the provided array and returns the number of removed elements.
5
- * The operation mutates the original array.
6
- * @template T
7
- * @param {Array<T>} array - The array to modify by removing specified items.
8
- * @param {...T} items - The values to remove from the array.
9
- * @return {number} The number of elements removed from the array.
10
- */
11
- export function pull<T>(array: Array<T>, ...items: Array<T>): number {
12
-
13
- let output = 0;
14
- for (const item of items) {
15
- const index = array.indexOf(item);
16
- if (index !== -1) {
17
- array.splice(index, 1);
18
- output++;
19
- }
20
- }
21
- return output;
22
- }
23
-
24
- /**
25
- * Splits an array into chunks of a given size.
26
- * @template T
27
- * @param {Array<T>} array - The array to split.
28
- * @param {number} size - The size of each chunk.
29
- * @return {Array<Array<T>>} The array of chunks.
30
- */
31
- export function chunk<T>(array: Array<T>, size: number): Array<Array<T>> {
32
- if (size <= 0) throw new Error("Size must be greater than 0");
33
- const result: Array<Array<T>> = [];
34
- for (let i = 0; i < array.length; i += size) {
35
- result.push(array.slice(i, i + size));
36
- }
37
- return result;
38
- }
39
-
40
- /**
41
- * Removes all elements from the array, mutating it.
42
- * @template T
43
- * @param {Array<T>} array - The array to clear.
44
- */
45
- export function clear<T>(array: Array<T>): void {
46
- array.length = 0;
47
- }
48
-
49
- /**
50
- * Removes all elements from the array that satisfy the predicate.
51
- * The operation mutates the original array.
52
- * @template T
53
- * @return {Array<T>} An array of removed elements.
54
- */
55
- export function remove<T>(array: Array<T>,predicate: Predicate<T>): Array<T> {
56
- const removed: Array<T> = [];
57
- let i = 0;
58
-
59
- while (i < array.length) {
60
- if (predicate(array[i])) {
61
- removed.push(array[i]);
62
- array.splice(i, 1); // muta el array
63
- } else {
64
- i++;
65
- }
66
- }
67
-
68
- return removed;
1
+ import type {Constructor, Predicate} from "./types.js";
2
+ import {monkeyPatch} from "./utilities.js";
3
+
4
+ declare global {
5
+ interface Array<T> {
6
+ pull(...items: Array<T>): number;
7
+ chunk(size: number): Array<Array<T>>;
8
+ clear(): void;
9
+ remove(predicate: Predicate<T>): Array<T>;
10
+ pushIfAbsent(element: T): boolean;
11
+ }
12
+ }
13
+
14
+
15
+ /**
16
+ * Removes all given values from the provided array and returns the number of removed elements.
17
+ * The operation mutates the original array.
18
+ * @template T
19
+ * @param {Array<T>} array - The array to modify by removing specified items.
20
+ * @param {...T} items - The values to remove from the array.
21
+ * @return {number} The number of elements removed from the array.
22
+ */
23
+ export function pull<T>(array: Array<T>, ...items: Array<T>): number {
24
+
25
+ let output = 0;
26
+ for (const item of items) {
27
+ let index;
28
+ while ((index = array.findIndex(val => Object.is(val, item))) !== -1) {
29
+ array.splice(index, 1);
30
+ output++;
31
+ }
32
+ }
33
+ return output;
34
+ }
35
+
36
+ /**
37
+ * Splits an array into chunks of a given size.
38
+ * @template T
39
+ * @param {Array<T>} array - The array to split.
40
+ * @param {number} size - The size of each chunk.
41
+ * @return {Array<Array<T>>} The array of chunks.
42
+ */
43
+ export function chunk<T>(array: Array<T>, size: number): Array<Array<T>> {
44
+ if (size <= 0) throw new Error("Size must be greater than 0");
45
+ const result: Array<Array<T>> = [];
46
+ for (let i = 0; i < array.length; i += size) {
47
+ result.push(array.slice(i, i + size));
48
+ }
49
+ return result;
50
+ }
51
+
52
+ /**
53
+ * Removes all elements from the array, mutating it.
54
+ * @template T
55
+ * @param {Array<T>} array - The array to clear.
56
+ */
57
+ export function clear<T>(array: Array<T>): void {
58
+ array.length = 0;
59
+ }
60
+
61
+ /**
62
+ * Removes all elements from the array that satisfy the predicate.
63
+ * The operation mutates the original array.
64
+ * @template T
65
+ * @return {Array<T>} An array of removed elements.
66
+ */
67
+ export function remove<T>(array: Array<T>,predicate: Predicate<T>): Array<T> {
68
+ const removed: Array<T> = [];
69
+ let i = 0;
70
+
71
+ while (i < array.length) {
72
+ if (predicate(array[i])) {
73
+ removed.push(array[i]);
74
+ array.splice(i, 1); // muta el array
75
+ } else {
76
+ i++;
77
+ }
78
+ }
79
+
80
+ return removed;
81
+ }
82
+
83
+ /**
84
+ * Adds an element to the array if it's not already present.
85
+ * The operation mutates the original array.
86
+ * @template T
87
+ * @param {Array<T>} array - The array to modify.
88
+ * @param {T} element - The element to add if absent.
89
+ * @return {boolean} True if the element was added, false otherwise.
90
+ */
91
+ export function pushIfAbsent<T>(array: Array<T>, element: T): boolean {
92
+ if (!array.includes(element)) {
93
+ array.push(element);
94
+ return true;
95
+ }
96
+ return false;
97
+ }
98
+
99
+ /**
100
+ * Patches the Array prototype with the methods defined in this module:
101
+ * - pull
102
+ * - chunk
103
+ * - clear
104
+ * - remove
105
+ * - pushIfAbsent
106
+ *
107
+ * Each method is added only if it doesn't already exist on Array.prototype.
108
+ */
109
+ export function patchArray(): void {
110
+ const target = Array as unknown as Constructor<Array<any>>;
111
+
112
+ monkeyPatch(target, pull);
113
+ monkeyPatch(target, chunk);
114
+ monkeyPatch(target, clear);
115
+ monkeyPatch(target, remove);
116
+ monkeyPatch(target, pushIfAbsent);
69
117
  }
@@ -1,85 +1,107 @@
1
- import type {Supplier} from "./types.js";
2
- import {delay} from "./utilities.js";
3
-
4
- export default class AsyncPoolExecutor {
5
- private _checkIntervalMs: number;
6
-
7
- get maxConcurrency(): number {
8
- return this._maxConcurrency;
9
- }
10
-
11
- set maxConcurrency(value: number) {
12
- this._maxConcurrency = value;
13
-
14
- }
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
- }
31
-
32
- /**
33
- * Submits a deferred task to a queue for asynchronous execution and returns a Promise resolving to its result.
34
- * @template T
35
- * @param {Supplier<T>} task - The deferred task to be executed asynchronously.
36
- */
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) {
54
- this._activeTasks++;
55
- setTimeout(async () => {
56
- try {
57
- await task();
58
- } finally {
59
- this._activeTasks--;
60
- }
61
- });
62
- }
63
-
64
-
65
- }
66
-
67
- this._proccess = null;
68
- }, 0);
69
-
70
-
71
- }
72
-
73
-
74
- /**
75
- * Waits until all tasks (both queued and active) are completed.
76
- * This method resolves only when there are no pending tasks.
77
- *
78
- * @return {Promise<void>} A promise that resolves when all tasks are complete.
79
- */
80
- public async shutdown(): Promise<void> {
81
- while (this._taskQueue.length > 0 || this._activeTasks > 0) {
82
- await delay(this._checkIntervalMs);
83
- }
84
- }
85
- }
1
+ import type {Supplier} from "./types.js";
2
+ import {delay} from "./utilities.js";
3
+
4
+ type QueuedTask<T> = {
5
+ task: Supplier<T | Promise<T>>;
6
+ resolve: (value: T) => void;
7
+ reject: (reason?: any) => void;
8
+ };
9
+
10
+ function normalizeMaxConcurrency(value: number): number {
11
+ if (!Number.isInteger(value) || value < 1) {
12
+ throw new RangeError("maxConcurrency must be a positive integer");
13
+ }
14
+ return value;
15
+ }
16
+
17
+ function normalizeCheckInterval(value: number): number {
18
+ return Number.isFinite(value) ? Math.max(0, value) : 0;
19
+ }
20
+
21
+ export default class AsyncPoolExecutor {
22
+ private _checkIntervalMs: number;
23
+
24
+ get maxConcurrency(): number {
25
+ return this._maxConcurrency;
26
+ }
27
+
28
+ set maxConcurrency(value: number) {
29
+ this._maxConcurrency = normalizeMaxConcurrency(value);
30
+
31
+ }
32
+
33
+ private _process: any;
34
+ private _maxConcurrency: number;
35
+ private _activeTasks: number;
36
+ private _taskQueue: Array<QueuedTask<any>> = [];
37
+
38
+
39
+ /**
40
+ * @param {number} maxConcurrency - The maximum number of concurrent tasks allowed.
41
+ * @param {number} [checkInterval=50] - The interval, in milliseconds, to check for capacity to run new tasks. Defaults to 50 ms.
42
+ */
43
+ constructor(maxConcurrency: number, checkInterval: number = 50) {
44
+ this._maxConcurrency = normalizeMaxConcurrency(maxConcurrency);
45
+ this._checkIntervalMs = normalizeCheckInterval(checkInterval);
46
+ this._activeTasks = 0;
47
+ }
48
+
49
+ /**
50
+ * Submits a deferred task to a queue for asynchronous execution and returns a Promise resolving to its result.
51
+ * @template T
52
+ * @param {Supplier<T>} task - The deferred task to be executed asynchronously.
53
+ */
54
+ public submit<T>(task: Supplier<T | Promise<T>>): Promise<T> {
55
+ const promise = new Promise<T>((resolve, reject) => {
56
+ this._taskQueue.push({task, resolve, reject});
57
+ });
58
+
59
+ if (this._process != null)
60
+ return promise;
61
+
62
+ this._process = setTimeout(async () => {
63
+
64
+ while (this._taskQueue.length > 0) {
65
+
66
+ while (this._activeTasks >= this._maxConcurrency) {
67
+ await delay(this._checkIntervalMs);
68
+ }
69
+
70
+ const queuedTask = this._taskQueue.shift();
71
+ if (queuedTask) {
72
+ this._activeTasks++;
73
+ setTimeout(async () => {
74
+ try {
75
+ queuedTask.resolve(await queuedTask.task());
76
+ } catch (error) {
77
+ queuedTask.reject(error);
78
+ } finally {
79
+ this._activeTasks--;
80
+ }
81
+ });
82
+ }
83
+
84
+
85
+ }
86
+
87
+ this._process = null;
88
+ }, 0);
89
+
90
+ return promise;
91
+
92
+
93
+ }
94
+
95
+
96
+ /**
97
+ * Waits until all tasks (both queued and active) are completed.
98
+ * This method resolves only when there are no pending tasks.
99
+ *
100
+ * @return {Promise<void>} A promise that resolves when all tasks are complete.
101
+ */
102
+ public async shutdown(): Promise<void> {
103
+ while (this._taskQueue.length > 0 || this._activeTasks > 0) {
104
+ await delay(this._checkIntervalMs);
105
+ }
106
+ }
107
+ }
@@ -51,28 +51,34 @@ export function submitForm(
51
51
  * @param keyPrefix - Key path, e.g., 'user[name]' or 'tags[]'
52
52
  * @param value - The value to append (can be nested)
53
53
  */
54
+ const appendInput = (key: string, value: any) => {
55
+ const input = document.createElement('input');
56
+ input.type = 'hidden';
57
+ input.name = key;
58
+ input.value = String(value);
59
+ form.appendChild(input);
60
+ };
61
+
54
62
  const appendInputs = (keyPrefix: string, value: any) => {
55
63
  if (Array.isArray(value)) {
56
64
  for (const val of value) {
57
65
  appendInputs(`${keyPrefix}[]`, val);
58
66
  }
67
+ } else if (value instanceof Date) {
68
+ appendInput(keyPrefix, value.toISOString());
59
69
  } else if (typeof value === 'object' && value !== null) {
60
70
  for (const subKey in value) {
61
- if (value.hasOwnProperty(subKey)) {
71
+ if (Object.prototype.hasOwnProperty.call(value, subKey)) {
62
72
  appendInputs(`${keyPrefix}[${subKey}]`, value[subKey]);
63
73
  }
64
74
  }
65
75
  } else {
66
- const input = document.createElement('input');
67
- input.type = 'hidden';
68
- input.name = keyPrefix;
69
- input.value = String(value);
70
- form.appendChild(input);
76
+ appendInput(keyPrefix, value);
71
77
  }
72
78
  };
73
79
 
74
80
  for (const key in data) {
75
- if (data.hasOwnProperty(key)) {
81
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
76
82
  appendInputs(key, data[key]);
77
83
  }
78
84
  }
@@ -86,7 +92,7 @@ export function formToObject(form: HTMLFormElement): Record<string, FormDataEntr
86
92
  const out: Record<string, FormDataEntryValue | FormDataEntryValue[]> = {};
87
93
 
88
94
  for (const [key, value] of fd.entries()) {
89
- if (key in out) {
95
+ if (Object.prototype.hasOwnProperty.call(out, key)) {
90
96
  const current = out[key];
91
97
  if (Array.isArray(current)) {
92
98
  current.push(value);
@@ -109,31 +115,26 @@ export function formToObject(form: HTMLFormElement): Record<string, FormDataEntr
109
115
  * @param {string} parentKey - The parent key to append to child keys in the `FormData`.
110
116
  * @returns {FormData} - The `FormData` instance with the converted data.
111
117
  */
112
- function _objectToFormData(data: Record<string, any>, formData: FormData, parentKey: string = ''): FormData {
118
+ function _appendFormDataValue(formData: FormData, key: string, value: any): void {
119
+ if (value instanceof Date) {
120
+ formData.append(key, value.toISOString());
121
+ } else if (value instanceof File) {
122
+ formData.append(key, value);
123
+ } else if (Array.isArray(value)) {
124
+ for (let index = 0; index < value.length; index++) {
125
+ _appendFormDataValue(formData, `${key}[${index}]`, value[index]);
126
+ }
127
+ } else if (value !== null && typeof value === 'object') {
128
+ _objectToFormData(value, formData, key);
129
+ } else {
130
+ formData.append(key, value);
131
+ }
132
+ }
113
133
 
134
+ function _objectToFormData(data: Record<string, any>, formData: FormData, parentKey: string = ''): FormData {
114
135
  for (const key in data) {
115
- if (data.hasOwnProperty(key)) {
116
- const value = data[key];
117
-
118
- if (value instanceof Date) {
119
- formData.append(parentKey ? `${parentKey}[${key}]` : key, value.toISOString());
120
- } else if (value instanceof File) {
121
- formData.append(parentKey ? `${parentKey}[${key}]` : key, value);
122
- } else if (typeof value === 'object' && !Array.isArray(value)) {
123
- _objectToFormData(value, formData, parentKey ? `${parentKey}[${key}]` : key);
124
- } else if (Array.isArray(value)) {
125
- for (let index = 0; index < value.length; index++) {
126
- const item = value[index];
127
- const arrayKey = `${parentKey ? `${parentKey}[${key}]` : key}[${index}]`;
128
- if (typeof item === 'object' && !Array.isArray(item)) {
129
- _objectToFormData(item, formData, arrayKey);
130
- } else {
131
- formData.append(arrayKey, item);
132
- }
133
- }
134
- } else {
135
- formData.append(parentKey ? `${parentKey}[${key}]` : key, value);
136
- }
136
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
137
+ _appendFormDataValue(formData, parentKey ? `${parentKey}[${key}]` : key, data[key]);
137
138
  }
138
139
  }
139
140