@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.
Files changed (367) hide show
  1. package/README.md +29 -3
  2. package/dist/browser.js +1 -2504
  3. package/package.json +31 -11
  4. package/src/HeartbeatServer.js +24 -3
  5. package/src/HeartbeatServer.md +33 -0
  6. package/src/array_chunk.js +1 -1
  7. package/src/array_chunk.md +8 -0
  8. package/src/array_chunk_balanced.md +14 -0
  9. package/src/array_fps.md +12 -0
  10. package/src/array_gcd.js +4 -2
  11. package/src/array_gcd.md +2 -1
  12. package/src/array_group.js +3 -3
  13. package/src/array_group.md +14 -0
  14. package/src/array_group_map.js +3 -3
  15. package/src/array_group_map.md +13 -0
  16. package/src/array_index.js +2 -2
  17. package/src/array_index.md +9 -0
  18. package/src/array_lcm.js +4 -2
  19. package/src/array_lcm.md +2 -1
  20. package/src/array_max.js +11 -4
  21. package/src/array_max.md +1 -1
  22. package/src/array_min.js +11 -4
  23. package/src/array_min.md +1 -1
  24. package/src/array_permutations.js +4 -0
  25. package/src/array_permutations.md +13 -0
  26. package/src/array_sort.js +7 -2
  27. package/src/array_sort.md +13 -0
  28. package/src/array_sort_other.js +8 -5
  29. package/src/array_sort_other.md +11 -0
  30. package/src/array_sum.js +2 -2
  31. package/src/array_sum.md +8 -0
  32. package/src/array_unique.js +2 -2
  33. package/src/array_unique_last.js +2 -2
  34. package/src/assert_valid_expires_at.md +10 -0
  35. package/src/clamp.md +9 -0
  36. package/src/cli-apps/watchdog.js +5 -0
  37. package/src/cli.js +3 -1
  38. package/src/cli.md +15 -0
  39. package/src/const_stream.md +7 -0
  40. package/src/const_type.md +5 -0
  41. package/src/countdown.js +22 -5
  42. package/src/countdown.md +21 -0
  43. package/src/crypto_decrypt_aes256.md +13 -0
  44. package/src/crypto_encrypt_aes256.md +13 -0
  45. package/src/crypto_hash_md5.md +10 -0
  46. package/src/crypto_hash_sha256.md +10 -0
  47. package/src/crypto_hmac_sha256.md +11 -0
  48. package/src/date_add_hours.md +8 -0
  49. package/src/date_add_milliseconds.md +4 -0
  50. package/src/date_add_minutes.md +4 -0
  51. package/src/date_add_months.md +13 -0
  52. package/src/date_add_seconds.md +4 -0
  53. package/src/date_diff_seconds.md +4 -0
  54. package/src/date_is_leap_year.md +9 -0
  55. package/src/escape_content_disposition.js +6 -3
  56. package/src/escape_content_disposition.md +13 -0
  57. package/src/escape_regexp.md +7 -0
  58. package/src/eta.js +7 -1
  59. package/src/eta.md +18 -0
  60. package/src/factorize_ms.js +3 -0
  61. package/src/factorize_ms.md +10 -0
  62. package/src/fastdl.js +14 -3
  63. package/src/fcmp_dates.md +12 -0
  64. package/src/fcmp_default.js +7 -0
  65. package/src/fcmp_default.md +29 -0
  66. package/src/fcmp_default_desc.js +4 -7
  67. package/src/fcmp_default_desc.md +10 -0
  68. package/src/fcmp_from_spec.md +13 -0
  69. package/src/fcmp_numbers.md +11 -0
  70. package/src/fcmp_tuples.md +17 -0
  71. package/src/fcmp_utf8_bin.md +14 -0
  72. package/src/fcmp_utf8_ci.md +14 -0
  73. package/src/fcmp_utf8_cs.md +15 -0
  74. package/src/fcmp_utf8_natural_bin.js +38 -0
  75. package/src/fcmp_utf8_natural_bin.md +8 -0
  76. package/src/fcmp_utf8_natural_ci.md +13 -0
  77. package/src/fcmp_utf8_natural_cs.md +13 -0
  78. package/src/fcmpx.md +26 -9
  79. package/src/filter1_from_spec.js +3 -3
  80. package/src/format_bytes.md +15 -0
  81. package/src/format_date.md +7 -0
  82. package/src/format_date_fs.md +7 -0
  83. package/src/format_date_human.md +6 -0
  84. package/src/format_date_ymd.md +6 -0
  85. package/src/format_error_report.js +3 -3
  86. package/src/format_error_report.md +12 -0
  87. package/src/format_kilo.md +13 -0
  88. package/src/format_ms.js +3 -2
  89. package/src/format_ms.md +12 -0
  90. package/src/format_ms2.js +6 -3
  91. package/src/format_ms2.md +12 -0
  92. package/src/format_ms3.js +3 -2
  93. package/src/format_ms3.md +12 -0
  94. package/src/format_percents.md +10 -0
  95. package/src/format_progress_bytes.md +13 -0
  96. package/src/format_progress_kilo.md +10 -0
  97. package/src/format_seconds.md +11 -0
  98. package/src/format_thousands.md +9 -0
  99. package/src/fs_append.md +7 -0
  100. package/src/fs_append_json.md +8 -0
  101. package/src/fs_append_utf8.md +6 -0
  102. package/src/fs_assert_file_exists.md +3 -0
  103. package/src/fs_assert_file_readable.js +1 -1
  104. package/src/fs_assert_file_readable.md +3 -0
  105. package/src/fs_assert_file_socket.md +2 -0
  106. package/src/fs_copy.md +7 -0
  107. package/src/fs_copy_excl.md +2 -0
  108. package/src/fs_exists.md +6 -0
  109. package/src/fs_fclose.md +5 -0
  110. package/src/fs_fi.js +13 -1
  111. package/src/fs_fi.md +11 -0
  112. package/src/fs_file_md5.md +8 -0
  113. package/src/fs_find.md +7 -0
  114. package/src/fs_fopen.md +6 -0
  115. package/src/fs_fread.js +2 -2
  116. package/src/fs_fread.md +11 -0
  117. package/src/fs_fsize.md +2 -0
  118. package/src/fs_fstat.md +2 -0
  119. package/src/fs_fwrite.js +2 -2
  120. package/src/fs_fwrite.md +9 -0
  121. package/src/fs_list.md +5 -0
  122. package/src/fs_list_deep.md +5 -0
  123. package/src/fs_ls.md +2 -0
  124. package/src/fs_lsr.md +4 -0
  125. package/src/fs_lstat.md +3 -0
  126. package/src/fs_mkdir.md +3 -0
  127. package/src/fs_mkdirp.js +3 -30
  128. package/src/fs_mkdirp.md +7 -0
  129. package/src/fs_path_basename.md +2 -0
  130. package/src/fs_path_dirname.md +2 -0
  131. package/src/fs_path_extname.md +9 -0
  132. package/src/fs_path_join.md +2 -0
  133. package/src/fs_path_relative.md +2 -0
  134. package/src/fs_path_resolve.md +2 -0
  135. package/src/fs_path_tempdir.md +2 -0
  136. package/src/fs_path_untildify.md +8 -0
  137. package/src/fs_read.md +3 -0
  138. package/src/fs_read_buffer.md +5 -0
  139. package/src/fs_read_json.md +6 -0
  140. package/src/fs_read_lines.md +7 -0
  141. package/src/fs_read_stream.md +2 -0
  142. package/src/fs_read_utf8.md +5 -0
  143. package/src/fs_readdir.md +3 -0
  144. package/src/fs_readlink.md +6 -0
  145. package/src/fs_rename.md +6 -0
  146. package/src/fs_rm.md +4 -0
  147. package/src/fs_rmdir.md +3 -0
  148. package/src/fs_rmf.md +2 -0
  149. package/src/fs_rmrf.md +8 -0
  150. package/src/fs_sha256.js +16 -0
  151. package/src/fs_sha256.md +9 -0
  152. package/src/fs_size.js +2 -2
  153. package/src/fs_size.md +6 -0
  154. package/src/fs_stat.md +2 -0
  155. package/src/fs_tempdir.js +20 -5
  156. package/src/fs_touch.md +6 -0
  157. package/src/fs_walk.js +2 -2
  158. package/src/fs_walk.md +14 -0
  159. package/src/fs_write.md +3 -0
  160. package/src/fs_write_json.md +7 -0
  161. package/src/fs_write_stream.md +2 -0
  162. package/src/gettype.md +13 -0
  163. package/src/http_delete.md +11 -0
  164. package/src/http_get_blob.md +8 -0
  165. package/src/http_get_buffer.md +10 -0
  166. package/src/http_get_file.js +8 -8
  167. package/src/http_get_file.md +14 -0
  168. package/src/http_get_json.md +10 -0
  169. package/src/http_get_stream.md +14 -0
  170. package/src/http_get_stream_range.js +27 -9
  171. package/src/http_get_stream_range.md +22 -0
  172. package/src/http_get_utf8.md +9 -0
  173. package/src/http_head.md +9 -0
  174. package/src/http_patch_json.md +10 -0
  175. package/src/http_post_json.md +11 -0
  176. package/src/http_post_multipart.md +15 -0
  177. package/src/http_post_urlencoded.md +11 -0
  178. package/src/http_put_buffer.md +9 -0
  179. package/src/http_put_file.js +9 -6
  180. package/src/http_put_file.md +16 -0
  181. package/src/http_put_json.md +11 -0
  182. package/src/http_put_utf8.md +9 -0
  183. package/src/http_range_parse.js +6 -3
  184. package/src/http_range_parse.md +18 -0
  185. package/src/http_stream_range.js +35 -22
  186. package/src/http_stream_range.md +29 -0
  187. package/src/identity.md +2 -0
  188. package/src/ignore.md +2 -0
  189. package/src/json_stringify_safe.md +10 -0
  190. package/src/json_stringify_stable.md +9 -0
  191. package/src/logger.js +2 -3
  192. package/src/logger.md +15 -0
  193. package/src/make_progress.js +8 -5
  194. package/src/make_progress.md +20 -0
  195. package/src/math_gcd.js +2 -1
  196. package/src/mongo_stream_upsert.js +10 -3
  197. package/src/mongo_stream_upsert.md +17 -0
  198. package/src/mongo_stream_write.js +10 -3
  199. package/src/mongo_stream_write.md +16 -0
  200. package/src/msval.md +10 -0
  201. package/src/now_fs.md +7 -0
  202. package/src/now_human.md +6 -0
  203. package/src/object_defaults.md +11 -0
  204. package/src/object_schema.js +2 -1
  205. package/src/object_schema.md +12 -0
  206. package/src/object_walk_preorder.md +16 -0
  207. package/src/parallel.js +23 -10
  208. package/src/parse_bytes.js +4 -2
  209. package/src/parse_bytes.md +15 -0
  210. package/src/parse_hms.js +1 -1
  211. package/src/parse_http_content_range.js +9 -5
  212. package/src/parse_http_content_range.md +16 -0
  213. package/src/perf_end_human.md +10 -0
  214. package/src/perf_end_ms.md +8 -0
  215. package/src/perf_measure.md +10 -0
  216. package/src/perf_measure_human.md +8 -0
  217. package/src/perf_start.md +9 -0
  218. package/src/pgid_exists.md +6 -0
  219. package/src/pgid_kill_grace.js +1 -1
  220. package/src/pgid_kill_grace.md +15 -0
  221. package/src/pid_exists.md +5 -0
  222. package/src/pid_kill_grace.js +1 -1
  223. package/src/pid_kill_grace.md +14 -0
  224. package/src/plural.md +13 -0
  225. package/src/random_hex.md +9 -0
  226. package/src/random_int.md +8 -0
  227. package/src/range.js +4 -2
  228. package/src/range.md +2 -0
  229. package/src/redis_connect.js +1 -1
  230. package/src/redis_connect.md +10 -0
  231. package/src/redis_lshift.md +14 -0
  232. package/src/redis_poll.js +1 -0
  233. package/src/redis_poll.md +17 -0
  234. package/src/redis_poll_zshift_callback_rpush.js +1 -2
  235. package/src/redis_poll_zshift_callback_rpush.md +17 -0
  236. package/src/redis_poll_zshift_spawn_rpush.js +2 -1
  237. package/src/redis_poll_zshift_spawn_rpush.md +20 -0
  238. package/src/redis_zshift.md +14 -0
  239. package/src/round.js +7 -8
  240. package/src/round.md +15 -0
  241. package/src/sanitize_dash_name.md +13 -0
  242. package/src/sanitize_filename.md +9 -0
  243. package/src/sanitize_var_name.md +14 -0
  244. package/src/sftp_get_file_info.js +2 -2
  245. package/src/sftp_get_file_info.md +14 -0
  246. package/src/sftp_get_stream_range.js +32 -22
  247. package/src/sftp_get_stream_range.md +20 -0
  248. package/src/shell_curl_progress.js +2 -1
  249. package/src/shell_curl_progress.md +17 -0
  250. package/src/shell_lines.js +2 -2
  251. package/src/shell_lines.md +1 -1
  252. package/src/shell_spawn.js +7 -0
  253. package/src/shell_ytdlp_progress.js +2 -1
  254. package/src/shell_ytdlp_progress.md +17 -0
  255. package/src/str_camel_to_snake.md +11 -0
  256. package/src/str_parse_kv.md +11 -0
  257. package/src/stream_curl_progress.md +14 -0
  258. package/src/stream_data_ln.js +7 -1
  259. package/src/stream_discard.md +8 -0
  260. package/src/stream_group.md +3 -0
  261. package/src/stream_gunzip.md +7 -0
  262. package/src/stream_hash.md +10 -0
  263. package/src/stream_map.js +8 -1
  264. package/src/stream_map_parallel.js +9 -1
  265. package/src/stream_md5.md +9 -0
  266. package/src/stream_multiplex.js +11 -0
  267. package/src/stream_multiplex.md +16 -0
  268. package/src/stream_through.md +3 -0
  269. package/src/stream_transform.md +2 -0
  270. package/src/stream_xml_analyze.js +9 -1
  271. package/src/stream_xml_parse.js +9 -1
  272. package/src/stream_ytdlp_progress.js +1 -1
  273. package/src/stream_ytdlp_progress.md +18 -0
  274. package/src/strtr.js +15 -5
  275. package/src/strtr.md +11 -0
  276. package/src/urlclean.js +9 -2
  277. package/src/urlmod.js +5 -0
  278. package/src/urlparts.md +17 -0
  279. package/src/wait_while.js +1 -1
  280. package/src/wait_while.md +1 -1
  281. package/src/HeartbeatServer.test.js +0 -31
  282. package/src/array_chunk.test.js +0 -24
  283. package/src/array_chunk_balanced.test.js +0 -37
  284. package/src/array_fps.test.js +0 -72
  285. package/src/array_gcd.test.js +0 -10
  286. package/src/array_index.test.js +0 -14
  287. package/src/array_lcm.test.js +0 -12
  288. package/src/array_max.test.js +0 -20
  289. package/src/array_min.test.js +0 -20
  290. package/src/array_permutations.test.js +0 -20
  291. package/src/array_sort.test.js +0 -85
  292. package/src/array_sort_other.test.js +0 -9
  293. package/src/array_sum.test.js +0 -11
  294. package/src/cli-apps/watchdog.d/connect_close.js +0 -17
  295. package/src/cli-apps/watchdog.d/connect_close2.js +0 -20
  296. package/src/cli-apps/watchdog.d/connect_close3.js +0 -25
  297. package/src/cli-apps/watchdog.d/connect_no_ping.js +0 -13
  298. package/src/cli-apps/watchdog.d/early_exit.js +0 -7
  299. package/src/cli-apps/watchdog.d/flood.js +0 -13
  300. package/src/cli-apps/watchdog.d/flood2.js +0 -15
  301. package/src/cli-apps/watchdog.d/hang.js +0 -8
  302. package/src/cli-apps/watchdog.d/huge_delay.js +0 -18
  303. package/src/cli-apps/watchdog.d/ignore_sigterm.js +0 -29
  304. package/src/cli-apps/watchdog.d/late_heartbeat.js +0 -21
  305. package/src/cli-apps/watchdog.d/my-exit-after-2-pings.js +0 -16
  306. package/src/cli-apps/watchdog.d/my-happy-path.js +0 -16
  307. package/src/cli-apps/watchdog.d/my-ignore-sigterm.js +0 -22
  308. package/src/cli-apps/watchdog.d/my-never-ping.js +0 -15
  309. package/src/cli-apps/watchdog.d/no_heartbeat.js +0 -5
  310. package/src/cli-apps/watchdog.d/ok.js +0 -17
  311. package/src/cli-apps/watchdog.d/quick-exit-after-2-pings.js +0 -15
  312. package/src/cli-apps/watchdog.d/quick-hang-after-1-ping.js +0 -15
  313. package/src/cli-apps/watchdog.d/spawn_children.js +0 -14
  314. package/src/cli-apps/watchdog.test.js +0 -48
  315. package/src/crypto_encrypt_aes256.test.js +0 -10
  316. package/src/crypto_hash_sha256.test.js +0 -10
  317. package/src/date_add_months.test.js +0 -40
  318. package/src/date_is_leap_year.test.js +0 -14
  319. package/src/escape_content_disposition.test.js +0 -22
  320. package/src/fcmp_from_spec.test.js +0 -91
  321. package/src/fcmpx.test.js +0 -173
  322. package/src/filter1_from_spec.test.js +0 -31
  323. package/src/format_bytes.test.js +0 -22
  324. package/src/format_error_report.d/src/1.js +0 -26
  325. package/src/format_error_report.d/src/2.js +0 -29
  326. package/src/format_kilo.test.js +0 -25
  327. package/src/format_ms.test.js +0 -33
  328. package/src/format_ms2.test.js +0 -33
  329. package/src/format_ms3.test.js +0 -33
  330. package/src/format_percents.test.js +0 -22
  331. package/src/format_progress_bytes.test.js +0 -19
  332. package/src/format_progress_kilo.test.js +0 -19
  333. package/src/format_seconds.test.js +0 -42
  334. package/src/format_thousands.test.js +0 -28
  335. package/src/fs_file_md5.test.js +0 -11
  336. package/src/fs_mkdirp.test.js +0 -24
  337. package/src/fs_path_extname.test.js +0 -22
  338. package/src/gettype.test.js +0 -27
  339. package/src/object_schema.test.js +0 -15
  340. package/src/object_walk_preorder.test.js +0 -17
  341. package/src/parallel.test.js +0 -11
  342. package/src/parse_bytes.test.js +0 -21
  343. package/src/parse_hms.test.js +0 -32
  344. package/src/parse_http_content_range.test.js +0 -14
  345. package/src/pid_kill_grace.d/ignore-sigterm-for-10ms.js +0 -33
  346. package/src/pid_kill_grace.d/ignore-sigterm.js +0 -22
  347. package/src/pid_kill_grace.test.js +0 -63
  348. package/src/ping_socket.test.js +0 -58
  349. package/src/plural.test.js +0 -20
  350. package/src/range.test.js +0 -41
  351. package/src/redis_lshift.test.js +0 -57
  352. package/src/redis_zshift.test.js +0 -58
  353. package/src/round.test.js +0 -56
  354. package/src/sanitize_dash_name.test.js +0 -59
  355. package/src/sanitize_var_name.test.js +0 -39
  356. package/src/shell_spawn.test.js +0 -30
  357. package/src/str_camel_to_snake.test.js +0 -17
  358. package/src/stream_curl_progress.d/basic +0 -3
  359. package/src/stream_curl_progress.d/basic.json +0 -42
  360. package/src/stream_curl_progress.test.js +0 -17
  361. package/src/stream_data_ln.test.js +0 -24
  362. package/src/stream_map_parallel.test.js +0 -26
  363. package/src/stream_multiplex.test.js +0 -67
  364. package/src/stream_strpbrk.test.js +0 -29
  365. package/src/urlclean.test.js +0 -18
  366. package/src/urlmod.test.js +0 -40
  367. package/src/urlparts.test.js +0 -294
