@vbarbarosh/node-helpers 3.75.0 → 3.76.1
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 +29 -3
- package/dist/browser.js +1 -2504
- package/dist/index.html +1 -1
- package/package.json +33 -12
- package/src/HeartbeatServer.js +24 -3
- package/src/HeartbeatServer.md +33 -0
- package/src/array_chunk.js +1 -1
- package/src/array_chunk.md +8 -0
- package/src/array_chunk_balanced.md +14 -0
- package/src/array_fps.md +12 -0
- package/src/array_gcd.js +4 -2
- package/src/array_gcd.md +2 -1
- package/src/array_group.js +3 -3
- package/src/array_group.md +14 -0
- package/src/array_group_map.js +3 -3
- package/src/array_group_map.md +13 -0
- package/src/array_index.js +2 -2
- package/src/array_index.md +9 -0
- package/src/array_lcm.js +4 -2
- package/src/array_lcm.md +2 -1
- package/src/array_max.js +11 -4
- package/src/array_max.md +1 -1
- package/src/array_min.js +11 -4
- package/src/array_min.md +1 -1
- package/src/array_permutations.js +4 -0
- package/src/array_permutations.md +13 -0
- package/src/array_sort.js +7 -2
- package/src/array_sort.md +13 -0
- package/src/array_sort_other.js +8 -5
- package/src/array_sort_other.md +11 -0
- package/src/array_sum.js +2 -2
- package/src/array_sum.md +8 -0
- package/src/array_unique.js +2 -2
- package/src/array_unique_last.js +2 -2
- package/src/assert_valid_expires_at.md +10 -0
- package/src/clamp.md +9 -0
- package/src/cli-apps/watchdog.js +5 -0
- package/src/cli.js +3 -1
- package/src/cli.md +15 -0
- package/src/const_stream.md +7 -0
- package/src/const_type.md +5 -0
- package/src/countdown.js +22 -5
- package/src/countdown.md +21 -0
- package/src/crypto_decrypt_aes256.md +13 -0
- package/src/crypto_encrypt_aes256.md +13 -0
- package/src/crypto_hash_md5.md +10 -0
- package/src/crypto_hash_sha256.md +10 -0
- package/src/crypto_hmac_sha256.md +11 -0
- package/src/date_add_hours.md +8 -0
- package/src/date_add_milliseconds.md +4 -0
- package/src/date_add_minutes.md +4 -0
- package/src/date_add_months.md +13 -0
- package/src/date_add_seconds.md +4 -0
- package/src/date_diff_seconds.md +4 -0
- package/src/date_is_leap_year.md +9 -0
- package/src/escape_content_disposition.js +6 -3
- package/src/escape_content_disposition.md +13 -0
- package/src/escape_regexp.md +7 -0
- package/src/eta.js +7 -1
- package/src/eta.md +18 -0
- package/src/factorize_ms.js +3 -0
- package/src/factorize_ms.md +10 -0
- package/src/fastdl.js +14 -3
- package/src/fcmp_dates.md +12 -0
- package/src/fcmp_default.js +7 -0
- package/src/fcmp_default.md +29 -0
- package/src/fcmp_default_desc.js +4 -7
- package/src/fcmp_default_desc.md +10 -0
- package/src/fcmp_from_spec.md +13 -0
- package/src/fcmp_numbers.md +11 -0
- package/src/fcmp_tuples.md +17 -0
- package/src/fcmp_utf8_bin.md +14 -0
- package/src/fcmp_utf8_ci.md +14 -0
- package/src/fcmp_utf8_cs.md +15 -0
- package/src/fcmp_utf8_natural_bin.js +38 -0
- package/src/fcmp_utf8_natural_bin.md +8 -0
- package/src/fcmp_utf8_natural_ci.md +13 -0
- package/src/fcmp_utf8_natural_cs.md +13 -0
- package/src/fcmpx.md +26 -9
- package/src/filter1_from_spec.js +3 -3
- package/src/format_bytes.md +15 -0
- package/src/format_date.md +7 -0
- package/src/format_date_fs.md +7 -0
- package/src/format_date_human.md +6 -0
- package/src/format_date_ymd.md +6 -0
- package/src/format_error_report.js +3 -3
- package/src/format_error_report.md +12 -0
- package/src/format_kilo.md +13 -0
- package/src/format_ms.js +3 -2
- package/src/format_ms.md +12 -0
- package/src/format_ms2.js +6 -3
- package/src/format_ms2.md +12 -0
- package/src/format_ms3.js +3 -2
- package/src/format_ms3.md +12 -0
- package/src/format_percents.md +10 -0
- package/src/format_progress_bytes.md +13 -0
- package/src/format_progress_kilo.md +10 -0
- package/src/format_seconds.md +11 -0
- package/src/format_thousands.md +9 -0
- package/src/fs_append.md +7 -0
- package/src/fs_append_json.md +8 -0
- package/src/fs_append_utf8.md +6 -0
- package/src/fs_assert_file_exists.md +3 -0
- package/src/fs_assert_file_readable.js +1 -1
- package/src/fs_assert_file_readable.md +3 -0
- package/src/fs_assert_file_socket.md +2 -0
- package/src/fs_copy.md +7 -0
- package/src/fs_copy_excl.md +2 -0
- package/src/fs_exists.md +6 -0
- package/src/fs_fclose.md +5 -0
- package/src/fs_fi.js +13 -1
- package/src/fs_fi.md +11 -0
- package/src/fs_file_md5.md +8 -0
- package/src/fs_find.md +7 -0
- package/src/fs_fopen.md +6 -0
- package/src/fs_fread.js +2 -2
- package/src/fs_fread.md +11 -0
- package/src/fs_fsize.md +2 -0
- package/src/fs_fstat.md +2 -0
- package/src/fs_fwrite.js +2 -2
- package/src/fs_fwrite.md +9 -0
- package/src/fs_list.md +5 -0
- package/src/fs_list_deep.md +5 -0
- package/src/fs_ls.md +2 -0
- package/src/fs_lsr.md +4 -0
- package/src/fs_lstat.md +3 -0
- package/src/fs_mkdir.md +3 -0
- package/src/fs_mkdirp.js +3 -30
- package/src/fs_mkdirp.md +7 -0
- package/src/fs_path_basename.md +2 -0
- package/src/fs_path_dirname.md +2 -0
- package/src/fs_path_extname.md +9 -0
- package/src/fs_path_join.md +2 -0
- package/src/fs_path_relative.md +2 -0
- package/src/fs_path_resolve.md +2 -0
- package/src/fs_path_tempdir.md +2 -0
- package/src/fs_path_untildify.md +8 -0
- package/src/fs_read.md +3 -0
- package/src/fs_read_buffer.md +5 -0
- package/src/fs_read_json.md +6 -0
- package/src/fs_read_lines.md +7 -0
- package/src/fs_read_stream.md +2 -0
- package/src/fs_read_utf8.md +5 -0
- package/src/fs_readdir.md +3 -0
- package/src/fs_readlink.md +6 -0
- package/src/fs_rename.md +6 -0
- package/src/fs_rm.md +4 -0
- package/src/fs_rmdir.md +3 -0
- package/src/fs_rmf.md +2 -0
- package/src/fs_rmrf.md +8 -0
- package/src/fs_sha256.js +16 -0
- package/src/fs_sha256.md +9 -0
- package/src/fs_size.js +2 -2
- package/src/fs_size.md +6 -0
- package/src/fs_stat.md +2 -0
- package/src/fs_tempdir.js +20 -5
- package/src/fs_touch.md +6 -0
- package/src/fs_walk.js +2 -2
- package/src/fs_walk.md +14 -0
- package/src/fs_write.md +3 -0
- package/src/fs_write_json.md +7 -0
- package/src/fs_write_stream.md +2 -0
- package/src/gettype.md +13 -0
- package/src/http_delete.md +11 -0
- package/src/http_get_blob.md +8 -0
- package/src/http_get_buffer.md +10 -0
- package/src/http_get_file.js +8 -8
- package/src/http_get_file.md +14 -0
- package/src/http_get_json.md +10 -0
- package/src/http_get_stream.md +14 -0
- package/src/http_get_stream_range.js +27 -9
- package/src/http_get_stream_range.md +22 -0
- package/src/http_get_utf8.md +9 -0
- package/src/http_head.md +9 -0
- package/src/http_patch_json.md +10 -0
- package/src/http_post_json.md +11 -0
- package/src/http_post_multipart.md +15 -0
- package/src/http_post_urlencoded.md +11 -0
- package/src/http_put_buffer.md +9 -0
- package/src/http_put_file.js +9 -6
- package/src/http_put_file.md +16 -0
- package/src/http_put_json.md +11 -0
- package/src/http_put_utf8.md +9 -0
- package/src/http_range_parse.js +6 -3
- package/src/http_range_parse.md +18 -0
- package/src/http_stream_range.js +35 -22
- package/src/http_stream_range.md +29 -0
- package/src/identity.md +2 -0
- package/src/ignore.md +2 -0
- package/src/json_stringify_safe.md +10 -0
- package/src/json_stringify_stable.md +9 -0
- package/src/logger.js +2 -3
- package/src/logger.md +15 -0
- package/src/make_progress.js +8 -5
- package/src/make_progress.md +20 -0
- package/src/math_gcd.js +2 -1
- package/src/mongo_stream_upsert.js +10 -3
- package/src/mongo_stream_upsert.md +17 -0
- package/src/mongo_stream_write.js +10 -3
- package/src/mongo_stream_write.md +16 -0
- package/src/msval.md +10 -0
- package/src/now_fs.md +7 -0
- package/src/now_human.md +6 -0
- package/src/object_defaults.md +11 -0
- package/src/object_schema.js +2 -1
- package/src/object_schema.md +12 -0
- package/src/object_walk_preorder.md +16 -0
- package/src/parallel.js +23 -10
- package/src/parse_bytes.js +4 -2
- package/src/parse_bytes.md +15 -0
- package/src/parse_hms.js +1 -1
- package/src/parse_http_content_range.js +9 -5
- package/src/parse_http_content_range.md +16 -0
- package/src/perf_end_human.md +10 -0
- package/src/perf_end_ms.md +8 -0
- package/src/perf_measure.md +10 -0
- package/src/perf_measure_human.md +8 -0
- package/src/perf_start.md +9 -0
- package/src/pgid_exists.md +6 -0
- package/src/pgid_kill_grace.js +1 -1
- package/src/pgid_kill_grace.md +15 -0
- package/src/pid_exists.md +5 -0
- package/src/pid_kill_grace.js +1 -1
- package/src/pid_kill_grace.md +14 -0
- package/src/plural.md +13 -0
- package/src/random_hex.md +9 -0
- package/src/random_int.md +8 -0
- package/src/range.js +4 -2
- package/src/range.md +2 -0
- package/src/redis_connect.js +1 -1
- package/src/redis_connect.md +10 -0
- package/src/redis_lshift.md +14 -0
- package/src/redis_poll.js +1 -0
- package/src/redis_poll.md +17 -0
- package/src/redis_poll_zshift_callback_rpush.js +1 -2
- package/src/redis_poll_zshift_callback_rpush.md +17 -0
- package/src/redis_poll_zshift_spawn_rpush.js +2 -1
- package/src/redis_poll_zshift_spawn_rpush.md +20 -0
- package/src/redis_zshift.md +14 -0
- package/src/round.js +7 -8
- package/src/round.md +15 -0
- package/src/sanitize_dash_name.md +13 -0
- package/src/sanitize_filename.md +9 -0
- package/src/sanitize_var_name.md +14 -0
- package/src/sftp_get_file_info.js +2 -2
- package/src/sftp_get_file_info.md +14 -0
- package/src/sftp_get_stream_range.js +32 -22
- package/src/sftp_get_stream_range.md +20 -0
- package/src/shell_curl_progress.js +2 -1
- package/src/shell_curl_progress.md +17 -0
- package/src/shell_lines.js +2 -2
- package/src/shell_lines.md +1 -1
- package/src/shell_spawn.js +7 -0
- package/src/shell_ytdlp_progress.js +2 -1
- package/src/shell_ytdlp_progress.md +17 -0
- package/src/str_camel_to_snake.md +11 -0
- package/src/str_parse_kv.md +11 -0
- package/src/stream_curl_progress.md +14 -0
- package/src/stream_data_ln.js +7 -1
- package/src/stream_discard.md +8 -0
- package/src/stream_group.md +3 -0
- package/src/stream_gunzip.md +7 -0
- package/src/stream_hash.md +10 -0
- package/src/stream_map.js +8 -1
- package/src/stream_map_parallel.js +9 -1
- package/src/stream_md5.md +9 -0
- package/src/stream_multiplex.js +11 -0
- package/src/stream_multiplex.md +16 -0
- package/src/stream_through.md +3 -0
- package/src/stream_transform.md +2 -0
- package/src/stream_xml_analyze.js +9 -1
- package/src/stream_xml_parse.js +9 -1
- package/src/stream_ytdlp_progress.js +1 -1
- package/src/stream_ytdlp_progress.md +18 -0
- package/src/strtr.js +15 -5
- package/src/strtr.md +11 -0
- package/src/urlclean.js +9 -2
- package/src/urlmod.js +22 -11
- package/src/urlmod.md +15 -3
- package/src/urlparts.md +17 -0
- package/src/wait_while.js +1 -1
- package/src/wait_while.md +1 -1
- package/src/HeartbeatServer.test.js +0 -31
- package/src/array_chunk.test.js +0 -24
- package/src/array_chunk_balanced.test.js +0 -37
- package/src/array_fps.test.js +0 -72
- package/src/array_gcd.test.js +0 -10
- package/src/array_index.test.js +0 -14
- package/src/array_lcm.test.js +0 -12
- package/src/array_max.test.js +0 -20
- package/src/array_min.test.js +0 -20
- package/src/array_permutations.test.js +0 -20
- package/src/array_sort.test.js +0 -85
- package/src/array_sort_other.test.js +0 -9
- package/src/array_sum.test.js +0 -11
- package/src/cli-apps/watchdog.d/connect_close.js +0 -17
- package/src/cli-apps/watchdog.d/connect_close2.js +0 -20
- package/src/cli-apps/watchdog.d/connect_close3.js +0 -25
- package/src/cli-apps/watchdog.d/connect_no_ping.js +0 -13
- package/src/cli-apps/watchdog.d/early_exit.js +0 -7
- package/src/cli-apps/watchdog.d/flood.js +0 -13
- package/src/cli-apps/watchdog.d/flood2.js +0 -15
- package/src/cli-apps/watchdog.d/hang.js +0 -8
- package/src/cli-apps/watchdog.d/huge_delay.js +0 -18
- package/src/cli-apps/watchdog.d/ignore_sigterm.js +0 -29
- package/src/cli-apps/watchdog.d/late_heartbeat.js +0 -21
- package/src/cli-apps/watchdog.d/my-exit-after-2-pings.js +0 -16
- package/src/cli-apps/watchdog.d/my-happy-path.js +0 -16
- package/src/cli-apps/watchdog.d/my-ignore-sigterm.js +0 -22
- package/src/cli-apps/watchdog.d/my-never-ping.js +0 -15
- package/src/cli-apps/watchdog.d/no_heartbeat.js +0 -5
- package/src/cli-apps/watchdog.d/ok.js +0 -17
- package/src/cli-apps/watchdog.d/quick-exit-after-2-pings.js +0 -15
- package/src/cli-apps/watchdog.d/quick-hang-after-1-ping.js +0 -15
- package/src/cli-apps/watchdog.d/spawn_children.js +0 -14
- package/src/cli-apps/watchdog.test.js +0 -48
- package/src/crypto_encrypt_aes256.test.js +0 -10
- package/src/crypto_hash_sha256.test.js +0 -10
- package/src/date_add_months.test.js +0 -40
- package/src/date_is_leap_year.test.js +0 -14
- package/src/escape_content_disposition.test.js +0 -22
- package/src/fcmp_from_spec.test.js +0 -91
- package/src/fcmpx.test.js +0 -173
- package/src/filter1_from_spec.test.js +0 -31
- package/src/format_bytes.test.js +0 -22
- package/src/format_error_report.d/src/1.js +0 -26
- package/src/format_error_report.d/src/2.js +0 -29
- package/src/format_kilo.test.js +0 -25
- package/src/format_ms.test.js +0 -33
- package/src/format_ms2.test.js +0 -33
- package/src/format_ms3.test.js +0 -33
- package/src/format_percents.test.js +0 -22
- package/src/format_progress_bytes.test.js +0 -19
- package/src/format_progress_kilo.test.js +0 -19
- package/src/format_seconds.test.js +0 -42
- package/src/format_thousands.test.js +0 -28
- package/src/fs_file_md5.test.js +0 -11
- package/src/fs_mkdirp.test.js +0 -24
- package/src/fs_path_extname.test.js +0 -22
- package/src/gettype.test.js +0 -27
- package/src/object_schema.test.js +0 -15
- package/src/object_walk_preorder.test.js +0 -17
- package/src/parallel.test.js +0 -11
- package/src/parse_bytes.test.js +0 -21
- package/src/parse_hms.test.js +0 -32
- package/src/parse_http_content_range.test.js +0 -14
- package/src/pid_kill_grace.d/ignore-sigterm-for-10ms.js +0 -33
- package/src/pid_kill_grace.d/ignore-sigterm.js +0 -22
- package/src/pid_kill_grace.test.js +0 -63
- package/src/ping_socket.test.js +0 -58
- package/src/plural.test.js +0 -20
- package/src/range.test.js +0 -41
- package/src/redis_lshift.test.js +0 -57
- package/src/redis_zshift.test.js +0 -58
- package/src/round.test.js +0 -56
- package/src/sanitize_dash_name.test.js +0 -59
- package/src/sanitize_var_name.test.js +0 -39
- package/src/shell_spawn.test.js +0 -30
- package/src/str_camel_to_snake.test.js +0 -17
- package/src/stream_curl_progress.d/basic +0 -3
- package/src/stream_curl_progress.d/basic.json +0 -42
- package/src/stream_curl_progress.test.js +0 -17
- package/src/stream_data_ln.test.js +0 -24
- package/src/stream_map_parallel.test.js +0 -26
- package/src/stream_multiplex.test.js +0 -67
- package/src/stream_strpbrk.test.js +0 -29
- package/src/urlclean.test.js +0 -18
- package/src/urlmod.test.js +0 -40
- package/src/urlparts.test.js +0 -294
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Runs a curl command and turns its progress meter into user-friendly status
|
|
2
|
+
lines. `args` is the full command including the binary (`['curl', url, ...]`);
|
|
3
|
+
`--no-silent --progress-meter` are appended, plus `-o /dev/null` when the args
|
|
4
|
+
contain no `-o` (curl only prints a progress meter when the response body is
|
|
5
|
+
redirected). stderr is parsed via `stream_curl_progress` and each row is
|
|
6
|
+
reported as `user_friendly_status('42% | 587M of 3217M at 18.5M/s ETA 0:02:22
|
|
7
|
+
duration=0:00:31')`; zero speed shows as `~`.
|
|
8
|
+
|
|
9
|
+
Rejects when the process exits with a non-zero code or is killed by a signal
|
|
10
|
+
(only exit code 0 is a success). Extra spawn options go under the `options`
|
|
11
|
+
key of the second argument.
|
|
12
|
+
|
|
13
|
+
## Signature
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
shell_curl_progress(args, {options, user_friendly_status}) → Promise<void>
|
|
17
|
+
```
|
package/src/shell_lines.js
CHANGED
|
@@ -2,8 +2,8 @@ const shell = require('./shell');
|
|
|
2
2
|
|
|
3
3
|
async function shell_lines(args, options)
|
|
4
4
|
{
|
|
5
|
-
const s = await shell(args, options);
|
|
6
|
-
return s.
|
|
5
|
+
const s = (await shell(args, options)).trimEnd();
|
|
6
|
+
return s === '' ? [] : s.split('\n');
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
module.exports = shell_lines;
|
package/src/shell_lines.md
CHANGED
|
@@ -3,7 +3,7 @@ Basic helper for running external commands via `execFile`, and splits stdout int
|
|
|
3
3
|
- Fails if the command exits with non-zero code.
|
|
4
4
|
- Fails if anything is printed to `stderr`.
|
|
5
5
|
- Strips trailing newline(s).
|
|
6
|
-
- Returns array of lines
|
|
6
|
+
- Returns array of lines; empty output produces `[]`, not `['']`.
|
|
7
7
|
|
|
8
8
|
## Signature
|
|
9
9
|
|
package/src/shell_spawn.js
CHANGED
|
@@ -35,6 +35,13 @@ function shell_spawn(args, options)
|
|
|
35
35
|
run.reject = reject;
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
+
// A spawn failure rejects both stages with the same error, and callers
|
|
39
|
+
// are expected to await only one of them (e.g. watchdog awaits init()
|
|
40
|
+
// alone): without a pre-registered handler the sibling rejection is
|
|
41
|
+
// reported as unhandled and can crash under --unhandled-rejections=strict.
|
|
42
|
+
init.promise.catch(ignore);
|
|
43
|
+
run.promise.catch(ignore);
|
|
44
|
+
|
|
38
45
|
const out = child_process.spawn(args[0], args.slice(1), options);
|
|
39
46
|
out.once('error', onerror);
|
|
40
47
|
out.once('spawn', onspawn);
|
|
@@ -12,7 +12,8 @@ async function shell_ytdlp_progress(args, {user_friendly_status, ...options})
|
|
|
12
12
|
const promises = [];
|
|
13
13
|
promises.push(new Promise(function (resolve, reject) {
|
|
14
14
|
proc.once('error', reject);
|
|
15
|
-
|
|
15
|
+
// A signal-killed process exits with code = null: only 0 is a success
|
|
16
|
+
proc.once('exit', (code, signal) => code === 0 ? resolve() : reject(new Error(`Process terminated with code ${code} and signal ${signal}`)));
|
|
16
17
|
}));
|
|
17
18
|
promises.push(stream.promises.pipeline(proc.stdout, stream_ytdlp_progress(), stream_each(progress_fn)));
|
|
18
19
|
promises.push(stream.promises.pipeline(proc.stderr, stream_each(v => console.log(`[stderr] ${v}`))));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Runs the `yt-dlp` binary (hardcoded name, resolved via `PATH`) with
|
|
2
|
+
`--progress` prepended to `args`, and turns its stdout progress lines into
|
|
3
|
+
user-friendly status lines. Each parsed row (see `stream_ytdlp_progress`)
|
|
4
|
+
is reported as `user_friendly_status('50.90% | [1/2] 8.0MB of 15.71MB at
|
|
5
|
+
33.83MB/s ETA 00:01 duration=31s')`; the merging stage reports
|
|
6
|
+
`'Merging... duration=...'`. `duration` is wall time since the spawn. stderr
|
|
7
|
+
lines are echoed to the console with a `[stderr]` prefix.
|
|
8
|
+
|
|
9
|
+
Rejects when the process exits with a non-zero code or is killed by a signal
|
|
10
|
+
(only exit code 0 is a success). Extra properties of the second argument are
|
|
11
|
+
passed through as spawn options.
|
|
12
|
+
|
|
13
|
+
## Signature
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
shell_ytdlp_progress(args, {user_friendly_status, ...options}) → Promise<void>
|
|
17
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Converts camelCase/PascalCase to snake_case and lowercases the result.
|
|
2
|
+
Acronyms are kept together as one word (`SomeUPCCode` → `some_upc_code`),
|
|
3
|
+
though an acronym at the end of the string has nothing to split it from the
|
|
4
|
+
previous word (`thisISNT` → `this_isnt`).
|
|
5
|
+
|
|
6
|
+
```js
|
|
7
|
+
str_camel_to_snake('CamelCase') // 'camel_case'
|
|
8
|
+
str_camel_to_snake('SomeUPCCode') // 'some_upc_code'
|
|
9
|
+
str_camel_to_snake('thisISDifficult') // 'this_is_difficult'
|
|
10
|
+
str_camel_to_snake('UPC') // 'upc'
|
|
11
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Splits a `key: value` string on the first colon and returns a trimmed
|
|
2
|
+
`[key, value]` pair. Only the first colon splits — the rest stays in the
|
|
3
|
+
value — so URLs survive. Without a colon, the whole string is the key and
|
|
4
|
+
the value is `''`.
|
|
5
|
+
|
|
6
|
+
```js
|
|
7
|
+
str_parse_kv('key: value') // ['key', 'value']
|
|
8
|
+
str_parse_kv('url: http://example.com') // ['url', 'http://example.com']
|
|
9
|
+
str_parse_kv('key') // ['key', '']
|
|
10
|
+
str_parse_kv(':value') // ['', 'value']
|
|
11
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Transform that parses curl's stderr progress meter (the `--progress-meter`
|
|
2
|
+
table) into objects. The two header lines are skipped; every following line
|
|
3
|
+
becomes `{perc, done, total, speed, eta, duration, time_total, ...}` with the
|
|
4
|
+
raw columns (`recv`, `transferred`, `speed_down`, `speed_up`, ...) included.
|
|
5
|
+
`done` is the received column, falling back to the transferred column while
|
|
6
|
+
received is `'0'` (uploads). `--:--:--` times are reported as `'~'`.
|
|
7
|
+
|
|
8
|
+
Lines starting with `curl:` (error messages) are written to
|
|
9
|
+
`process.stderr` and dropped from the output.
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
stream.compose(proc.stderr, stream_curl_progress())
|
|
13
|
+
// {perc: '18', done: '587M', total: '3217M', speed: '19.0M', eta: '0:02:22', ...}
|
|
14
|
+
```
|
package/src/stream_data_ln.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const {StringDecoder} = require('string_decoder');
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Split stream on each \n and call `fn` for each line.
|
|
3
5
|
*
|
|
@@ -7,6 +9,9 @@
|
|
|
7
9
|
*/
|
|
8
10
|
function stream_data_ln(stream, fn)
|
|
9
11
|
{
|
|
12
|
+
// StringDecoder buffers a multi-byte character split across chunk
|
|
13
|
+
// boundaries; plain buffer.toString('utf8') would corrupt it into �.
|
|
14
|
+
const decoder = new StringDecoder('utf8');
|
|
10
15
|
let utf8 = '';
|
|
11
16
|
stream.on('data', data);
|
|
12
17
|
stream.on('end', end);
|
|
@@ -18,12 +23,13 @@ function stream_data_ln(stream, fn)
|
|
|
18
23
|
}
|
|
19
24
|
function end() {
|
|
20
25
|
off();
|
|
26
|
+
utf8 += decoder.end();
|
|
21
27
|
if (utf8) {
|
|
22
28
|
fn(utf8, true);
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
function data(buffer) {
|
|
26
|
-
utf8 += buffer
|
|
32
|
+
utf8 += (typeof buffer === 'string') ? buffer : decoder.write(buffer);
|
|
27
33
|
for (let iteration = 1; true; ++iteration) {
|
|
28
34
|
if (iteration == 1000000) {
|
|
29
35
|
throw new Error('Too many iterations');
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
A writable sink that accepts and discards every chunk — useful to drain a
|
|
2
|
+
pipeline whose output is irrelevant. Byte mode by default; pass
|
|
3
|
+
`{objectMode: true}` for object streams. Consumes empty streams fine.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
await stream.promises.pipeline(source, stream_discard());
|
|
7
|
+
await stream.promises.pipeline(objects, stream_discard({objectMode: true}));
|
|
8
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Transform that consumes all input chunks and emits a single output chunk at
|
|
2
|
+
flush: the hex digest of the whole stream. `algorithm` defaults to `'md5'`;
|
|
3
|
+
any `crypto.createHash` algorithm name works, and `options` is passed
|
|
4
|
+
through to it. An empty stream still emits the digest of empty input.
|
|
5
|
+
|
|
6
|
+
```js
|
|
7
|
+
const chunks = await stream.Readable.from(['aaa', 'bbb']).pipe(stream_hash('sha256')).toArray();
|
|
8
|
+
Buffer.concat(chunks).toString('utf8');
|
|
9
|
+
// '2ce109e9d0faf820b2434e166297934e6177b65ab9951dbc3e204cad4689b39c'
|
|
10
|
+
```
|
package/src/stream_map.js
CHANGED
|
@@ -2,6 +2,10 @@ const stream = require('stream');
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Transform each item using a simple function.
|
|
5
|
+
*
|
|
6
|
+
* Returning null or undefined from `fn` drops the item: streams cannot
|
|
7
|
+
* carry null (it is an eof mark), so pushing it would end the stream and
|
|
8
|
+
* silently discard everything after it.
|
|
5
9
|
*/
|
|
6
10
|
function stream_map(fn)
|
|
7
11
|
{
|
|
@@ -9,7 +13,10 @@ function stream_map(fn)
|
|
|
9
13
|
objectMode: true,
|
|
10
14
|
transform: async function (item, encoding, callback) {
|
|
11
15
|
try {
|
|
12
|
-
|
|
16
|
+
const out = await fn(item);
|
|
17
|
+
if (out !== null && out !== undefined) {
|
|
18
|
+
this.push(out);
|
|
19
|
+
}
|
|
13
20
|
callback();
|
|
14
21
|
}
|
|
15
22
|
catch (error) {
|
|
@@ -3,6 +3,10 @@ const stream = require('stream');
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Transform each item using a simple function in parallel.
|
|
6
|
+
*
|
|
7
|
+
* Returning null or undefined from `handler` drops the item: streams cannot
|
|
8
|
+
* carry null (it is an eof mark), so pushing it would end the stream and
|
|
9
|
+
* silently discard everything after it.
|
|
6
10
|
*/
|
|
7
11
|
function stream_map_parallel({handler, concurrency})
|
|
8
12
|
{
|
|
@@ -46,7 +50,11 @@ function stream_map_parallel({handler, concurrency})
|
|
|
46
50
|
function ready() {
|
|
47
51
|
running--;
|
|
48
52
|
while (buf.length && buf[0].isFulfilled()) {
|
|
49
|
-
|
|
53
|
+
const value = buf.shift().value();
|
|
54
|
+
// null is an eof mark, pushing it would end the stream
|
|
55
|
+
if (value !== null && value !== undefined) {
|
|
56
|
+
out.push(value);
|
|
57
|
+
}
|
|
50
58
|
}
|
|
51
59
|
if (callback_next && buf.length < buf_limit) {
|
|
52
60
|
const tmp = callback_next;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Transform that consumes all input chunks and emits a single output chunk at
|
|
2
|
+
flush: the md5 hex digest of the whole stream. An empty stream still emits
|
|
3
|
+
`'d41d8cd98f00b204e9800998ecf8427e'`. Equivalent to `stream_hash('md5')`;
|
|
4
|
+
the source carries a TODO to rename this to `stream_hash_md5`.
|
|
5
|
+
|
|
6
|
+
```js
|
|
7
|
+
const chunks = await stream.Readable.from(['aaa', 'bbb']).pipe(stream_md5()).toArray();
|
|
8
|
+
Buffer.concat(chunks).toString('utf8'); // '6547436690a26a399603a7096e876a2d'
|
|
9
|
+
```
|
package/src/stream_multiplex.js
CHANGED
|
@@ -3,6 +3,17 @@ const stream = require('stream');
|
|
|
3
3
|
|
|
4
4
|
function stream_multiplex(...streams)
|
|
5
5
|
{
|
|
6
|
+
if (streams.length === 0) {
|
|
7
|
+
// Multiplex of nothing is a sink which accepts and discards all writes
|
|
8
|
+
// (the generic write/final below would never invoke their callbacks).
|
|
9
|
+
return stream.Writable({
|
|
10
|
+
objectMode: true,
|
|
11
|
+
write: function (chunk, encoding, callback) {
|
|
12
|
+
callback();
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
6
17
|
if (streams.length === 1) {
|
|
7
18
|
return streams[0];
|
|
8
19
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Combines several writable streams into one object-mode writable that
|
|
2
|
+
duplicates every chunk to all of them. Backpressure is respected: a write
|
|
3
|
+
completes only after every target accepted the chunk.
|
|
4
|
+
|
|
5
|
+
- Zero streams → a sink that accepts and discards all writes.
|
|
6
|
+
- One stream → returned as is (no wrapper).
|
|
7
|
+
- Ending the multiplex ends all targets; destroying it destroys all targets.
|
|
8
|
+
- An error in any target destroys the multiplex (and, through it, the other
|
|
9
|
+
targets) with that error — the first error wins.
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
await stream.promises.pipeline(
|
|
13
|
+
source,
|
|
14
|
+
stream_multiplex(ws1, ws2),
|
|
15
|
+
);
|
|
16
|
+
```
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const htmlparser2 = require('htmlparser2');
|
|
2
2
|
const stream = require('stream');
|
|
3
|
+
const {StringDecoder} = require('string_decoder');
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Consume XML, produce an object with analytics about provided xml stream.
|
|
@@ -30,13 +31,20 @@ function stream_xml_analyze()
|
|
|
30
31
|
};
|
|
31
32
|
|
|
32
33
|
const parser = new htmlparser2.Parser(events, options);
|
|
34
|
+
// StringDecoder buffers a multi-byte character split across chunk
|
|
35
|
+
// boundaries; plain buf.toString() would corrupt it into �.
|
|
36
|
+
const decoder = new StringDecoder('utf8');
|
|
33
37
|
return out = new stream.Transform({
|
|
34
38
|
objectMode: true,
|
|
35
39
|
transform: function (buf, encoding, callback) {
|
|
36
|
-
parser.write(buf.
|
|
40
|
+
parser.write(typeof buf === 'string' ? buf : decoder.write(buf));
|
|
37
41
|
callback();
|
|
38
42
|
},
|
|
39
43
|
flush: function (callback) {
|
|
44
|
+
const tail = decoder.end();
|
|
45
|
+
if (tail) {
|
|
46
|
+
parser.write(tail);
|
|
47
|
+
}
|
|
40
48
|
parser.end();
|
|
41
49
|
callback();
|
|
42
50
|
},
|
package/src/stream_xml_parse.js
CHANGED
|
@@ -2,6 +2,7 @@ const assert = require('assert');
|
|
|
2
2
|
const const_stream = require('./const_stream');
|
|
3
3
|
const htmlparser2 = require('htmlparser2');
|
|
4
4
|
const stream = require('stream');
|
|
5
|
+
const {StringDecoder} = require('string_decoder');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Consume XML, produce objects.
|
|
@@ -48,13 +49,20 @@ function stream_xml_parse(selector, mapper = stream_xml_parse.guess)
|
|
|
48
49
|
};
|
|
49
50
|
|
|
50
51
|
const parser = new htmlparser2.Parser(events, options);
|
|
52
|
+
// StringDecoder buffers a multi-byte character split across chunk
|
|
53
|
+
// boundaries; plain buf.toString() would corrupt it into �.
|
|
54
|
+
const decoder = new StringDecoder('utf8');
|
|
51
55
|
return out = new stream.Transform({
|
|
52
56
|
objectMode: true,
|
|
53
57
|
transform: function (buf, encoding, callback) {
|
|
54
|
-
parser.write(buf.
|
|
58
|
+
parser.write(typeof buf === 'string' ? buf : decoder.write(buf));
|
|
55
59
|
callback();
|
|
56
60
|
},
|
|
57
61
|
flush: function (callback) {
|
|
62
|
+
const tail = decoder.end();
|
|
63
|
+
if (tail) {
|
|
64
|
+
parser.write(tail);
|
|
65
|
+
}
|
|
58
66
|
parser.end();
|
|
59
67
|
callback();
|
|
60
68
|
},
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Transform that parses yt-dlp `--progress` output (stdout) into objects:
|
|
2
|
+
`{current_part, total_parts, perc, done, total, speed, eta, merging}`. Sizes
|
|
3
|
+
are re-formatted via `parse_bytes`/`format_bytes` (`15.71MiB` → `'15.71MB'`,
|
|
4
|
+
`done` computed from the percentage), `Unknown` speed/ETA become `'~'`, and
|
|
5
|
+
non-progress lines are dropped.
|
|
6
|
+
|
|
7
|
+
- `[info] ...: Downloading N format(s): 251+248` plus the per-part
|
|
8
|
+
`[download] Destination: ....fNNN.ext` lines drive
|
|
9
|
+
`current_part`/`total_parts` for multi-format downloads (otherwise
|
|
10
|
+
`1`/`0`).
|
|
11
|
+
- A `[Merger]` line re-emits the last row with `merging: true`. The last row
|
|
12
|
+
is mutated in place, so copy rows if you collect them.
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
stream.Readable.from(lines).pipe(stream_ytdlp_progress())
|
|
16
|
+
// {current_part: 1, total_parts: 0, perc: '50.90%', done: '8.0MB',
|
|
17
|
+
// total: '15.71MB', speed: '33.83MB/s', eta: '00:01', merging: false}
|
|
18
|
+
```
|
package/src/strtr.js
CHANGED
|
@@ -2,13 +2,23 @@
|
|
|
2
2
|
// echo strtr("hello", ["he" => "X", "hell" => "Y"]);
|
|
3
3
|
function strtr(subject, map)
|
|
4
4
|
{
|
|
5
|
-
|
|
6
|
-
Object.
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
// Single pass, like PHP: replaced text is never scanned again
|
|
6
|
+
const keys = Object.keys(map).filter(v => v.length).sort(fcmp);
|
|
7
|
+
let out = '';
|
|
8
|
+
for (let i = 0; i < subject.length; ) {
|
|
9
|
+
const key = keys.find(v => subject.startsWith(v, i));
|
|
10
|
+
if (key) {
|
|
11
|
+
out += map[key];
|
|
12
|
+
i += key.length;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
out += subject[i];
|
|
16
|
+
i++;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
9
19
|
return out;
|
|
10
20
|
function fcmp(b, a) {
|
|
11
|
-
return a
|
|
21
|
+
return a.length - b.length;
|
|
12
22
|
}
|
|
13
23
|
}
|
|
14
24
|
|
package/src/strtr.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Replaces substrings in `subject` using a `{from: to}` map, like PHP's
|
|
2
|
+
`strtr`. Single pass: replaced text is never scanned again, so maps like
|
|
3
|
+
`{a: 'b', b: 'c'}` cannot cascade. When keys overlap, the longest matching
|
|
4
|
+
key wins regardless of map order. Empty keys are ignored.
|
|
5
|
+
|
|
6
|
+
```js
|
|
7
|
+
strtr('hello world', {world: 'there'}) // 'hello there'
|
|
8
|
+
strtr('hello', {he: 'X', hell: 'Y'}) // 'Yo' (longest key wins)
|
|
9
|
+
strtr('ab', {a: 'b', b: 'c'}) // 'bc' (single pass, no cascade)
|
|
10
|
+
strtr('hello', {l: ''}) // 'heo'
|
|
11
|
+
```
|
package/src/urlclean.js
CHANGED
|
@@ -6,6 +6,13 @@ const querystring = require('querystring');
|
|
|
6
6
|
*/
|
|
7
7
|
function urlclean(url)
|
|
8
8
|
{
|
|
9
|
+
// The #fragment is not part of the query string: without splitting it
|
|
10
|
+
// off first it would be percent-encoded into the last query value.
|
|
11
|
+
const h = url.indexOf('#');
|
|
12
|
+
const hash = (h === -1) ? '' : url.slice(h);
|
|
13
|
+
if (hash) {
|
|
14
|
+
url = url.slice(0, h);
|
|
15
|
+
}
|
|
9
16
|
const i = url.indexOf('?') + 1;
|
|
10
17
|
if (i) {
|
|
11
18
|
const s = querystring.stringify(querystring.parse(url.slice(i)), '&', '=', {
|
|
@@ -13,9 +20,9 @@ function urlclean(url)
|
|
|
13
20
|
return encodeURIComponent(v).replaceAll('%3A', ':').replaceAll('%2F', '/');
|
|
14
21
|
},
|
|
15
22
|
});
|
|
16
|
-
return url.slice(0, i) + s;
|
|
23
|
+
return url.slice(0, i) + s + hash;
|
|
17
24
|
}
|
|
18
|
-
return url;
|
|
25
|
+
return url + hash;
|
|
19
26
|
}
|
|
20
27
|
|
|
21
28
|
module.exports = urlclean;
|
package/src/urlmod.js
CHANGED
|
@@ -7,29 +7,40 @@
|
|
|
7
7
|
*/
|
|
8
8
|
function urlmod(url, params)
|
|
9
9
|
{
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
10
|
+
const input_url = String(url || '');
|
|
11
|
+
const entries = Object.entries(params || {});
|
|
12
|
+
if (!entries.length) {
|
|
13
|
+
return input_url;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const hash_pos = input_url.indexOf('#');
|
|
17
|
+
const hash = hash_pos === -1 ? '' : input_url.slice(hash_pos);
|
|
18
|
+
const before_hash = hash_pos === -1 ? input_url : input_url.slice(0, hash_pos);
|
|
19
|
+
const query_pos = before_hash.indexOf('?');
|
|
20
|
+
const before_query = query_pos === -1 ? before_hash : before_hash.slice(0, query_pos);
|
|
21
|
+
const query = query_pos === -1 ? '' : before_hash.slice(query_pos + 1);
|
|
22
|
+
const search = new URLSearchParams(query);
|
|
23
|
+
|
|
24
|
+
entries.forEach(function ([key, value]) {
|
|
13
25
|
switch (value) {
|
|
14
26
|
case null:
|
|
15
27
|
case undefined:
|
|
16
|
-
|
|
28
|
+
search.delete(key);
|
|
17
29
|
break;
|
|
18
30
|
case true:
|
|
19
|
-
|
|
31
|
+
search.set(key, '1');
|
|
20
32
|
break;
|
|
21
33
|
case false:
|
|
22
|
-
|
|
34
|
+
search.set(key, '0');
|
|
23
35
|
break;
|
|
24
36
|
default:
|
|
25
|
-
|
|
37
|
+
search.set(key, String(value));
|
|
26
38
|
break;
|
|
27
39
|
}
|
|
28
40
|
});
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
return tmp_url.toString().replace(/^xxx:\/\/___base___\//, '');
|
|
41
|
+
|
|
42
|
+
const output_query = search.toString();
|
|
43
|
+
return before_query + (output_query ? `?${output_query}` : '') + hash;
|
|
33
44
|
}
|
|
34
45
|
|
|
35
46
|
module.exports = urlmod;
|
package/src/urlmod.md
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
Set, change, or remove query string parameters.
|
|
2
2
|
|
|
3
|
+
Only the query string is parsed and rebuilt. The URL text before `?` and the
|
|
4
|
+
fragment starting with `#` are preserved, so absolute, relative,
|
|
5
|
+
protocol-relative, and non-standard URL-like strings are supported. Passing no
|
|
6
|
+
parameters, or an empty parameters object, returns the input unchanged.
|
|
7
|
+
|
|
8
|
+
`null` and `undefined` remove a parameter. Boolean values are encoded as `1`
|
|
9
|
+
and `0`; other values use the standard `URLSearchParams` conversion and
|
|
10
|
+
encoding rules.
|
|
11
|
+
|
|
3
12
|
```js
|
|
4
|
-
urlmod('', {a: 1})
|
|
5
|
-
urlmod('?a=1', {a: 2})
|
|
6
|
-
urlmod('?a=1', {a: null})
|
|
13
|
+
urlmod('', {a: 1}) // '?a=1'
|
|
14
|
+
urlmod('?a=1', {a: 2}) // '?a=2'
|
|
15
|
+
urlmod('?a=1#top', {a: null}) // '#top'
|
|
16
|
+
urlmod('../api?old=1', {old: 2}) // '../api?old=2'
|
|
17
|
+
urlmod('//cdn.example/app.js', {v: 2}) // '//cdn.example/app.js?v=2'
|
|
18
|
+
urlmod('/search', {exact: true}) // '/search?exact=1'
|
|
7
19
|
```
|
package/src/urlparts.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Splits a URL into a fixed-shape plain object. Accepts a `URL` instance or a
|
|
2
|
+
string; strings are parsed against the base `fake://fake/`, so relative paths
|
|
3
|
+
work (and non-string input degrades to the bare base instead of throwing).
|
|
4
|
+
The keys mirror the `URL` properties, except `pathname` is exposed as `path`.
|
|
5
|
+
|
|
6
|
+
```js
|
|
7
|
+
urlparts('https://john:secret@example.com:8080/users/15?page=2#top')
|
|
8
|
+
// {
|
|
9
|
+
// href: 'https://john:secret@example.com:8080/users/15?page=2#top',
|
|
10
|
+
// protocol: 'https:', hostname: 'example.com',
|
|
11
|
+
// username: 'john', password: 'secret',
|
|
12
|
+
// host: 'example.com:8080', port: '8080',
|
|
13
|
+
// path: '/users/15', search: '?page=2', hash: '#top',
|
|
14
|
+
// }
|
|
15
|
+
urlparts('/users?page=5').path // '/users'
|
|
16
|
+
urlparts('/users?page=5').protocol // 'fake:'
|
|
17
|
+
```
|
package/src/wait_while.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const Promise = require('bluebird');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Wait
|
|
4
|
+
* Wait while `fn` returns a truthy value; resolve as soon as it turns falsy.
|
|
5
5
|
*
|
|
6
6
|
* W A R N I N G
|
|
7
7
|
* This method was designed mainly for prototyping (where code cleanliness is important).
|
package/src/wait_while.md
CHANGED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
const HeartbeatServer = require('./HeartbeatServer');
|
|
2
|
-
const assert = require('assert');
|
|
3
|
-
const fs_assert_file_socket = require('./fs_assert_file_socket');
|
|
4
|
-
const ping_socket = require('./ping_socket');
|
|
5
|
-
|
|
6
|
-
// 💎 Only the lack of a valid PING within WATCHDOG_INTERVAL is fatal
|
|
7
|
-
|
|
8
|
-
// 📕 Notes by ChatGPT
|
|
9
|
-
// If listen() fails (EADDRINUSE, perms, etc.), constructor will throw,
|
|
10
|
-
// and heartbeat_server will be undefined in finally { await heartbeat_server.dispose() }.
|
|
11
|
-
|
|
12
|
-
describe('HeartbeatServer', function () {
|
|
13
|
-
it('Happy Path', async function () {
|
|
14
|
-
const server = new HeartbeatServer();
|
|
15
|
-
try {
|
|
16
|
-
let counter = 0;
|
|
17
|
-
server.on('heartbeat', () => counter++);
|
|
18
|
-
await fs_assert_file_socket(server.socket_path);
|
|
19
|
-
await ping_socket(server.socket_path);
|
|
20
|
-
await ping_socket(server.socket_path);
|
|
21
|
-
assert.strictEqual(counter, 2);
|
|
22
|
-
}
|
|
23
|
-
finally {
|
|
24
|
-
await server.dispose();
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// should emit a "warning" event on any client errors
|
|
29
|
-
// should not send any heartbeat signals after rejection (decision to kill a child process)
|
|
30
|
-
// should reject when no heartbeat received in an expected interval
|
|
31
|
-
});
|
package/src/array_chunk.test.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
const array_chunk = require('./array_chunk');
|
|
2
|
-
const assert = require('assert');
|
|
3
|
-
|
|
4
|
-
describe('array_chunk', function () {
|
|
5
|
-
it('should accept no arguments', function () {
|
|
6
|
-
assert.deepStrictEqual(array_chunk(), []);
|
|
7
|
-
});
|
|
8
|
-
it('should handle basic input', function () {
|
|
9
|
-
assert.deepStrictEqual(array_chunk([]), []);
|
|
10
|
-
assert.deepStrictEqual(array_chunk([1,2,3,4,5]), [[1],[2],[3],[4],[5]]);
|
|
11
|
-
assert.deepStrictEqual(array_chunk([1,2,3,4,5], 1), [[1],[2],[3],[4],[5]]);
|
|
12
|
-
assert.deepStrictEqual(array_chunk([1,2,3,4,5], 2), [[1,2],[3,4],[5]]);
|
|
13
|
-
assert.deepStrictEqual(array_chunk([1,2,3,4,5], 3), [[1,2,3],[4,5]]);
|
|
14
|
-
assert.deepStrictEqual(array_chunk([1,2,3,4,5], 4), [[1,2,3,4],[5]]);
|
|
15
|
-
assert.deepStrictEqual(array_chunk([1,2,3,4,5], 5), [[1,2,3,4,5]]);
|
|
16
|
-
assert.deepStrictEqual(array_chunk([1,2,3,4,5], 6), [[1,2,3,4,5]]);
|
|
17
|
-
});
|
|
18
|
-
it('should throw when limit is less than 1', function () {
|
|
19
|
-
assert.throws(() => array_chunk([], 0));
|
|
20
|
-
assert.throws(() => array_chunk([], -1));
|
|
21
|
-
assert.throws(() => array_chunk([1], 0));
|
|
22
|
-
assert.throws(() => array_chunk([1], -1));
|
|
23
|
-
});
|
|
24
|
-
});
|