@vbarbarosh/node-helpers 3.67.0 → 3.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +2 -2
  2. package/dist/browser.js +603 -141
  3. package/package.json +1 -1
  4. package/src/_finally.js +8 -0
  5. package/src/_finally.md +19 -0
  6. package/src/_perf.js +18 -0
  7. package/src/_perf.md +13 -0
  8. package/src/_restore.js +16 -0
  9. package/src/_restore.md +21 -0
  10. package/src/_try.js +11 -0
  11. package/src/_try.md +5 -0
  12. package/src/array_max.md +1 -0
  13. package/src/array_min.md +1 -0
  14. package/src/array_shuffle.md +5 -0
  15. package/src/array_unique.md +1 -0
  16. package/src/array_unique_last.md +1 -0
  17. package/src/browser/index.js +15 -7
  18. package/src/fastdl.md +8 -0
  19. package/src/fcmp_from_spec.js +2 -0
  20. package/src/fcmpx.md +17 -0
  21. package/src/fcmpx.test.js +16 -1
  22. package/src/filter1_from_spec.md +7 -0
  23. package/src/format_hrtime.md +1 -0
  24. package/src/fs_fopen_update.md +5 -0
  25. package/src/fs_size_enoent.md +3 -0
  26. package/src/fs_tempdir.md +6 -0
  27. package/src/now_atom.js +1 -1
  28. package/src/now_atom.md +1 -0
  29. package/src/parallel.md +5 -0
  30. package/src/ping_socket.md +3 -0
  31. package/src/stream_chunk.md +1 -0
  32. package/src/stream_data_ln.md +1 -0
  33. package/src/stream_each.md +1 -0
  34. package/src/stream_filter.md +1 -0
  35. package/src/stream_lines.md +1 -0
  36. package/src/stream_map.md +1 -0
  37. package/src/stream_map_flatten.md +1 -0
  38. package/src/stream_map_parallel.md +1 -0
  39. package/src/stream_parse_csv.md +3 -0
  40. package/src/stream_progress.js +1 -1
  41. package/src/stream_progress.md +8 -0
  42. package/src/stream_skip.md +1 -0
  43. package/src/stream_strpbrk.md +1 -0
  44. package/src/stream_tap.md +1 -0
  45. package/src/stream_xml_analyze.md +1 -0
  46. package/src/stream_xml_parse.md +1 -0
  47. package/src/throttle.md +3 -0
  48. package/src/urlclean.js +1 -1
  49. package/src/urlclean.md +2 -0
  50. package/src/urlmod.md +7 -0
  51. package/src/user_friendly_status.md +4 -0
  52. package/src/wait_while.md +5 -0
  53. package/src/waitcb.md +12 -0
