@vbarbarosh/node-helpers 3.63.1 → 3.64.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.
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
@@ -38,10 +38,10 @@ function serializer(replacer, cycleReplacer) {
38
38
 
39
39
  /***/ }),
40
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%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%7Cformat%7Cplural%7Crandom_int%7Curlmod%7Cwaitcb)[^/]*(?<%21\.test)\.js$ ***!
44
- \***************************************************************************************************************************************************************************************************************************************************************************************************************************************/
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
+ \*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
45
45
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
46
46
 
47
47
  var map = {
@@ -61,6 +61,11 @@ var map = {
61
61
  "./array_unique_last.js": "./src/array_unique_last.js",
62
62
  "./date_add_months.js": "./src/date_add_months.js",
63
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",
64
69
  "./format_bytes.js": "./src/format_bytes.js",
65
70
  "./format_date.js": "./src/format_date.js",
66
71
  "./format_date_ymd.js": "./src/format_date_ymd.js",
@@ -113,7 +118,7 @@ webpackContext.keys = function webpackContextKeys() {
113
118
  };
114
119
  webpackContext.resolve = webpackContextResolve;
115
120
  module.exports = webpackContext;
116
- 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%7Cformat%7Cplural%7Crandom_int%7Curlmod%7Cwaitcb)[^/]*(?<%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$";
117
122
 
118
123
  /***/ }),
119
124
 
@@ -630,6 +635,103 @@ function factorize_ms(v)
630
635
  module.exports = factorize_ms;
631
636
 
632
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
+
633
735
  /***/ }),
634
736
 
635
737
  /***/ "./src/fcmp_strings.js":
@@ -646,6 +748,91 @@ function fcmp_strings(a, b)
646
748
  module.exports = fcmp_strings;
647
749
 
648
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
+
649
836
  /***/ }),
650
837
 
651
838
  /***/ "./src/format_bytes.js":
@@ -1582,7 +1769,7 @@ var __webpack_exports__ = {};
1582
1769
  \******************************/
1583
1770
  // https://github.com/webpack/webpack/issues/625
1584
1771
  // https://webpack.js.org/guides/dependency-management/#require-context
