@vbarbarosh/node-helpers 3.74.1 → 3.76.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 +29 -3
- package/dist/browser.js +1 -2504
- package/package.json +31 -11
- 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 +5 -0
- 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,9 @@
|
|
|
1
|
+
Thin wrapper over node's `path.extname(p)`, kept for the consistent `fs_*` naming.
|
|
2
|
+
Returns the extension including the dot, or `''` when there is none — note node's dotfile rules:
|
|
3
|
+
|
|
4
|
+
```js
|
|
5
|
+
fs_path_extname('file.js'); // '.js'
|
|
6
|
+
fs_path_extname('.foo'); // ''
|
|
7
|
+
fs_path_extname('..foo'); // '.foo'
|
|
8
|
+
fs_path_extname('/a/b.js/c'); // ''
|
|
9
|
+
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Expands a leading `~` in a path to the current user's home directory (ported from sindresorhus/untildify).
|
|
2
|
+
Only a `~` that is the whole path or is followed by `/` or `\` is expanded; anything else is returned unchanged.
|
|
3
|
+
If the home directory cannot be determined, the path is returned as-is.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
fs_path_untildify('~/x'); // '/home/ubuntu/x'
|
|
7
|
+
fs_path_untildify('~foo/x'); // '~foo/x'
|
|
8
|
+
```
|
package/src/fs_read.md
ADDED
package/src/fs_rename.md
ADDED
package/src/fs_rm.md
ADDED
package/src/fs_rmdir.md
ADDED
package/src/fs_rmf.md
ADDED
package/src/fs_rmrf.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Removes a file or directory recursively, like `rm -rf`.
|
|
2
|
+
A missing path is silently ignored; children of a directory are removed in parallel.
|
|
3
|
+
Uses `lstat`, so a symlink is removed itself — its target is never followed.
|
|
4
|
+
|
|
5
|
+
**Signature:** `fs_rmrf(path, progress = ignore) → Promise<void>`
|
|
6
|
+
|
|
7
|
+
The optional `progress` callback is called as `progress('rm', path)` before each file
|
|
8
|
+
and `progress('rmdir', path)` before each directory removal.
|
package/src/fs_sha256.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
|
|
4
|
+
async function fs_sha256(path)
|
|
5
|
+
{
|
|
6
|
+
const hash = crypto.createHash('sha256');
|
|
7
|
+
|
|
8
|
+
const highWaterMark = 1024*1024;
|
|
9
|
+
for await (const chunk of fs.createReadStream(path, {highWaterMark})) {
|
|
10
|
+
hash.update(chunk);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return hash.digest('hex');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
module.exports = fs_sha256;
|
package/src/fs_sha256.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Computes the SHA-256 of a file, streaming it in 1 MiB chunks (constant
|
|
2
|
+
memory regardless of file size). Returns the digest as a lowercase hex
|
|
3
|
+
string. Rejects with `ENOENT` for a missing file; an empty file gives the
|
|
4
|
+
well-known empty-input digest.
|
|
5
|
+
|
|
6
|
+
```js
|
|
7
|
+
await fs_sha256('/tmp/data.txt')
|
|
8
|
+
// '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824' ('hello')
|
|
9
|
+
```
|
package/src/fs_size.js
CHANGED
package/src/fs_size.md
ADDED
package/src/fs_stat.md
ADDED
package/src/fs_tempdir.js
CHANGED
|
@@ -11,9 +11,16 @@ const mkdtemp = util.promisify(fs.mkdtemp);
|
|
|
11
11
|
// * http://www.tldp.org/LDP/abs/html/exitcodes.html from https://stackoverflow.com/q/14031763/1478566
|
|
12
12
|
// * https://www.exratione.com/2013/05/die-child-process-die/
|
|
13
13
|
|
|
14
|
+
// A single shared SIGINT listener no matter how many calls are in flight:
|
|
15
|
+
// one listener per call trips MaxListenersExceededWarning at 10+ concurrent calls.
|
|
16
|
+
const cleanups = new Set();
|
|
17
|
+
|
|
14
18
|
async function fs_tempdir(fn)
|
|
15
19
|
{
|
|
16
|
-
|
|
20
|
+
cleanups.add(clean);
|
|
21
|
+
if (cleanups.size === 1) {
|
|
22
|
+
process.on('SIGINT', sigint);
|
|
23
|
+
}
|
|
17
24
|
|
|
18
25
|
let d = null, out;
|
|
19
26
|
try {
|
|
@@ -26,17 +33,25 @@ async function fs_tempdir(fn)
|
|
|
26
33
|
return out;
|
|
27
34
|
|
|
28
35
|
async function clean() {
|
|
29
|
-
|
|
36
|
+
if (!cleanups.delete(clean)) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (cleanups.size === 0) {
|
|
40
|
+
process.removeListener('SIGINT', sigint);
|
|
41
|
+
}
|
|
30
42
|
if (d) {
|
|
31
43
|
await fs_rmrf(d);
|
|
32
44
|
}
|
|
33
45
|
}
|
|
46
|
+
}
|
|
34
47
|
|
|
35
|
-
|
|
48
|
+
async function sigint()
|
|
49
|
+
{
|
|
50
|
+
for (const clean of [...cleanups]) {
|
|
36
51
|
await clean().catch(function () {/* ignore */});
|
|
37
|
-
// https://stackoverflow.com/questions/14031763/doing-a-cleanup-action-just-before-node-js-exits#comment68567869_21947851
|
|
38
|
-
process.kill(process.pid, 'SIGINT');
|
|
39
52
|
}
|
|
53
|
+
// https://stackoverflow.com/questions/14031763/doing-a-cleanup-action-just-before-node-js-exits#comment68567869_21947851
|
|
54
|
+
process.kill(process.pid, 'SIGINT');
|
|
40
55
|
}
|
|
41
56
|
|
|
42
57
|
module.exports = fs_tempdir;
|
package/src/fs_touch.md
ADDED
package/src/fs_walk.js
CHANGED
|
@@ -3,7 +3,7 @@ const fs_path_join = require('./fs_path_join');
|
|
|
3
3
|
const fs_readdir = require('./fs_readdir');
|
|
4
4
|
const ignore = require('./ignore');
|
|
5
5
|
|
|
6
|
-
async function fs_walk({path = '.', user_friendly_status = ignore, error_handler =
|
|
6
|
+
async function fs_walk({path = '.', user_friendly_status = ignore, error_handler = default_error_handler, signal})
|
|
7
7
|
{
|
|
8
8
|
const out = [];
|
|
9
9
|
const queue = [path];
|
|
@@ -32,7 +32,7 @@ async function fs_walk({path = '.', user_friendly_status = ignore, error_handler
|
|
|
32
32
|
return out;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
function
|
|
35
|
+
function default_error_handler(error)
|
|
36
36
|
{
|
|
37
37
|
console.log(`⚠️ ${error.message}`);
|
|
38
38
|
}
|
package/src/fs_walk.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Walks a directory tree and resolves with a flat array of `lstat` results,
|
|
2
|
+
each with a `path` property added; the root entry is included. Order is not guaranteed.
|
|
3
|
+
|
|
4
|
+
**Options:** `fs_walk({path = '.', user_friendly_status, error_handler, signal})`
|
|
5
|
+
- `user_friendly_status(text)` — called with `Reading <path>` per entry
|
|
6
|
+
- `error_handler(error)` — per-entry errors are reported here and the walk continues (default logs to console)
|
|
7
|
+
- `signal` — an `AbortSignal` to cancel the walk
|
|
8
|
+
|
|
9
|
+
Symlinks are not followed (`lstat`), and the contents of `/dev` and `/proc` are skipped.
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
await fs_walk({path: 'w'});
|
|
13
|
+
// [Stats {path: 'w', ...}, Stats {path: 'w/sub', ...}, Stats {path: 'w/a.txt', ...}, ...]
|
|
14
|
+
```
|
package/src/fs_write.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Serializes `data` with `JSON.stringify(data, null, 4)` and writes it to the file as UTF-8.
|
|
2
|
+
The output is pretty-printed with 4-space indentation and has no trailing newline.
|
|
3
|
+
|
|
4
|
+
```js
|
|
5
|
+
await fs_write_json(file, {name: 'x'});
|
|
6
|
+
// file content: '{\n "name": "x"\n}'
|
|
7
|
+
```
|
package/src/gettype.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Returns the type of a value as a string (see `const_type`). Like `typeof`,
|
|
2
|
+
but with the usual annoyances fixed: `null` is `'null'` (not `'object'`),
|
|
3
|
+
arrays are `'array'`, and the special numbers get their own names — `'nan'`,
|
|
4
|
+
`'-inf'`, `'+inf'`.
|
|
5
|
+
|
|
6
|
+
```js
|
|
7
|
+
gettype(null) // 'null'
|
|
8
|
+
gettype([]) // 'array'
|
|
9
|
+
gettype(NaN) // 'nan'
|
|
10
|
+
gettype(-Infinity) // '-inf'
|
|
11
|
+
gettype(1n) // 'bigint'
|
|
12
|
+
gettype({}) // 'object'
|
|
13
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Sends a `DELETE` request via axios with `responseType: 'json'` and resolves
|
|
2
|
+
with `response.data`. Extra axios options pass through (and may override the
|
|
3
|
+
defaults).
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
await http_delete('https://api.example.com/items/15')
|
|
7
|
+
// → parsed response body
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Sibling of `http_get_json`, `http_post_json`, `http_put_json`,
|
|
11
|
+
`http_patch_json`.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Sends a `GET` request via axios with `responseType: 'blob'` and resolves with
|
|
2
|
+
`response.data` — a `Blob`. Meant for browser code; in Node prefer
|
|
3
|
+
`http_get_buffer` (Buffer) or `http_get_stream` (readable stream). Extra axios
|
|
4
|
+
options pass through.
|
|
5
|
+
|
|
6
|
+
```js
|
|
7
|
+
const blob = await http_get_blob('https://example.com/image.png');
|
|
8
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Sends a `GET` request via axios with `responseType: 'arraybuffer'` and
|
|
2
|
+
resolves with `response.data` — a `Buffer` in Node, an `ArrayBuffer` in the
|
|
3
|
+
browser. Extra axios options pass through.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
const buf = await http_get_buffer('https://example.com/image.png');
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
See also `http_get_utf8` (string), `http_get_json` (parsed JSON),
|
|
10
|
+
`http_get_blob` (browser Blob), `http_get_stream` (readable stream).
|
package/src/http_get_file.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
const axios = require('axios');
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const stream = require('stream');
|
|
4
|
-
const util = require('util');
|
|
5
|
-
|
|
6
|
-
const stream_finished = util.promisify(stream.finished);
|
|
7
4
|
|
|
8
5
|
// https://stackoverflow.com/a/61269447
|
|
9
|
-
function http_get_file(url, out_file, options)
|
|
6
|
+
async function http_get_file(url, out_file, options)
|
|
10
7
|
{
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
// Create out_file only after a successful response: a failed request
|
|
9
|
+
// (e.g. 404) should not leave an empty file behind.
|
|
10
|
+
const response = await axios.get(url, {responseType: 'stream', ...options});
|
|
11
|
+
// pipeline destroys both streams on any failure: an aborted download
|
|
12
|
+
// rejects instead of hanging forever, an unwritable out_file rejects
|
|
13
|
+
// instead of raising an uncaught 'error' event.
|
|
14
|
+
await stream.promises.pipeline(response.data, fs.createWriteStream(out_file));
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
module.exports = http_get_file;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Downloads `url` into `out_file`.
|
|
2
|
+
|
|
3
|
+
- An HTTP error status (e.g. 404) rejects and does not create `out_file` —
|
|
4
|
+
the file is only created after a successful response.
|
|
5
|
+
- Rejects when the server aborts the download mid-stream (no hanging) and
|
|
6
|
+
when `out_file` is not writable; both streams are destroyed on any failure.
|
|
7
|
+
- `options` are passed through to `axios.get` (after
|
|
8
|
+
`responseType: 'stream'`).
|
|
9
|
+
|
|
10
|
+
## Signature
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
http_get_file(url, out_file, options) → Promise<void>
|
|
14
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Sends a `GET` request via axios with `responseType: 'json'` and resolves with
|
|
2
|
+
`response.data` — the parsed response body. Extra axios options (headers,
|
|
3
|
+
params, timeout, ...) pass through.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
const user = await http_get_json('https://api.example.com/users/15');
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
See also `http_get_utf8` (raw string), `http_get_buffer`/`http_get_blob`
|
|
10
|
+
(binary), `http_get_stream` (readable stream).
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Sends a `GET` request via axios with `responseType: 'stream'` and resolves
|
|
2
|
+
with the response's readable stream, decorated with two extra properties:
|
|
3
|
+
`headers` (the response headers) and `total` (the `Content-Length` as an
|
|
4
|
+
integer, or `null` when the header is missing or unparsable). Extra axios
|
|
5
|
+
options pass through.
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
const stream = await http_get_stream('https://example.com/big.bin');
|
|
9
|
+
stream.total // 3000000 (or null)
|
|
10
|
+
stream.headers // response headers
|
|
11
|
+
stream.pipe(dest);
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
See also `http_get_buffer` when the whole body fits in memory.
|
|
@@ -10,21 +10,39 @@ async function http_get_stream_range(url, first, last)
|
|
|
10
10
|
const res = await axios.get(url, {responseType: 'stream', headers});
|
|
11
11
|
const out = res.data;
|
|
12
12
|
out.headers = res.headers;
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
try {
|
|
14
|
+
if (res.headers['content-range']) {
|
|
15
|
+
out.content_range = parse_http_content_range(res.headers['content-range']);
|
|
16
|
+
}
|
|
17
|
+
else if (res.headers['content-length']) {
|
|
18
|
+
const len = +res.headers['content-length'];
|
|
19
|
+
out.content_range = parse_http_content_range(`bytes 0-${len - 1}/${len}`);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
// Chunked 200 response: the body starts at byte 0, size unknown
|
|
23
|
+
out.content_range = {type: 'bytes', first: 0, last: null, total: null};
|
|
24
|
+
}
|
|
15
25
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
26
|
+
catch (error) {
|
|
27
|
+
out.destroy(); // release the socket; nobody will ever read this stream
|
|
28
|
+
throw error;
|
|
19
29
|
}
|
|
20
|
-
|
|
21
|
-
|
|
30
|
+
// A server reaching the end of the resource returns a shorter range than
|
|
31
|
+
// requested: `bytes=0-999999` of a 500-byte file is `bytes 0-499/500` (RFC 7233)
|
|
32
|
+
const expected_last = (b === '' || out.content_range.total === null) ? b : Math.min(b, out.content_range.total - 1);
|
|
33
|
+
if (a !== '' && out.content_range.first !== a) {
|
|
34
|
+
out.destroy(new Error(`First byte of a returned range (${fmt(out.content_range.first)}) is not as expected: [${fmt(a)}]`));
|
|
22
35
|
}
|
|
23
|
-
else if (b && out.content_range.last !==
|
|
24
|
-
out.destroy(new Error(`Last byte of a returned range (${
|
|
36
|
+
else if (b !== '' && out.content_range.last !== expected_last) {
|
|
37
|
+
out.destroy(new Error(`Last byte of a returned range (${fmt(out.content_range.last)}) is not as expected: [${fmt(expected_last)}]`));
|
|
25
38
|
}
|
|
26
39
|
out.total = out.content_range.total;
|
|
27
40
|
return out;
|
|
28
41
|
}
|
|
29
42
|
|
|
43
|
+
function fmt(v)
|
|
44
|
+
{
|
|
45
|
+
return v === null ? 'null' : format_thousands(v);
|
|
46
|
+
}
|
|
47
|
+
|
|
30
48
|
module.exports = http_get_stream_range;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
GETs `url` with a `Range: bytes=first-last` header and returns the response
|
|
2
|
+
body as a readable stream. Either bound may be omitted (non-integer) to send
|
|
3
|
+
an open-ended range; with both omitted a plain `bytes=-` request degrades to
|
|
4
|
+
a regular GET.
|
|
5
|
+
|
|
6
|
+
The stream gets extra properties attached: `headers` (raw response headers),
|
|
7
|
+
`content_range` (parsed `{type, first, last, total}`), and `total`. When the
|
|
8
|
+
server sends no `Content-Range`, it is synthesized from `Content-Length`; a
|
|
9
|
+
chunked 200 response (neither header) is accepted as
|
|
10
|
+
`{first: 0, last: null, total: null}` — body starts at byte 0, size unknown.
|
|
11
|
+
|
|
12
|
+
The returned range is validated: a `first` or `last` that differs from the
|
|
13
|
+
request destroys the stream with an error (reading it rejects) — this also
|
|
14
|
+
catches a server that ignores the range and replies 200. A `last` clamped to
|
|
15
|
+
the end of the resource is accepted: `bytes=0-999999` of a 500-byte file is
|
|
16
|
+
`bytes 0-499/500` (RFC 7233).
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
const rs = await http_get_stream_range(url, 100, 199);
|
|
20
|
+
rs.content_range // {type: 'bytes', first: 100, last: 199, total: 1000}
|
|
21
|
+
rs.total // 1000 (null when unknown)
|
|
22
|
+
```
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Sends a `GET` request via axios with `responseType: 'text'` and
|
|
2
|
+
`responseEncoding: 'utf8'`, and resolves with `response.data` — the body as a
|
|
3
|
+
UTF-8 string. Extra axios options pass through.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
const html = await http_get_utf8('https://example.com/');
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
See also `http_get_json` (parsed JSON) and `http_get_buffer` (binary).
|
package/src/http_head.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Sends a `HEAD` request via axios and resolves with the raw response headers
|
|
2
|
+
(`response.request.res.headers` — the Node http headers object, keys
|
|
3
|
+
lowercased), not the body. Extra axios options pass through.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
const headers = await http_head('https://example.com/file.bin');
|
|
7
|
+
headers['content-length'] // '3000000'
|
|
8
|
+
headers['content-type'] // 'application/octet-stream'
|
|
9
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Sends a `PATCH` request via axios with `body` as the request payload (a plain
|
|
2
|
+
object is serialized as JSON by axios) and resolves with `response.data`.
|
|
3
|
+
Extra axios options pass through.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
await http_patch_json('https://api.example.com/items/15', {title: 'New title'})
|
|
7
|
+
// → parsed response body
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Sibling of `http_post_json`, `http_put_json`, `http_delete`.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Sends a `POST` request via axios with `body` as the request payload (a plain
|
|
2
|
+
object is serialized as JSON by axios) and resolves with `response.data`.
|
|
3
|
+
Extra axios options pass through.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
await http_post_json('https://api.example.com/items', {title: 'Hello'})
|
|
7
|
+
// → parsed response body
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
See also `http_post_urlencoded` and `http_post_multipart` for other request
|
|
11
|
+
body encodings.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Sends a `POST` request with a `multipart/form-data` body built from an array
|
|
2
|
+
of `{name, body, options}` items and resolves with `response.data`. `body` may
|
|
3
|
+
be a string, Buffer, or readable stream; `options` (e.g. `{filename}`) is
|
|
4
|
+
passed to `FormData#append` when present. In Node the `form-data` package is
|
|
5
|
+
used and its boundary headers are merged into `options.headers`; in the
|
|
6
|
+
browser (with `form-data` webpack-externed to the native `FormData`) the form
|
|
7
|
+
is posted as-is. Extra axios options pass through.
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
const items = [
|
|
11
|
+
{name: 'subject', body: 'Hello'},
|
|
12
|
+
{name: 'attachment', body: fs_read_stream(file), options: {filename: 'hello.txt'}},
|
|
13
|
+
];
|
|
14
|
+
await http_post_multipart(url, items, {auth});
|
|
15
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Sends a `POST` request via axios with `body` serialized by Node's
|
|
2
|
+
`querystring.stringify` into an `application/x-www-form-urlencoded` string,
|
|
3
|
+
and resolves with `response.data`. Extra axios options (e.g. a `Content-Type`
|
|
4
|
+
header) pass through.
|
|
5
|
+
|
|
6
|
+
```js
|
|
7
|
+
await http_post_urlencoded(url, {grant_type: 'refresh_token', refresh_token})
|
|
8
|
+
// body sent as 'grant_type=refresh_token&refresh_token=...'
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
See also `http_post_json` and `http_post_multipart`.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Sends a `PUT` request via axios with `body` (a Buffer, or anything axios
|
|
2
|
+
accepts as a request body) sent as-is, and resolves with `response.data`.
|
|
3
|
+
Extra axios options — e.g. a `Content-Type` header — pass through.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
await http_put_buffer(upload_url, buf, {headers: {'Content-Type': 'image/png'}});
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Sibling of `http_put_utf8` (string body) and `http_put_json` (JSON body).
|
package/src/http_put_file.js
CHANGED
|
@@ -32,13 +32,11 @@ async function http_put_file(url, file, options = {})
|
|
|
32
32
|
chunks.push(chunk);
|
|
33
33
|
});
|
|
34
34
|
response.on('end', function () {
|
|
35
|
-
|
|
36
|
-
case 200:
|
|
35
|
+
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
37
36
|
resolve({request, response, data: Buffer.concat(chunks)});
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
40
39
|
reject(new Error(`${response.statusCode} ${response.statusMessage}\n\n${Buffer.concat(chunks).toString('utf8')}`));
|
|
41
|
-
break;
|
|
42
40
|
}
|
|
43
41
|
});
|
|
44
42
|
});
|
|
@@ -53,7 +51,12 @@ async function http_put_file(url, file, options = {})
|
|
|
53
51
|
prev = ready;
|
|
54
52
|
});
|
|
55
53
|
}
|
|
56
|
-
fs.createReadStream(file)
|
|
54
|
+
const rs = fs.createReadStream(file);
|
|
55
|
+
rs.on('error', function (error) {
|
|
56
|
+
reject(error);
|
|
57
|
+
request.destroy();
|
|
58
|
+
});
|
|
59
|
+
rs.pipe(request);
|
|
57
60
|
});
|
|
58
61
|
}
|
|
59
62
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
PUTs a local file to `url` with an explicit `Content-Length` header (some
|
|
2
|
+
services, e.g. S3, reject `Transfer-Encoding: chunked`). Any 2xx status
|
|
3
|
+
resolves with `{request, response, data}` where `data` is the response body
|
|
4
|
+
as a Buffer; any other status rejects with an error containing the status
|
|
5
|
+
line and the response body. Errors reading the file reject too, even when
|
|
6
|
+
the request is already in flight.
|
|
7
|
+
|
|
8
|
+
**Options:**
|
|
9
|
+
- `headers` — extra request headers (`Content-Length` is always set).
|
|
10
|
+
- `progress_upload(delta, ready, total)` — called on socket drain.
|
|
11
|
+
- `progress_download(delta, ready, total)` — called per response chunk;
|
|
12
|
+
`total` is `null` without a response `Content-Length`.
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
const {response, data} = await http_put_file(signed_url, '/tmp/build.zip');
|
|
16
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Sends a `PUT` request via axios with `body` as the request payload (a plain
|
|
2
|
+
object is serialized as JSON by axios) and resolves with `response.data`.
|
|
3
|
+
Extra axios options pass through.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
await http_put_json('https://api.example.com/items/15', {title: 'New title'})
|
|
7
|
+
// → parsed response body
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Sibling of `http_post_json`, `http_patch_json`, `http_put_buffer`,
|
|
11
|
+
`http_put_utf8`.
|