@vbarbarosh/node-helpers 3.62.0 → 3.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,16 +1,38 @@
1
1
  A set of helpers for JavaScript/Node.js
2
2
 
3
- ![](img/node-helpers-by-chat-gpt.webp)
3
+
4
+ <p align="center">
5
+ <a href="https://github.com/vbarbarosh/node-helpers/actions"><img src="https://github.com/vbarbarosh/node-helpers/actions/workflows/node.js.yml/badge.svg" alt="@vbarbarosh/node-helpers CI status" /></a>
6
+ <a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/vbarbarosh/node-helpers" alt="License" /></a>
7
+ <a href="https://www.npmjs.com/package/@vbarbarosh/node-helpers" rel="nofollow"><img src="https://img.shields.io/npm/dw/@vbarbarosh/node-helpers.svg" alt="npm" /></a>
8
+ <a href="https://github.com/vbarbarosh/node-helpers" rel="nofollow"><img src="https://img.shields.io/github/stars/vbarbarosh/node-helpers" alt="stars" /></a>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <img src="img/node-helpers-by-chat-gpt.webp" style="max-height:400px;" />
13
+ </p>
4
14
 
5
15
  ## Installation
6
16
 
7
- npm install @vbarbarosh/node-helpers
17
+ ```sh
18
+ npm install @vbarbarosh/node-helpers
19
+ ```
20
+
21
+ A subset of `@vbarbarosh/node-helpers` is available for browser:
22
+
23
+ ```html
24
+ <script src="https://unpkg.com/@vbarbarosh/node-helpers@latest/dist/browser.js"></script>
25
+ ```
26
+
27
+ ⚠️ All supported functions are exposed globally.
8
28
 
9
29
  ## Test
10
30
 
11
- bin/test
31
+ ```sh
32
+ bin/test
33
+ ```
12
34
 
13
- ## Conventions
35
+ ## 📖 Conventions
14
36
 
15
37
  `concurrency` - limit for parallel processes.
16
38
 