1585
- 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%7Cformat%7Cplural%7Crandom_int%7Curlmod%7Cwaitcb)[^/]*(?<%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$");
1586
1773
  require_tmp.keys().forEach(function (key) {
1587
1774
  const [, basename] = key.match(/([^/]+)\.js$/);
1588
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.1",
5
+ "version": "3.64.0",
6
6
  "description": "A set of helpers for JavaScript/Node.js",
7
7
  "unpkg": "dist/browser.js",
8
8
  "jsdelivr": "dist/browser.js",
@@ -28,6 +28,7 @@
28
28
  "url": "https://github.com/vbarbarosh/node-helpers/issues"
29
29
  },
30
30
  "peerDependencies": {
31
+ "@vbarbarosh/type-helpers": "^0.1.0",
31
32
  "axios": "^1.7.9",
32
33
  "bluebird": "^3.7.2",
33
34
  "csv-parse": "^5.6.0",
@@ -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|format|plural|random_int|urlmod|waitcb)[^/]*(?<!\.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);
@@ -1,7 +1,7 @@
1
1
  const format_bytes = require('./format_bytes');
2
2
  const format_percents = require('./format_percents');
3
3
  const format_seconds = require('./format_seconds');
4
- const is_number_gt = require('./is_number_gt');
4
+ const is_number_gt = require('@vbarbarosh/type-helpers/src/is_number_gt');
5
5
 
6
6
  function format_progress_bytes({percents, total, done, rate, eta, duration})
7
7
  {
@@ -1,7 +1,7 @@
1
1
  const format_kilo = require('./format_kilo');
2
2
  const format_percents = require('./format_percents');
3
3
  const format_seconds = require('./format_seconds');
4
- const is_number_gt = require('./is_number_gt');
4
+ const is_number_gt = require('@vbarbarosh/type-helpers/src/is_number_gt');
5
5
 
6
6
  function format_progress_kilo({percents, total, done, rate, eta, duration})
7
7
  {
@@ -0,0 +1,8 @@
1
+ const fs = require('fs');
2
+
3
+ function fs_copy_excl(src, dest)
4
+ {
5
+ return fs.promises.copyFile(src, dest, fs.constants.COPYFILE_EXCL);
6
+ }
7
+
8
+ module.exports = fs_copy_excl;
@@ -0,0 +1,8 @@
1
+ const path = require('path');
2
+
3
+ function fs_path_relative(from, to)
4
+ {
5
+ return path.relative(from, to);
6
+ }
7
+
8
+ module.exports = fs_path_relative;
@@ -1,5 +1,5 @@
1
1
  const axios = require('axios');
2
- const make_int = require('./make_int');
2
+ const make_int = require('@vbarbarosh/type-helpers/src/make_int');
3
3
 
4
4
  async function http_get_stream(url, options)
5
5
  {
package/src/parallel.js CHANGED
@@ -1,11 +1,20 @@
1
1
  const NotImplemented = require('./errors/NotImplemented');
2
+ const Promise = require('bluebird');
3
+ const is_async_function = require('@vbarbarosh/type-helpers/src/is_async_function');
4
+ const is_async_generator = require('@vbarbarosh/type-helpers/src/is_async_generator');
2
5
 
3
6
  /**
4
7
  * - Run until `spawn` return `null`.
5
8
  * - Keep no more than `concurrency` number of workers at a time.
9
+ *
10
+ * ⚠️ Warning: `spawn` should not be async function (async functions are always return `promise`).
11
+ * Instead, it should be a simple function returning either `null` or a `promise`.
6
12
  */
7
13
  async function parallel({concurrency, spawn, progress})
8
14
  {
15
+ if (is_async_function(spawn) || is_async_generator(spawn)) {
16
+ throw new Error('[spawn] should not be async function. Instead, it should be a simple function returning either [null] or a [promise].');
17
+ }
9
18
  const running = [];
10
19
  return new Promise(function (resolve, reject) {
11
20
  let failed = false;
@@ -0,0 +1,11 @@
1
+ const assert = require('assert');
2
+ const parallel = require('./parallel');
3
+
4
+ describe('parallel', function () {
5
+ it('should reject when [spawn] is async function', function () {
6
+ assert.rejects(parallel({spawn: async function () {}}));
7
+ })
8
+ it('should reject when [spawn] is async generator', function () {
9
+ assert.rejects(parallel({spawn: async function* () {}}));
10
+ })
11
+ });
package/src/is_number.js DELETED
@@ -1,6 +0,0 @@
1
- function is_number(value)
2
- {
3
- return (typeof value === 'number') && isFinite(value);
4
- }
5
-
6
- module.exports = is_number;
@@ -1,20 +0,0 @@
1
- const assert = require('assert');
2
- const is_number = require('./is_number');
3
-
4
- const items = [
5
- ['-inf → false', -Infinity, false],
6
- ['+inf → false', +Infinity, false],
7
- ['null → false', null, false],
8
- ['{} → false', {}, false],
9
- ['Symbol() → false', Symbol(), false],
10
- ['Function → false', () => 1, false],
11
- ['BigInt(1) → false', 1n, false],
12
- ];
13
-
14
- describe('is_number', function () {
15
- items.forEach(function ([title, input, expected]) {
16
- it(title, function () {
17
- assert.deepStrictEqual(is_number(input), expected);
18
- });
19
- });
20
- });
@@ -1,8 +0,0 @@
1
- const is_number = require('./is_number');
2
-
3
- function is_number_gt(value, min)
4
- {
5
- return is_number(value) && value > min;
6
- }
7
-
8
- module.exports = is_number_gt;
package/src/make_int.js DELETED
@@ -1,15 +0,0 @@
1
- function make_int(value, default_value = 0, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER)
2
- {
3
- switch (typeof value) {
4
- case 'bigint':
5
- return Math.max(min, Math.min(max, Number(value)));
6
- case 'symbol':
7
- return default_value;
8
- }
9
- if (value === null || value === undefined || !isFinite(value)) {
10
- return default_value;
11
- }
12
- return Math.max(min, Math.min(max, Math.round(value === 0 ? value : (+value||default_value))));
13
- }
14
-
15
- module.exports = make_int;
@@ -1,15 +0,0 @@
1
- function make_number(value, default_value = 0, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER)
2
- {
3
- switch (typeof value) {
4
- case 'bigint':
5
- return Number(value);
6
- case 'symbol':
7
- return default_value;
8
- }
9
- if (value === null || value === undefined || !isFinite(value)) {
10
- return default_value;
11
- }
12
- return Math.max(min, Math.min(max, Math.round(value === 0 ? value : (+value||default_value))));
13
- }
14
-
15
- module.exports = make_number;
@@ -1,25 +0,0 @@
1
- const assert = require('assert');
2
- const make_number = require('./make_number');
3
-
4
- const items = [
5
- ['null → 0', null, 0],
6
- ['undefined → 0', undefined, 0],
7
- ['{} → 0', {}, 0],
8
- ['nan → 0', NaN, 0],
9
- ['-inf → 0', -Infinity, 0],
10
- ['+inf → 0', +Infinity, 0],
11
- ['false → 0', false, 0],
12
- ['true → 1', true, 1],
13
- ['Symbol() → 0', Symbol(), 0],
14
- ['Function → 0', () => 1, 0],
15
- ['BigInt(1) → 1', 1n, 1],
16
- ['"123" → 123', '123', 123],
17
- ];
18
-
19
- describe('make_number', function () {
20
- items.forEach(function ([title, input, expected]) {
21
- it(title, function () {
22
- assert.deepStrictEqual(make_number(input), expected);
23
- });
24
- });
25
- });