@@ -1,20 +0,0 @@
1
- const array_max = require('./array_max');
2
- const assert = require('assert');
3
-
4
- describe('array_max', function () {
5
- it('should accept empty array', function () {
6
- assert.deepStrictEqual(array_max([]), null);
7
- });
8
- it('should handle basic input', function () {
9
- assert.deepStrictEqual(array_max([1, 1, 2, 2, 3, 3, 1]), 3);
10
- assert.deepStrictEqual(array_max([{x:1},{x:2}], v => v.x), {x: 2});
11
- });
12
- it('should handle strings', function () {
13
- const items = [
14
- {id: 1, time: '2025-08-08T05:03:13+00:00'},
15
- {id: 2, time: '2025-08-07T05:03:13+00:00'},
16
- {id: 3, time: '2025-08-06T05:03:13+00:00'},
17
- ];
18
- assert.deepStrictEqual(array_max(items, v => v.time), items[0]);
19
- });
20
- });
@@ -1,20 +0,0 @@
1
- const array_min = require('./array_min');
2
- const assert = require('assert');
3
-
4
- describe('array_min', function () {
5
- it('should accept empty array', function () {
6
- assert.deepStrictEqual(array_min([]), null);
7
- });
8
- it('should handle basic input', function () {
9
- assert.deepStrictEqual(array_min([1, 1, 2, 2, 3, 3, 1]), 1);
10
- assert.deepStrictEqual(array_min([{x:2},{x:1}], v => v.x), {x: 1});
11
- });
12
- it('should handle strings', function () {
13
- const items = [
14
- {id: 1, time: '2025-08-08T05:03:13+00:00'},
15
- {id: 2, time: '2025-08-07T05:03:13+00:00'},
16
- {id: 3, time: '2025-08-06T05:03:13+00:00'},
17
- ];
18
- assert.deepStrictEqual(array_min(items, v => v.time), items[2]);
19
- });
20
- });
@@ -1,20 +0,0 @@
1
- const array_permutations = require('./array_permutations');
2
- const assert = require('assert');
3
-
4
- describe('array_permutations', function () {
5
- it('should handle basic input', function () {
6
- assert.deepStrictEqual(array_permutations([]), [[]]);
7
- assert.deepStrictEqual(array_permutations([1,2]), [[1,2],[2,1]]);
8
- assert.deepStrictEqual(array_permutations([1,2,3]), [[1,2,3],[2,1,3],[3,1,2],[1,3,2],[2,3,1],[3,2,1]]);
9
- });
10
- it('should handle k', function () {
11
- assert.deepStrictEqual(array_permutations([1,2], 1), [[1],[2]]);
12
- assert.deepStrictEqual(array_permutations([1,2,3], 2), [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]);
13
- assert.deepStrictEqual(array_permutations([1,2,3,4], 3), [
14
- [1,2,3],[1,2,4],[1,3,2],[1,3,4],[1,4,2],[1,4,3],
15
- [2,1,3],[2,1,4],[2,3,1],[2,3,4],[2,4,1],[2,4,3],
16
- [3,1,2],[3,1,4],[3,2,1],[3,2,4],[3,4,1],[3,4,2],
17
- [4,1,2],[4,1,3],[4,2,1],[4,2,3],[4,3,1],[4,3,2]
18
- ]);
19
- });
20
- });
@@ -1,85 +0,0 @@
1
- const array_sort = require('./array_sort');
2
- const assert = require('assert');
3
- const fs_path_extname = require('./fs_path_extname');
4
-
5
- describe('array_sort', function () {
6
- it('should handle basic input', function () {
7
- assert.deepStrictEqual(array_sort([5,4,3,2,1], v => [v]), [1,2,3,4,5]);
8
- assert.deepStrictEqual(array_sort([5,4,3,2,1], v => [v]), [1,2,3,4,5]);
9
- assert.deepStrictEqual(array_sort([{id:5},{id:4},{id:3},{id:2},{id:1}], v => [v.id]), [{id:1},{id:2},{id:3},{id:4},{id:5}]);
10
- });
11
- it('should handle sort by priorities', function () {
12
- assert.deepStrictEqual(array_sort([1,2,3,4,5], v => [[5].indexOf(v) >>> 0]), [5,1,2,3,4]);
13
- assert.deepStrictEqual(array_sort([{id:1},{id:2},{id:3},{id:4},{id:5}], v => [[5].indexOf(v.id) >>> 0]), [{id:5},{id:1},{id:2},{id:3},{id:4}]);
14
- });
15
- it('should handle sort by priorities #2', function () {
16
- const files = [
17
- {name: 'README.md', size: 1024, type: 'file'},
18
- {name: 'package.json', size: 860, type: 'file'},
19
- {name: 'src', size: 0, type: 'dir'},
20
- {name: 'src/index.js', size: 2048, type: 'file'},
21
- {name: 'src/utils', size: 0, type: 'dir'},
22
- {name: 'src/utils/helpers.js', size: 1536, type: 'file'},
23
- {name: 'node_modules', size: 0, type: 'dir'},
24
- {name: 'LICENSE', size: 1078, type: 'file'},
25
- ];
26
- const expected = [
27
- {name: 'node_modules', size: 0, type: 'dir'},
28
- {name: 'src', size: 0, type: 'dir'},
29
- {name: 'src/utils', size: 0, type: 'dir'},
30
- {name: 'LICENSE', size: 1078, type: 'file'},
31
- {name: 'README.md', size: 1024, type: 'file'},
32
- {name: 'package.json', size: 860, type: 'file'},
33
- {name: 'src/index.js', size: 2048, type: 'file'},
34
- {name: 'src/utils/helpers.js', size: 1536, type: 'file'},
35
- ];
36
- const actual = array_sort(files, v => [pri_start(v.type, ['dir']), v.name]);
37
- assert.deepStrictEqual(actual, expected);
38
- });
39
- it('sort by name, directory first; .js, then .txt, then all the reset', function () {
40
- const files = [
41
- {name: 'docs', type: 'dir', size: 0},
42
- {name: 'zeta.txt', type: 'file', size: 1200},
43
- {name: 'alpha.js', type: 'file', size: 1500},
44
- {name: 'src', type: 'dir', size: 0},
45
- {name: 'readme.txt', type: 'file', size: 800},
46
- {name: 'beta.js', type: 'file', size: 1600},
47
- {name: 'build', type: 'dir', size: 0},
48
- {name: 'build.foo.js', type: 'dir', size: 0},
49
- {name: 'build.foo.md', type: 'dir', size: 0},
50
- {name: 'build.foo.txt', type: 'dir', size: 0},
51
- {name: 'notes.md', type: 'file', size: 400},
52
- {name: 'zeta.js', type: 'file', size: 1000},
53
- {name: 'config', type: 'dir', size: 0},
54
- ];
55
- const expected = [
56
- {name: 'build.foo.js', type: 'dir', size: 0},
57
- {name: 'build.foo.txt', type: 'dir', size: 0},
58
- {name: 'build', type: 'dir', size: 0},
59
- {name: 'build.foo.md', type: 'dir', size: 0},
60
- {name: 'config', type: 'dir', size: 0},
61
- {name: 'docs', type: 'dir', size: 0},
62
- {name: 'src', type: 'dir', size: 0},
63
- {name: 'alpha.js', type: 'file', size: 1500},
64
- {name: 'beta.js', type: 'file', size: 1600},
65
- {name: 'zeta.js', type: 'file', size: 1000},
66
- {name: 'readme.txt', type: 'file', size: 800},
67
- {name: 'zeta.txt', type: 'file', size: 1200},
68
- {name: 'notes.md', type: 'file', size: 400},
69
- ];
70
- array_sort(files, v => [pri_start(v.type, ['dir']), pri_start(fs_path_extname(v.name), ['.js', '.txt']), v.name])
71
- assert.deepStrictEqual(files, expected);
72
- });
73
- });
74
-
75
- // priorities.indexOf(v) >>> 0
76
- function pri_start(value, array)
77
- {
78
- const i = array.indexOf(value);
79
- return i === -1 ? array.length : i;
80
- }
81
-
82
- function pri_end(value, array)
83
- {
84
- return array.indexOf(value);
85
- }
@@ -1,9 +0,0 @@
1
- const array_sort_other = require('./array_sort_other');
2
- const assert = require('assert');
3
-
4
- describe('array_sort_other', function () {
5
- it('should handle basic input', function () {
6
- assert.deepStrictEqual(array_sort_other([1,2,3,4,5], v => v, [5]), [5,1,2,3,4]);
7
- assert.deepStrictEqual(array_sort_other([{id:1},{id:2},{id:3},{id:4},{id:5}], v => v.id, [5]), [{id:5},{id:1},{id:2},{id:3},{id:4}]);
8
- });
9
- });
@@ -1,11 +0,0 @@
1
- const array_sum = require('./array_sum');
2
- const assert = require('assert');
3
-
4
- describe('array_sum', function () {
5
- it('should handle basic input', function () {
6
- assert.deepStrictEqual(array_sum([1,2,3,4,5]), 15);
7
- });
8
- it('should cast strings to numbers', function () {
9
- assert.deepStrictEqual(array_sum(['1','2','3','4','5']), 15);
10
- });
11
- });
@@ -1,17 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // 9. Client that connects but sends absolutely NO DATA.
4
- // Watchdog must NOT treat this as a PING.
5
-
6
- const net = require('net');
7
-
8
- const SOCKET = process.env.WATCHDOG_SOCKET;
9
- if (!SOCKET) throw new Error('WATCHDOG_SOCKET missing');
10
-
11
- // Connect → immediately destroy the socket → NO write events
12
- const socket = net.connect(SOCKET, () => {
13
- console.log('connected (no ping), closing immediately');
14
- socket.destroy(); // IMPORTANT: destroy() does not flush anything
15
- });
16
-
17
- setInterval(() => {}, 1000);
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // 9. Client that connects but sends absolutely NO DATA.
4
- // Watchdog must NOT treat this as a PING.
5
-
6
- const net = require('net');
7
-
8
- const SOCKET = process.env.WATCHDOG_SOCKET;
9
- if (!SOCKET) throw new Error('WATCHDOG_SOCKET missing');
10
-
11
- setInterval(ping, 1000);
12
-
13
- function ping()
14
- {
15
- // Connect → immediately destroy the socket → NO write events
16
- const socket = net.connect(SOCKET, () => {
17
- console.log('connected (no ping), closing immediately');
18
- socket.destroy(); // IMPORTANT: destroy() does not flush anything
19
- });
20
- }
@@ -1,25 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ❌ 11. Client sends heartbeats sporadically (sometimes missing)
4
- // Simulates flaky client.
5
-
6
- const net = require('net');
7
-
8
- const SOCKET = process.env.WATCHDOG_SOCKET;
9
- if (!SOCKET) throw new Error('WATCHDOG_SOCKET missing');
10
-
11
- setInterval(ping, 1000);
12
-
13
- function ping()
14
- {
15
- // Connect → immediately destroy the socket → NO write events
16
- const socket = net.connect(SOCKET, () => {
17
- if (Math.random() > 0.5) {
18
- socket.end('PING');
19
- }
20
- else {
21
- console.log('connected (no ping), closing immediately');
22
- socket.destroy(); // IMPORTANT: destroy() does not flush anything
23
- }
24
- });
25
- }
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ❌ 8. Client connects but NEVER sends PING
4
- // Simulates misbehaving client.
5
-
6
- const net = require('net');
7
-
8
- net.connect(process.env.WATCHDOG_SOCKET, () => {
9
- console.log('connected but no ping');
10
- // do nothing
11
- });
12
-
13
- setInterval(() => {}, 1000);
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ❌ 4. Client that exits immediately
4
- // Watchdog must detect child exit first.
5
-
6
- console.log('bye');
7
- process.exit(0);
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ❌ 7. Client that floods watchdog with 1GB of data
4
- // Outcome: watchdog must handle MASSIVE reads and still time out.
5
-
6
- const fs = require('fs');
7
- const net = require('net');
8
-
9
- const socket = net.connect(process.env.WATCHDOG_SOCKET, () => {
10
- console.log('connected');
11
- const stream = fs.createReadStream('/dev/zero');
12
- stream.pipe(socket);
13
- });
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ❌ 7. Client that floods watchdog with 1GB of data
4
- // Outcome: watchdog must handle MASSIVE reads and still time out.
5
-
6
- const fs = require('fs');
7
- const net = require('net');
8
-
9
- const socket = net.connect(process.env.WATCHDOG_SOCKET, () => {
10
- console.log('connected');
11
- const stream = fs.createReadStream('/dev/zero');
12
- stream.pipe(socket).on('error', () => 0);
13
- });
14
-
15
- setInterval(() => {}, 1000);
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ❌ 5. Client that freezes (event loop blocked)
4
- // Watchdog will not receive PINGs.
5
-
6
- while (true) {
7
- // infinite CPU loop
8
- }
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ❌ 10. Client sends heartbeats but with huge delay
4
- // Tests delayed heartbeat behavior.
5
- // Expected: watchdog should kill before that.
6
-
7
- const net = require('net');
8
-
9
- const INTERVAL = Number(process.env.WATCHDOG_INTERVAL || 1000);
10
-
11
- const socket = net.connect(process.env.WATCHDOG_SOCKET, () => {
12
- console.log('connected');
13
-
14
- setTimeout(() => {
15
- console.log('sending late heartbeat');
16
- socket.end('PING');
17
- }, INTERVAL * 10);
18
- });
@@ -1,29 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // 1️⃣ Client that ignores SIGTERM
4
- // Goal: process stays alive after SIGTERM and only dies on SIGKILL (exactly what pid_kill_grace should handle).
5
- //
6
- // What this tests for watchdog:
7
- // - watchdog sends SIGTERM → process prints “ignored” and keeps running.
8
- // - pid_kill_grace waits grace_timeout_ms, sees PID still alive, sends SIGKILL.
9
- // - Process must die after SIGKILL.
10
- // - Watchdog should log the whole sequence correctly.
11
- // This is a realistic scenario.
12
-
13
- console.log('PID:', process.pid);
14
-
15
- // Ignore SIGTERM
16
- process.on('SIGTERM', function () {
17
- console.log('SIGTERM received, but intentionally ignored');
18
- });
19
-
20
- // Still react to SIGINT (Ctrl+C) so you can stop it manually if needed
21
- process.on('SIGINT', function () {
22
- console.log('SIGINT received, exiting');
23
- process.exit(130);
24
- });
25
-
26
- // Keep process alive
27
- setInterval(() => {
28
- // simulate work
29
- }, 1000);
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ❌ 11. Client sends heartbeats sporadically (sometimes missing)
4
- // Simulates flaky client.
5
-
6
- const net = require('net');
7
-
8
- function randomDelay() {
9
- return Math.floor(Math.random() * 5000);
10
- }
11
-
12
- setTimeout(ping, randomDelay());
13
-
14
- function ping()
15
- {
16
- const socket = net.connect(process.env.WATCHDOG_SOCKET);
17
- socket.on('connect', () => {
18
- socket.end('PING');
19
- setTimeout(ping, randomDelay());
20
- });
21
- }
@@ -1,16 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const Promise = require('bluebird');
4
- const cli = require('../../cli');
5
- const ping_socket = require('../../ping_socket');
6
-
7
- cli(main);
8
-
9
- async function main()
10
- {
11
- for (let iter = 1, last = 2; iter <= last; ++iter) {
12
- await ping_socket(process.env.WATCHDOG_SOCKET);
13
- await Promise.delay(1000);
14
- }
15
- console.log('Bye!');
16
- }
@@ -1,16 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const Promise = require('bluebird');
4
- const cli = require('@vbarbarosh/node-helpers/src/cli');
5
- const ping_socket = require('@vbarbarosh/node-helpers/src/ping_socket');
6
-
7
- cli(main);
8
-
9
- async function main()
10
- {
11
- for (let i = 0; i < 100; ++i) {
12
- console.log('[client]', i);
13
- await ping_socket(process.env.WATCHDOG_SOCKET);
14
- await Promise.delay(1000);
15
- }
16
- }
@@ -1,22 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const Promise = require('bluebird');
4
- const cli = require('@vbarbarosh/node-helpers/src/cli');
5
- const now_human = require('@vbarbarosh/node-helpers/src/now_human');
6
-
7
- cli(main);
8
-
9
- async function main()
10
- {
11
- process.on('SIGTERM', function () {
12
- console.log(`[${now_human()}][ignore-sigterm] SIGTERM, ignoring...`);
13
- });
14
- process.on('SIGINT', function () {
15
- console.log(`[${now_human()}][ignore-sigterm] SIGINT, ignoring...`);
16
- });
17
-
18
- for (let iter = 1, last = 100; iter <= last; ++iter) {
19
- console.log(`[${now_human()}][ignore-sigterm] ${iter} of ${last}`);
20
- await Promise.delay(100);
21
- }
22
- }
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const Promise = require('bluebird');
4
- const cli = require('@vbarbarosh/node-helpers/src/cli');
5
- const now_human = require('@vbarbarosh/node-helpers/src/now_human');
6
-
7
- cli(main);
8
-
9
- async function main()
10
- {
11
- for (let iter = 1, last = 100; iter <= last; ++iter) {
12
- console.log(`[${now_human()}][never-ping] ${iter} of ${last}`);
13
- await Promise.delay(100);
14
- }
15
- }
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ❌ 2. Client that never sends heartbeat (expected: watchdog kills it)
4
-
5
- setInterval(() => {}, 1000); // alive but no PINGs
@@ -1,17 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ✅ 1. Client that works normally (sends correct PINGs)
4
-
5
- const net = require('net');
6
-
7
- const SOCKET = process.env.WATCHDOG_SOCKET;
8
- const INTERVAL = Number(process.env.WATCHDOG_INTERVAL || 1000);
9
-
10
- if (!SOCKET) throw new Error('WATCHDOG_SOCKET missing');
11
-
12
- setInterval(ping, INTERVAL / 2);
13
-
14
- function ping()
15
- {
16
- const socket = net.connect(SOCKET, () => socket.end('PING'));
17
- }
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const Promise = require('bluebird');
4
- const cli = require('../../cli');
5
- const ping_socket = require('../../ping_socket');
6
-
7
- cli(main);
8
-
9
- async function main()
10
- {
11
- for (let iter = 1, last = 2; iter <= last; ++iter) {
12
- await ping_socket(process.env.WATCHDOG_SOCKET);
13
- await Promise.delay(10);
14
- }
15
- }
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const Promise = require('bluebird');
4
- const cli = require('../../cli');
5
- const ping_socket = require('../../ping_socket');
6
-
7
- cli(main);
8
-
9
- async function main()
10
- {
11
- await ping_socket(process.env.WATCHDOG_SOCKET);
12
- while (true) {
13
- await Promise.delay(1000);
14
- }
15
- }
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ❌ 6. Client that spawns children
4
- // This tests your process group killing.
5
- // If watchdog does not kill the entire group, the sleeps will remain after watchdog exits.
6
-
7
- const {spawn} = require('child_process');
8
-
9
- spawn('sleep', ['9999'], {detached: false});
10
- spawn('sleep', ['9999'], {detached: false});
11
-
12
- console.log('spawned 2 children');
13
-
14
- setInterval(() => {}, 1000);
@@ -1,48 +0,0 @@
1
- const assert = require('assert');
2
- const pid_exists = require('../pid_exists');
3
- const shell_spawn = require('../shell_spawn');
4
- const stream = require('stream');
5
- const stream_each = require('../stream_each');
6
- const stream_lines = require('../stream_lines');
7
-
8
- // watchdog true -> race condition; true exists too quickly; bug in shell_spawn
9
-
10
- describe('watchdog', function () {
11
- this.timeout(1000);
12
- it('Happy Path', async function () {
13
- const env = {...process.env, WATCHDOG_INTERVAL: 100, __TESTING__: 1};
14
- const proc = shell_spawn([`${__dirname}/watchdog.js`, `${__dirname}/watchdog.d/quick-exit-after-2-pings.js`], {env});
15
- try {
16
- const stdout = [];
17
- await Promise.all([
18
- stream.promises.pipeline(proc.stdout, stream_lines(), stream_each(v => stdout.push(v))),
19
- proc.promise(),
20
- ]);
21
- assert.strictEqual(stdout.filter(v => v.includes('[watchdog_ping]')).length, 2);
22
- assert.strictEqual(stdout.filter(v => v.includes('[watchdog_end_ok] pings=2')).length, 1);
23
- }
24
- finally {
25
- if (pid_exists(proc.pid)) {
26
- process.kill(proc.pid, 'SIGTERM');
27
- }
28
- }
29
- });
30
- it('Hang after 1 ping', async function () {
31
- const env = {...process.env, WATCHDOG_INTERVAL: 100, __TESTING__: 1};
32
- const proc = shell_spawn([`${__dirname}/watchdog.js`, `${__dirname}/watchdog.d/quick-hang-after-1-ping.js`], {env});
33
- const stdout = [];
34
- try {
35
- await Promise.all([
36
- stream.promises.pipeline(proc.stdout, stream_lines(), stream_each(v => stdout.push(v))),
37
- assert.rejects(proc.promise().timeout(500), {message: 'Process terminated with code 124 and signal null'}),
38
- ]);
39
- assert.strictEqual(stdout.filter(v => v.includes('[watchdog_ping]')).length, 1);
40
- assert.strictEqual(stdout.filter(v => v.includes('[watchdog_end_error] pings=1 | No heartbeat for the last 100ms')).length, 1);
41
- }
42
- finally {
43
- if (pid_exists(proc.pid)) {
44
- process.kill(proc.pid, 'SIGTERM');
45
- }
46
- }
47
- });
48
- });
@@ -1,10 +0,0 @@
1
- const assert = require('assert');
2
- const crypto_decrypt_aes256 = require('./crypto_decrypt_aes256');
3
- const crypto_encrypt_aes256 = require('./crypto_encrypt_aes256');
4
-
5
- describe('crypto_encrypt_aes256', function () {
6
- it('should handle basic input', function () {
7
- const password = 'pass123';
8
- assert.deepStrictEqual(crypto_decrypt_aes256(password, crypto_encrypt_aes256(password, 'hello')).toString('utf8'), 'hello');
9
- });
10
- });
@@ -1,10 +0,0 @@
1
- const assert = require('assert');
2
- const crypto_hash_sha256 = require('./crypto_hash_sha256');
3
-
4
- describe('crypto_hash_sha256', function () {
5
- it('should handle basic input', function () {
6
- assert.deepStrictEqual(crypto_hash_sha256('').toString('hex'), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855');
7
- assert.deepStrictEqual(crypto_hash_sha256('1').toString('hex'), '6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b');
8
- assert.deepStrictEqual(crypto_hash_sha256('hello').toString('hex'), '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824');
9
- });
10
- });
@@ -1,40 +0,0 @@
1
- const assert = require('assert');
2
- const date_add_months = require('./date_add_months');
3
- const format_date_ymd = require('./format_date_ymd');
4
-
5
- const items = [
6
- ['2024/12/24', '2024/12/24', 0],
7
- ['2024/12/24', '2025/01/24', 1],
8
- ['2024/12/24', '2024/11/24', -1],
9
- ['2012/01/14', '2011/10/14', -3],
10
- ['2019/03/31', '2019/02/28', -1],
11
- ['2023/01/15', '2023/04/15', 3, 'Basic Positive Addition'],
12
- ['2023/05/15', '2023/03/15', -2, 'Basic Negative Addition'],
13
- ['2023/10/15', '2024/03/15', 5, 'Year Crossover (Positive)'],
14
- ['2023/03/15', '2022/10/15', -5, 'Year Crossover (Negative)'],
15
- ['2024/02/29', '2025/02/28', 12, 'Leap Year - Adding Months in Leap Year'],
16
- ['2024/03/01', '2023/03/01', -12, 'Negative Leap Year Crossover'],
17
- ['2023/01/31', '2023/02/28', 1, 'End of Month (31st to Shorter Month)'],
18
- ['2023/03/31', '2023/02/28', -1, 'End of Month Crossover (Negative)'],
19
- ['2023/06/15', '2023/06/15', 0, 'Zero Months Added'],
20
- ['2023/01/01', '2033/01/01', 120, 'Large Positive Addition'],
21
- ['2023/01/01', '2013/01/01', -120, 'Large Negative Addition'],
22
- ['2020/02/29', '2024/02/29', 48, 'Multiple Leap Years'],
23
- ['2023/12/15', '2024/01/15', 1, 'Adding to December'],
24
- ['2023/01/15', '2022/12/15', -1, 'Subtracting from January'],
25
- ['2023/05/31', '2023/06/30', 1, 'Day Preservation with Shorter Month'],
26
- ['2023/02/28', '2024/02/28', 12, 'Adding Months to February (Non-Leap Year)'],
27
- ['2024/03/01', '2023/02/01', -13, 'Negative Months Across Leap Year'],
28
- ['2000/01/01', '2030/01/01', 360, 'Multiple Decades'],
29
- ['1970/01/01', '2020/01/01', 600, 'Edge Case: Epoch Date'],
30
- ['3000/01/01', '2900/01/01', -1200, 'Far Future Date']
31
- ];
32
-
33
- describe('date_add_months', function () {
34
- items.forEach(function ([input, expected, months, message]) {
35
- it(`${input} → ${expected}`, function () {
36
- const d = date_add_months(new Date(input), months);
37
- assert.strictEqual(format_date_ymd(d), expected, message);
38
- });
39
- });
40
- });
@@ -1,14 +0,0 @@
1
- const assert = require('assert');
2
- const date_is_leap_year = require('./date_is_leap_year');
3
-
4
- describe('date_add_months', function () {
5
- it('Brute force', function () {
6
- for (let year = 100; year < 9999; ++year) {
7
- const d = new Date(`${year}/01/01 00:00:00`);
8
- const d2 = new Date(`${year}/02/29 00:00:00`);
9
- assert.strictEqual(d.getFullYear(), year);
10
- assert.strictEqual(d2.getFullYear(), year);
11
- assert.strictEqual(date_is_leap_year(d), d2.getMonth() === 1, year);
12
- }
13
- });
14
- });