@creejs/commons-lang 2.0.0 → 2.0.2

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.
@@ -0,0 +1,1553 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.CommonsLang = {}));
5
+ })(this, (function (exports) { 'use strict';
6
+
7
+ /**
8
+ * @module LangUtils
9
+ * @description Language utility functions
10
+ */
11
+
12
+ var LangUtils = {
13
+ constructorName,
14
+ defaults,
15
+ extend,
16
+ extends: extend,
17
+ equals,
18
+ isBrowser,
19
+ isNode
20
+ };
21
+
22
+ /**
23
+ * Gets the constructor name of a value.
24
+ * @param {*} value - The value to check.
25
+ * @returns {string|undefined} The constructor name, or undefined if value has no constructor.
26
+ */
27
+ function constructorName (value) {
28
+ return value?.constructor?.name
29
+ }
30
+
31
+ /**
32
+ * Assigns default values from source objects to target object for undefined properties.
33
+ * @param {Object<string, any>} target - The target object to assign defaults to
34
+ * @param {...Object<string, any>} sources - Source objects containing default values
35
+ * @returns {Object<string, any>} The modified target object with defaults applied
36
+ * @throws {TypeError} If target is null or undefined
37
+ */
38
+ function defaults (target, ...sources) {
39
+ if (target == null) {
40
+ throw new TypeError('"target" must not be null or undefined')
41
+ }
42
+ for (const source of sources) {
43
+ if (source == null) {
44
+ continue
45
+ }
46
+ for (const key in source) {
47
+ if (target[key] === undefined) {
48
+ target[key] = source[key];
49
+ }
50
+ }
51
+ }
52
+ return target
53
+ }
54
+
55
+ /**
56
+ * Extends a target object with properties from one or more source objects.
57
+ * @param {Object<string, any>} target - The target object to extend (must not be null/undefined)
58
+ * @param {...Object<string, any>} sources - One or more source objects to copy properties from
59
+ * @returns {Object<string, any>} The modified target object
60
+ * @throws {TypeError} If target is null or undefined
61
+ */
62
+ function extend (target, ...sources) {
63
+ if (target == null) {
64
+ throw new TypeError('"target" must not be null or undefined')
65
+ }
66
+ for (const source of sources) {
67
+ if (source == null) {
68
+ continue
69
+ }
70
+ for (const key in source) {
71
+ target[key] = source[key];
72
+ }
73
+ }
74
+ return target
75
+ }
76
+
77
+ /**
78
+ * Compares two values for equality
79
+ * 1. First checks strict equality (===),
80
+ * 2. then checks if either value has an `equals` method and uses it.
81
+ * @param {*} value1 - First value to compare
82
+ * @param {*} value2 - Second value to compare
83
+ * @returns {boolean} True if values are equal, false otherwise
84
+ */
85
+ function equals (value1, value2) {
86
+ if (value1 === value2) {
87
+ return true
88
+ }
89
+ if (typeof value1?.equals === 'function') {
90
+ return value1.equals(value2)
91
+ }
92
+ if (typeof value2?.equals === 'function') {
93
+ return value2.equals(value1)
94
+ }
95
+ return false
96
+ }
97
+
98
+ /**
99
+ * Check if the current environment is a browser
100
+ * @returns {boolean}
101
+ */
102
+ function isBrowser () {
103
+ return typeof window !== 'undefined' && typeof document !== 'undefined'
104
+ }
105
+
106
+ /**
107
+ * Check if the current environment is a nodejs
108
+ * @returns {boolean}
109
+ */
110
+ function isNode () {
111
+ return !isBrowser()
112
+ }
113
+
114
+ /**
115
+ * @module TypeUtils
116
+ * @description Utility functions for type checking and validation.
117
+ */
118
+ var TypeUtils = {
119
+ isArray,
120
+ isBoolean,
121
+ isBuffer,
122
+ isFunction,
123
+ isInstance,
124
+ isIterable,
125
+ isDate,
126
+ isError,
127
+ isMap,
128
+ isWeakMap,
129
+ isNumber,
130
+ isPositive,
131
+ isNegative,
132
+ isNil,
133
+ isNullOrUndefined,
134
+ isNull,
135
+ isUndefined,
136
+ isPlainObject: isPlainObject$1,
137
+ isObject,
138
+ isPromise,
139
+ isRegExp,
140
+ isSet,
141
+ isWeakSet,
142
+ isStream,
143
+ isString,
144
+ isSymbol,
145
+ isPrimitive
146
+ };
147
+ /**
148
+ * Checks if the given value is an array.
149
+ * @param {*} value - The value to check.
150
+ * @returns {boolean} True if the value is an array, false otherwise.
151
+ */
152
+ function isArray (value) {
153
+ return Array.isArray(value)
154
+ }
155
+
156
+ /**
157
+ * Checks if the given value is a boolean.
158
+ * @param {*} value - The value to check.
159
+ * @returns {boolean} True if the value is a boolean, false otherwise.
160
+ */
161
+ function isBoolean (value) {
162
+ return typeof value === 'boolean'
163
+ }
164
+
165
+ /**
166
+ * Checks if the given value is a Buffer.
167
+ * @param {*} value - The value to check.
168
+ * @returns {boolean} True if the value is a Buffer, false otherwise.
169
+ */
170
+ function isBuffer (value) {
171
+ return value != null && Buffer.isBuffer(value)
172
+ }
173
+
174
+ /**
175
+ * Checks if the given value is a Date.
176
+ * @param {*} value - The value to check.
177
+ * @returns {boolean} True if the value is a Date, false otherwise.
178
+ */
179
+ function isDate (value) {
180
+ return value != null && value instanceof Date
181
+ }
182
+
183
+ /**
184
+ * Checks if the given value is an instance of Error.
185
+ * @param {*} value - The value to check.
186
+ * @returns {boolean} True if the value is an Error, false otherwise.
187
+ */
188
+ function isError (value) {
189
+ return value != null && value instanceof Error
190
+ }
191
+
192
+ /**
193
+ * Checks if the given value is a function.
194
+ * @param {*} value - The value to check.
195
+ * @returns {boolean} True if the value is a function, false otherwise.
196
+ */
197
+ function isFunction (value) {
198
+ return typeof value === 'function'
199
+ }
200
+
201
+ /**
202
+ * Checks if a value is a class instance (non-null and not a plain object).
203
+ * @param {*} value - The value to check.
204
+ * @returns {boolean} True if the value is a class instance, false otherwise.
205
+ */
206
+ function isInstance (value) {
207
+ return value != null && typeof value === 'object' && !isPlainObject$1(value)
208
+ }
209
+
210
+ /**
211
+ * Checks if a value is isIterable
212
+ * @param {*} value - The value to check.
213
+ * @returns {boolean} True if the value is isIterable, false otherwise.
214
+ */
215
+ function isIterable (value) {
216
+ return value != null && typeof value[Symbol.iterator] === 'function'
217
+ }
218
+
219
+ /**
220
+ * Checks if a value is Map
221
+ * @param {*} value - The value to check.
222
+ * @returns {boolean} True if the value is Map, otherwise false.
223
+ */
224
+ function isMap (value) {
225
+ return value != null && typeof value === 'object' && value.constructor === Map
226
+ }
227
+
228
+ /**
229
+ * Checks if a value is WeakMap
230
+ * @param {*} value - The value to check.
231
+ * @returns {boolean} True if the value is WeakMap, otherwise false.
232
+ */
233
+ function isWeakMap (value) {
234
+ return value != null && typeof value === 'object' && value.constructor === WeakMap
235
+ }
236
+
237
+ /**
238
+ * Checks if a value is null or undefined.
239
+ * 1. value == null
240
+ * 2. return true, if value is null or undefined
241
+ * @param {*} value - The value to check.
242
+ * @returns {boolean} True if the value is null or undefined, otherwise false.
243
+ */
244
+ function isNil (value) {
245
+ return value == null
246
+ }
247
+
248
+ /**
249
+ * Checks if a value is null or undefined.
250
+ * 1. same with isNil()
251
+ * @param {*} value - The value to check.
252
+ * @returns {boolean} True if the value is null or undefined, otherwise false.
253
+ */
254
+ function isNullOrUndefined (value) {
255
+ return value == null
256
+ }
257
+
258
+ /**
259
+ * check that a value is a positive number.
260
+ * @param {number} value - The value to check.
261
+ * @returns {boolean}
262
+ */
263
+ function isPositive (value) {
264
+ if (!isNumber(value)) {
265
+ return false
266
+ }
267
+ return value > 0
268
+ }
269
+
270
+ /**
271
+ * check that a value is a Negative number.
272
+ * @param {number} value - The value to check.
273
+ */
274
+ function isNegative (value) {
275
+ if (!isNumber(value)) {
276
+ return false
277
+ }
278
+ return value < 0
279
+ }
280
+
281
+ /**
282
+ * Checks if the given value is exactly null.
283
+ * @param {*} value - The value to check.
284
+ * @returns {boolean} True if the value is null, false otherwise.
285
+ */
286
+ function isNull (value) {
287
+ return value === null
288
+ }
289
+
290
+ /**
291
+ * Checks if a value is exactly undefined.
292
+ * @param {*} value - The value to check.
293
+ * @returns {boolean} True if the value is undefined, false otherwise.
294
+ */
295
+ function isUndefined (value) {
296
+ return value === undefined
297
+ }
298
+
299
+ /**
300
+ * Checks if a value is a number.
301
+ * @param {*} value - The value to check.
302
+ * @returns {boolean} True if the value is a number, false otherwise.
303
+ */
304
+ function isNumber (value) {
305
+ return value != null && typeof value === 'number'
306
+ }
307
+
308
+ /**
309
+ * Checks if a value is an object (and not null).
310
+ * @param {*} value - The value to check
311
+ * @returns {boolean} True if the value is an object (not null), false otherwise
312
+ */
313
+ function isObject (value) {
314
+ return value != null && typeof value === 'object'
315
+ }
316
+
317
+ /**
318
+ * Checks if a value is a plain object (created by the Object constructor).
319
+ * @param {*} value - The value to check.
320
+ * @returns {boolean} True if the value is a plain object, false otherwise.
321
+ */
322
+ function isPlainObject$1 (value) {
323
+ return value !== null && typeof value === 'object' && (value.constructor === Object || value.constructor === undefined)
324
+ }
325
+
326
+ /**
327
+ * check if value is primitive: string, number, boolean
328
+ * 1. null/undefined returns false
329
+ * @param {*} value
330
+ * @returns {boolean}
331
+ */
332
+ function isPrimitive (value) {
333
+ return value !== null && (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean')
334
+ }
335
+
336
+ /**
337
+ * Checks if a value is a Promise.
338
+ * @param {*} value - The value to check.
339
+ * @returns {boolean} True if the value is a Promise, false otherwise.
340
+ */
341
+ function isPromise (value) {
342
+ return value != null && typeof value.then === 'function'
343
+ }
344
+
345
+ /**
346
+ * Checks if a RegExp
347
+ * @param {*} value - The value to check.
348
+ * @returns {boolean} True if the value is RegExp, otherwise false.
349
+ */
350
+ function isRegExp (value) {
351
+ return value != null && typeof value === 'object' && value.constructor === RegExp
352
+ }
353
+
354
+ /**
355
+ * Checks if a Set
356
+ * @param {*} value - The value to check.
357
+ * @returns {boolean} True if the value is Set, otherwise false.
358
+ */
359
+ function isSet (value) {
360
+ return value != null && typeof value === 'object' && value.constructor === Set
361
+ }
362
+
363
+ /**
364
+ * Checks if a WeakSet
365
+ * @param {*} value - The value to check.
366
+ * @returns {boolean} True if the value is WeakSet, otherwise false.
367
+ */
368
+ function isWeakSet (value) {
369
+ return value != null && typeof value === 'object' && value.constructor === WeakSet
370
+ }
371
+
372
+ /**
373
+ * Check if the value is a string
374
+ * @param {*} value
375
+ * @return {boolean}
376
+ */
377
+ function isStream (value) {
378
+ return value != null && typeof value.pipe === 'function'
379
+ }
380
+
381
+ /**
382
+ * Check if the value is a string
383
+ * @param {*} value
384
+ * @return {boolean}
385
+ */
386
+ function isString (value) {
387
+ return value != null && typeof value === 'string'
388
+ }
389
+
390
+ /**
391
+ * Checks if the given value is a Symbol.
392
+ * @param {*} value - The value to check.
393
+ * @returns {boolean} True if the value is a Symbol, false otherwise.
394
+ */
395
+ function isSymbol (value) {
396
+ return value != null && typeof value === 'symbol'
397
+ }
398
+
399
+ // 3rd
400
+ // internal
401
+ // owned
402
+ /**
403
+ * @module TypeAssert
404
+ * @description Type assertion utility functions for validating data types and throwing errors for invalid types.
405
+ */
406
+ var TypeAssert = {
407
+ assertNumber,
408
+ assertPositive,
409
+ assertNegative,
410
+ assertBoolean,
411
+ assertObject,
412
+ assertPlainObject,
413
+ assertSymbol,
414
+ assertFunction,
415
+ assertInstance,
416
+ assertPromise,
417
+ assertNil,
418
+ assertNotNil,
419
+ assertNull,
420
+ assertNotNull,
421
+ assertUndefined,
422
+ assertString,
423
+ assertArray,
424
+ assertStringOrSymbol
425
+ };
426
+ /**
427
+ * if value is not Array, throw error
428
+ * @param {*} value
429
+ * @param {string} [paramName] - The name of the parameter to check
430
+ * @returns {void}
431
+ * @throws {Error}
432
+ */
433
+ function assertArray (value, paramName) {
434
+ if (!Array.isArray(value)) {
435
+ throw new Error(`${paramName ? paramName + '' : ' '}Not Array: type=${typeof value} value=${JSON.stringify(value)}`)
436
+ }
437
+ }
438
+ /**
439
+ * if value is not a string, throw error
440
+ * @param {*} value
441
+ * @param {string} [paramName] - The name of the parameter to check
442
+ * @returns {void}
443
+ * @throws {Error}
444
+ */
445
+ function assertString (value, paramName) {
446
+ if (!isString(value)) {
447
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not String: type=${typeof value} value=${JSON.stringify(value)}`)
448
+ }
449
+ }
450
+ /**
451
+ * if value is not a Number, throw error
452
+ * @param {*} value
453
+ * @param {string} [paramName] - The name of the parameter to check
454
+ * @returns {void}
455
+ * @throws {Error}
456
+ */
457
+ function assertNumber (value, paramName) {
458
+ if (!isNumber(value)) {
459
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Number: type=${typeof value} value=${JSON.stringify(value)}`)
460
+ }
461
+ }
462
+
463
+ /**
464
+ * Asserts that a value is a positive number.
465
+ * @param {number} value - The value to check.
466
+ * @param {string} [paramName] - Optional name of the parameter for error message.
467
+ * @throws {Error} If the value is not a number or is less than or equal to zero.
468
+ */
469
+ function assertPositive (value, paramName) {
470
+ if (!isPositive(value)) {
471
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Positive: ${value}`)
472
+ }
473
+ }
474
+
475
+ /**
476
+ * Asserts that a value is a Negative number.
477
+ * @param {number} value - The value to check.
478
+ * @param {string} [paramName] - Optional name of the parameter for error message.
479
+ * @throws {Error} If the value is not a number or is less than or equal to zero.
480
+ */
481
+ function assertNegative (value, paramName) {
482
+ if (!isNegative(value)) {
483
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Negative: ${value}`)
484
+ }
485
+ }
486
+
487
+ /**
488
+ * if value is not a string, throw error
489
+ * @param {*} value
490
+ * @param {string} [paramName] - The name of the parameter to check
491
+ * @returns {void}
492
+ * @throws {Error}
493
+ */
494
+ function assertBoolean (value, paramName) {
495
+ if (!isBoolean(value)) {
496
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Boolean: type=${typeof value} value=${JSON.stringify(value)}`)
497
+ }
498
+ }
499
+ /**
500
+ * if value is not a Object, throw error
501
+ * @param {*} value
502
+ * @param {string} [paramName] - The name of the parameter to check
503
+ * @returns {void}
504
+ * @throws {Error}
505
+ */
506
+ function assertObject (value, paramName) {
507
+ if (!isObject(value)) {
508
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Object: type=${typeof value} value=${JSON.stringify(value)}`)
509
+ }
510
+ }
511
+ /**
512
+ * if value is not a PlainObject, throw error
513
+ * @param {*} value
514
+ * @param {string} [paramName] - The name of the parameter to check
515
+ * @returns {void}
516
+ * @throws {Error}
517
+ */
518
+ function assertPlainObject (value, paramName) {
519
+ if (!isPlainObject$1(value)) {
520
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not PlainObject: type=${typeof value} value=${JSON.stringify(value)}`)
521
+ }
522
+ }
523
+ /**
524
+ * if value is not a Symbol, throw error
525
+ * @param {*} value
526
+ * @param {string} [paramName] - The name of the parameter to check@param {string} [paramName] - The name of the parameter to check
527
+ * @returns {void}
528
+ * @throws {Error}
529
+ */
530
+ function assertSymbol (value, paramName) {
531
+ if (!isSymbol(value)) {
532
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Symbol: type=${typeof value} value=${JSON.stringify(value)}`)
533
+ }
534
+ }
535
+ /**
536
+ * if value is not a Function, throw error
537
+ * @param {*} value
538
+ * @param {string} [paramName] - The name of the parameter to check
539
+ * @returns {void}
540
+ * @throws {Error}
541
+ */
542
+ function assertFunction (value, paramName) {
543
+ if (!isFunction(value)) {
544
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Function: type=${typeof value} value=${JSON.stringify(value)}`)
545
+ }
546
+ }
547
+ /**
548
+ * if value is not a Class instance, throw error
549
+ * @param {*} value
550
+ * @param {string} [paramName] - The name of the parameter to check
551
+ * @returns {void}
552
+ * @throws {Error}
553
+ */
554
+ function assertInstance (value, paramName) {
555
+ if (!isInstance(value)) {
556
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Class Instance: type=${typeof value} value=${JSON.stringify(value)}`)
557
+ }
558
+ }
559
+ /**
560
+ * if value is not a string, throw error
561
+ * @param {*} value
562
+ * @param {string} [paramName] - The name of the parameter to check
563
+ * @returns {void}
564
+ * @throws {Error}
565
+ */
566
+ function assertPromise (value, paramName) {
567
+ if (!isPromise(value)) {
568
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Promise: type=${typeof value} value=${JSON.stringify(value)}`)
569
+ }
570
+ }
571
+ /**
572
+ * if value is not a Null or Undefined, throw error
573
+ * @param {*} value
574
+ * @param {string} [paramName] - The name of the parameter to check
575
+ * @returns {void}
576
+ * @throws {Error}
577
+ */
578
+ function assertNil (value, paramName) {
579
+ if (!isNil(value)) {
580
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Neither Null nor Undefined: type=${typeof value} value=${JSON.stringify(value)}`)
581
+ }
582
+ }
583
+
584
+ /**
585
+ * Asserts that the given value is not nil.
586
+ * @param {*} value - The value to check
587
+ * @param {string} [paramName] - The name of the parameter to check
588
+ * @throws {Error} Throws an error if the value is nil
589
+ */
590
+ function assertNotNil (value, paramName) {
591
+ if (isNil(value)) {
592
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Should Not Nil`)
593
+ }
594
+ }
595
+
596
+ /**
597
+ * if value is not a Null, throw error
598
+ * @param {*} value
599
+ * @param {string} [paramName] - The name of the parameter to check
600
+ * @returns {void}
601
+ * @throws {Error}
602
+ */
603
+ function assertNull (value, paramName) {
604
+ if (!isNull(value)) {
605
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Null: type=${typeof value} value=${JSON.stringify(value)}`)
606
+ }
607
+ }
608
+
609
+ /**
610
+ * Asserts that the given value is not null.
611
+ * @param {*} value - The value to check
612
+ * @param {string} [paramName] - The name of the parameter to check
613
+ * @throws {Error} Throws an error if the value is null
614
+ */
615
+ function assertNotNull (value, paramName) {
616
+ if (isNull(value)) {
617
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Should Not Null`)
618
+ }
619
+ }
620
+ /**
621
+ * if value is not a Undefined, throw error
622
+ * @param {*} value
623
+ * @param {string} [paramName] - The name of the parameter to check
624
+ * @returns {void}
625
+ * @throws {Error}
626
+ */
627
+ function assertUndefined (value, paramName) {
628
+ if (!isUndefined(value)) {
629
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Undefined: type=${typeof value} value=${JSON.stringify(value)}`)
630
+ }
631
+ }
632
+
633
+ /**
634
+ * Asserts that the given value is either a string or a symbol.
635
+ * @param {*} value - The value to check.
636
+ * @param {string} [paramName] - Optional parameter name for error message.
637
+ * @throws {Error} Throws an error if the value is not a string or symbol.
638
+ */
639
+ function assertStringOrSymbol (value, paramName) {
640
+ if (!isString(value) && !isSymbol(value)) {
641
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not String or Symbol: type=${typeof value} value=${JSON.stringify(value)}`)
642
+ }
643
+ }
644
+
645
+ // 3rd
646
+ // internal
647
+ // owned
648
+
649
+ /**
650
+ * @module StringUtils
651
+ * @description Utility functions for string manipulation, validation, and transformation.
652
+ */
653
+ var StringUtils = {
654
+ isEmpty,
655
+ assertNotEmpty,
656
+ isBlank,
657
+ assertNotBlank,
658
+ capitalize,
659
+ decapitalize,
660
+ splitWithFixedLength,
661
+ split,
662
+ findMarkerPositions,
663
+ findMarkerPositionsRegex,
664
+ substringBefore,
665
+ substringBeforeLast,
666
+ substringAfter,
667
+ substringAfterLast,
668
+ substringBetween,
669
+ substringBetweenGreedy,
670
+ substringsBetween
671
+ };
672
+
673
+ /**
674
+ * Checks if a string is null, undefined, or length is 0.
675
+ * @param {string} str
676
+ * @returns {boolean}
677
+ * @throws {Error} If `str` is not null or undefined, and not a string.
678
+ */
679
+ function isEmpty (str) {
680
+ if (str == null) {
681
+ return true
682
+ }
683
+ assertString(str);
684
+ return str.length === 0
685
+ }
686
+
687
+ /**
688
+ * Asserts that the given string is not empty.
689
+ * @param {string} str - The string to check.
690
+ * @throws {Error} Throws an error if the string is empty.
691
+ */
692
+ function assertNotEmpty (str) {
693
+ if (isEmpty(str)) {
694
+ throw new Error(`Empty String: ${str}`)
695
+ }
696
+ }
697
+
698
+ /**
699
+ * Checks if a string is null, undefined, or consists only of whitespace.
700
+ * @param {string} str - The string to check.
701
+ * @returns {boolean} True if the string is blank, false otherwise.
702
+ * @throws {Error} If `str` is not null or undefined, and not a string.
703
+ */
704
+ function isBlank (str) {
705
+ if (str == null) {
706
+ return true
707
+ }
708
+ assertString(str);
709
+ return str.trim().length === 0
710
+ }
711
+
712
+ /**
713
+ * Asserts that the given string is not blank.
714
+ * @param {string} str - The string to check.
715
+ * @throws {Error} Throws an error if the string is blank.
716
+ */
717
+ function assertNotBlank (str) {
718
+ if (isBlank(str)) {
719
+ throw new Error(`Blank String: ${str}`)
720
+ }
721
+ }
722
+
723
+ /**
724
+ * Capitalizes the first character of a string.
725
+ * @param {string} str - The string to capitalize.
726
+ * @returns {string} The capitalized string or original if unchanged.
727
+ */
728
+ function capitalize (str) {
729
+ assertString(str);
730
+ if (str.length === 0) {
731
+ return str
732
+ }
733
+ const char0 = str.charAt(0);
734
+ const upperChar = char0.toUpperCase();
735
+ return char0 === upperChar ? str : upperChar + str.slice(1)
736
+ }
737
+
738
+ /**
739
+ * Converts the first character of a string to lowercase.
740
+ * If the string is null or empty, returns it unchanged.
741
+ * @param {string} str - The input string to decapitalize.
742
+ * @returns {string} The decapitalized string or original if unchanged.
743
+ */
744
+ function decapitalize (str) {
745
+ assertString(str);
746
+ if (str.length === 0) {
747
+ return str
748
+ }
749
+ const char0 = str.charAt(0);
750
+ const lowerChar = char0.toLowerCase();
751
+ return char0 === lowerChar ? str : lowerChar + str.slice(1)
752
+ }
753
+
754
+ /**
755
+ * Splits a string into chunks of fixed length, padding the last chunk if needed.
756
+ * 1. if str is empty, returns an empty array "[]"
757
+ * 2. if length is less than string length, returns an array with the string padded with "padding" as the only element
758
+ * 3. the last chunk is padded with "padding" if needed
759
+ * @param {string} str - The string to split.
760
+ * @param {number} length - The desired length of each chunk.
761
+ * @param {string} [padding=' '] - The padding character for the last chunk.
762
+ * @returns {string[]} An array of string chunks with fixed length.
763
+ * @throws {Error} If `str` is not a string or `length` is not a number.
764
+ */
765
+ function splitWithFixedLength (str, length, padding = ' ') {
766
+ assertString(str);
767
+ assertNumber(length);
768
+ assertString(padding);
769
+ if (str.length === 0) {
770
+ return []
771
+ }
772
+ if (length <= 0) {
773
+ throw new Error('length muse >=0')
774
+ }
775
+ if (str.length < length) {
776
+ return [str.padEnd(length, padding)]
777
+ }
778
+ const chunks = [];
779
+ for (let i = 0; i < str.length; i += length) {
780
+ const splitted = str.substring(i, i + length);
781
+ chunks.push(splitted.padEnd(length, padding));
782
+ }
783
+ return chunks
784
+ }
785
+
786
+ /**
787
+ * Splits a string into chunks using the specified markers.
788
+ * 1. If no markers are provided, defaults to comma (',').
789
+ * 2. null/undefined values are ignored
790
+ * 3. empty array "[]" returned, if string does not include any markers
791
+ * @param {string} str - The string to split.
792
+ * @param {...string} markers - The markers to split the string by.
793
+ * @returns {Array<string>} An array of string chunks.
794
+ * @throws {Error} If the input is not a string.
795
+ */
796
+ function split (str, ...markers) {
797
+ assertString(str);
798
+ const strLength = str.length;
799
+ if (strLength === 0) {
800
+ return []
801
+ }
802
+ const workingMarkers = [...markers];
803
+ if (markers.length === 0) {
804
+ markers.push(',');
805
+ }
806
+ const markerPostionPairs = findMarkerPositionsRegex(str, ...workingMarkers);
807
+ if (markerPostionPairs.length === 0) {
808
+ return []
809
+ }
810
+ const chunks = [];
811
+ let chunk = '';
812
+ let startIndex = 0;
813
+ for (const { marker, index: endIndex } of markerPostionPairs) {
814
+ chunk = str.substring(startIndex, endIndex);
815
+ chunks.push(chunk);
816
+ startIndex = endIndex + marker.length;
817
+ }
818
+ // add rested into chunks
819
+ chunk = str.substring(startIndex);
820
+ chunks.push(chunk);
821
+ return chunks
822
+ }
823
+
824
+ /**
825
+ * Finds all positions of markers in a string.
826
+ * 1. use loop to iterate over markers
827
+ * 2. use sting.indexOf to find position of each marker
828
+ * @param {string} str - The input string to search in.
829
+ * @param {...string} markers - The markers to search for.
830
+ * @returns {Array<{marker: string, index: number}>} Array of objects containing marker and its index.
831
+ * @throws {Error} If `str` is not a string or no markers are provided.
832
+ */
833
+ function findMarkerPositions (str, ...markers) {
834
+ assertString(str);
835
+ if (markers.length === 0) {
836
+ throw new Error('At least one marker must be provided')
837
+ }
838
+
839
+ const positions = [];
840
+ for (const marker of new Set(markers)) { // filter duplicated markers
841
+ if (isEmpty(marker)) { // 'abc'.indexOf('') === 0
842
+ continue
843
+ }
844
+ assertString(marker);
845
+ let index = str.indexOf(marker);
846
+ while (index !== -1) {
847
+ positions.push({ marker, index });
848
+ index = str.indexOf(marker, index + marker.length);
849
+ }
850
+ }
851
+ // Sort positions by index in ascending order
852
+ positions.sort((p1, p2) => p1.index - p2.index);
853
+ return positions
854
+ }
855
+
856
+ /**
857
+ * Finds all positions of markers in a string.
858
+ * 1. Finds all positions of markers in a string using regular expressions.
859
+ * 2. Each marker is included as a separate capture group in a single regex.
860
+ * @param {string} str - The input string to search in.
861
+ * @param {...string} markers - The markers to search for.
862
+ * @returns {Array<{marker: string, index: number}>} Array of objects containing marker and its index.
863
+ * @throws {Error} If `str` is not a string or no markers are provided.
864
+ */
865
+ function findMarkerPositionsRegex (str, ...markers) {
866
+ assertString(str);
867
+ if (markers.length === 0) {
868
+ throw new Error('At least one marker must be provided')
869
+ }
870
+
871
+ // filter duplicated, empty markers
872
+ // Escape special regex characters in markers
873
+ const escapedMarkers = [...new Set(markers.filter(v => v != null))].map(marker => {
874
+ assertString(marker);
875
+ return marker.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
876
+ });
877
+
878
+ // Create regex pattern with each marker as a separate capture group
879
+ // Format: (marker1)|(marker2)|(marker3)...
880
+ const pattern = new RegExp(escapedMarkers.map(m => `(${m})`).join('|'), 'g');
881
+
882
+ const positions = [];
883
+ let match = null;
884
+
885
+ // Find all matches
886
+ while ((match = pattern.exec(str)) !== null) {
887
+ // Determine which marker was matched by checking which capture group has a value
888
+ for (let i = 1; i < match.length; i++) {
889
+ if (match[i]) {
890
+ positions.push({
891
+ marker: markers[i - 1], // Use the original marker, not the escaped version
892
+ index: match.index
893
+ });
894
+ break // Only one group will match for each exec call
895
+ }
896
+ }
897
+
898
+ // Avoid infinite loops with zero-width matches
899
+ if (match[0].length === 0) {
900
+ pattern.lastIndex++;
901
+ }
902
+ }
903
+
904
+ return positions
905
+ }
906
+
907
+ /**
908
+ * Returns the substring before the first occurrence of a marker.
909
+ * @param {string} str - The input string to search in.
910
+ * @param {string} marker - The string to search for.
911
+ * @returns {string | undefined} The substring before the marker, or undefined if marker not found.
912
+ * @throws {Error} If either input is not a string.
913
+ */
914
+ function substringBefore (str, marker) {
915
+ assertString(str);
916
+ assertString(marker);
917
+ if (str.length === 0 || marker.length === 0) {
918
+ return
919
+ }
920
+ const index = str.indexOf(marker);
921
+ if (index === -1) {
922
+ return undefined
923
+ }
924
+ return str.substring(0, index)
925
+ }
926
+
927
+ /**
928
+ * Returns the substring before the last occurrence of a marker.
929
+ * @param {string} str
930
+ * @param {string} marker
931
+ * @returns {string | undefined}The substring before the last marker, or undefined if marker not found.
932
+ * @throws {Error} If either input is not a string.
933
+ */
934
+ function substringBeforeLast (str, marker) {
935
+ assertString(str);
936
+ assertString(marker);
937
+ if (str.length === 0 || marker.length === 0) {
938
+ return
939
+ }
940
+ const index = str.lastIndexOf(marker);
941
+ if (index === -1) {
942
+ return
943
+ }
944
+ return str.substring(0, index)
945
+ }
946
+
947
+ /**
948
+ * Returns the substring after the first occurrence of the specified marker.
949
+ * If the marker is not found, returns an empty string.
950
+ *
951
+ * @param {string} str - The string to search in
952
+ * @param {string} marker - The string to search for
953
+ * @returns {string | undefined} The substring after the marker, or undefined if not found
954
+ */
955
+ function substringAfter (str, marker) {
956
+ assertString(str);
957
+ assertString(marker);
958
+ if (str.length === 0 || marker.length === 0) {
959
+ return
960
+ }
961
+ const index = str.indexOf(marker);
962
+ if (index === -1) {
963
+ return
964
+ }
965
+ return str.substring(index + marker.length)
966
+ }
967
+
968
+ /**
969
+ * Returns the substring after the last occurrence of a marker in a string.
970
+ * @param {string} str - The input string to search in.
971
+ * @param {string} marker - The marker to search for.
972
+ * @returns {string|undefined} The substring after the last marker, or undefined if marker not found.
973
+ */
974
+ function substringAfterLast (str, marker) {
975
+ assertString(str);
976
+ assertString(marker);
977
+ if (str.length === 0 || marker.length === 0) {
978
+ return
979
+ }
980
+ const index = str.lastIndexOf(marker);
981
+ if (index === -1) {
982
+ return
983
+ }
984
+ return str.substring(index + marker.length)
985
+ }
986
+
987
+ /**
988
+ * Extracts the substring between the specified start and end markers in a string.
989
+ * 1. NOT Greedy, substring between the FIRST startMarker and FIRST endMarker
990
+ * 2. undefined returned, if Not Found neither startMarker nor endMarker
991
+ * @param {string} str - The input string to search within
992
+ * @param {string} startMarker - The starting marker string
993
+ * @param {string} endMarker - The ending marker string
994
+ * @returns {string|undefined} The substring between markers, or undefined if markers not found
995
+ * @throws {Error} If any input is not a string.
996
+ */
997
+ function substringBetween (str, startMarker, endMarker) {
998
+ assertNotEmpty(str);
999
+ assertNotEmpty(startMarker);
1000
+ assertNotEmpty(endMarker);
1001
+ const startIndex = str.indexOf(startMarker);
1002
+ if (startIndex === -1) {
1003
+ return
1004
+ }
1005
+ const endIndex = str.indexOf(endMarker, startIndex + startMarker.length);
1006
+ if (endIndex === -1) {
1007
+ return
1008
+ }
1009
+ return str.substring(startIndex + startMarker.length, endIndex)
1010
+ }
1011
+
1012
+ /**
1013
+ * Extracts the substring between the first occurrence of `startMarker` and the last occurrence of `endMarker` in `str`.
1014
+ * 1. Greedy, substring between the FIRST startMarker and LAST endMarker
1015
+ * 2. undefined returned, if Not Found neither startMarker nor endMarker
1016
+ * @param {string} str - The input string to search.
1017
+ * @param {string} startMarker - The starting marker.
1018
+ * @param {string} endMarker - The ending marker.
1019
+ * @returns {string|undefined} The substring between markers, or `undefined` if markers are not found.
1020
+ * @throws {Error} If any input is not a string.
1021
+ */
1022
+ function substringBetweenGreedy (str, startMarker, endMarker) {
1023
+ assertNotEmpty(str);
1024
+ assertNotEmpty(startMarker);
1025
+ assertNotEmpty(endMarker);
1026
+ const startIndex = str.indexOf(startMarker);
1027
+ if (startIndex === -1) {
1028
+ return
1029
+ }
1030
+ const endIndex = str.lastIndexOf(endMarker);
1031
+ if (endIndex === -1 || endIndex <= startIndex) {
1032
+ return
1033
+ }
1034
+ return str.substring(startIndex + startMarker.length, endIndex)
1035
+ }
1036
+
1037
+ /**
1038
+ * Extracts all substrings between specified start and end markers in a string.
1039
+ * 1. NOT Greedy
1040
+ * @param {string} str - The input string to search within
1041
+ * @param {string} startMarker - The substring marking the start of extraction
1042
+ * @param {string} endMarker - The substring marking the end of extraction
1043
+ * @returns {string[]} Array of all found substrings between markers, empty array "[]" returned if not found
1044
+ * @throws {Error} If any input is not a string
1045
+ */
1046
+ function substringsBetween (str, startMarker, endMarker) {
1047
+ assertNotEmpty(str);
1048
+ assertNotEmpty(startMarker);
1049
+ assertNotEmpty(endMarker);
1050
+ const substrings = [];
1051
+ let start = 0;
1052
+ while (true) {
1053
+ const index = str.indexOf(startMarker, start);
1054
+ if (index === -1) {
1055
+ break
1056
+ }
1057
+ const endIndex = str.indexOf(endMarker, index + startMarker.length);
1058
+ if (endIndex === -1) {
1059
+ break
1060
+ }
1061
+ substrings.push(str.substring(index + startMarker.length, endIndex));
1062
+ start = endIndex + endMarker.length;
1063
+ }
1064
+ return substrings
1065
+ }
1066
+
1067
+ /**
1068
+ * Executes a task silently, suppressing any errors or rejections.
1069
+ * @param {Function} task - The export function to execute.
1070
+ * @returns {Promise<*>|*} The return value of the task, or a Promise if the task is asynchronous.
1071
+ */
1072
+ function quiet (task) {
1073
+ assertFunction(task);
1074
+ try {
1075
+ const rtnVal = task();
1076
+ if (isPromise(rtnVal)) {
1077
+ return rtnVal.catch(() => {
1078
+ // do nothing
1079
+ })
1080
+ }
1081
+ return rtnVal
1082
+ } catch (e) {
1083
+ // do nothing
1084
+ }
1085
+ }
1086
+
1087
+ /**
1088
+ * Executes a task quietly, capturing any errors and passing them to the errorKeeper.
1089
+ * 1. Handles both synchronous and asynchronous (Promise) tasks.
1090
+ * @param {Function} task - The export function to execute.
1091
+ * @param {Error[]} errorKeeper - The array to store any caught errors.
1092
+ * @returns {Promise<*>|*} The return value of the task, or a Promise if the task is asynchronous.
1093
+ */
1094
+ function quietKeepError (task, errorKeeper) {
1095
+ assertFunction(task);
1096
+ assertArray(errorKeeper);
1097
+ try {
1098
+ const rtnVal = task();
1099
+ if (isPromise(rtnVal)) {
1100
+ // @ts-ignore
1101
+ return rtnVal.catch(e => errorKeeper.push(e))
1102
+ }
1103
+ return rtnVal
1104
+ } catch (e) {
1105
+ // @ts-ignore
1106
+ errorKeeper.push(e);
1107
+ }
1108
+ }
1109
+ var ExecUtils = {
1110
+ quiet,
1111
+ quietKeepError
1112
+ };
1113
+
1114
+ // @ts-nocheck
1115
+
1116
+ /**
1117
+ * @module PromiseUtils
1118
+ * @description Promise utility functions for enhanced promise handling, including timeout, delay, parallel execution, and series execution.
1119
+ */
1120
+ var PromiseUtils = {
1121
+ defer,
1122
+ delay,
1123
+ timeout,
1124
+ allSettled,
1125
+ returnValuePromised,
1126
+ series,
1127
+ seriesAllSettled,
1128
+ parallel,
1129
+ parallelAllSettled
1130
+ };
1131
+
1132
+ /**
1133
+ * Creates a "Deferred" Object with Timeout support
1134
+ * 1. timeout=-1, it means no timeout check
1135
+ * @param {number} [timeout=-1] - Timeout duration in milliseconds
1136
+ * @param {string} [timeoutMessage]
1137
+ * @returns {{promise: Promise<*>, reject: function, resolve: function}}
1138
+ */
1139
+ function defer (timeout = -1, timeoutMessage) {
1140
+ assertNumber(timeout);
1141
+ const rtnVal = {};
1142
+
1143
+ let timerHandler;
1144
+ if (timeout >= 0) {
1145
+ rtnVal.timerHandler = timerHandler = setTimeout(() => {
1146
+ clearTimeout(timerHandler); // must clear it
1147
+ rtnVal.timerCleared = true; // easy to check in test case
1148
+ rtnVal.reject(new Error(timeoutMessage ?? `Promise Timeout: ${timeout}ms`));
1149
+ }, timeout);
1150
+ rtnVal.timerHandler = timerHandler;
1151
+ }
1152
+
1153
+ rtnVal.promise = new Promise((resolve, reject) => {
1154
+ rtnVal.resolve = (...args) => {
1155
+ if (timerHandler != null) {
1156
+ clearTimeout(timerHandler); // must clear it
1157
+ rtnVal.timerCleared = true; // easy to check in test case
1158
+ }
1159
+ rtnVal.resolved = true;
1160
+ resolve(...args);
1161
+ };
1162
+
1163
+ rtnVal.reject = (err) => {
1164
+ if (timerHandler != null) {
1165
+ clearTimeout(timerHandler); // must clear it
1166
+ rtnVal.timerCleared = true; // easy to check in test case
1167
+ }
1168
+ rtnVal.rejected = true;
1169
+ reject(err);
1170
+ };
1171
+ });
1172
+ rtnVal.promise.cancel = () => {
1173
+ if (timerHandler != null) {
1174
+ clearTimeout(timerHandler); // must clear it
1175
+ rtnVal.timerCleared = true; // easy to check in test case
1176
+ }
1177
+ rtnVal.rejected = true; // easy to check in test case
1178
+ rtnVal.canceled = rtnVal.promise.canceled = true; // easy to check in test case
1179
+ rtnVal.reject(new Error('Cancelled'));
1180
+ };
1181
+ return rtnVal
1182
+ }
1183
+
1184
+ /**
1185
+ * Creates a timeout wrapper around a promise that rejects if the promise doesn't resolve within the given time.
1186
+ * @param {Promise<*>} promise - The promise to wrap with a timeout
1187
+ * @param {number} [time=1] - Timeout duration in milliseconds
1188
+ * @param {string} [message=`Promise Timeout: ${time}ms`] - Custom rejection message
1189
+ * @returns {Promise<*>} A new promise that either resolves with the original promise's value, rejects with original promise's error or timeout error
1190
+ * @throws {TypeError} If input is not a promise or timeout is not a number
1191
+ */
1192
+ function timeout (promise, time, message) {
1193
+ assertPromise(promise);
1194
+
1195
+ time = time ?? 1;
1196
+ assertNumber(time);
1197
+
1198
+ const deferred = defer(time, message);
1199
+ const startTs = Date.now();
1200
+ promise.then((...args) => { // original promise settled, but timeout
1201
+ const elapsed = Date.now() - startTs;
1202
+ if (elapsed <= time) {
1203
+ deferred.resolve(...args);
1204
+ } else {
1205
+ deferred.reject(new Error(message ?? `Promise Timeout: ${time}ms`));
1206
+ }
1207
+ }).catch((err) => {
1208
+ // prevent double reject
1209
+ !deferred.resolved && !deferred.rejected && deferred.reject(err);
1210
+ });
1211
+ return deferred.promise
1212
+ }
1213
+
1214
+ /**
1215
+ * Excutes All promises in parallel and returns an array of results.
1216
+ *
1217
+ * Why:
1218
+ * 1. Promise.allSettled() returns
1219
+ * * { status: 'fulfilled', value: any } when promise fulfills
1220
+ * * { status: 'rejected', reason: any } when promise rejects
1221
+ * 2. It's NOT convenient to use Promise.allSettled() to get the results of all promises.
1222
+ * * the data structure is not consistent when fullfilled or rejected
1223
+ * * have to check "string" type of status to know sucess or failure
1224
+ * @param {Promise} promises
1225
+ * @returns {Array<{ok: boolean, result: any}>}
1226
+ */
1227
+ async function allSettled (promises) {
1228
+ assertArray(promises);
1229
+ const results = await Promise.allSettled(promises);
1230
+ const rtnVal = [];
1231
+ for (const result of results) {
1232
+ if (result.status === 'fulfilled') {
1233
+ rtnVal.push({ ok: true, result: result.value });
1234
+ }
1235
+ if (result.status === 'rejected') {
1236
+ rtnVal.push({ ok: false, result: result.reason });
1237
+ }
1238
+ }
1239
+ return rtnVal
1240
+ }
1241
+
1242
+ /**
1243
+ * Execute the task Function, and ensure it returns a Promise.
1244
+ * @param {function} task
1245
+ * @returns {Promise<*>}
1246
+ */
1247
+ function returnValuePromised (task) {
1248
+ try {
1249
+ const taskRtnVal = task();
1250
+ if (isPromise(taskRtnVal)) {
1251
+ return taskRtnVal
1252
+ }
1253
+ return Promise.resolve(taskRtnVal)
1254
+ } catch (e) {
1255
+ return Promise.reject(e)
1256
+ }
1257
+ }
1258
+
1259
+ /**
1260
+ * Delays a promise by a specified time.
1261
+ * 1. delay(), wait 1ms
1262
+ * 2. delay(1000), wait 1000ms
1263
+ * 3. delay(promise), after promise settled, wait 1000ms
1264
+ * 4. delay(promise, 2000), after promise settled, wait 2000ms
1265
+ *
1266
+ * @param {Promise<*>|number|undefined} [promise] - The input promise to delay
1267
+ * @param {number|undefined} [ms] - Minimum delay in milliseconds (default: 1)
1268
+ * @returns {Promise} A new promise that settles after the delay period
1269
+ */
1270
+ function delay (promise, ms) {
1271
+ if (isNumber(promise)) {
1272
+ ms = promise;
1273
+ promise = Promise.resolve();
1274
+ } else if (promise == null && ms == null) {
1275
+ ms = 1;
1276
+ promise = Promise.resolve();
1277
+ }
1278
+ promise != null && assertPromise(promise);
1279
+ ms = ms ?? 1000;
1280
+ assertNumber(ms);
1281
+ const deferred = defer();
1282
+ const startTs = Date.now();
1283
+ promise
1284
+ .then((...args) => {
1285
+ const escaped = Date.now() - startTs;
1286
+ if (escaped < ms) {
1287
+ setTimeout(() => deferred.resolve(...args), ms - escaped);
1288
+ } else {
1289
+ deferred.resolve(...args);
1290
+ }
1291
+ })
1292
+ .catch((err) => {
1293
+ const escaped = Date.now() - startTs;
1294
+ if (escaped < ms) {
1295
+ setTimeout(() => deferred.reject(err), ms - escaped);
1296
+ } else {
1297
+ deferred.reject(err);
1298
+ }
1299
+ });
1300
+ return deferred.promise
1301
+ }
1302
+
1303
+ /**
1304
+ * Fast-Fail mode to execute Tasks(functions) in series (one after another) and returns their results in order.
1305
+ * 1. export function are executed one by one
1306
+ * 2. Fast Fail: if any tasks fail, the whole chain is rejected with the first error
1307
+ * 3. if an element is not function, rejects the whole chain with Error(Not Function)
1308
+ * @param {Function[]} promises
1309
+ * @returns {Promise<Array>} Promise that resolves with an array of results in the same order as input tasks
1310
+ */
1311
+ async function series (tasks) {
1312
+ assertArray(tasks);
1313
+ const results = [];
1314
+ for (const task of tasks) {
1315
+ assertFunction(task);
1316
+ results.push(await task());
1317
+ }
1318
+ return results
1319
+ }
1320
+
1321
+ /**
1322
+ * AllSettled Mode to execute Tasks(functions) in series (one after another) and returns their results in order.
1323
+ * 1. tasks are executed one by one
1324
+ * 2. Each result is an object with `ok` (boolean) and `result` (resolved value or error).
1325
+ * 3. if a task is not Function, rejects the whole chain with Error(Not Function)
1326
+ * @param {Function[]} tasks
1327
+ * @returns {Promise<Array<{ok: boolean, result: *}>>}
1328
+ */
1329
+ async function seriesAllSettled (tasks) {
1330
+ assertArray(tasks);
1331
+ const results = [];
1332
+ for (const task of tasks) {
1333
+ assertFunction(task);
1334
+ try {
1335
+ results.push({ ok: true, result: await task() });
1336
+ } catch (err) {
1337
+ results.push({ ok: false, result: err });
1338
+ }
1339
+ }
1340
+ return results
1341
+ }
1342
+
1343
+ /**
1344
+ * FastFail Mode to Execute tasks in parallel with a maximum concurrency limit
1345
+ * 1. tasks are executed in parallel with a maximum concurrency limit
1346
+ * 2. rejects whole chain with the first error, when first task fails
1347
+ * @param {Function[]} tasks
1348
+ * @param {number} [maxParallel=5]
1349
+ * @returns {Promise<Array>} Array of resolved values from all promises
1350
+ * @throws {TypeError} If input is not an array of export function or maxParallel is not a number
1351
+ */
1352
+ async function parallel (tasks, maxParallel = 5) {
1353
+ assertArray(tasks);
1354
+ assertNumber(maxParallel);
1355
+ if (maxParallel <= 0) {
1356
+ throw new Error(`Invalid maxParallel: ${maxParallel}, should > 0`)
1357
+ }
1358
+ tasks.forEach((task) => assertFunction(task));
1359
+ const rtnVal = [];
1360
+ // once for all, run all tasks
1361
+ if (tasks.length <= maxParallel) {
1362
+ const resultsForBatch = await Promise.all(tasks.map(task => returnValuePromised(task)));
1363
+ rtnVal.push(...resultsForBatch);
1364
+ return rtnVal
1365
+ }
1366
+ // run group by MaxParallel
1367
+ const tasksToRun = [];
1368
+ for (const task of tasks) {
1369
+ assertFunction(task);
1370
+ tasksToRun.push(task);
1371
+ if (tasksToRun.length >= maxParallel) {
1372
+ const resultsForBatch = await Promise.all(tasksToRun.map(task => returnValuePromised(task)));
1373
+ rtnVal.push(...resultsForBatch);
1374
+ tasksToRun.length = 0;
1375
+ }
1376
+ }
1377
+ // Run all rested
1378
+ if (tasksToRun.length > 0 && tasksToRun.length < maxParallel) {
1379
+ const resultsForBatch = await Promise.all(tasksToRun.map(task => returnValuePromised(task)));
1380
+ rtnVal.push(...resultsForBatch);
1381
+ }
1382
+ return rtnVal
1383
+ }
1384
+
1385
+ /**
1386
+ * AllSettled Mode to execute tasks in parallel with a maximum concurrency limit
1387
+ * 1. tasks are executed in parallel with a maximum concurrency limit
1388
+ * 2. all tasks will be executed, even some of them failed.
1389
+ * @param {Function[]} tasks
1390
+ * @param {number} [maxParallel=5] - Maximum number of tasks to run in parallel
1391
+ * @returns {Promise<Array>} Array of resolved values from all promises
1392
+ * @throws {TypeError} If input is not an array of export function or maxParallel is not a number
1393
+ */
1394
+ async function parallelAllSettled (tasks, maxParallel = 5) {
1395
+ assertArray(tasks);
1396
+ assertNumber(maxParallel);
1397
+ if (maxParallel <= 0) {
1398
+ throw new Error(`Invalid maxParallel: ${maxParallel}, should > 0`)
1399
+ }
1400
+ tasks.forEach((task) => assertFunction(task));
1401
+ const rtnVal = [];
1402
+ // once for all, run all promises
1403
+ if (tasks.length <= maxParallel) {
1404
+ const resultsForBatch = await allSettled(tasks.map(task => returnValuePromised(task)));
1405
+ rtnVal.push(...resultsForBatch);
1406
+ return rtnVal
1407
+ }
1408
+ // run group by MaxParallel
1409
+ const tasksToRun = [];
1410
+ for (const task of tasks) {
1411
+ assertFunction(task);
1412
+ tasksToRun.push(task);
1413
+ if (tasksToRun.length >= maxParallel) {
1414
+ const resultsForBatch = await allSettled(tasksToRun.map(task => returnValuePromised(task)));
1415
+ rtnVal.push(...resultsForBatch);
1416
+ tasksToRun.length = 0;
1417
+ }
1418
+ }
1419
+ // Run all rested
1420
+ if (tasksToRun.length > 0 && tasksToRun.length < maxParallel) {
1421
+ const resultsForBatch = await allSettled(tasksToRun.map(task => returnValuePromised(task)));
1422
+ rtnVal.push(...resultsForBatch);
1423
+ }
1424
+ return rtnVal
1425
+ }
1426
+
1427
+ // owned
1428
+
1429
+ const { isPlainObject } = TypeUtils;
1430
+
1431
+ /**
1432
+ * @module ClassProxyUtils
1433
+ */
1434
+ var ClassProxyUtils = {
1435
+ proxy: proxy$1,
1436
+ newProxyInstance
1437
+ };
1438
+
1439
+ /**
1440
+ * Creates a Proxy Class for given class.
1441
+ * @template {object} T
1442
+ * @param {Function} cls - The class to proxycls - The class to proxy
1443
+ * @param {ProxyHandler<T>} [propertyHandler = {}] - Proxy Property Handler
1444
+ * @param {boolean} [sealed=true] - Whether to seal the instance
1445
+ * @returns {Function} A proxied classA proxied instance of the class
1446
+ */
1447
+ function proxy$1 (cls, propertyHandler, sealed = true) {
1448
+ if (typeof cls !== 'function') {
1449
+ throw new TypeError(`Not Class: type=${typeof cls}, value=${JSON.stringify(cls)}`)
1450
+ }
1451
+ if (propertyHandler != null) {
1452
+ if (!isPlainObject(propertyHandler)) {
1453
+ throw new TypeError(`Not PropertyHandler: type=${typeof propertyHandler}, value=${JSON.stringify(propertyHandler)}`)
1454
+ }
1455
+ const { get, set } = propertyHandler;
1456
+ if (get != null && typeof get !== 'function') {
1457
+ throw new TypeError(`Not PropertyHandler.get: type=${typeof get}, value=${JSON.stringify(get)}`)
1458
+ }
1459
+ if (set != null && typeof set !== 'function') {
1460
+ throw new TypeError(`Not PropertyHandler.set: type=${typeof set}, value=${JSON.stringify(set)}`)
1461
+ }
1462
+ }
1463
+ const construcHandler = {
1464
+ /**
1465
+ * Creates a proxied instance of a class, optionally sealing it.
1466
+ * @param {Function} constructor - The class constructor to instantiate.
1467
+ * @param {any[]} args - Arguments to pass to the constructor.
1468
+ * @param {Function} [newTarget] - The constructor that was originally called by `new`.
1469
+ * @returns {Proxy} A proxied instance of the constructed class.
1470
+ */
1471
+ construct (constructor, args, newTarget) {
1472
+ const clsInstance = Reflect.construct(constructor, args);
1473
+ return new Proxy(sealed ? Object.preventExtensions(clsInstance) : clsInstance, propertyHandler ?? {})
1474
+ }
1475
+ };
1476
+ return new Proxy(cls, construcHandler)
1477
+ }
1478
+
1479
+ /**
1480
+ * Creates a proxied instance of a class with custom property handling.
1481
+ * @template {object} T
1482
+ * @param {Function} cls - The class to proxy
1483
+ * @param {any[]} args - Arguments to pass to the constructor
1484
+ * @param {ProxyHandler<T>} propertyHandler - Handler for property access/mutation
1485
+ * @param {boolean} [sealed=true] - Whether the proxy should be sealed
1486
+ * @returns {T} Proxied class instance
1487
+ */
1488
+ function newProxyInstance (cls, args, propertyHandler, sealed = true) {
1489
+ const proxyCls = proxy$1(cls, propertyHandler, sealed);
1490
+ return Reflect.construct(proxyCls, args ?? [])
1491
+ }
1492
+
1493
+ /**
1494
+ * @module InstanceProxyUtils
1495
+ */
1496
+
1497
+ /**
1498
+ * Creates a proxy wrapper around an object instance with optional property handler.
1499
+ * @template {object} T
1500
+ * @param {T} instance - The target object to proxy
1501
+ * @param {ProxyHandler<T>} [propertyHandler] - Optional proxy handler for property access
1502
+ * @param {boolean} [sealed=true] - Whether to prevent extensions on the target object
1503
+ * @returns {T} The proxied object instance
1504
+ * @throws {TypeError} If instance is not an object
1505
+ */
1506
+ function proxy (instance, propertyHandler, sealed = true) {
1507
+ if (isNil(instance) || !isObject(instance) || isArray(instance)) {
1508
+ throw new TypeError(`Not Object: type=${typeof instance}, value=${JSON.stringify(instance)}`)
1509
+ }
1510
+ return new Proxy(sealed ? Object.preventExtensions(instance) : instance, propertyHandler ?? {})
1511
+ }
1512
+
1513
+ var InstanceProxyUtils = {
1514
+ proxy
1515
+ };
1516
+
1517
+ /**
1518
+ * @module Lang
1519
+ * @description Core language utilities for type checking, string manipulation, and common operations.
1520
+ */
1521
+
1522
+
1523
+ var index = {
1524
+ LangUtils,
1525
+ StringUtils,
1526
+ TypeUtils,
1527
+ TypeAssert,
1528
+ ExecUtils,
1529
+ PromiseUtils,
1530
+ Lang: LangUtils,
1531
+ Type: TypeUtils,
1532
+ Exec: ExecUtils,
1533
+ ClassProxyUtils,
1534
+ InstanceProxyUtils
1535
+ };
1536
+
1537
+ exports.ClassProxyUtils = ClassProxyUtils;
1538
+ exports.Exec = ExecUtils;
1539
+ exports.ExecUtils = ExecUtils;
1540
+ exports.InstanceProxyUtils = InstanceProxyUtils;
1541
+ exports.Lang = LangUtils;
1542
+ exports.LangUtils = LangUtils;
1543
+ exports.PromiseUtils = PromiseUtils;
1544
+ exports.StringUtils = StringUtils;
1545
+ exports.Type = TypeUtils;
1546
+ exports.TypeAssert = TypeAssert;
1547
+ exports.TypeUtils = TypeUtils;
1548
+ exports.default = index;
1549
+
1550
+ Object.defineProperty(exports, '__esModule', { value: true });
1551
+
1552
+ }));
1553
+ //# sourceMappingURL=index.dev.js.map