@@ -0,0 +1,949 @@
1
+ /******/ (() => { // webpackBootstrap
2
+ /******/ var __webpack_modules__ = ({
3
+
4
+ /***/ "./src sync recursive \\b(array%7Cdate%7Chttp_delete%7Chttp_get_blob%7Chttp_get_buffer%7Chttp_get_json%7Chttp_get_utf8%7Chttp_head%7Chttp_patch_json%7Chttp_post_json%7Chttp_post_multipart%7Chttp_put_buffer%7Chttp_put_json%7Chttp_put_utf8%7Cidentity%7Cignore).*(?<%21\\.test)\\.js$":
5
+ /*!***********************************************************************************************************************************************************************************************************************************************************************************!*\
6
+ !*** ./src/ sync \b(array%7Cdate%7Chttp_delete%7Chttp_get_blob%7Chttp_get_buffer%7Chttp_get_json%7Chttp_get_utf8%7Chttp_head%7Chttp_patch_json%7Chttp_post_json%7Chttp_post_multipart%7Chttp_put_buffer%7Chttp_put_json%7Chttp_put_utf8%7Cidentity%7Cignore).*(?<%21\.test)\.js$ ***!
7
+ \***********************************************************************************************************************************************************************************************************************************************************************************/
8
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
9
+
10
+ var map = {
11
+ "./array_chunk.js": "./src/array_chunk.js",
12
+ "./array_gcd.js": "./src/array_gcd.js",
13
+ "./array_group.js": "./src/array_group.js",
14
+ "./array_group_map.js": "./src/array_group_map.js",
15
+ "./array_index.js": "./src/array_index.js",
16
+ "./array_max.js": "./src/array_max.js",
17
+ "./array_min.js": "./src/array_min.js",
18
+ "./array_permutations.js": "./src/array_permutations.js",
19
+ "./array_shuffle.js": "./src/array_shuffle.js",
20
+ "./array_sort.js": "./src/array_sort.js",
21
+ "./array_sort_other.js": "./src/array_sort_other.js",
22
+ "./array_sum.js": "./src/array_sum.js",
23
+ "./array_unique.js": "./src/array_unique.js",
24
+ "./array_unique_last.js": "./src/array_unique_last.js",
25
+ "./date_add_months.js": "./src/date_add_months.js",
26
+ "./date_is_leap_year.js": "./src/date_is_leap_year.js",
27
+ "./http_delete.js": "./src/http_delete.js",
28
+ "./http_get_blob.js": "./src/http_get_blob.js",
29
+ "./http_get_buffer.js": "./src/http_get_buffer.js",
30
+ "./http_get_json.js": "./src/http_get_json.js",
31
+ "./http_get_utf8.js": "./src/http_get_utf8.js",
32
+ "./http_head.js": "./src/http_head.js",
33
+ "./http_patch_json.js": "./src/http_patch_json.js",
34
+ "./http_post_json.js": "./src/http_post_json.js",
35
+ "./http_post_multipart.js": "./src/http_post_multipart.js",
36
+ "./http_put_buffer.js": "./src/http_put_buffer.js",
37
+ "./http_put_json.js": "./src/http_put_json.js",
38
+ "./http_put_utf8.js": "./src/http_put_utf8.js",
39
+ "./identity.js": "./src/identity.js",
40
+ "./ignore.js": "./src/ignore.js"
41
+ };
42
+
43
+
44
+ function webpackContext(req) {
45
+ var id = webpackContextResolve(req);
46
+ return __webpack_require__(id);
47
+ }
48
+ function webpackContextResolve(req) {
49
+ if(!__webpack_require__.o(map, req)) {
50
+ var e = new Error("Cannot find module '" + req + "'");
51
+ e.code = 'MODULE_NOT_FOUND';
52
+ throw e;
53
+ }
54
+ return map[req];
55
+ }
56
+ webpackContext.keys = function webpackContextKeys() {
57
+ return Object.keys(map);
58
+ };
59
+ webpackContext.resolve = webpackContextResolve;
60
+ module.exports = webpackContext;
61
+ webpackContext.id = "./src sync recursive \\b(array%7Cdate%7Chttp_delete%7Chttp_get_blob%7Chttp_get_buffer%7Chttp_get_json%7Chttp_get_utf8%7Chttp_head%7Chttp_patch_json%7Chttp_post_json%7Chttp_post_multipart%7Chttp_put_buffer%7Chttp_put_json%7Chttp_put_utf8%7Cidentity%7Cignore).*(?<%21\\.test)\\.js$";
62
+
63
+ /***/ }),
64
+
65
+ /***/ "./src/array_chunk.js":
66
+ /*!****************************!*\
67
+ !*** ./src/array_chunk.js ***!
68
+ \****************************/
69
+ /***/ ((module) => {
70
+
71
+ /**
72
+ * Split an array into chunks.
73
+ *
74
+ * @param array
75
+ * @param limit
76
+ * @returns {*[]}
77
+ */
78
+ function array_chunk(array = [], limit = 1)
79
+ {
80
+ if (limit < 1) {
81
+ throw new Error('Limit value should be greater than 1');
82
+ }
83
+
84
+ const out = [];
85
+ for (let i = 0, end = array.length; i < end; i += limit) {
86
+ out.push(array.slice(i, i + limit));
87
+ }
88
+ return out;
89
+ }
90
+
91
+ module.exports = array_chunk;
92
+
93
+
94
+ /***/ }),
95
+
96
+ /***/ "./src/array_gcd.js":
97
+ /*!**************************!*\
98
+ !*** ./src/array_gcd.js ***!
99
+ \**************************/
100
+ /***/ ((module) => {
101
+
102
+ // https://stackoverflow.com/a/39764792/1478566
103
+ function array_gcd(array, fn = Number)
104
+ {
105
+ return array.reduce((a,b) => gcd(fn(a), fn(b)));
106
+ }
107
+
108
+ // https://stackoverflow.com/a/39764792/1478566
109
+ function gcd(a, b)
110
+ {
111
+ if (b) {
112
+ return gcd(b, a % b);
113
+ }
114
+ return a;
115
+ }
116
+
117
+ module.exports = array_gcd;
118
+
119
+
120
+ /***/ }),
121
+
122
+ /***/ "./src/array_group.js":
123
+ /*!****************************!*\
124
+ !*** ./src/array_group.js ***!
125
+ \****************************/
126
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
127
+
128
+ const array_group_map = __webpack_require__(/*! ./array_group_map */ "./src/array_group_map.js");
129
+
130
+ /**
131
+ * Group items by common key and return an array of groups.
132
+ *
133
+ * @param array
134
+ * @param fn
135
+ * @returns {unknown[]}
136
+ */
137
+ function array_group(array, fn)
138
+ {
139
+ return Object.values(array_group_map(array, fn));
140
+ }
141
+
142
+ module.exports = array_group;
143
+
144
+
145
+ /***/ }),
146
+
147
+ /***/ "./src/array_group_map.js":
148
+ /*!********************************!*\
149
+ !*** ./src/array_group_map.js ***!
150
+ \********************************/
151
+ /***/ ((module) => {
152
+
153
+ /**
154
+ * Group items by common key and return an object of items grouped by key.
155
+ *
156
+ * @param array
157
+ * @param fn
158
+ * @returns {{}}
159
+ */
160
+ function array_group_map(array, fn)
161
+ {
162
+ const out = {};
163
+ array.forEach(function (item) {
164
+ const key = fn(item);
165
+ out[key] = out[key] || {key, items: []};
166
+ out[key].items.push(item);
167
+ });
168
+ return out;
169
+ }
170
+
171
+ module.exports = array_group_map;
172
+
173
+
174
+ /***/ }),
175
+
176
+ /***/ "./src/array_index.js":
177
+ /*!****************************!*\
178
+ !*** ./src/array_index.js ***!
179
+ \****************************/
180
+ /***/ ((module) => {
181
+
182
+ /**
183
+ * Usage:
184
+ * array_index(items, v => v.name)
185
+ *
186
+ * Seems, there is a native way to do it:
187
+ * Object.fromEntries(items.map(v => [v.name, v]));
188
+ */
189
+ function array_index(array, fn)
190
+ {
191
+ const out = {};
192
+ array.forEach(v => out[fn(v)] = v);
193
+ return out;
194
+ }
195
+
196
+ module.exports = array_index;
197
+
198
+
199
+ /***/ }),
200
+
201
+ /***/ "./src/array_max.js":
202
+ /*!**************************!*\
203
+ !*** ./src/array_max.js ***!
204
+ \**************************/
205
+ /***/ ((module) => {
206
+
207
+ /**
208
+ * Return first among maximum values.
209
+ *
210
+ * @param array
211
+ * @param fn
212
+ */
213
+ function array_max(array, fn = identity)
214
+ {
215
+ let out = null;
216
+ let out_value = null;
217
+ array.forEach(function (item) {
218
+ const item_value = fn(item);
219
+ if (item_value > out_value || out_value === null) {
220
+ out = item;
221
+ out_value = item_value;
222
+ }
223
+ });
224
+ return out;
225
+ }
226
+
227
+ function identity(value)
228
+ {
229
+ return value;
230
+ }
231
+
232
+ module.exports = array_max;
233
+
234
+
235
+ /***/ }),
236
+
237
+ /***/ "./src/array_min.js":
238
+ /*!**************************!*\
239
+ !*** ./src/array_min.js ***!
240
+ \**************************/
241
+ /***/ ((module) => {
242
+
243
+ /**
244
+ * Return first among minimum values.
245
+ *
246
+ * @param array
247
+ * @param fn
248
+ */
249
+ function array_min(array, fn = identity)
250
+ {
251
+ let out = null;
252
+ let out_value = null;
253
+ array.forEach(function (item) {
254
+ const item_value = fn(item);
255
+ if (item_value < out_value || out_value === null) {
256
+ out = item;
257
+ out_value = item_value;
258
+ }
259
+ });
260
+ return out;
261
+ }
262
+
263
+ function identity(value)
264
+ {
265
+ return value;
266
+ }
267
+
268
+ module.exports = array_min;
269
+
270
+
271
+ /***/ }),
272
+
273
+ /***/ "./src/array_permutations.js":
274
+ /*!***********************************!*\
275
+ !*** ./src/array_permutations.js ***!
276
+ \***********************************/
277
+ /***/ ((module) => {
278
+
279
+ // https://stackoverflow.com/a/37580979/23502239
280
+ function array_permutations(array)
281
+ {
282
+ var length = array.length,
283
+ out = [array.slice()],
284
+ c = new Array(length).fill(0),
285
+ i = 1, k, p;
286
+
287
+ while (i < length) {
288
+ if (c[i] < i) {
289
+ k = i % 2 && c[i];
290
+ p = array[i];
291
+ array[i] = array[k];
292
+ array[k] = p;
293
+ ++c[i];
294
+ i = 1;
295
+ out.push(array.slice());
296
+ }
297
+ else {
298
+ c[i] = 0;
299
+ ++i;
300
+ }
301
+ }
302
+ return out;
303
+ }
304
+
305
+ module.exports = array_permutations;
306
+
307
+
308
+ /***/ }),
309
+
310
+ /***/ "./src/array_shuffle.js":
311
+ /*!******************************!*\
312
+ !*** ./src/array_shuffle.js ***!
313
+ \******************************/
314
+ /***/ ((module) => {
315
+
316
+ /**
317
+ * Shuffles an array using Durstenfeld shuffle algorithm.
318
+ *
319
+ * Note: This function performs shuffle in-place. In order
320
+ * to get a shuffled copy use call slice before calling, e.g.
321
+ * array_shuffle(items.slice()).
322
+ *
323
+ * @param array
324
+ * @returns array
325
+ * @link https://stackoverflow.com/a/6274381/1478566
326
+ * @link https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
327
+ */
328
+ function array_shuffle(array)
329
+ {
330
+ for (let i = array.length; --i > 0; ) {
331
+ const j = Math.floor(Math.random() * (i + 1));
332
+ const x = array[i];
333
+ array[i] = array[j];
334
+ array[j] = x;
335
+ }
336
+ return array;
337
+ }
338
+
339
+ module.exports = array_shuffle;
340
+
341
+
342
+ /***/ }),
343
+
344
+ /***/ "./src/array_sort.js":
345
+ /*!***************************!*\
346
+ !*** ./src/array_sort.js ***!
347
+ \***************************/
348
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
349
+
350
+ const fcmp_strings = __webpack_require__(/*! ./fcmp_strings */ "./src/fcmp_strings.js");
351
+
352
+ /**
353
+ * Sort items in an `array`.
354
+ *
355
+ * @param array
356
+ * @param fn
357
+ * @param fcmp
358
+ * @returns {*}
359
+ */
360
+ function array_sort(array, fn = identity, fcmp = fcmp_strings)
361
+ {
362
+ return array.sort(function (a, b) {
363
+ return fcmp(fn(a), fn(b));
364
+ });
365
+ }
366
+
367
+ function identity(v)
368
+ {
369
+ return v;
370
+ }
371
+
372
+ module.exports = array_sort;
373
+
374
+
375
+ /***/ }),
376
+
377
+ /***/ "./src/array_sort_other.js":
378
+ /*!*********************************!*\
379
+ !*** ./src/array_sort_other.js ***!
380
+ \*********************************/
381
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
382
+
383
+ const fcmp_strings = __webpack_require__(/*! ./fcmp_strings */ "./src/fcmp_strings.js");
384
+
385
+ /**
386
+ * Sort items in an `array` at the same order as in `other`. Values which
387
+ * are not in the `other` are added to the end of the result defined by `fcmp`.
388
+ *
389
+ * @param array
390
+ * @param fn
391
+ * @param other
392
+ * @param fcmp
393
+ * @returns {*}
394
+ */
395
+ function array_sort_other(array, fn, other, fcmp = fcmp_strings)
396
+ {
397
+ const other_map = {};
398
+ other.forEach((v,i) => other_map[v] = i + 1);
399
+ return array.sort(function (a, b) {
400
+ const ax = other_map[fn(a)];
401
+ const bx = other_map[fn(b)];
402
+ if (ax && bx) {
403
+ return ax - bx;
404
+ }
405
+ if (ax) {
406
+ return -1;
407
+ }
408
+ if (bx) {
409
+ return 1;
410
+ }
411
+ return fcmp(a, b);
412
+ });
413
+ }
414
+
415
+ module.exports = array_sort_other;
416
+
417
+
418
+ /***/ }),
419
+
420
+ /***/ "./src/array_sum.js":
421
+ /*!**************************!*\
422
+ !*** ./src/array_sum.js ***!
423
+ \**************************/
424
+ /***/ ((module) => {
425
+
426
+ function array_sum(array, fn = Number)
427
+ {
428
+ let out = 0;
429
+ array.forEach(function (item) {
430
+ out += fn(item);
431
+ });
432
+ return out;
433
+ }
434
+
435
+ module.exports = array_sum;
436
+
437
+
438
+ /***/ }),
439
+
440
+ /***/ "./src/array_unique.js":
441
+ /*!*****************************!*\
442
+ !*** ./src/array_unique.js ***!
443
+ \*****************************/
444
+ /***/ ((module) => {
445
+
446
+ function array_unique(values)
447
+ {
448
+ const set = new Set();
449
+ return values.filter(function (item) {
450
+ if (set.has(item)) {
451
+ return false;
452
+ }
453
+ set.add(item);
454
+ return true;
455
+ });
456
+ }
457
+
458
+ module.exports = array_unique;
459
+
460
+
461
+ /***/ }),
462
+
463
+ /***/ "./src/array_unique_last.js":
464
+ /*!**********************************!*\
465
+ !*** ./src/array_unique_last.js ***!
466
+ \**********************************/
467
+ /***/ ((module) => {
468
+
469
+ /**
470
+ * Return only unique values. If there are many values - prefer last one.
471
+ *
472
+ * @param array
473
+ * @param fn
474
+ * @returns {*[]}
475
+ */
476
+ function array_unique_last(array, fn = identity)
477
+ {
478
+ const out = [];
479
+ const taken = {};
480
+ for (let i = array.length; --i >= 0; ) {
481
+ const item = array[i];
482
+ const pk = fn(item);
483
+ if (!taken[pk]) {
484
+ taken[pk] = true;
485
+ out.push(item);
486
+ }
487
+ }
488
+ return out.reverse();
489
+ }
490
+
491
+ function identity(value)
492
+ {
493
+ return value;
494
+ }
495
+
496
+ module.exports = array_unique_last;
497
+
498
+
499
+ /***/ }),
500
+
501
+ /***/ "./src/date_add_months.js":
502
+ /*!********************************!*\
503
+ !*** ./src/date_add_months.js ***!
504
+ \********************************/
505
+ /***/ ((module) => {
506
+
507
+ /**
508
+ * @link https://stackoverflow.com/a/7937257
509
+ */
510
+ function date_add_months(d, months)
511
+ {
512
+ if (!months) {
513
+ return d;
514
+ }
515
+
516
+ // https://github.com/briannesbitt/Carbon/blob/f01cfa96468f4c38325f507ab81a4f1d2cd93cfe/src/Carbon/Traits/Units.php#L360C1-L361C1
517
+ // > } elseif (isset($canOverflow, $day) && $canOverflow && $day !== $date?->day) {
518
+ // > $date = $date?->modify('last day of previous month');
519
+ // > }
520
+
521
+ const date0 = d.getDate();
522
+ d.setMonth(d.getMonth() + months);
523
+ if (d.getDate() !== date0) {
524
+ d.setDate(0);
525
+ }
526
+
527
+ return d;
528
+ }
529
+
530
+ module.exports = date_add_months;
531
+
532
+
533
+ /***/ }),
534
+
535
+ /***/ "./src/date_is_leap_year.js":
536
+ /*!**********************************!*\
537
+ !*** ./src/date_is_leap_year.js ***!
538
+ \**********************************/
539
+ /***/ ((module) => {
540
+
541
+ /**
542
+ * @link https://github.com/moment/moment/blob/18aba135ab927ffe7f868ee09276979bed6993a6/src/lib/utils/is-leap-year.js
543
+ * @link https://en.wikipedia.org/wiki/Leap_year
544
+ * > Each leap year has 366 days instead of 365. This extra leap day
545
+ * > occurs in each year that is a multiple of 4, except for years
546
+ * > evenly divisible by 100 but not by 400.
547
+ */
548
+ function date_is_leap_year(d)
549
+ {
550
+ const year = d.getFullYear();
551
+ // return (year % 4 === 0) && !(year % 100 === 0 && year % 400 !== 0);
552
+ return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
553
+ }
554
+
555
+ module.exports = date_is_leap_year;
556
+
557
+
558
+ /***/ }),
559
+
560
+ /***/ "./src/fcmp_strings.js":
561
+ /*!*****************************!*\
562
+ !*** ./src/fcmp_strings.js ***!
563
+ \*****************************/
564
+ /***/ ((module) => {
565
+
566
+ function fcmp_strings(a, b)
567
+ {
568
+ return String(a).localeCompare(b);
569
+ }
570
+
571
+ module.exports = fcmp_strings;
572
+
573
+
574
+ /***/ }),
575
+
576
+ /***/ "./src/http_delete.js":
577
+ /*!****************************!*\
578
+ !*** ./src/http_delete.js ***!
579
+ \****************************/
580
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
581
+
582
+ const axios = __webpack_require__(/*! axios */ "axios");
583
+
584
+ function http_delete(url, options)
585
+ {
586
+ return axios.delete(url, {responseType: 'json', ...options}).then(v => v.data);
587
+ }
588
+
589
+ module.exports = http_delete;
590
+
591
+
592
+ /***/ }),
593
+
594
+ /***/ "./src/http_get_blob.js":
595
+ /*!******************************!*\
596
+ !*** ./src/http_get_blob.js ***!
597
+ \******************************/
598
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
599
+
600
+ const axios = __webpack_require__(/*! axios */ "axios");
601
+
602
+ function http_get_blob(url, options)
603
+ {
604
+ return axios.get(url, {responseType: 'blob', ...options}).then(v => v.data);
605
+ }
606
+
607
+ module.exports = http_get_blob;
608
+
609
+
610
+ /***/ }),
611
+
612
+ /***/ "./src/http_get_buffer.js":
613
+ /*!********************************!*\
614
+ !*** ./src/http_get_buffer.js ***!
615
+ \********************************/
616
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
617
+
618
+ const axios = __webpack_require__(/*! axios */ "axios");
619
+
620
+ function http_get_buffer(url, options)
621
+ {
622
+ return axios.get(url, {responseType: 'arraybuffer', ...options}).then(v => v.data);
623
+ }
624
+
625
+ module.exports = http_get_buffer;
626
+
627
+
628
+ /***/ }),
629
+
630
+ /***/ "./src/http_get_json.js":
631
+ /*!******************************!*\
632
+ !*** ./src/http_get_json.js ***!
633
+ \******************************/
634
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
635
+
636
+ const axios = __webpack_require__(/*! axios */ "axios");
637
+
638
+ function http_get_json(url, options)
639
+ {
640
+ return axios.get(url, {responseType: 'json', ...options}).then(v => v.data);
641
+ }
642
+
643
+ module.exports = http_get_json;
644
+
645
+
646
+ /***/ }),
647
+
648
+ /***/ "./src/http_get_utf8.js":
649
+ /*!******************************!*\
650
+ !*** ./src/http_get_utf8.js ***!
651
+ \******************************/
652
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
653
+
654
+ const axios = __webpack_require__(/*! axios */ "axios");
655
+
656
+ function http_get_utf8(url, options)
657
+ {
658
+ return axios.get(url, {responseType: 'text', responseEncoding: 'utf8', ...options}).then(v => v.data);
659
+ }
660
+
661
+ module.exports = http_get_utf8;
662
+
663
+
664
+ /***/ }),
665
+
666
+ /***/ "./src/http_head.js":
667
+ /*!**************************!*\
668
+ !*** ./src/http_head.js ***!
669
+ \**************************/
670
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
671
+
672
+ const axios = __webpack_require__(/*! axios */ "axios");
673
+
674
+ function http_head(url, options)
675
+ {
676
+ return axios.head(url, options).then(v => v.request.res.headers);
677
+ }
678
+
679
+ module.exports = http_head;
680
+
681
+
682
+ /***/ }),
683
+
684
+ /***/ "./src/http_patch_json.js":
685
+ /*!********************************!*\
686
+ !*** ./src/http_patch_json.js ***!
687
+ \********************************/
688
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
689
+
690
+ const axios = __webpack_require__(/*! axios */ "axios");
691
+
692
+ function http_patch_json(url, body, options)
693
+ {
694
+ return axios.patch(url, body, options).then(v => v.data);
695
+ }
696
+
697
+ module.exports = http_patch_json;
698
+
699
+
700
+ /***/ }),
701
+
702
+ /***/ "./src/http_post_json.js":
703
+ /*!*******************************!*\
704
+ !*** ./src/http_post_json.js ***!
705
+ \*******************************/
706
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
707
+
708
+ const axios = __webpack_require__(/*! axios */ "axios");
709
+
710
+ function http_post_json(url, body, options)
711
+ {
712
+ return axios.post(url, body, options).then(v => v.data);
713
+ }
714
+
715
+ module.exports = http_post_json;
716
+
717
+
718
+ /***/ }),
719
+
720
+ /***/ "./src/http_post_multipart.js":
721
+ /*!************************************!*\
722
+ !*** ./src/http_post_multipart.js ***!
723
+ \************************************/
724
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
725
+
726
+ const FormData = __webpack_require__(/*! form-data */ "form-data");
727
+ const axios = __webpack_require__(/*! axios */ "axios");
728
+
729
+ // Provide examples for the following common tasks:
730
+ //
731
+ // * send plain text
732
+ // * send json
733
+ // * send image
734
+ // * send attachment
735
+
736
+ // import fetch from 'node-fetch';
737
+ //
738
+ // async function http_post_multipart(url, rows)
739
+ // {
740
+ // const form = new FormData();
741
+ // for (let i = 0, end = rows.length; i < end; ++i) {
742
+ // const {name, body} = rows[i];
743
+ // form.append(name, body);
744
+ // }
745
+ // return await fetch(url, {method: 'POST', body: form});
746
+ // }
747
+ //
748
+ // Example:
749
+ //
750
+ // const rows = [];
751
+ // rows.push({name: 'from', body: MAILGUN_FROM});
752
+ // rows.push({name: 'to', body: to});
753
+ // rows.push({name: 'subject', body: subject});
754
+ // rows.push({name: 'text', body: text});
755
+ // rows.push({name: 'attachment', body: fs_read_stream(__filename), options: {filename: 'hello.txt'}});
756
+ // return http_post_multipart(`${MAILGUN_BASE}/messages`, rows, options);
757
+
758
+ // https://github.com/axios/axios/issues/318#issuecomment-344620216
759
+ // https://github.com/axios/axios/issues/1006#issuecomment-320165427
760
+ function http_post_multipart(url, items, options)
761
+ {
762
+ const form = new FormData();
763
+ for (let i = 0, end = items.length; i < end; ++i) {
764
+ const item = items[i];
765
+ // Without this, all string vales (ordinary fields) will
766
+ // be empty in _Chrome 59.0.3071.86 (Official Build) (64-bit)_
767
+ if (item.options) {
768
+ form.append(item.name, item.body, item.options);
769
+ }
770
+ else {
771
+ form.append(item.name, item.body);
772
+ }
773
+ }
774
+ // For Node
775
+ // import FormData from 'form-data'
776
+ // noinspection JSUnresolvedVariable
777
+ if (form.getHeaders) {
778
+ const options2 = {...options};
779
+ options2.headers = {...options2.headers, ...form.getHeaders()};
780
+ return Promise.resolve(axios.post(url, form, options2)).then(v => v.data);
781
+ }
782
+ // For Browser
783
+ // webpack.config.js
784
+ // externals: {"form-data": "FormData"}
785
+ return Promise.resolve(axios.post(url, form, options)).then(v => v.data);
786
+ }
787
+
788
+ module.exports = http_post_multipart;
789
+
790
+
791
+ /***/ }),
792
+
793
+ /***/ "./src/http_put_buffer.js":
794
+ /*!********************************!*\
795
+ !*** ./src/http_put_buffer.js ***!
796
+ \********************************/
797
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
798
+
799
+ const axios = __webpack_require__(/*! axios */ "axios");
800
+
801
+ function http_put_buffer(url, body, options)
802
+ {
803
+ return axios.put(url, body, options).then(v => v.data);
804
+ }
805
+
806
+ module.exports = http_put_buffer;
807
+
808
+
809
+ /***/ }),
810
+
811
+ /***/ "./src/http_put_json.js":
812
+ /*!******************************!*\
813
+ !*** ./src/http_put_json.js ***!
814
+ \******************************/
815
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
816
+
817
+ const axios = __webpack_require__(/*! axios */ "axios");
818
+
819
+ function http_put_json(url, body, options)
820
+ {
821
+ return axios.put(url, body, options).then(v => v.data);
822
+ }
823
+
824
+ module.exports = http_put_json;
825
+
826
+
827
+ /***/ }),
828
+
829
+ /***/ "./src/http_put_utf8.js":
830
+ /*!******************************!*\
831
+ !*** ./src/http_put_utf8.js ***!
832
+ \******************************/
833
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
834
+
835
+ const axios = __webpack_require__(/*! axios */ "axios");
836
+
837
+ async function http_put_utf8(url, utf8, options)
838
+ {
839
+ return axios.put(url, utf8, options).then(v => v.data);
840
+ }
841
+
842
+ module.exports = http_put_utf8;
843
+
844
+
845
+ /***/ }),
846
+
847
+ /***/ "./src/identity.js":
848
+ /*!*************************!*\
849
+ !*** ./src/identity.js ***!
850
+ \*************************/
851
+ /***/ ((module) => {
852
+
853
+ function identity(value)
854
+ {
855
+ return value;
856
+ }
857
+
858
+ module.exports = identity;
859
+
860
+
861
+ /***/ }),
862
+
863
+ /***/ "./src/ignore.js":
864
+ /*!***********************!*\
865
+ !*** ./src/ignore.js ***!
866
+ \***********************/
867
+ /***/ ((module) => {
868
+
869
+ function ignore()
870
+ {
871
+ }
872
+
873
+ module.exports = ignore;
874
+
875
+
876
+ /***/ }),
877
+
878
+ /***/ "axios":
879
+ /*!************************!*\
880
+ !*** external "axios" ***!
881
+ \************************/
882
+ /***/ ((module) => {
883
+
884
+ "use strict";
885
+ module.exports = axios;
886
+
887
+ /***/ }),
888
+
889
+ /***/ "form-data":
890
+ /*!***************************!*\
891
+ !*** external "FormData" ***!
892
+ \***************************/
893
+ /***/ ((module) => {
894
+
895
+ "use strict";
896
+ module.exports = FormData;
897
+
898
+ /***/ })
899
+
900
+ /******/ });
901
+ /************************************************************************/
902
+ /******/ // The module cache
903
+ /******/ var __webpack_module_cache__ = {};
904
+ /******/
905
+ /******/ // The require function
906
+ /******/ function __webpack_require__(moduleId) {
907
+ /******/ // Check if module is in cache
908
+ /******/ var cachedModule = __webpack_module_cache__[moduleId];
909
+ /******/ if (cachedModule !== undefined) {
910
+ /******/ return cachedModule.exports;
911
+ /******/ }
912
+ /******/ // Create a new module (and put it into the cache)
913
+ /******/ var module = __webpack_module_cache__[moduleId] = {
914
+ /******/ // no module.id needed
915
+ /******/ // no module.loaded needed
916
+ /******/ exports: {}
917
+ /******/ };
918
+ /******/
919
+ /******/ // Execute the module function
920
+ /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
921
+ /******/
922
+ /******/ // Return the exports of the module
923
+ /******/ return module.exports;
924
+ /******/ }
925
+ /******/
926
+ /************************************************************************/
927
+ /******/ /* webpack/runtime/hasOwnProperty shorthand */
928
+ /******/ (() => {
929
+ /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
930
+ /******/ })();
931
+ /******/
932
+ /************************************************************************/
933
+ // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
934
+ (() => {
935
+ /*!******************************!*\
936
+ !*** ./src/browser/index.js ***!
937
+ \******************************/
938
+ // https://github.com/webpack/webpack/issues/625
939
+ // https://webpack.js.org/guides/dependency-management/#require-context
940
+ const require_tmp = __webpack_require__("./src sync recursive \\b(array%7Cdate%7Chttp_delete%7Chttp_get_blob%7Chttp_get_buffer%7Chttp_get_json%7Chttp_get_utf8%7Chttp_head%7Chttp_patch_json%7Chttp_post_json%7Chttp_post_multipart%7Chttp_put_buffer%7Chttp_put_json%7Chttp_put_utf8%7Cidentity%7Cignore).*(?<%21\\.test)\\.js$");
941
+ require_tmp.keys().forEach(function (key) {
942
+ const [, basename] = key.match(/([^/]+)\.js$/);
943
+ window[basename] = require_tmp(key);
944
+ });
945
+
946
+ })();
947
+
948
+ /******/ })()
949
+ ;
@@ -0,0 +1,19 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6
+ <link href="https://unpkg.com/@vbarbarosh/smcss@1.2.0/dist/reset.css" rel="stylesheet">
7
+ <link href="https://unpkg.com/@vbarbarosh/smcss@1.2.0/dist/sm.css" rel="stylesheet">
8
+ <title>@vbarbarsh/node-helpers</title>
9
+ </head>
10
+ <body>
11
+
12
+ <div id="app"></div>
13
+
14
+ <script src="https://unpkg.com/axios@1.7.9/dist/axios.js"></script>
15
+ <script src="https://unpkg.com/bluebird@3.7.2/js/browser/bluebird.js"></script>
16
+ <script src="browser.js"></script>
17
+
18
+ </body>
19
+ </html>
package/package.json CHANGED
@@ -2,13 +2,18 @@
2
2
  "author": "Vladimir Barbarosh <vladimir.barbarosh@gmail.com>",