package/dist/browser.js CHANGED
@@ -1,6 +1,40 @@
1
1
  /******/ (() => { // webpackBootstrap
2
2
  /******/ var __webpack_modules__ = ({
3
3
 
4
+ /***/ "./node_modules/@vbarbarosh/type-helpers/src/is_num.js":
5
+ /*!*************************************************************!*\
6
+ !*** ./node_modules/@vbarbarosh/type-helpers/src/is_num.js ***!
7
+ \*************************************************************/
8
+ /***/ ((module) => {
9
+
10
+ function is_num(input)
11
+ {
12
+ return (typeof input === 'number') && isFinite(input);
13
+ }
14
+
15
+ module.exports = is_num;
16
+
17
+
18
+ /***/ }),
19
+
20
+ /***/ "./node_modules/@vbarbarosh/type-helpers/src/is_num_gt.js":
21
+ /*!****************************************************************!*\
22
+ !*** ./node_modules/@vbarbarosh/type-helpers/src/is_num_gt.js ***!
23
+ \****************************************************************/
24
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
25
+
26
+ const is_num = __webpack_require__(/*! ./is_num */ "./node_modules/@vbarbarosh/type-helpers/src/is_num.js");
27
+
28
+ function is_num_gt(input, min)
29
+ {
30
+ return is_num(input) && input > min;
31
+ }
32
+
33
+ module.exports = is_num_gt;
34
+
35
+
36
+ /***/ }),
37
+
4
38
  /***/ "./node_modules/json-stringify-safe/stringify.js":
5
39
  /*!*******************************************************!*\
6
40
  !*** ./node_modules/json-stringify-safe/stringify.js ***!
@@ -59,15 +93,30 @@ var map = {
59
93
  "./array_sum.js": "./src/array_sum.js",
60
94
  "./array_unique.js": "./src/array_unique.js",
61
95
  "./array_unique_last.js": "./src/array_unique_last.js",
96
+ "./date_add_hours.js": "./src/date_add_hours.js",
97
+ "./date_add_milliseconds.js": "./src/date_add_milliseconds.js",
98
+ "./date_add_minutes.js": "./src/date_add_minutes.js",
62
99
  "./date_add_months.js": "./src/date_add_months.js",
100
+ "./date_add_seconds.js": "./src/date_add_seconds.js",
101
+ "./date_diff_seconds.js": "./src/date_diff_seconds.js",
63
102
  "./date_is_leap_year.js": "./src/date_is_leap_year.js",
64
103
  "./fcmp_dates.js": "./src/fcmp_dates.js",
104
+ "./fcmp_default.js": "./src/fcmp_default.js",
105
+ "./fcmp_default_desc.js": "./src/fcmp_default_desc.js",
65
106
  "./fcmp_from_spec.js": "./src/fcmp_from_spec.js",
66
107
  "./fcmp_numbers.js": "./src/fcmp_numbers.js",
67
- "./fcmp_strings.js": "./src/fcmp_strings.js",
108
+ "./fcmp_tuples.js": "./src/fcmp_tuples.js",
109
+ "./fcmp_utf8_bin.js": "./src/fcmp_utf8_bin.js",
110
+ "./fcmp_utf8_ci.js": "./src/fcmp_utf8_ci.js",
111
+ "./fcmp_utf8_cs.js": "./src/fcmp_utf8_cs.js",
112
+ "./fcmp_utf8_natural_ci.js": "./src/fcmp_utf8_natural_ci.js",
113
+ "./fcmp_utf8_natural_cs.js": "./src/fcmp_utf8_natural_cs.js",
114
+ "./fcmpx.js": "./src/fcmpx.js",
68
115
  "./filter1_from_spec.js": "./src/filter1_from_spec.js",
69
116
  "./format_bytes.js": "./src/format_bytes.js",
70
117
  "./format_date.js": "./src/format_date.js",
118
+ "./format_date_fs.js": "./src/format_date_fs.js",
119
+ "./format_date_human.js": "./src/format_date_human.js",
71
120
  "./format_date_ymd.js": "./src/format_date_ymd.js",
72
121
  "./format_error_report.js": "./src/format_error_report.js",
73
122
  "./format_hrtime.js": "./src/format_hrtime.js",
@@ -183,20 +232,24 @@ module.exports = array_gcd;
183
232
  /*!****************************!*\
184
233
  !*** ./src/array_group.js ***!
185
234
  \****************************/
186
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
187
-
188
- const array_group_map = __webpack_require__(/*! ./array_group_map */ "./src/array_group_map.js");
235
+ /***/ ((module) => {
189
236
 
190
237
  /**
191
- * Group items by common key and return an array of groups.
238
+ * Group items by a common key and return an array of groups.
192
239
  *
193
- * @param array
194
- * @param fn
195
- * @returns {unknown[]}
240
+ * @alternative Map.groupBy(items, fn)
196
241
  */
197
242
  function array_group(array, fn)
198
243
  {
199
- return Object.values(array_group_map(array, fn));
244
+ const map = new Map();
245
+ array.forEach(function (item) {
246
+ const key = fn(item);
247
+ if (!map.has(key)) {
248
+ map.set(key, {key, items: []});
249
+ }
250
+ map.get(key).items.push(item);
251
+ });
252
+ return map.values().toArray();
200
253
  }
201
254
 
202
255
  module.exports = array_group;
@@ -237,7 +290,9 @@ module.exports = array_group_map;
237
290
  /*!****************************!*\
238
291
  !*** ./src/array_index.js ***!
239
292
  \****************************/
240
- /***/ ((module) => {
293
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
294
+
295
+ const identity = __webpack_require__(/*! ./identity */ "./src/identity.js");
241
296
 
242
297
  /**
243
298
  * Usage:
@@ -246,7 +301,7 @@ module.exports = array_group_map;
246
301
  * Seems, there is a native way to do it:
247
302
  * Object.fromEntries(items.map(v => [v.name, v]));
248
303
  */
249
- function array_index(array, fn)
304
+ function array_index(array, fn = identity)
250
305
  {
251
306
  const out = {};
252
307
  array.forEach(v => out[fn(v)] = v);
@@ -262,33 +317,27 @@ module.exports = array_index;
262
317
  /*!**************************!*\
263
318
  !*** ./src/array_max.js ***!
264
319
  \**************************/
265
- /***/ ((module) => {
320
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
321
+
322
+ const identity = __webpack_require__(/*! ./identity */ "./src/identity.js");
266
323
 
267
324
  /**
268
- * Return first among maximum values.
269
- *
270
- * @param array
271
- * @param fn
325
+ * Returns the first element in the array with the maximal weight
272
326
  */
273
327
  function array_max(array, fn = identity)
274
328
  {
275
329
  let out = null;
276
- let out_value = null;
277
- array.forEach(function (item) {
278
- const item_value = fn(item);
279
- if (item_value > out_value || out_value === null) {
330
+ let max = null;
331
+ array.forEach(function (item, i) {
332
+ const weight = fn(item);
333
+ if (i === 0 || max < weight) {
334
+ max = weight;
280
335
  out = item;
281
- out_value = item_value;
282
336
  }
283
337
  });
284
338
  return out;
285
339
  }
286
340
 
287
- function identity(value)
288
- {
289
- return value;
290
- }
291
-
292
341
  module.exports = array_max;
293
342
 
294
343
 
@@ -298,33 +347,27 @@ module.exports = array_max;
298
347
  /*!**************************!*\
299
348
  !*** ./src/array_min.js ***!
300
349
  \**************************/
301
- /***/ ((module) => {
350
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
351
+
352
+ const identity = __webpack_require__(/*! ./identity */ "./src/identity.js");
302
353
 
303
354
  /**
304
- * Return first among minimum values.
305
- *
306
- * @param array
307
- * @param fn
355
+ * Returns the first element in the array with the minimal weight
308
356
  */
309
357
  function array_min(array, fn = identity)
310
358
  {
311
359
  let out = null;
312
- let out_value = null;
313
- array.forEach(function (item) {
314
- const item_value = fn(item);
315
- if (item_value < out_value || out_value === null) {
360
+ let min = null;
361
+ array.forEach(function (item, i) {
362
+ const weight = fn(item);
363
+ if (i === 0 || min > weight) {
364
+ min = weight;
316
365
  out = item;
317
- out_value = item_value;
318
366
  }
319
367
  });
320
368
  return out;
321
369
  }
322
370
 
323
- function identity(value)
324
- {
325
- return value;
326
- }
327
-
328
371
  module.exports = array_min;
329
372
 
330
373
 
@@ -337,19 +380,23 @@ module.exports = array_min;
337
380
  /***/ ((module) => {
338
381
 
339
382
  // https://stackoverflow.com/a/37580979/23502239
340
- function array_permutations(array)
383
+ function array_permutations(array, k = array.length)
341
384
  {
342
- var length = array.length,
343
- out = [array.slice()],
344
- c = new Array(length).fill(0),
345
- i = 1, k, p;
385
+ if (k !== array.length) {
386
+ return array_permutations_k(array, k);
387
+ }
388
+
389
+ let length = array.length;
390
+ let out = [array.slice()];
391
+ let c = new Array(length).fill(0);
392
+ let i = 1, kk, p;
346
393
 
347
394
  while (i < length) {
348
395
  if (c[i] < i) {
349
- k = i % 2 && c[i];
396
+ kk = i % 2 && c[i];
350
397
  p = array[i];
351
- array[i] = array[k];
352
- array[k] = p;
398
+ array[i] = array[kk];
399
+ array[kk] = p;
353
400
  ++c[i];
354
401
  i = 1;
355
402
  out.push(array.slice());
@@ -362,6 +409,27 @@ function array_permutations(array)
362
409
  return out;
363
410
  }
364
411
 
412
+ function array_permutations_k(array, k)
413
+ {
414
+ if (k === 0) {
415
+ return [
416
+ []
417
+ ];
418
+ }
419
+ if (array.length < k) {
420
+ return [];
421
+ }
422
+
423
+ const out = [];
424
+ for (let i = 0; i < array.length; i++) {
425
+ const rest = array.slice(0, i).concat(array.slice(i + 1));
426
+ for (const perm of array_permutations(rest, k - 1)) {
427
+ out.push([array[i], ...perm]);
428
+ }
429
+ }
430
+ return out;
431
+ }
432
+
365
433
  module.exports = array_permutations;
366
434
 
367
435
 
@@ -407,27 +475,36 @@ module.exports = array_shuffle;
407
475
  \***************************/
408
476
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
409
477
 
410
- const fcmp_strings = __webpack_require__(/*! ./fcmp_strings */ "./src/fcmp_strings.js");
478
+ const fcmp_default = __webpack_require__(/*! ./fcmp_default */ "./src/fcmp_default.js");
479
+ const fcmp_tuples = __webpack_require__(/*! ./fcmp_tuples */ "./src/fcmp_tuples.js");
411
480
 
412
481
  /**
413
- * Sort items in an `array`.
482
+ * Sorts an array in place by the result of applying `fn` to each item,
483
+ * using `fcmp` to compare the results.
414
484
  *
415
- * @param array
416
- * @param fn
417
- * @param fcmp
418
- * @returns {*}
485
+ * array_sort(items, v => [v.name])
486
+ * array_sort(items, v => [v.age, v.name])
419
487
  */
420
- function array_sort(array, fn = identity, fcmp = fcmp_strings)
488
+ function array_sort(array, mapper, fcmp = fcmp_default)
421
489
  {
490
+ const keys = new Map();
422
491
  return array.sort(function (a, b) {
423
- return fcmp(fn(a), fn(b));
492
+ if (!keys.has(a)) {
493
+ keys.set(a, mapper(a));
494
+ }
495
+ if (!keys.has(b)) {
496
+ keys.set(b, mapper(b));
497
+ }
498
+ return fcmp_tuples(keys.get(a), keys.get(b), fcmp);
424
499
  });
425
500
  }
426
501
 
427
- function identity(v)
428
- {
429
- return v;
430
- }
502
+ // function array_sort(array, fn = identity, fcmp = fcmp_default)
503
+ // {
504
+ // return array.sort(function (a, b) {
505
+ // return fcmp(fn(a), fn(b));
506
+ // });
507
+ // }
431
508
 
432
509
  module.exports = array_sort;
433
510
 
@@ -440,7 +517,7 @@ module.exports = array_sort;
440
517
  \*********************************/
441
518
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
442
519
 
443
- const fcmp_strings = __webpack_require__(/*! ./fcmp_strings */ "./src/fcmp_strings.js");
520
+ const fcmp_default = __webpack_require__(/*! ./fcmp_default */ "./src/fcmp_default.js");
444
521
 
445
522
  /**
446
523
  * Sort items in an `array` at the same order as in `other`. Values which
@@ -452,7 +529,7 @@ const fcmp_strings = __webpack_require__(/*! ./fcmp_strings */ "./src/fcmp_strin
452
529
  * @param fcmp
453
530
  * @returns {*}
454
531
  */
455
- function array_sort_other(array, fn, other, fcmp = fcmp_strings)
532
+ function array_sort_other(array, fn, other, fcmp = fcmp_default)
456
533
  {
457
534
  const other_map = {};
458
535
  other.forEach((v,i) => other_map[v] = i + 1);
@@ -501,16 +578,22 @@ module.exports = array_sum;
501
578
  /*!*****************************!*\
502
579
  !*** ./src/array_unique.js ***!
503
580
  \*****************************/
504
- /***/ ((module) => {
581
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
505
582
 
506
- function array_unique(values)
583
+ const identity = __webpack_require__(/*! ./identity */ "./src/identity.js");
584
+
585
+ /**
586
+ * Return unique values; if a value occurs multiple times, keep the first one.
587
+ */
588
+ function array_unique(values, fn = identity)
507
589
  {
508
590
  const set = new Set();
509
591
  return values.filter(function (item) {
510
- if (set.has(item)) {
592
+ const key = fn(item);
593
+ if (set.has(key)) {
511
594
  return false;
512
595
  }
513
- set.add(item);
596
+ set.add(key);
514
597
  return true;
515
598
  });
516
599
  }
@@ -524,36 +607,80 @@ module.exports = array_unique;
524
607
  /*!**********************************!*\
525
608
  !*** ./src/array_unique_last.js ***!
526
609
  \**********************************/
527
- /***/ ((module) => {
610
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
611
+
612
+ const identity = __webpack_require__(/*! ./identity */ "./src/identity.js");
528
613
 
529
614
  /**
530
- * Return only unique values. If there are many values - prefer last one.
531
- *
532
- * @param array
533
- * @param fn
534
- * @returns {*[]}
615
+ * Return unique values; if a value occurs multiple times, keep the last one.
535
616
  */
536
617
  function array_unique_last(array, fn = identity)
537
618
  {
538
619
  const out = [];
539
- const taken = {};
620
+ const set = new Set();
540
621
  for (let i = array.length; --i >= 0; ) {
541
622
  const item = array[i];
542
- const pk = fn(item);
543
- if (!taken[pk]) {
544
- taken[pk] = true;
623
+ const key = fn(item);
624
+ if (!set.has(key)) {
625
+ set.add(key);
545
626
  out.push(item);
546
627
  }
547
628
  }
548
629
  return out.reverse();
549
630
  }
550
631
 
551
- function identity(value)
632
+ module.exports = array_unique_last;
633
+
634
+
635
+ /***/ }),
636
+
637
+ /***/ "./src/date_add_hours.js":
638
+ /*!*******************************!*\
639
+ !*** ./src/date_add_hours.js ***!
640
+ \*******************************/
641
+ /***/ ((module) => {
642
+
643
+ function date_add_hours(date, hours)
552
644
  {
553
- return value;
645
+ date.setHours(date.getHours() + hours);
646
+ return date;
554
647
  }
555
648
 
556
- module.exports = array_unique_last;
649
+ module.exports = date_add_hours;
650
+
651
+
652
+ /***/ }),
653
+
654
+ /***/ "./src/date_add_milliseconds.js":
655
+ /*!**************************************!*\
656
+ !*** ./src/date_add_milliseconds.js ***!
657
+ \**************************************/
658
+ /***/ ((module) => {
659
+
660
+ function date_add_milliseconds(date, milliseconds)
661
+ {
662
+ date.setMilliseconds(date.getMilliseconds() + milliseconds);
663
+ return date;
664
+ }
665
+
666
+ module.exports = date_add_milliseconds;
667
+
668
+
669
+ /***/ }),
670
+
671
+ /***/ "./src/date_add_minutes.js":
672
+ /*!*********************************!*\
673
+ !*** ./src/date_add_minutes.js ***!
674
+ \*********************************/
675
+ /***/ ((module) => {
676
+
677
+ function date_add_minutes(date, minutes)
678
+ {
679
+ date.setMinutes(date.getMinutes() + minutes);
680
+ return date;
681
+ }
682
+
683
+ module.exports = date_add_minutes;
557
684
 
558
685
 
559
686
  /***/ }),
@@ -590,6 +717,39 @@ function date_add_months(d, months)
590
717
  module.exports = date_add_months;
591
718
 
592
719
 
720
+ /***/ }),
721
+
722
+ /***/ "./src/date_add_seconds.js":
723
+ /*!*********************************!*\
724
+ !*** ./src/date_add_seconds.js ***!
725
+ \*********************************/
726
+ /***/ ((module) => {
727
+
728
+ function date_add_seconds(date, seconds)
729
+ {
730
+ date.setSeconds(date.getSeconds() + seconds);
731
+ return date;
732
+ }
733
+
734
+ module.exports = date_add_seconds;
735
+
736
+
737
+ /***/ }),
738
+
739
+ /***/ "./src/date_diff_seconds.js":
740
+ /*!**********************************!*\
741
+ !*** ./src/date_diff_seconds.js ***!
742
+ \**********************************/
743
+ /***/ ((module) => {
744
+
745
+ function date_diff_seconds(a, b)
746
+ {
747
+ return Math.floor((a.getTime() - b.getTime())/1000);
748
+ }
749
+
750
+ module.exports = date_diff_seconds;
751
+
752
+
593
753
  /***/ }),
594
754
 
595
755
  /***/ "./src/date_is_leap_year.js":
@@ -651,6 +811,50 @@ function fcmp_dates(a, b)
651
811
  module.exports = fcmp_dates;
652
812
 
653
813
 
814
+ /***/ }),
815
+
816
+ /***/ "./src/fcmp_default.js":
817
+ /*!*****************************!*\
818
+ !*** ./src/fcmp_default.js ***!
819
+ \*****************************/
820
+ /***/ ((module) => {
821
+
822
+ function fcmp_default(a, b)
823
+ {
824
+ if (a < b) {
825
+ return -1;
826
+ }
827
+ if (a > b) {
828
+ return 1;
829
+ }
830
+ return 0;
831
+ }
832
+
833
+ module.exports = fcmp_default;
834
+
835
+
836
+ /***/ }),
837
+
838
+ /***/ "./src/fcmp_default_desc.js":
839
+ /*!**********************************!*\
840
+ !*** ./src/fcmp_default_desc.js ***!
841
+ \**********************************/
842
+ /***/ ((module) => {
843
+
844
+ function fcmp_default_desc(b, a)
845
+ {
846
+ if (a < b) {
847
+ return -1;
848
+ }
849
+ if (a > b) {
850
+ return 1;
851
+ }
852
+ return 0;
853
+ }
854
+
855
+ module.exports = fcmp_default_desc;
856
+
857
+
654
858
  /***/ }),
655
859
 
656
860
  /***/ "./src/fcmp_from_spec.js":
@@ -662,6 +866,8 @@ module.exports = fcmp_dates;
662
866
  /**
663
867
  * Create fcmp from an array of props. For desc order a prop should be prefixed
664
868
  * with minus sign (e.g. -price).
869
+ *
870
+ * @deprecated Deprecated in favor of fcmpx
665
871
  */
666
872
  function fcmp_from_spec(props)
667
873
  {
@@ -726,7 +932,7 @@ module.exports = fcmp_from_spec;
726
932
 
727
933
  function fcmp_numbers(a, b)
728
934
  {
729
- return Number(a) - b;
935
+ return a - b;
730
936
  }
731
937
 
732
938
  module.exports = fcmp_numbers;
@@ -734,18 +940,248 @@ module.exports = fcmp_numbers;
734
940
 
735
941
  /***/ }),
736
942
 
737
- /***/ "./src/fcmp_strings.js":
943
+ /***/ "./src/fcmp_tuples.js":
944
+ /*!****************************!*\
945
+ !*** ./src/fcmp_tuples.js ***!
946
+ \****************************/
947
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
948
+
949
+ const fcmp_default = __webpack_require__(/*! ./fcmp_default */ "./src/fcmp_default.js");
950
+
951
+ function fcmp_tuples(a, b, fcmp = fcmp_default)
952
+ {
953
+ const end = Math.min(a.length, b.length);
954
+ for (let i = 0; i < end; ++i) {
955
+ const tmp = fcmp(a[i], b[i]);
956
+ if (tmp) {
957
+ return tmp;
958
+ }
959
+ }
960
+ return 0;
961
+ }
962
+
963
+ module.exports = fcmp_tuples;
964
+
965
+
966
+ /***/ }),
967
+
968
+ /***/ "./src/fcmp_utf8_bin.js":
969
+ /*!******************************!*\
970
+ !*** ./src/fcmp_utf8_bin.js ***!
971
+ \******************************/
972
+ /***/ ((module) => {
973
+
974
+ // Strict binary (codepoint) comparison, like MySQL's utf8_bin collation
975
+ function fcmp_utf8_bin(a, b)
976
+ {
977
+ if (a < b) {
978
+ return -1;
979
+ }
980
+ if (a > b) {
981
+ return 1;
982
+ }
983
+ return 0;
984
+ }
985
+
986
+ module.exports = fcmp_utf8_bin;
987
+
988
+
989
+ /***/ }),
990
+
991
+ /***/ "./src/fcmp_utf8_ci.js":
738
992
  /*!*****************************!*\
739
- !*** ./src/fcmp_strings.js ***!
993
+ !*** ./src/fcmp_utf8_ci.js ***!
740
994
  \*****************************/
741
995
  /***/ ((module) => {
742
996
 
743
- function fcmp_strings(a, b)
997
+ // Locale-aware, case-insensitive, like utf8_ci or utf8mb4_ci
998
+ function fcmp_utf8_ci(a, b)
999
+ {
1000
+ return a.localeCompare(b, undefined, {sensitivity: 'base'});
1001
+ }
1002
+
1003
+ module.exports = fcmp_utf8_ci;
1004
+
1005
+
1006
+ /***/ }),
1007
+
1008
+ /***/ "./src/fcmp_utf8_cs.js":
1009
+ /*!*****************************!*\
1010
+ !*** ./src/fcmp_utf8_cs.js ***!
1011
+ \*****************************/
1012
+ /***/ ((module) => {
1013
+
1014
+ // Locale-aware, case-sensitive, like utf8_cs or utf8mb4_cs (but using system locale)
1015
+ function fcmp_utf8_cs(a, b)
1016
+ {
1017
+ return a.localeCompare(b, undefined, {sensitivity: 'variant'});
1018
+ }
1019
+
1020
+ module.exports = fcmp_utf8_cs;
1021
+
1022
+
1023
+ /***/ }),
1024
+
1025
+ /***/ "./src/fcmp_utf8_natural_ci.js":
1026
+ /*!*************************************!*\
1027
+ !*** ./src/fcmp_utf8_natural_ci.js ***!
1028
+ \*************************************/
1029
+ /***/ ((module) => {
1030
+
1031
+ // Natural sort (numeric), case-insensitive
1032
+ function fcmp_utf8_natural_ci(a, b)
1033
+ {
1034
+ return a.localeCompare(b, undefined, {numeric: true, sensitivity: 'base'});
1035
+ }
1036
+
1037
+ module.exports = fcmp_utf8_natural_ci;
1038
+
1039
+
1040
+ /***/ }),
1041
+
1042
+ /***/ "./src/fcmp_utf8_natural_cs.js":
1043
+ /*!*************************************!*\
1044
+ !*** ./src/fcmp_utf8_natural_cs.js ***!
1045
+ \*************************************/
1046
+ /***/ ((module) => {
1047
+
1048
+ // Natural sort (numeric), case-sensitive
1049
+ function fcmp_utf8_natural_cs(a, b)
1050
+ {
1051
+ return a.localeCompare(b, undefined, {numeric: true, sensitivity: 'variant'});
1052
+ }
1053
+
1054
+ module.exports = fcmp_utf8_natural_cs;
1055
+
1056
+
1057
+ /***/ }),
1058
+
1059
+ /***/ "./src/fcmpx.js":
1060
+ /*!**********************!*\
1061
+ !*** ./src/fcmpx.js ***!
1062
+ \**********************/
1063
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1064
+
1065
+ const fcmp_default = __webpack_require__(/*! ./fcmp_default */ "./src/fcmp_default.js");
1066
+ const fcmp_default_desc = __webpack_require__(/*! ./fcmp_default_desc */ "./src/fcmp_default_desc.js");
1067
+ const identity = __webpack_require__(/*! ./identity */ "./src/identity.js");
1068
+
1069
+ const MISSING = Symbol('fcmpx.missing');
1070
+
1071
+ /**
1072
+ * Comparator builder using compact expressions.
1073
+ *
1074
+ * fcmp expression — Creates an `fcmp` function from an expression, suitable for use with `[].sort()`.
1075
+ *
1076
+ * fcmpx('user.email')
1077
+ * fcmpx('-user.age,user.email')
1078
+ * fcmpx(v => v.user.email)
1079
+ * fcmpx(['user.age', 'user.email'])
1080
+ * fcmpx(['-user.age', 'user.email'])
1081
+ */
1082
+ function fcmpx(expr)
1083
+ {
1084
+ if (typeof expr === 'string') {
1085
+ if (expr.includes(',')) {
1086
+ return fcmpx(expr.split(','));
1087
+ }
1088
+ return fcmpx_compile(expr);
1089
+ }
1090
+ if (!Array.isArray(expr)) {
1091
+ return fcmpx_compile(expr);
1092
+ }
1093
+ const fcmp_items = expr.map(fcmpx_parse);
1094
+ return function (a, b) {
1095
+ const tuple1 = fcmp_items.map(v => v.read(a));
1096
+ const tuple2 = fcmp_items.map(v => v.read(b));
1097
+ for (let i = 0; i < fcmp_items.length; ++i) {
1098
+ const tmp = fcmp_items[i].fcmp(tuple1[i], tuple2[i]);
1099
+ if (tmp) {
1100
+ return tmp;
1101
+ }
1102
+ }
1103
+ return 0;
1104
+ };
1105
+ }
1106
+
1107
+ function fcmpx_compile(expr)
744
1108
  {
745
- return String(a).localeCompare(b);
1109
+ const {read, fcmp} = fcmpx_parse(expr);
1110
+ return function (a, b) {
1111
+ return fcmp(read(a), read(b));
1112
+ };
746
1113
  }
747
1114
 
748
- module.exports = fcmp_strings;
1115
+ function fcmpx_parse(expr)
1116
+ {
1117
+ if (typeof expr === 'function') {
1118
+ return {read: fcmpx_compile_read(expr), fcmp: fcmp_wrapper(fcmp_default)};
1119
+ }
1120
+ if (typeof expr === 'string') {
1121
+ const desc = expr.startsWith('-');
1122
+ const read = desc ? fcmpx_compile_read(expr.slice(1)) : fcmpx_compile_read(expr);
1123
+ const fcmp = fcmp_wrapper(desc ? fcmp_default_desc : fcmp_default);
1124
+ return {read, fcmp};
1125
+ }
1126
+ const fcmp_user = expr.fcmp;
1127
+ const read = fcmpx_compile_read(expr.read);
1128
+ const desc = expr.desc ?? false;
1129
+ const fcmp = fcmp_wrapper(desc ? (fcmp_user ? (b, a) => fcmp_user(a, b) : fcmp_default_desc) : (fcmp_user ?? fcmp_default));
1130
+ if (Array.isArray(expr.top)) {
1131
+ const priority = new Map(expr.top.map((v, i) => [v, i]));
1132
+ return {read: v => priority.get(read(v)) ?? priority.size, fcmp};
1133
+ }
1134
+ if (Array.isArray(expr.bottom)) {
1135
+ const priority = new Map(expr.bottom.map((v, i) => [v, i]));
1136
+ return {read: v => priority.get(read(v)) ?? -1, fcmp};
1137
+ }
1138
+ return {read, fcmp};
1139
+ }
1140
+
1141
+ function fcmpx_compile_read(read)
1142
+ {
1143
+ if (read === undefined || read === '' || read === '.') {
1144
+ return identity;
1145
+ }
1146
+ if (typeof read === 'function') {
1147
+ return function (value) {
1148
+ return read(value) ?? MISSING;
1149
+ };
1150
+ }
1151
+ if (typeof read === 'string') {
1152
+ const props = read.split('.');
1153
+ const [a, b, c, d, e] = props;
1154
+ switch (props.length) {
1155
+ case 1: return v => v?.[a] ?? MISSING;
1156
+ case 2: return v => v?.[a]?.[b] ?? MISSING;
1157
+ case 3: return v => v?.[a]?.[b]?.[c] ?? MISSING;
1158
+ case 4: return v => v?.[a]?.[b]?.[c]?.[d] ?? MISSING;
1159
+ case 5: return v => v?.[a]?.[b]?.[c]?.[d]?.[e] ?? MISSING;
1160
+ default: return v => props.reduce((a,p) => a?.[p], v) ?? MISSING;
1161
+ }
1162
+ }
1163
+ return v => v?.[read] ?? MISSING;
1164
+ }
1165
+
1166
+ // Sorting rule: Missing values are considered greater than any defined value
1167
+ // and are therefore placed after all defined values.
1168
+ function fcmp_wrapper(fcmp)
1169
+ {
1170
+ return function (a, b) {
1171
+ if (a === MISSING) {
1172
+ if (b === MISSING) {
1173
+ return 0;
1174
+ }
1175
+ return 1;
1176
+ }
1177
+ if (b === MISSING) {
1178
+ return -1;
1179
+ }
1180
+ return fcmp(a, b);
1181
+ };
1182
+ }
1183
+
1184
+ module.exports = fcmpx;
749
1185
 
750
1186
 
751
1187
  /***/ }),
@@ -887,6 +1323,52 @@ function format_date(d)
887
1323
  module.exports = format_date;
888
1324
 
889
1325
 
1326
+ /***/ }),
1327
+
1328
+ /***/ "./src/format_date_fs.js":
1329
+ /*!*******************************!*\
1330
+ !*** ./src/format_date_fs.js ***!
1331
+ \*******************************/
1332
+ /***/ ((module) => {
1333
+
1334
+ function format_date_fs(d)
1335
+ {
1336
+ const ymd = d.getFullYear() + dd(d.getMonth() + 1) + dd(d.getDate());
1337
+ const hms = dd(d.getHours()) + dd(d.getMinutes()) + dd(d.getSeconds());
1338
+ return ymd + '_' + hms;
1339
+ }
1340
+
1341
+ function dd(v)
1342
+ {
1343
+ return v > 9 ? `${v}` : `0${v}`;
1344
+ }
1345
+
1346
+ module.exports = format_date_fs;
1347
+
1348
+
1349
+ /***/ }),
1350
+
1351
+ /***/ "./src/format_date_human.js":
1352
+ /*!**********************************!*\
1353
+ !*** ./src/format_date_human.js ***!
1354
+ \**********************************/
1355
+ /***/ ((module) => {
1356
+
1357
+ function format_date_human(d)
1358
+ {
1359
+ const ymd = d.getFullYear() + '/' + dd(d.getMonth() + 1) + '/' + dd(d.getDate());
1360
+ const hms = dd(d.getHours()) + ':' + dd(d.getMinutes()) + ':' + dd(d.getSeconds());
1361
+ return ymd + ' ' + hms;
1362
+ }
1363
+
1364
+ function dd(v)
1365
+ {
1366
+ return v > 9 ? `${v}` : `0${v}`;
1367
+ }
1368
+
1369
+ module.exports = format_date_human;
1370
+
1371
+
890
1372
  /***/ }),
891
1373
 
892
1374
  /***/ "./src/format_date_ymd.js":
@@ -1142,22 +1624,22 @@ module.exports = format_percents;
1142
1624
  const format_bytes = __webpack_require__(/*! ./format_bytes */ "./src/format_bytes.js");
1143
1625
  const format_percents = __webpack_require__(/*! ./format_percents */ "./src/format_percents.js");
1144
1626
  const format_seconds = __webpack_require__(/*! ./format_seconds */ "./src/format_seconds.js");
1145
- const is_number_gt = __webpack_require__(/*! ./is_number_gt */ "./src/is_number_gt.js");
1627
+ const is_num_gt = __webpack_require__(/*! @vbarbarosh/type-helpers/src/is_num_gt */ "./node_modules/@vbarbarosh/type-helpers/src/is_num_gt.js");
1146
1628
 
1147
1629
  function format_progress_bytes({percents, total, done, rate, eta, duration})
1148
1630
  {
1149
- const bps = is_number_gt(rate, 0) ? `${format_bytes(rate)}/s` : '~';
1631
+ const bps = is_num_gt(rate, 0) ? `${format_bytes(rate)}/s` : '~';
1150
1632
  if (done > total) {
1151
1633
  return `${format_bytes(done)} at ${bps} duration=${format_seconds(duration)}`;
1152
1634
  }
1153
- if (is_number_gt(total, 0)) {
1154
- const eta_str = is_number_gt(eta, 0) ? format_seconds(eta) : '~';
1635
+ if (is_num_gt(total, 0)) {
1636
+ const eta_str = is_num_gt(eta, 0) ? format_seconds(eta) : '~';
1155
1637
  return `${format_percents(percents)} | ${format_bytes(done)} of ${format_bytes(total)} at ${bps} ETA ${eta_str} duration=${format_seconds(duration)}`;
1156
1638
  }
1157
- if (is_number_gt(done, 0)) {
1639
+ if (is_num_gt(done, 0)) {
1158
1640
  return `${format_bytes(done)} of ~ at ${bps} duration=${format_seconds(duration)}`;
1159
1641
  }
1160
- if (is_number_gt(duration, 0)) {
1642
+ if (is_num_gt(duration, 0)) {
1161
1643
  return `~ duration=${format_seconds(duration)}`;
1162
1644
  }
1163
1645
  return '~';
@@ -1177,22 +1659,22 @@ module.exports = format_progress_bytes;
1177
1659
  const format_kilo = __webpack_require__(/*! ./format_kilo */ "./src/format_kilo.js");
1178
1660
  const format_percents = __webpack_require__(/*! ./format_percents */ "./src/format_percents.js");
1179
1661
  const format_seconds = __webpack_require__(/*! ./format_seconds */ "./src/format_seconds.js");
1180
- const is_number_gt = __webpack_require__(/*! ./is_number_gt */ "./src/is_number_gt.js");
1662
+ const is_num_gt = __webpack_require__(/*! @vbarbarosh/type-helpers/src/is_num_gt */ "./node_modules/@vbarbarosh/type-helpers/src/is_num_gt.js");
1181
1663
 
1182
1664
  function format_progress_kilo({percents, total, done, rate, eta, duration})
1183
1665
  {
1184
- const speed = is_number_gt(rate, 0) ? `${format_kilo(rate)}/s` : '~';
1666
+ const speed = is_num_gt(rate, 0) ? `${format_kilo(rate)}/s` : '~';
1185
1667
  if (done > total) {
1186
1668
  return `${format_kilo(done)} at ${speed} duration=${format_seconds(duration)}`;
1187
1669
  }
1188
- if (is_number_gt(total, 0)) {
1189
- const eta_str = is_number_gt(eta, 0) ? format_seconds(eta) : '~';
1670
+ if (is_num_gt(total, 0)) {
1671
+ const eta_str = is_num_gt(eta, 0) ? format_seconds(eta) : '~';
1190
1672
  return `${format_percents(percents)} | ${format_kilo(done)} of ${format_kilo(total)} at ${speed} ETA ${eta_str} duration=${format_seconds(duration)}`;
1191
1673
  }
1192
- if (is_number_gt(done, 0)) {
1674
+ if (is_num_gt(done, 0)) {
1193
1675
  return `${format_kilo(done)} of ~ at ${speed} duration=${format_seconds(duration)}`;
1194
1676
  }
1195
- if (is_number_gt(duration, 0)) {
1677
+ if (is_num_gt(duration, 0)) {
1196
1678
  return `~ duration=${format_seconds(duration)}`;
1197
1679
  }
1198
1680
  return '~';
@@ -1541,40 +2023,6 @@ function ignore()
1541
2023
  module.exports = ignore;
1542
2024
 
1543
2025
 
1544
- /***/ }),
1545
-
1546
- /***/ "./src/is_number.js":
1547
- /*!**************************!*\
1548
- !*** ./src/is_number.js ***!
1549
- \**************************/
1550
- /***/ ((module) => {
1551
-
1552
- function is_number(value)
1553
- {
1554
- return (typeof value === 'number') && isFinite(value);
1555
- }
1556
-
1557
- module.exports = is_number;
1558
-
1559
-
1560
- /***/ }),
1561
-
1562
- /***/ "./src/is_number_gt.js":
1563
- /*!*****************************!*\
1564
- !*** ./src/is_number_gt.js ***!
1565
- \*****************************/
1566
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1567
-
1568
- const is_number = __webpack_require__(/*! ./is_number */ "./src/is_number.js");
1569
-
1570
- function is_number_gt(value, min)
1571
- {
1572
- return is_number(value) && value > min;
1573
- }
1574
-
1575
- module.exports = is_number_gt;
1576
-
1577
-
1578
2026
  /***/ }),
1579
2027
 
1580
2028
  /***/ "./src/json_stringify_safe.js":
@@ -1596,9 +2044,15 @@ module.exports = json_stringify_safe;
1596
2044
  \***********************/
1597
2045
  /***/ ((module) => {
1598
2046
 
1599
- function plural(n, apple, apples)
2047
+ function plural(n, singular, plural, zero)
1600
2048
  {
1601
- return (n % 10 === 1 && n % 100 !== 11) ? apple.split('#').join(n) : apples.split('#').join(n);
2049
+ if (n === 0 && typeof zero === 'string') {
2050
+ return zero;
2051
+ }
2052
+ if (n % 10 === 1 && n % 100 !== 11) {
2053
+ return singular.split('#').join(n);
2054
+ }
2055
+ return plural.split('#').join(n);
1602
2056
  }
1603
2057
 
1604
2058
  module.exports = plural;
@@ -1767,13 +2221,21 @@ var __webpack_exports__ = {};
1767
2221
  /*!******************************!*\
1768
2222
  !*** ./src/browser/index.js ***!
1769
2223
  \******************************/
1770
- // https://github.com/webpack/webpack/issues/625
1771
- // https://webpack.js.org/guides/dependency-management/#require-context
1772
- const require_tmp = __webpack_require__("./src sync recursive \\b(array%7Cdate%7Chttp_delete%7Chttp_get_blob%7Chttp_get_buffer%7Chttp_get_json%7Chttp_get_utf8%7Chttp_head%7Chttp_patch_json%7Chttp_post_json%7Chttp_post_multipart%7Chttp_put_buffer%7Chttp_put_json%7Chttp_put_utf8%7Cidentity%7Cignore%7Cfcmp%7Cfilter%7Cformat%7Cplural%7Crandom_int%7Curlmod%7Cwaitcb)[^/]*(?<%21\\.test)\\.js$");
1773
- require_tmp.keys().forEach(function (key) {
1774
- const [, basename] = key.match(/([^/]+)\.js$/);
1775
- window[basename] = require_tmp(key);
1776
- });
2224
+ const ns = new URL(document.currentScript.src).searchParams.get('var') ?? 'h';
2225
+ if (typeof window[ns] !== 'undefined') {
2226
+ console.log(`❌ @vbarbarosh/node-helpers@${"3.68.0"} was not injected — window.${ns} is already in use`);
2227
+ }
2228
+ else {
2229
+ console.log(`🎉 @vbarbarosh/node-helpers@${"3.68.0"} successfully exposed as window.${ns}`);
2230
+ window[ns] = {};
2231
+ // https://github.com/webpack/webpack/issues/625
2232
+ // https://webpack.js.org/guides/dependency-management/#require-context
2233
+ const require_tmp = __webpack_require__("./src sync recursive \\b(array%7Cdate%7Chttp_delete%7Chttp_get_blob%7Chttp_get_buffer%7Chttp_get_json%7Chttp_get_utf8%7Chttp_head%7Chttp_patch_json%7Chttp_post_json%7Chttp_post_multipart%7Chttp_put_buffer%7Chttp_put_json%7Chttp_put_utf8%7Cidentity%7Cignore%7Cfcmp%7Cfilter%7Cformat%7Cplural%7Crandom_int%7Curlmod%7Cwaitcb)[^/]*(?<%21\\.test)\\.js$");
2234
+ require_tmp.keys().forEach(function (key) {
2235
+ const [, basename] = key.match(/([^/]+)\.js$/);
2236
+ window[ns][basename] = require_tmp(key);
2237
+ });
2238
+ }
1777
2239
 
1778
2240
  })();
1779
2241