@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.
- package/README.md +2 -2
- package/dist/browser.js +603 -141
- package/package.json +1 -1
- package/src/_finally.js +8 -0
- package/src/_finally.md +19 -0
- package/src/_perf.js +18 -0
- package/src/_perf.md +13 -0
- package/src/_restore.js +16 -0
- package/src/_restore.md +21 -0
- package/src/_try.js +11 -0
- package/src/_try.md +5 -0
- package/src/array_max.md +1 -0
- package/src/array_min.md +1 -0
- package/src/array_shuffle.md +5 -0
- package/src/array_unique.md +1 -0
- package/src/array_unique_last.md +1 -0
- package/src/browser/index.js +15 -7
- package/src/fastdl.md +8 -0
- package/src/fcmp_from_spec.js +2 -0
- package/src/fcmpx.md +17 -0
- package/src/fcmpx.test.js +16 -1
- package/src/filter1_from_spec.md +7 -0
- package/src/format_hrtime.md +1 -0
- package/src/fs_fopen_update.md +5 -0
- package/src/fs_size_enoent.md +3 -0
- package/src/fs_tempdir.md +6 -0
- package/src/now_atom.js +1 -1
- package/src/now_atom.md +1 -0
- package/src/parallel.md +5 -0
- package/src/ping_socket.md +3 -0
- package/src/stream_chunk.md +1 -0
- package/src/stream_data_ln.md +1 -0
- package/src/stream_each.md +1 -0
- package/src/stream_filter.md +1 -0
- package/src/stream_lines.md +1 -0
- package/src/stream_map.md +1 -0
- package/src/stream_map_flatten.md +1 -0
- package/src/stream_map_parallel.md +1 -0
- package/src/stream_parse_csv.md +3 -0
- package/src/stream_progress.js +1 -1
- package/src/stream_progress.md +8 -0
- package/src/stream_skip.md +1 -0
- package/src/stream_strpbrk.md +1 -0
- package/src/stream_tap.md +1 -0
- package/src/stream_xml_analyze.md +1 -0
- package/src/stream_xml_parse.md +1 -0
- package/src/throttle.md +3 -0
- package/src/urlclean.js +1 -1
- package/src/urlclean.md +2 -0
- package/src/urlmod.md +7 -0
- package/src/user_friendly_status.md +4 -0
- package/src/wait_while.md +5 -0
- package/src/waitcb.md +12 -0
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.
|
|
5
|
+
"version": "3.69.0",
|
|
6
6
|
"description": "A set of helpers for JavaScript/Node.js",
|
|
7
7
|
"unpkg": "dist/browser.js",
|
|
8
8
|
"jsdelivr": "dist/browser.js",
|
package/src/_finally.js
ADDED
package/src/_finally.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
`_finally` lets you register cleanup code that always runs when the scope ends.
|
|
2
|
+
|
|
3
|
+
```js
|
|
4
|
+
this.foo = 12345;
|
|
5
|
+
using _ = _finally(() => this.foo = null);
|
|
6
|
+
// ...
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
This is essentially the same as:
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
this.foo = 12345;
|
|
13
|
+
try {
|
|
14
|
+
// ..
|
|
15
|
+
}
|
|
16
|
+
finally {
|
|
17
|
+
this.foo = null;
|
|
18
|
+
}
|
|
19
|
+
```
|
package/src/_perf.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
function _perf(name, print = s => console.log(s))
|
|
2
|
+
{
|
|
3
|
+
const time0 = performance.now();
|
|
4
|
+
return {
|
|
5
|
+
times: 1,
|
|
6
|
+
[Symbol.dispose]: function () {
|
|
7
|
+
const duration = performance.now() - time0;
|
|
8
|
+
if (this.times > 1) {
|
|
9
|
+
print(`[${name}] ${duration.toFixed(4)}ms x ${this.times}`);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
print(`[${name}] ${duration.toFixed(4)}ms`);
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = _perf;
|
package/src/_perf.md
ADDED
package/src/_restore.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// 1) Capture original value
|
|
2
|
+
// 2) Assign a temporary one
|
|
3
|
+
// 3) Automatically restore on scope exit
|
|
4
|
+
//
|
|
5
|
+
// Basically: set variable, and automatically restore the original value at the end of scope.
|
|
6
|
+
function _restore(value, callback)
|
|
7
|
+
{
|
|
8
|
+
const [original] = callback(value);
|
|
9
|
+
return {
|
|
10
|
+
[Symbol.dispose]: function () {
|
|
11
|
+
callback(original);
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
module.exports = _restore;
|
package/src/_restore.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The pattern "set a new value now, restore the old one when scope ends".
|
|
2
|
+
|
|
3
|
+
```js
|
|
4
|
+
using _ = _restore(false, v => [this.controls.play, this.controls.play = v]);
|
|
5
|
+
// ...
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
This is essentially the same as:
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
{
|
|
12
|
+
const _old = this.controls.play;
|
|
13
|
+
this.controls.play = false;
|
|
14
|
+
try {
|
|
15
|
+
// ...
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
this.controls.play = _old;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
package/src/_try.js
ADDED
package/src/_try.md
ADDED
package/src/array_max.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Returns the first element in the array with the maximal weight.
|
package/src/array_min.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Returns the first element in the array with the minimal weight.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Return unique values; if a value occurs multiple times, keep the first one.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Return unique values; if a value occurs multiple times, keep the last one.
|
package/src/browser/index.js
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
1
|
+
const ns = new URL(document.currentScript.src).searchParams.get('var') ?? 'h';
|
|
2
|
+
if (typeof window[ns] !== 'undefined') {
|
|
3
|
+
console.log(`❌ @vbarbarosh/node-helpers@${__VERSION__} was not injected — window.${ns} is already in use`);
|
|
4
|
+
}
|
|
5
|
+
else {
|
|
6
|
+
console.log(`🎉 @vbarbarosh/node-helpers@${__VERSION__} successfully exposed as window.${ns}`);
|
|
7
|
+
window[ns] = {};
|
|
8
|
+
// https://github.com/webpack/webpack/issues/625
|
|
9
|
+
// https://webpack.js.org/guides/dependency-management/#require-context
|
|
10
|
+
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$/);
|
|
11
|
+
require_tmp.keys().forEach(function (key) {
|
|
12
|
+
const [, basename] = key.match(/([^/]+)\.js$/);
|
|
13
|
+
window[ns][basename] = require_tmp(key);
|
|
14
|
+
});
|
|
15
|
+
}
|
package/src/fastdl.md
ADDED
package/src/fcmp_from_spec.js
CHANGED
package/src/fcmpx.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Comparator builder using compact expressions.
|
|
2
|
+
|
|
3
|
+
fcmp expression — Creates an `fcmp` function from an expression, suitable for use with `[].sort()`.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
fcmpx('user.email')
|
|
7
|
+
fcmpx('-user.age,user.email')
|
|
8
|
+
fcmpx(v => v.user.email)
|
|
9
|
+
fcmpx(['user.age', 'user.email'])
|
|
10
|
+
fcmpx(['-user.age', 'user.email'])
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Sorting rule: Missing values are considered greater than any defined value
|
|
14
|
+
and are therefore placed after all defined values.
|
|
15
|
+
|
|
16
|
+
- YouTube: [Сортировка объектов в JavaScript](https://www.youtube.com/watch?v=rHEH_JfQjL4)
|
|
17
|
+
- https://github.com/vbarbarosh/speaking/tree/master/20250822-js-sort-fcmpx
|
package/src/fcmpx.test.js
CHANGED
|
@@ -8,6 +8,21 @@ const users = [
|
|
|
8
8
|
{id: 'betty|32|-', user: {name: 'betty', tag: {short: 'bar', long: 'barbar'}, age: 32}},
|
|
9
9
|
];
|
|
10
10
|
|
|
11
|
+
// https://dummyjson.com/docs/products
|
|
12
|
+
|
|
13
|
+
const products = [
|
|
14
|
+
{id: 1, name: 'Yoga Mat', category: 'Yoga', price: 25.99, brand: 'BalanceFrom', rating: 4.6, discount: 0.1, availability: 'in_stock'},
|
|
15
|
+
{id: 2, name: 'Adjustable Dumbbells', category: 'Strength', price: 199.99, brand: 'Bowflex', rating: 4.8, availability: 'preorder'},
|
|
16
|
+
{id: 3, name: 'Resistance Bands Set', category: 'Strength', price: 32.5, brand: 'Fit Simplify', rating: 4.5, discount: 0.15, availability: 'in_stock'},
|
|
17
|
+
{id: 4, name: 'Treadmill', category: 'Cardio', price: 899, brand: 'NordicTrack', rating: 4.7, availability: 'out_of_stock'},
|
|
18
|
+
{id: 5, name: 'Kettlebell 20lb', category: 'Strength', price: 45, brand: 'CAP Barbell', rating: 4.4, discount: 0.05, availability: 'in_stock'},
|
|
19
|
+
{id: 6, name: 'Foam Roller', category: 'Recovery', price: 19.99, brand: 'TriggerPoint', rating: 4.6, availability: 'limited'},
|
|
20
|
+
{id: 7, name: 'Exercise Bike', category: 'Cardio', price: 599, brand: 'Peloton', rating: 4.9, discount: 0.2, availability: 'in_stock'},
|
|
21
|
+
{id: 8, name: 'Pull-Up Bar', category: 'Strength', price: 29.95, brand: 'Iron Gym', rating: 4.3, availability: 'in_stock'},
|
|
22
|
+
{id: 9, name: 'Jump Rope', category: 'Cardio', price: 12.99, brand: 'WOD Nation', rating: 4.2, discount: 0.25, availability: 'limited'},
|
|
23
|
+
{id: 10, name: 'Ab Roller', category: 'Core', price: 21.49, brand: 'Perfect Fitness', rating: 4.5, availability: 'in_stock'},
|
|
24
|
+
];
|
|
25
|
+
|
|
11
26
|
const tests = [
|
|
12
27
|
{
|
|
13
28
|
description: 'missing: should move undefined values to the bottom',
|
|
@@ -149,7 +164,7 @@ const tests = [
|
|
|
149
164
|
describe('fcmpx', function () {
|
|
150
165
|
tests.forEach(function (test) {
|
|
151
166
|
test.expressions.forEach(function (expr, i) {
|
|
152
|
-
it(`${test.description}: #${i+1} | ${test.description}`, function () {
|
|
167
|
+
it(`${test.description}: #${i + 1} | ${test.description}`, function () {
|
|
153
168
|
const actual = test.items.slice().sort(fcmpx(expr)).map(test.extract);
|
|
154
169
|
assert.deepStrictEqual(actual, test.expected);
|
|
155
170
|
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Creates a filtering function based on the following spec:
|
|
2
|
+
|
|
3
|
+
1. Substrings are separated by `/`.
|
|
4
|
+
2. Each substring may have special characters:
|
|
5
|
+
- `^`: Substring must appear at the beginning.
|
|
6
|
+
- `$`: Substring must appear at the end.
|
|
7
|
+
- `!`: Negates the condition (substring must not appear).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Return a human-readable representation of hrtime (the return value from `process.hrtime(hrtime0)`).
|
package/src/now_atom.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Return current date in ATOM format (e.g. "2021-07-17T23:27:01.030Z")
|
|
2
|
+
* Return the current date in ATOM format (e.g. "2021-07-17T23:27:01.030Z")
|
|
3
3
|
*
|
|
4
4
|
* @returns {string}
|
|
5
5
|
* @link https://www.php.net/manual/en/class.datetimeinterface.php#datetime.constants.atom
|
package/src/now_atom.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Return the current date in ATOM format (e.g. "2021-07-17T23:27:01.030Z")
|
package/src/parallel.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
- Run until `spawn` return `null`.
|
|
2
|
+
- Keep no more than `concurrency` number of workers at a time.
|
|
3
|
+
|
|
4
|
+
⚠️ Warning: `spawn` should not be async function (async functions are always return `promise`).
|
|
5
|
+
Instead, it should be a simple function returning either `null` or a `promise`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Split a stream into chunks of objects.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Split stream on each `\n` and call `fn` for each line.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Pass each item to a simple function. This is a final step.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Pass down only those items passed user-defined criteria.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Split stream into lines.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Transform each item using a simple function.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Pass each item through a user-defined generator, passes down each yielded item.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Transform each item using a simple function in parallel.
|
package/src/stream_progress.js
CHANGED
|
@@ -7,7 +7,7 @@ const stream = require('stream');
|
|
|
7
7
|
* Monitor the progress of data through a pipe, similar to the UNIX `pv` command.
|
|
8
8
|
*
|
|
9
9
|
* Requirements:
|
|
10
|
-
* - should emit first message as fast as possible
|
|
10
|
+
* - should emit the first message as fast as possible
|
|
11
11
|
* - should always emit 100% message
|
|
12
12
|
*
|
|
13
13
|
* @similar https://www.npmjs.com/package/progress-stream
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Skip first `n` records.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Split the input stream by consecutive delimiters in `chars`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Call `fn` on each item.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Consume XML, produce an object with analytics about provided xml stream.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Consume XML, produce objects.
|
package/src/throttle.md
ADDED
package/src/urlclean.js
CHANGED
|
@@ -2,7 +2,7 @@ const querystring = require('querystring');
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Replace unnecessary encodes symbols with chars. The returned url will be
|
|
5
|
-
* more human
|
|
5
|
+
* more human-friendly, at the same time it will still be valid url.
|
|
6
6
|
*/
|
|
7
7
|
function urlclean(url)
|
|
8
8
|
{
|
package/src/urlclean.md
ADDED
package/src/urlmod.md
ADDED
package/src/waitcb.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Wait for a Node-like function to finish (which will call `callback`
|
|
2
|
+
with 2 arguments: `error` and `value`).
|
|
3
|
+
|
|
4
|
+
```js
|
|
5
|
+
await waitcb(cb => fs.writeFile('a', 'hello\n', cb));
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
The same as:
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
const [promise, resolve, reject] = (a => [new Promise((...v) => a = v), ...a])();
|
|
12
|
+
```
|