3
3
  "license": "MIT",
4
4
  "name": "@vbarbarosh/node-helpers",
5
- "version": "3.62.0",
5
+ "version": "3.63.0",
6
6
  "description": "A set of helpers for JavaScript/Node.js",
7
+ "unpkg": "dist/browser.js",
8
+ "jsdelivr": "dist/browser.js",
9
+ "homepage": "https://vbarbarosh.github.io/node-helpers/",
7
10
  "files": [
11
+ "dist",
8
12
  "src"
9
13
  ],
10
14
  "scripts": {
11
- "test": "echo \"Error: no test specified\" && exit 1"
15
+ "build": "rm -rf dist; webpack",
16
+ "test": "mocha src/**/*.test.js"
12
17
  },
13
18
  "keywords": [
14
19
  "js",
@@ -29,17 +34,22 @@
29
34
  "form-data": "^4.0.1",
30
35
  "htmlparser2": "^10.0.0",
31
36
  "json-stable-stringify": "^1.2.1",
37
+ "json-stringify-safe": "^5.0.1",
32
38
  "mime-types": "^2.1.35",
33
39
  "sanitize-filename": "^1.6.3",
34
40
  "split": "^1.0.1",
35
41
  "ssh2": "^1.16.0"
36
42
  },
37
43
  "devDependencies": {
44
+ "copy-webpack-plugin": "^12.0.2",
45
+ "express": "^4.21.2",
38
46
  "mocha": "^11.0.1",
39
47
  "redis-v1": "npm:redis@1",
40
48
  "redis-v2": "npm:redis@2",
41
49
  "redis-v3": "npm:redis@3",
42
50
  "redis-v4": "npm:redis@4",
43
- "throttle": "^1.0.3"
51
+ "throttle": "^1.0.3",
52
+ "webpack": "^5.98.0",
53
+ "webpack-cli": "^6.0.1"
44
54
  }
