@vbarbarosh/node-helpers 3.63.0 → 3.63.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.
package/README.md CHANGED
@@ -1,6 +1,5 @@
1
1
  A set of helpers for JavaScript/Node.js
2
2
 
3
-
4
3
  <p align="center">
5
4
  <a href="https://github.com/vbarbarosh/node-helpers/actions"><img src="https://github.com/vbarbarosh/node-helpers/actions/workflows/node.js.yml/badge.svg" alt="@vbarbarosh/node-helpers CI status" /></a>
6
5
  <a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/vbarbarosh/node-helpers" alt="License" /></a>
@@ -24,7 +23,7 @@ A subset of `@vbarbarosh/node-helpers` is available for browser:
24
23
  <script src="https://unpkg.com/@vbarbarosh/node-helpers@latest/dist/browser.js"></script>
25
24
  ```
26
25
 
27
- ⚠️ All supported functions are exposed globally.
26
+ ⚠️ All browser functions are exposed globally.
28
27
 
29
28
  ## Test
30
29
 
package/dist/browser.js CHANGED
@@ -1,10 +1,47 @@
1
1
  /******/ (() => { // webpackBootstrap
2
2
  /******/ var __webpack_modules__ = ({
3
3
 
4
- /***/ "./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).*(?<%21\\.test)\\.js$":
5
- /*!***********************************************************************************************************************************************************************************************************************************************************************************!*\
6
- !*** ./src/ sync \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).*(?<%21\.test)\.js$ ***!
7
- \***********************************************************************************************************************************************************************************************************************************************************************************/
4
+ /***/ "./node_modules/json-stringify-safe/stringify.js":
5
+ /*!*******************************************************!*\
6
+ !*** ./node_modules/json-stringify-safe/stringify.js ***!
7
+ \*******************************************************/
8
+ /***/ ((module, exports) => {
9
+
10
+ exports = module.exports = stringify
11
+ exports.getSerialize = serializer
12
+
13
+ function stringify(obj, replacer, spaces, cycleReplacer) {
14
+ return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces)
15
+ }
16
+
17
+ function serializer(replacer, cycleReplacer) {
18
+ var stack = [], keys = []
19
+
20
+ if (cycleReplacer == null) cycleReplacer = function(key, value) {
21
+ if (stack[0] === value) return "[Circular ~]"
22
+ return "[Circular ~." + keys.slice(0, stack.indexOf(value)).join(".") + "]"
23
+ }
24
+
25
+ return function(key, value) {
26
+ if (stack.length > 0) {
27
+ var thisPos = stack.indexOf(this)
28
+ ~thisPos ? stack.splice(thisPos + 1) : stack.push(this)
29
+ ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key)
30
+ if (~stack.indexOf(value)) value = cycleReplacer.call(this, key, value)
31
+ }
32
+ else stack.push(value)
33
+
34
+ return replacer == null ? value : replacer.call(this, key, value)
35
+ }
36
+ }
37
+
38
+
39
+ /***/ }),
40
+
41
+ /***/ "./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$":
42
+ /*!*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
43
+ !*** ./src/ sync \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$ ***!
44
+ \*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
8
45
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
9
46
 
10
47
  var map = {
@@ -24,6 +61,25 @@ var map = {
24
61
  "./array_unique_last.js": "./src/array_unique_last.js",
25
62
  "./date_add_months.js": "./src/date_add_months.js",
26
63
  "./date_is_leap_year.js": "./src/date_is_leap_year.js",
64
+ "./fcmp_dates.js": "./src/fcmp_dates.js",
65
+ "./fcmp_from_spec.js": "./src/fcmp_from_spec.js",
66
+ "./fcmp_numbers.js": "./src/fcmp_numbers.js",
67
+ "./fcmp_strings.js": "./src/fcmp_strings.js",
68
+ "./filter1_from_spec.js": "./src/filter1_from_spec.js",
69
+ "./format_bytes.js": "./src/format_bytes.js",
70
+ "./format_date.js": "./src/format_date.js",
71
+ "./format_date_ymd.js": "./src/format_date_ymd.js",
72
+ "./format_error_report.js": "./src/format_error_report.js",
73
+ "./format_hrtime.js": "./src/format_hrtime.js",
74
+ "./format_kilo.js": "./src/format_kilo.js",
75
+ "./format_ms.js": "./src/format_ms.js",
76
+ "./format_ms2.js": "./src/format_ms2.js",
77
+ "./format_ms3.js": "./src/format_ms3.js",
78
+ "./format_percents.js": "./src/format_percents.js",
79
+ "./format_progress_bytes.js": "./src/format_progress_bytes.js",
80
+ "./format_progress_kilo.js": "./src/format_progress_kilo.js",
81
+ "./format_seconds.js": "./src/format_seconds.js",
82
+ "./format_thousands.js": "./src/format_thousands.js",
27
83
  "./http_delete.js": "./src/http_delete.js",
28
84
  "./http_get_blob.js": "./src/http_get_blob.js",
29
85
  "./http_get_buffer.js": "./src/http_get_buffer.js",
@@ -37,7 +93,11 @@ var map = {
37
93
  "./http_put_json.js": "./src/http_put_json.js",
38
94
  "./http_put_utf8.js": "./src/http_put_utf8.js",
39
95
  "./identity.js": "./src/identity.js",
40
- "./ignore.js": "./src/ignore.js"
96
+ "./ignore.js": "./src/ignore.js",
97
+ "./plural.js": "./src/plural.js",
98
+ "./random_int.js": "./src/random_int.js",
99
+ "./urlmod.js": "./src/urlmod.js",
100
+ "./waitcb.js": "./src/waitcb.js"
41
101
  };
42
102
 
43
103
 
@@ -58,7 +118,7 @@ webpackContext.keys = function webpackContextKeys() {
58
118
  };
59
119
  webpackContext.resolve = webpackContextResolve;
60
120
  module.exports = webpackContext;
61
- webpackContext.id = "./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).*(?<%21\\.test)\\.js$";
121
+ webpackContext.id = "./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$";
62
122
 
63
123
  /***/ }),
64
124
 
@@ -555,6 +615,123 @@ function date_is_leap_year(d)
555
615
  module.exports = date_is_leap_year;
556
616
 
557
617
 
618
+ /***/ }),
619
+
620
+ /***/ "./src/factorize_ms.js":
621
+ /*!*****************************!*\
622
+ !*** ./src/factorize_ms.js ***!
623
+ \*****************************/
624
+ /***/ ((module) => {
625
+
626
+ function factorize_ms(v)
627
+ {
628
+ const h = Math.floor(v / 3600000);
629
+ const m = Math.floor(v % 3600000 / 60000);
630
+ const s = Math.floor(v % 60000 / 1000);
631
+ const ms = v % 1000;
632
+ return [h, m, s, ms];
633
+ }
634
+
635
+ module.exports = factorize_ms;
636
+
637
+
638
+ /***/ }),
639
+
640
+ /***/ "./src/fcmp_dates.js":
641
+ /*!***************************!*\
642
+ !*** ./src/fcmp_dates.js ***!
643
+ \***************************/
644
+ /***/ ((module) => {
645
+
646
+ function fcmp_dates(a, b)
647
+ {
648
+ return a.getTime() - b.getTime();
649
+ }
650
+
651
+ module.exports = fcmp_dates;
652
+
653
+
654
+ /***/ }),
655
+
656
+ /***/ "./src/fcmp_from_spec.js":
657
+ /*!*******************************!*\
658
+ !*** ./src/fcmp_from_spec.js ***!
659
+ \*******************************/
660
+ /***/ ((module) => {
661
+
662
+ /**
663
+ * Create fcmp from an array of props. For desc order a prop should be prefixed
664
+ * with minus sign (e.g. -price).
665
+ */
666
+ function fcmp_from_spec(props)
667
+ {
668
+ const fcmp = props.map(one);
669
+ switch (fcmp.length) {
670
+ case 0:
671
+ return () => 0;
672
+ case 1:
673
+ return fcmp[0];
674
+ case 2:
675
+ return function (a, b) {
676
+ return fcmp[0](a, b) || fcmp[1](a, b);
677
+ };
678
+ case 3:
679
+ return function (a, b) {
680
+ return fcmp[0](a, b) || fcmp[1](a, b) || fcmp[2](a, b);
681
+ };
682
+ default:
683
+ return function (a, b) {
684
+ for (let i = 0; i < fcmp.length; ++i) {
685
+ const tmp = fcmp[i](a, b);
686
+ if (tmp) {
687
+ return tmp;
688
+ }
689
+ }
690
+ return 0;
691
+ };
692
+ }
693
+ }
694
+
695
+ function one(prop)
696
+ {
697
+ if (prop[0] === '-') {
698
+ prop = prop.slice(1);
699
+ return function (b, a) {
700
+ return comp_types(a[prop], b[prop]);
701
+ };
702
+ }
703
+ return function (a, b) {
704
+ return comp_types(a[prop], b[prop]);
705
+ };
706
+ }
707
+
708
+ function comp_types(a, b)
709
+ {
710
+ if (typeof a === 'string' && typeof b === 'string') {
711
+ return a.localeCompare(b);
712
+ }
713
+ return a - b;
714
+ }
715
+
716
+ module.exports = fcmp_from_spec;
717
+
718
+
719
+ /***/ }),
720
+
721
+ /***/ "./src/fcmp_numbers.js":
722
+ /*!*****************************!*\
723
+ !*** ./src/fcmp_numbers.js ***!
724
+ \*****************************/
725
+ /***/ ((module) => {
726
+
727
+ function fcmp_numbers(a, b)
728
+ {
729
+ return Number(a) - b;
730
+ }
731
+
732
+ module.exports = fcmp_numbers;
733
+
734
+
558
735
  /***/ }),
559
736
 
560
737
  /***/ "./src/fcmp_strings.js":
@@ -571,6 +748,497 @@ function fcmp_strings(a, b)
571
748
  module.exports = fcmp_strings;
572
749
 
573
750
 
751
+ /***/ }),
752
+
753
+ /***/ "./src/filter1_from_spec.js":
754
+ /*!**********************************!*\
755
+ !*** ./src/filter1_from_spec.js ***!
756
+ \**********************************/
757
+ /***/ ((module) => {
758
+
759
+ /**
760
+ * Creates a filtering function based on the following spec:
761
+ * 1. Substrings are separated by `/`.
762
+ * 2. Each substring may have special characters:
763
+ * - `^`: Substring must appear at the beginning.
764
+ * - `$`: Substring must appear at the end.
765
+ * - `!`: Negates the condition (substring must not appear).
766
+ */
767
+ function filter1_from_spec(spec)
768
+ {
769
+ let a, b, c, d;
770
+ const parts = parse_spec(spec);
771
+ switch (parts.length) {
772
+ case 0:
773
+ // No filters, always true
774
+ return () => true;
775
+ case 1:
776
+ return parts[0];
777
+ case 2:
778
+ [a, b] = parts;
779
+ return s => a(s) && b(s);
780
+ case 3:
781
+ [a, b, c] = parts;
782
+ return s => a(s) && b(s) && c(s);
783
+ case 4:
784
+ [a, b, c, d] = parts;
785
+ return s => a(s) && b(s) && c(s) && d(s);
786
+ default:
787
+ return s => parts.every(fn => fn(s));
788
+ }
789
+ }
790
+
791
+ function parse_spec(spec)
792
+ {
793
+ return spec.split('/').filter(v => v).map(parse_expr);
794
+ }
795
+
796
+ // convert expr into an array of objects {substr, starts, ends}
797
+ function parse_expr(expr)
798
+ {
799
+ let substr;
800
+ let starts = false; // ^
801
+ let ends = false; // $
802
+ substr = expr.replaceAll('^', '');
803
+ starts = (substr.length !== expr.length);
804
+ expr = substr;
805
+ substr = expr.replaceAll('$', '');
806
+ ends = (substr.length !== expr.length);
807
+ expr = substr;
808
+ substr = expr.replaceAll('!', '');
809
+ if ((expr.length - substr.length) % 2) { // not
810
+ if (starts && ends) {
811
+ return s => !s.startsWith(substr) && !s.endsWith(substr);
812
+ }
813
+ if (starts) {
814
+ return s => !s.startsWith(substr);
815
+ }
816
+ if (ends) {
817
+ return s => !s.endsWith(substr);
818
+ }
819
+ return s => !s.includes(substr);
820
+ }
821
+ if (starts && ends) {
822
+ return s => s.startsWith(substr) && s.endsWith(substr);
823
+ }
824
+ if (starts) {
825
+ return s => s.startsWith(substr);
826
+ }
827
+ if (ends) {
828
+ return s => s.endsWith(substr);
829
+ }
830
+ return s => s.includes(substr);
831
+ }
832
+
833
+ module.exports = filter1_from_spec;
834
+
835
+
836
+ /***/ }),
837
+
838
+ /***/ "./src/format_bytes.js":
839
+ /*!*****************************!*\
840
+ !*** ./src/format_bytes.js ***!
841
+ \*****************************/
842
+ /***/ ((module) => {
843
+
844
+ /**
845
+ * @link https://stackoverflow.com/a/18650828
846
+ */
847
+ function format_bytes(bytes)
848
+ {
849
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
850
+ if (typeof bytes !== 'number' || Number.isNaN(bytes)) {
851
+ return 'n/a';
852
+ }
853
+ if (!bytes) {
854
+ return '0KB';
855
+ }
856
+ if (bytes < 1024) {
857
+ return '1KB';
858
+ }
859
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
860
+ return `${(bytes / (1024 ** i)).toFixed(bytes > 1024*1024 ? 2 : 0)}${sizes[i]}`.replace(/\.00/, '.0');
861
+ }
862
+
863
+ module.exports = format_bytes;
864
+
865
+ // https://wiki.ubuntu.com/UnitsPolicy
866
+ // > Applications must use SI standard for base-10 units:
867
+ // >
868
+ // > 1 kB = 1,000 bytes (Note: small k)
869
+ // > 1 MB = 1,000 kB = 1,000,000 bytes
870
+ // > 1 GB = 1,000 MB = 1,000,000 kB = 1,000,000,000 bytes
871
+ // > 1 TB = 1,000 GB = 1,000,000 MB = 1,000,000,000 kB = 1,000,000,000,000 bytes
872
+
873
+
874
+ /***/ }),
875
+
876
+ /***/ "./src/format_date.js":
877
+ /*!****************************!*\
878
+ !*** ./src/format_date.js ***!
879
+ \****************************/
880
+ /***/ ((module) => {
881
+
882
+ function format_date(d)
883
+ {
884
+ return d.getFullYear() + `/0${d.getMonth()+1}/0${d.getDate()} 0${d.getHours()}:0${d.getMinutes()}:0${d.getSeconds()}`.replace(/0(\d\d)/g, '$1');
885
+ }
886
+
887
+ module.exports = format_date;
888
+
889
+
890
+ /***/ }),
891
+
892
+ /***/ "./src/format_date_ymd.js":
893
+ /*!********************************!*\
894
+ !*** ./src/format_date_ymd.js ***!
895
+ \********************************/
896
+ /***/ ((module) => {
897
+
898
+ function format_date_ymd(d)
899
+ {
900
+ return d.getFullYear() + `/0${d.getMonth()+1}/0${d.getDate()}`.replace(/0(\d\d)/g, '$1');
901
+ }
902
+
903
+ module.exports = format_date_ymd;
904
+
905
+
906
+ /***/ }),
907
+
908
+ /***/ "./src/format_error_report.js":
909
+ /*!************************************!*\
910
+ !*** ./src/format_error_report.js ***!
911
+ \************************************/
912
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
913
+
914
+ const json_stringify_safe = __webpack_require__(/*! ./json_stringify_safe */ "./src/json_stringify_safe.js");
915
+
916
+ function format_error_report(error)
917
+ {
918
+ if (!error) {
919
+ return json_stringify_safe({error: error === undefined ? '---undefined---' : error});
920
+ }
921
+
922
+ if (error.response?.status && error.response?.statusText && error.response?.config) {
923
+ return fm_axios_response(error);
924
+ }
925
+
926
+ if (error.config) {
927
+ return fm_axios_config(error);
928
+ }
929
+
930
+ return json_stringify_safe({
931
+ code: error.code,
932
+ name: error.name,
933
+ message: error.message ?? 'n/a',
934
+ stack: error.stack && error.stack.split(/\n\s*/)
935
+ }, null, 4);
936
+ }
937
+
938
+ function fm_axios_response(error)
939
+ {
940
+ return `
941
+ ${error.message ?? 'n/a'}
942
+
943
+ --- REQUEST ---
944
+
945
+ ${(error.response.config.method||'').toUpperCase()} ${error.response.config.url}
946
+
947
+ ${JSON.stringify(error.response.config.headers||{}, null, 4).slice(1, -1).replace(/^\s+|,$/mg, '').trim()}
948
+
949
+ --- RESPONSE ---
950
+
951
+ ${error.response.status} ${error.response.statusText}
952
+
953
+ ${(error.response.data.toString()||'').slice(0, 10240) || 'n/a'}
954
+
955
+ --- STACK ---
956
+
957
+ ${error.stack ? error.stack.split(/\\n\\s*/) : 'n/a'}
958
+ `.trimStart();
959
+ }
960
+
961
+ function fm_axios_config(error)
962
+ {
963
+ return `
964
+ ${error.message ?? 'n/a'}
965
+
966
+ --- REQUEST ---
967
+
968
+ ${(error.config.method||'').toUpperCase()} ${error.config.url}
969
+
970
+ ${JSON.stringify(error.config.headers||{}, null, 4).slice(1, -1).replace(/^\s+|,$/mg, '').trim()}
971
+
972
+ --- STACK ---
973
+
974
+ ${error.stack ? error.stack.split(/\\n\\s*/) : 'n/a'}
975
+ `.trimStart();
976
+ }
977
+
978
+ module.exports = format_error_report;
979
+
980
+
981
+ /***/ }),
982
+
983
+ /***/ "./src/format_hrtime.js":
984
+ /*!******************************!*\
985
+ !*** ./src/format_hrtime.js ***!
986
+ \******************************/
987
+ /***/ ((module) => {
988
+
989
+ /**
990
+ * Return a human-readable representation of hrtime (the return value from `process.hrtime(hrtime0)`).
991
+ */
992
+ function format_hrtime(hrtime, digits = 6)
993
+ {
994
+ const [u, v] = hrtime; // process.hrtime(hrtime0)
995
+ return (u + v/1E9).toFixed(digits) + 's';
996
+ }
997
+
998
+ module.exports = format_hrtime;
999
+
1000
+
1001
+ /***/ }),
1002
+
1003
+ /***/ "./src/format_kilo.js":
1004
+ /*!****************************!*\
1005
+ !*** ./src/format_kilo.js ***!
1006
+ \****************************/
1007
+ /***/ ((module) => {
1008
+
1009
+ function format_kilo(num)
1010
+ {
1011
+ const sizes = ['', 'K', 'M', 'G', 'T', 'P'];
1012
+ if (typeof num !== 'number' || Number.isNaN(num)) {
1013
+ return 'n/a';
1014
+ }
1015
+ if (!num) {
1016
+ return '0';
1017
+ }
1018
+ if (num < 1000) {
1019
+ return num.toFixed(0);
1020
+ }
1021
+ const i = parseInt(Math.floor(Math.log(num) / Math.log(1000)), 10);
1022
+ return `${(num / (1000 ** i)).toFixed(2)}${sizes[i]}`;
1023
+ }
1024
+
1025
+ module.exports = format_kilo;
1026
+
1027
+
1028
+ /***/ }),
1029
+
1030
+ /***/ "./src/format_ms.js":
1031
+ /*!**************************!*\
1032
+ !*** ./src/format_ms.js ***!
1033
+ \**************************/
1034
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1035
+
1036
+ const factorize_ms = __webpack_require__(/*! ./factorize_ms */ "./src/factorize_ms.js");
1037
+
1038
+ /**
1039
+ * Format milliseconds
1040
+ */
1041
+ function format_ms(ms)
1042
+ {
1043
+ if (!ms) {
1044
+ ms = 0;
1045
+ }
1046
+
1047
+ // 00:05
1048
+ const [h, m, s] = factorize_ms(ms);
1049
+ if (h) {
1050
+ return `0${h}:0${m}:0${s}`.replace(/0+(?=\d\d)/g, '');
1051
+ }
1052
+ return `0${m}:0${s}`.replace(/0+(?=\d\d)/g, '');
1053
+ }
1054
+
1055
+ module.exports = format_ms;
1056
+
1057
+
1058
+ /***/ }),
1059
+
1060
+ /***/ "./src/format_ms2.js":
1061
+ /*!***************************!*\
1062
+ !*** ./src/format_ms2.js ***!
1063
+ \***************************/
1064
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1065
+
1066
+ const factorize_ms = __webpack_require__(/*! ./factorize_ms */ "./src/factorize_ms.js");
1067
+
1068
+ /**
1069
+ * Format milliseconds
1070
+ */
1071
+ function format_ms2(ms)
1072
+ {
1073
+ if (!ms) {
1074
+ ms = 0;
1075
+ }
1076
+
1077
+ // 00:05.45
1078
+ const [h, m, s, xx] = factorize_ms(ms);
1079
+ if (h) {
1080
+ return `0${h}:0${m}:0${s}.0${Math.round(xx/10)}`.replace(/0+(?=\d\d)/g, '');
1081
+ }
1082
+ return `0${m}:0${s}.0${Math.round(xx/10)}`.replace(/0+(?=\d\d)/g, '');
1083
+ }
1084
+
1085
+ module.exports = format_ms2;
1086
+
1087
+
1088
+ /***/ }),
1089
+
1090
+ /***/ "./src/format_ms3.js":
1091
+ /*!***************************!*\
1092
+ !*** ./src/format_ms3.js ***!
1093
+ \***************************/
1094
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1095
+
1096
+ const factorize_ms = __webpack_require__(/*! ./factorize_ms */ "./src/factorize_ms.js");
1097
+
1098
+ /**
1099
+ * Format milliseconds
1100
+ */
1101
+ function format_ms3(ms)
1102
+ {
1103
+ if (!ms) {
1104
+ ms = 0;
1105
+ }
1106
+
1107
+ // 00:05.445
1108
+ const [h, m, s, xx] = factorize_ms(ms);
1109
+ if (h) {
1110
+ return `0${h}:0${m}:0${s}.00${xx}`.replace(/0+(?=\d\d+[:.]|\d\d\d)/g, '');
1111
+ }
1112
+ return `0${m}:0${s}.00${xx}`.replace(/0+(?=\d\d+[:.]|\d\d\d)/g, '')
1113
+ }
1114
+
1115
+ module.exports = format_ms3;
1116
+
1117
+
1118
+ /***/ }),
1119
+
1120
+ /***/ "./src/format_percents.js":
1121
+ /*!********************************!*\
1122
+ !*** ./src/format_percents.js ***!
1123
+ \********************************/
1124
+ /***/ ((module) => {
1125
+
1126
+ function format_percents(v)
1127
+ {
1128
+ return (v*100).toFixed(2).replace(/^(0|100).00$/, '$1') + '%';
1129
+ }
1130
+
1131
+ module.exports = format_percents;
1132
+
1133
+
1134
+ /***/ }),
1135
+
1136
+ /***/ "./src/format_progress_bytes.js":
1137
+ /*!**************************************!*\
1138
+ !*** ./src/format_progress_bytes.js ***!
1139
+ \**************************************/
1140
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1141
+
1142
+ const format_bytes = __webpack_require__(/*! ./format_bytes */ "./src/format_bytes.js");
1143
+ const format_percents = __webpack_require__(/*! ./format_percents */ "./src/format_percents.js");
1144
+ 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");
1146
+
1147
+ function format_progress_bytes({percents, total, done, rate, eta, duration})
1148
+ {
1149
+ const bps = is_number_gt(rate, 0) ? `${format_bytes(rate)}/s` : '~';
1150
+ if (done > total) {
1151
+ return `${format_bytes(done)} at ${bps} duration=${format_seconds(duration)}`;
1152
+ }
1153
+ if (is_number_gt(total, 0)) {
1154
+ const eta_str = is_number_gt(eta, 0) ? format_seconds(eta) : '~';
1155
+ return `${format_percents(percents)} | ${format_bytes(done)} of ${format_bytes(total)} at ${bps} ETA ${eta_str} duration=${format_seconds(duration)}`;
1156
+ }
1157
+ if (is_number_gt(done, 0)) {
1158
+ return `${format_bytes(done)} of ~ at ${bps} duration=${format_seconds(duration)}`;
1159
+ }
1160
+ if (is_number_gt(duration, 0)) {
1161
+ return `~ duration=${format_seconds(duration)}`;
1162
+ }
1163
+ return '~';
1164
+ }
1165
+
1166
+ module.exports = format_progress_bytes;
1167
+
1168
+
1169
+ /***/ }),
1170
+
1171
+ /***/ "./src/format_progress_kilo.js":
1172
+ /*!*************************************!*\
1173
+ !*** ./src/format_progress_kilo.js ***!
1174
+ \*************************************/
1175
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1176
+
1177
+ const format_kilo = __webpack_require__(/*! ./format_kilo */ "./src/format_kilo.js");
1178
+ const format_percents = __webpack_require__(/*! ./format_percents */ "./src/format_percents.js");
1179
+ 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");
1181
+
1182
+ function format_progress_kilo({percents, total, done, rate, eta, duration})
1183
+ {
1184
+ const speed = is_number_gt(rate, 0) ? `${format_kilo(rate)}/s` : '~';
1185
+ if (done > total) {
1186
+ return `${format_kilo(done)} at ${speed} duration=${format_seconds(duration)}`;
1187
+ }
1188
+ if (is_number_gt(total, 0)) {
1189
+ const eta_str = is_number_gt(eta, 0) ? format_seconds(eta) : '~';
1190
+ return `${format_percents(percents)} | ${format_kilo(done)} of ${format_kilo(total)} at ${speed} ETA ${eta_str} duration=${format_seconds(duration)}`;
1191
+ }
1192
+ if (is_number_gt(done, 0)) {
1193
+ return `${format_kilo(done)} of ~ at ${speed} duration=${format_seconds(duration)}`;
1194
+ }
1195
+ if (is_number_gt(duration, 0)) {
1196
+ return `~ duration=${format_seconds(duration)}`;
1197
+ }
1198
+ return '~';
1199
+ }
1200
+
1201
+ module.exports = format_progress_kilo;
1202
+
1203
+
1204
+ /***/ }),
1205
+
1206
+ /***/ "./src/format_seconds.js":
1207
+ /*!*******************************!*\
1208
+ !*** ./src/format_seconds.js ***!
1209
+ \*******************************/
1210
+ /***/ ((module) => {
1211
+
1212
+ function format_seconds(seconds)
1213
+ {
1214
+ const v = Math.abs(Math.trunc(seconds));
1215
+ const hh = Math.floor(v / 60 / 60);
1216
+ const mm = Math.floor(v / 60) % 60;
1217
+ const ss = v % 60;
1218
+ const tmp = `0${hh}:0${mm}:0${ss}`.replace(/0(\d\d)/g, '$1');
1219
+ return (seconds <= -1) ? ('-' + tmp) : tmp;
1220
+ }
1221
+
1222
+ module.exports = format_seconds;
1223
+
1224
+
1225
+ /***/ }),
1226
+
1227
+ /***/ "./src/format_thousands.js":
1228
+ /*!*********************************!*\
1229
+ !*** ./src/format_thousands.js ***!
1230
+ \*********************************/
1231
+ /***/ ((module) => {
1232
+
1233
+ // https://stackoverflow.com/a/2901298
1234
+ function format_thousands(x)
1235
+ {
1236
+ return x.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ',');
1237
+ }
1238
+
1239
+ module.exports = format_thousands;
1240
+
1241
+
574
1242
  /***/ }),
575
1243
 
576
1244
  /***/ "./src/http_delete.js":
@@ -873,6 +1541,158 @@ function ignore()
873
1541
  module.exports = ignore;
874
1542
 
875
1543
 
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
+ /***/ }),
1579
+
1580
+ /***/ "./src/json_stringify_safe.js":
1581
+ /*!************************************!*\
1582
+ !*** ./src/json_stringify_safe.js ***!
1583
+ \************************************/
1584
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1585
+
1586
+ const json_stringify_safe = __webpack_require__(/*! json-stringify-safe */ "./node_modules/json-stringify-safe/stringify.js");
1587
+
1588
+ module.exports = json_stringify_safe;
1589
+
1590
+
1591
+ /***/ }),
1592
+
1593
+ /***/ "./src/plural.js":
1594
+ /*!***********************!*\
1595
+ !*** ./src/plural.js ***!
1596
+ \***********************/
1597
+ /***/ ((module) => {
1598
+
1599
+ function plural(n, apple, apples)
1600
+ {
1601
+ return (n % 10 === 1 && n % 100 !== 11) ? apple.split('#').join(n) : apples.split('#').join(n);
1602
+ }
1603
+
1604
+ module.exports = plural;
1605
+
1606
+
1607
+ /***/ }),
1608
+
1609
+ /***/ "./src/random_int.js":
1610
+ /*!***************************!*\
1611
+ !*** ./src/random_int.js ***!
1612
+ \***************************/
1613
+ /***/ ((module) => {
1614
+
1615
+ function random_int(min, max)
1616
+ {
1617
+ return Math.floor(Math.random()*(max - min + 1) + min);
1618
+ }
1619
+
1620
+ module.exports = random_int;
1621
+
1622
+
1623
+ /***/ }),
1624
+
1625
+ /***/ "./src/urlmod.js":
1626
+ /*!***********************!*\
1627
+ !*** ./src/urlmod.js ***!
1628
+ \***********************/
1629
+ /***/ ((module) => {
1630
+
1631
+ /**
1632
+ * Set, change, or remove query string parameters.
1633
+ *
1634
+ * urlmod('', {a: 1}) '?a=1' set
1635
+ * urlmod('?a=1', {a: 2}) '?a=2' change
1636
+ * urlmod('?a=1', {a: null}) '' remove
1637
+ */
1638
+ function urlmod(url, params)
1639
+ {
1640
+ const tmp_url = new URL(url||'', 'xxx://___base___/');
1641
+ const tmp_search = tmp_url.searchParams;
1642
+ Object.entries(params || {}).forEach(function ([key, value]) {
1643
+ switch (value) {
1644
+ case null:
1645
+ case undefined:
1646
+ tmp_search.delete(key);
1647
+ break;
1648
+ case true:
1649
+ tmp_search.set(key, 1);
1650
+ break;
1651
+ case false:
1652
+ tmp_search.set(key, 0);
1653
+ break;
1654
+ default:
1655
+ tmp_search.set(key, value);
1656
+ break;
1657
+ }
1658
+ });
1659
+ if (url && url[0] === '/') {
1660
+ return tmp_url.toString().replace(/^xxx:\/\/___base___/, '');
1661
+ }
1662
+ return tmp_url.toString().replace(/^xxx:\/\/___base___\//, '');
1663
+ }
1664
+
1665
+ module.exports = urlmod;
1666
+
1667
+
1668
+ /***/ }),
1669
+
1670
+ /***/ "./src/waitcb.js":
1671
+ /*!***********************!*\
1672
+ !*** ./src/waitcb.js ***!
1673
+ \***********************/
1674
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1675
+
1676
+ const Promise = __webpack_require__(/*! bluebird */ "bluebird");
1677
+
1678
+ /**
1679
+ * Wait for a Node-like function to finish (which will call `callback`
1680
+ * with 2 arguments: `error` and `value`).
1681
+ *
1682
+ * await waitcb(cb => fs.writeFile('a', 'hello\n', cb));
1683
+ */
1684
+ function waitcb(fn)
1685
+ {
1686
+ return new Promise(function (resolve, reject) {
1687
+ fn(function (error, out) {
1688
+ error ? reject(error) : resolve(out);
1689
+ });
1690
+ });
1691
+ }
1692
+
1693
+ module.exports = waitcb;
1694
+
1695
+
876
1696
  /***/ }),
877
1697
 
878
1698
  /***/ "axios":
@@ -886,6 +1706,17 @@ module.exports = axios;
886
1706
 
887
1707
  /***/ }),
888
1708
 
1709
+ /***/ "bluebird":
1710
+ /*!**************************!*\
1711
+ !*** external "Promise" ***!
1712
+ \**************************/
1713
+ /***/ ((module) => {
1714
+
1715
+ "use strict";
1716
+ module.exports = Promise;
1717
+
1718
+ /***/ }),
1719
+
889
1720
  /***/ "form-data":
890
1721
  /*!***************************!*\
891
1722
  !*** external "FormData" ***!
@@ -930,6 +1761,7 @@ module.exports = FormData;
930
1761
  /******/ })();
931
1762
  /******/
932
1763
  /************************************************************************/
1764
+ var __webpack_exports__ = {};
933
1765
  // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
934
1766
  (() => {
935
1767
  /*!******************************!*\
@@ -937,7 +1769,7 @@ module.exports = FormData;
937
1769
  \******************************/
938
1770
  // https://github.com/webpack/webpack/issues/625
939
1771
  // https://webpack.js.org/guides/dependency-management/#require-context
940
- 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).*(?<%21\\.test)\\.js$");
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$");
941
1773
  require_tmp.keys().forEach(function (key) {
942
1774
  const [, basename] = key.match(/([^/]+)\.js$/);
943
1775
  window[basename] = require_tmp(key);
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "author": "Vladimir Barbarosh <vladimir.barbarosh@gmail.com>",
3
3
  "license": "MIT",
4
4
  "name": "@vbarbarosh/node-helpers",
5
- "version": "3.63.0",
5
+ "version": "3.63.2",
6
6
  "description": "A set of helpers for JavaScript/Node.js",
7
7
  "unpkg": "dist/browser.js",
8
8
  "jsdelivr": "dist/browser.js",
@@ -1,6 +1,6 @@
1
1
  // https://github.com/webpack/webpack/issues/625
2
2
  // https://webpack.js.org/guides/dependency-management/#require-context
3
- const require_tmp = require.context('..', true, /\b(array|date|http_delete|http_get_blob|http_get_buffer|http_get_json|http_get_utf8|http_head|http_patch_json|http_post_json|http_post_multipart|http_put_buffer|http_put_json|http_put_utf8|identity|ignore).*(?<!\.test)\.js$/);
3
+ const require_tmp = require.context('..', true, /\b(array|date|http_delete|http_get_blob|http_get_buffer|http_get_json|http_get_utf8|http_head|http_patch_json|http_post_json|http_post_multipart|http_put_buffer|http_put_json|http_put_utf8|identity|ignore|fcmp|filter|format|plural|random_int|urlmod|waitcb)[^/]*(?<!\.test)\.js$/);
4
4
  require_tmp.keys().forEach(function (key) {
5
5
  const [, basename] = key.match(/([^/]+)\.js$/);
6
6
  window[basename] = require_tmp(key);