45
55
  }
@@ -0,0 +1,13 @@
1
+ function array_unique(values)
2
+ {
3
+ const set = new Set();
4
+ return values.filter(function (item) {
5
+ if (set.has(item)) {
6
+ return false;
7
+ }
8
+ set.add(item);
9
+ return true;
10
+ });
11
+ }
12
+
13
+ module.exports = array_unique;
@@ -0,0 +1,7 @@
1
+ // https://github.com/webpack/webpack/issues/625
2
+ // https://webpack.js.org/guides/dependency-management/#require-context
3
+ const require_tmp = require.context('..', true, /\b(array|date|http_delete|http_get_blob|http_get_buffer|http_get_json|http_get_utf8|http_head|http_patch_json|http_post_json|http_post_multipart|http_put_buffer|http_put_json|http_put_utf8|identity|ignore).*(?<!\.test)\.js$/);
4
+ require_tmp.keys().forEach(function (key) {
5
+ const [, basename] = key.match(/([^/]+)\.js$/);
6
+ window[basename] = require_tmp(key);
7
+ });
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+
3
+ const axios = require('axios');
4
+ const cli = require('../../cli');
5
+ const express = require('express');
6
+ const fs_path_resolve = require('../../fs_path_resolve');
7
+ const fs_write = require('../../fs_write');
8
+ const json_stringify_safe = require('../../json_stringify_safe');
9
+
10
+ cli(main);
11
+
12
+ async function main()
13
+ {
14
+ const app = express();
15
+ app.get('/', (req, res) => {});
16
+ const server = app.listen(3000);
17
+
18
+ try {
19
+ await axios('http://127.0.0.1:3000', {timeout: 1});
20
+ }
21
+ catch (error) {
22
+ await fs_write(fs_path_resolve(__dirname, '../1.json'), json_stringify_safe(error, null, 4).replaceAll(fs_path_resolve(__dirname, '../../../..'), '/app'));
23
+ }
24
+
25
+ server.close();
26
+ }
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+
3
+ const axios = require('axios');
4
+ const cli = require('../../cli');
5
+ const express = require('express');
6
+ const fs_path_resolve = require('../../fs_path_resolve');
7
+ const fs_write = require('../../fs_write');
8
+ const json_stringify_safe = require('../../json_stringify_safe');
9
+
10
+ cli(main);
11
+
12
+ async function main()
13
+ {
14
+ const app = express();
15
+ app.post('/fail', function (req, res) {
16
+ throw new Error('Some Error Here');
17
+ });
18
+ const server = app.listen(3000);
19
+
20
+ try {
21
+ await axios.post('http://127.0.0.1:3000/fail');
22
+ }
23
+ catch (error) {
24
+ console.log(error);
25
+ await fs_write(fs_path_resolve(__dirname, '../2.json'), json_stringify_safe(error, null, 4).replaceAll(fs_path_resolve(__dirname, '../../../..'), '/app'));
26
+ }
27
+
28
+ server.close();
29
+ }
@@ -0,0 +1,65 @@
1
+ const json_stringify_safe = require('./json_stringify_safe');
2
+
3
+ function format_error_report(error)
4
+ {
5
+ if (!error) {
6
+ return json_stringify_safe({error: error === undefined ? '---undefined---' : error});
7
+ }
8
+
9
+ if (error.response?.status && error.response?.statusText && error.response?.config) {
10
+ return fm_axios_response(error);
11
+ }
12
+
13
+ if (error.config) {
14
+ return fm_axios_config(error);
15
+ }
16
+
17
+ return json_stringify_safe({
18
+ code: error.code,
19
+ name: error.name,
20
+ message: error.message ?? 'n/a',
21
+ stack: error.stack && error.stack.split(/\n\s*/)
22
+ }, null, 4);
23
+ }
24
+
25
+ function fm_axios_response(error)
26
+ {
27
+ return `
28
+ ${error.message ?? 'n/a'}
29
+
30
+ --- REQUEST ---
31
+
32
+ ${(error.response.config.method||'').toUpperCase()} ${error.response.config.url}
33
+
34
+ ${JSON.stringify(error.response.config.headers||{}, null, 4).slice(1, -1).replace(/^\s+|,$/mg, '').trim()}
35
+
36
+ --- RESPONSE ---
37
+
38
+ ${error.response.status} ${error.response.statusText}
39
+
40
+ ${(error.response.data.toString()||'').slice(0, 10240) || 'n/a'}
41
+
42
+ --- STACK ---
43
+
44
+ ${error.stack ? error.stack.split(/\\n\\s*/) : 'n/a'}
45
+ `.trimStart();
46
+ }
47
+
48
+ function fm_axios_config(error)
49
+ {
50
+ return `
51
+ ${error.message ?? 'n/a'}
52
+
53
+ --- REQUEST ---
54
+
55
+ ${(error.config.method||'').toUpperCase()} ${error.config.url}
56
+
57
+ ${JSON.stringify(error.config.headers||{}, null, 4).slice(1, -1).replace(/^\s+|,$/mg, '').trim()}
58
+
59
+ --- STACK ---
60
+
61
+ ${error.stack ? error.stack.split(/\\n\\s*/) : 'n/a'}
62
+ `.trimStart();
63
+ }
64
+
65
+ module.exports = format_error_report;
@@ -0,0 +1,3 @@
1
+ const json_stringify_safe = require('json-stringify-safe');
2
+
3
+ module.exports = json_stringify_safe;
@@ -18,6 +18,13 @@ const items = [
18
18
  ['% de disponibilidad de tiendas', 'de_disponibilidad_de_tiendas'],
19
19
  ['%Tiendas con precio moda', 'tiendas_con_precio_moda'],
20
20
 
21
+ // https://stackoverflow.com/questions/30521224/javascript-convert-pascalcase-to-underscore-case-snake-case
22
+ ['TypeOfData.AlphaBeta', 'type_of_data_alpha_beta'],
23
+ ['thisISDifficult', 'this_is_difficult'],
24
+ ['thisISNT', 'this_isnt'],
25
+ ['thisISNT', 'this_isnt'],
26
+ ['somethingEasyLikeThis', 'something_easy_like_this'],
27
+
21
28
  // https://github.com/Advanon/sanitize-s3-objectkey
22
29
  // https://github.com/hamxabaig/s3-filename
23
30
  // ['some 漢字 ćööł % #fíłéñàmé.jpg', 'some_cool_filename_jpg'],