tuijs-util 1.4.6 → 1.4.9

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/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "tuijs-util",
3
- "version": "1.4.6",
3
+ "version": "1.4.9",
4
4
  "module": "src/esm/index.js",
5
5
  "main": "src/cjs/index.cjs",
6
6
  "exports": {
7
- ".": {
8
- "import": "./src/esm/index.js",
9
- "require": "./src/cjs/index.cjs"
10
- }
7
+ ".": {
8
+ "import": "./src/esm/index.js",
9
+ "require": "./src/cjs/index.cjs"
10
+ }
11
11
  },
12
12
  "description": "A simple JavaScript utility library",
13
13
  "author": "TechTB LLC",
@@ -15,11 +15,12 @@
15
15
  "repository": "github:TechTB-OpenSource/tuijs-util",
16
16
  "type": "module",
17
17
  "scripts": {
18
- "build": "rollup -c rollup.config.js"
18
+ "build": "rollup -c rollup.config.js",
19
+ "list": "node bin\\index.js"
19
20
  },
20
21
  "devDependencies": {
21
22
  "@rollup/plugin-babel": "^6.0.4",
22
- "@rollup/plugin-node-resolve": "^16.0.0",
23
- "rollup": "^4.30.1"
23
+ "@rollup/plugin-node-resolve": "^16.0.1",
24
+ "rollup": "^4.37.0"
24
25
  }
25
- }
26
+ }
package/src/cjs/index.cjs CHANGED
@@ -27,6 +27,15 @@ const regExUrl = new RegExp('^(https?:\\/\\/)?' +
27
27
  // query string
28
28
  '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
29
29
  const regExEmail = /^[\w-\.]+@([\w-]+\.)+[a-zA-Z]{2,}$/;
30
+ const regExIpv4 = /^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$/;
31
+ const regExIpv6 = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
32
+ const regExMacNoSeparator = /^[0-9a-fA-F]{12}$/;
33
+ const regExMacHyphenPairs = /^[0-9a-fA-F]{2}(-[0-9a-fA-F]{2}){5}$/;
34
+ const regExMacHyphenQuads = /^[0-9a-fA-F]{4}(-[0-9a-fA-F]{4}){2}$/;
35
+ const regExMacDotPairs = /^[0-9a-fA-F]{2}(\.[0-9a-fA-F]{2}){5}$/;
36
+ const regExMacDotQuads = /^[0-9a-fA-F]{4}(\.[0-9a-fA-F]{4}){2}$/;
37
+ const regExMacColonPairs = /^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}$/;
38
+ const regExMacColonQuads = /^[0-9a-fA-F]{4}(:[0-9a-fA-F]{4}){2}$/;
30
39
 
31
40
  /**
32
41
  * Removes characters from a string based on a provided regex pattern.
@@ -78,12 +87,60 @@ function checkUrl(string) {
78
87
  return false;
79
88
  }
80
89
  ;
81
- return regExUrl.test(string); // Returns false if the url is invalid
90
+ return regExUrl.test(string);
82
91
  } catch (er) {
83
92
  console.error(er);
84
93
  }
85
94
  }
86
95
 
96
+ /**
97
+ * Checks for a valid Mac Address (Uses RegEx).
98
+ * @param {string} string
99
+ * @returns {boolean} - Returns true if test is successful and false if the string is not validated or the RegEx test fails.
100
+ */
101
+ function checkMac(string) {
102
+ if (typeof string !== 'string' || string.length === 0) {
103
+ return false;
104
+ }
105
+ if (regExMacNoSeparator.test(string) || regExMacColonPairs.test(string) || regExMacColonQuads.test(string) || regExMacHyphenPairs.test(string) || regExMacHyphenQuads.test(string) || regExMacDotPairs.test(string) || regExMacDotQuads.test(string)) {
106
+ return true;
107
+ }
108
+ return false;
109
+ }
110
+
111
+ /**
112
+ * Checks for a valid IP (Uses checkIpv4 and checkIpv6).
113
+ * @param {string} string
114
+ * @returns {boolean} - Returns true if test is successful and false if the string is not validated or the RegEx test fails.
115
+ */
116
+ function checkIp(string) {
117
+ return checkIpv4(string) || checkIpv6(string);
118
+ }
119
+
120
+ /**
121
+ * Checks for a valid IPv4 (Uses RegEx).
122
+ * @param {string} string
123
+ * @returns {boolean} - Returns true if test is successful and false if the string is not validated or the RegEx test fails.
124
+ */
125
+ function checkIpv4(string) {
126
+ if (typeof string !== 'string' || string.length === 0) {
127
+ return false;
128
+ }
129
+ return regExIpv4.test(string);
130
+ }
131
+
132
+ /**
133
+ * Checks for a valid IPv6 (Uses RegEx).
134
+ * @param {string} string
135
+ * @returns {boolean} - Returns true if test is successful and false if the string is not validated or the RegEx test fails.
136
+ */
137
+ function checkIpv6(string) {
138
+ if (typeof string !== 'string' || string.length === 0) {
139
+ return false;
140
+ }
141
+ return regExIpv6.test(string);
142
+ }
143
+
87
144
  /**
88
145
  * Checks for special characters (Uses RegEx).
89
146
  * @param {string} string
@@ -262,6 +319,39 @@ function checkIsFunction(input) {
262
319
  }
263
320
  }
264
321
 
322
+ /**
323
+ * Checks an input to determine if it is a valid subnet mask.
324
+ * @param {string} mask
325
+ * @returns {boolean} - Returns true if the input is a Function and false if not.
326
+ * @throws {Error} - Throws error message if error occurs.
327
+ */
328
+ function checkSubnetMask(mask) {
329
+ try {
330
+ if (typeof mask != 'string') {
331
+ return false;
332
+ }
333
+ const maskArray = mask.split('.').map(octet => parseInt(octet, 10));
334
+ if (maskArray.length !== 4) {
335
+ return false;
336
+ }
337
+ if (maskArray.some(num => Number.isNaN(num))) {
338
+ return false;
339
+ }
340
+ const binaryMask = maskArray.map(num => num.toString(2).padStart(8, '0')).join('');
341
+ if (/01.*10/.test(binaryMask)) {
342
+ return false;
343
+ }
344
+ for (let i = 0; i < maskArray.length; i++) {
345
+ if (maskArray[i] > 255 || maskArray[i] < 0) {
346
+ return false;
347
+ }
348
+ }
349
+ return true;
350
+ } catch (er) {
351
+ console.error(er);
352
+ }
353
+ }
354
+
265
355
  /**
266
356
  * Takes an HTML template literal, parses it, then extracts it.
267
357
  * All elements in the template MUST be contained within a single set of template tags.
@@ -385,21 +475,153 @@ function urlAddHttps(url) {
385
475
  }
386
476
  }
387
477
 
478
+ /**
479
+
480
+ */
481
+ function createReqInstance() {
482
+ let controllers = new Map();
483
+ function createController(id) {
484
+ if (controllers.has(id)) {
485
+ abortRequest(id); // Ensure previous request is aborted
486
+ }
487
+ const controller = new AbortController();
488
+ controllers.set(id, controller);
489
+ return controller.signal;
490
+ }
491
+ function abortRequest(id) {
492
+ if (controllers.has(id)) {
493
+ controllers.get(id).abort();
494
+ controllers.delete(id);
495
+ }
496
+ }
497
+ function abortAll() {
498
+ controllers.forEach(controller => controller.abort());
499
+ controllers.clear();
500
+ }
501
+ async function reqGet(url, id) {
502
+ try {
503
+ const signal = createController(id);
504
+ const res = await fetch(url, {
505
+ method: 'GET',
506
+ signal
507
+ });
508
+ return res;
509
+ } catch (er) {
510
+ if (er.name === 'AbortError') {
511
+ console.warn('Fetch aborted:', url);
512
+ } else {
513
+ console.error(er);
514
+ }
515
+ }
516
+ }
517
+ async function reqGetJson(url, id) {
518
+ try {
519
+ const signal = createController(id);
520
+ const res = await fetch(url, {
521
+ method: 'GET',
522
+ signal
523
+ });
524
+ return await res.json();
525
+ } catch (er) {
526
+ if (er.name === 'AbortError') {
527
+ console.warn('Fetch aborted:', url);
528
+ } else {
529
+ console.error(er);
530
+ }
531
+ }
532
+ }
533
+ async function reqGetText(url, id) {
534
+ try {
535
+ const signal = createController(id);
536
+ const res = await fetch(url, {
537
+ method: 'GET',
538
+ signal
539
+ });
540
+ return await res.text();
541
+ } catch (er) {
542
+ if (er.name === 'AbortError') {
543
+ console.warn('Fetch aborted:', url);
544
+ } else {
545
+ console.error(er);
546
+ }
547
+ }
548
+ }
549
+ async function reqPostJson(url, dataJson, id) {
550
+ try {
551
+ const signal = createController(id);
552
+ if (!dataJson || typeof dataJson !== 'object') {
553
+ throw new Error(`Invalid JSON data`);
554
+ }
555
+ const res = await fetch(url, {
556
+ method: 'POST',
557
+ headers: {
558
+ 'Content-Type': 'application/json'
559
+ },
560
+ body: JSON.stringify(dataJson),
561
+ signal
562
+ });
563
+ return res;
564
+ } catch (er) {
565
+ if (er.name === 'AbortError') {
566
+ console.warn('Fetch aborted:', url);
567
+ } else {
568
+ console.error(er);
569
+ }
570
+ }
571
+ }
572
+ async function reqPostForm(url, dataForm, id) {
573
+ try {
574
+ const signal = createController(id);
575
+ if (!(dataForm instanceof FormData)) {
576
+ throw new Error(`Provided data is not FormData`);
577
+ }
578
+ const res = await fetch(url, {
579
+ method: 'POST',
580
+ body: dataForm,
581
+ signal
582
+ });
583
+ return res;
584
+ } catch (er) {
585
+ if (er.name === 'AbortError') {
586
+ console.warn('Fetch aborted:', url);
587
+ } else {
588
+ console.error(er);
589
+ }
590
+ }
591
+ }
592
+ return {
593
+ createController,
594
+ abortRequest,
595
+ abortAll,
596
+ reqGet,
597
+ reqGetJson,
598
+ reqGetText,
599
+ reqPostJson,
600
+ reqPostForm
601
+ };
602
+ }
603
+
388
604
  /**
389
605
  * Sends GET request to specified URL
390
606
  * @async
391
607
  * @param {string} url
608
+ * @param { }
392
609
  * @returns {Promise<Object>} - Returns response if response is ok, otherwise it throws an Error.
393
610
  * @throws {Error} - Throws Error if an error is detected.
394
611
  */
395
- async function reqGet(url) {
612
+ async function reqGet(url, signal = null) {
396
613
  try {
397
614
  const res = await fetch(url, {
398
- method: 'GET'
615
+ method: 'GET',
616
+ signal
399
617
  });
400
618
  return res;
401
619
  } catch (er) {
402
- console.error(er);
620
+ if (er.name === 'AbortError') {
621
+ console.warn('Fetch aborted:', url);
622
+ } else {
623
+ console.error(er);
624
+ }
403
625
  }
404
626
  }
405
627
 
@@ -410,15 +632,19 @@ async function reqGet(url) {
410
632
  * @returns {Promise<Object>} - Returns data if response is ok, otherwise it throws an Error.
411
633
  * @throws {Error} - Throws Error if an error is detected.
412
634
  */
413
- async function reqGetJson(url) {
635
+ async function reqGetJson(url, signal = null) {
414
636
  try {
415
637
  const res = await fetch(url, {
416
- method: 'GET'
638
+ method: 'GET',
639
+ signal
417
640
  });
418
- const data = await res.json();
419
- return data;
641
+ return await res.json();
420
642
  } catch (er) {
421
- console.error(er);
643
+ if (er.name === 'AbortError') {
644
+ console.warn('Fetch aborted:', url);
645
+ } else {
646
+ console.error(er);
647
+ }
422
648
  }
423
649
  }
424
650
 
@@ -429,15 +655,19 @@ async function reqGetJson(url) {
429
655
  * @returns {Promise<Object>} - Returns data if response is ok, otherwise it throws an Error.
430
656
  * @throws {Error} - Throws Error if an error is detected.
431
657
  */
432
- async function reqGetText(url) {
658
+ async function reqGetText(url, signal = null) {
433
659
  try {
434
660
  const res = await fetch(url, {
435
- method: 'GET'
661
+ method: 'GET',
662
+ signal
436
663
  });
437
- const data = await res.text();
438
- return data;
664
+ return await res.text();
439
665
  } catch (er) {
440
- console.error(er);
666
+ if (er.name === 'AbortError') {
667
+ console.warn('Fetch aborted:', url);
668
+ } else {
669
+ console.error(er);
670
+ }
441
671
  }
442
672
  }
443
673
 
@@ -449,24 +679,26 @@ async function reqGetText(url) {
449
679
  * @returns {Promise<Object>} - Returns response if response is ok, otherwise it throws an Error.
450
680
  * @throws {Error} - Throws Error if an error is detected.
451
681
  */
452
- async function reqPostJson(url, dataJson) {
682
+ async function reqPostJson(url, dataJson, signal = null) {
453
683
  try {
454
- if (dataJson === null || dataJson === undefined) {
455
- throw new Error(`No data provided.`);
456
- }
457
- if (!checkIsJson(dataJson)) {
458
- throw new Error(`Provided data is not JSON.`);
684
+ if (!dataJson || typeof dataJson !== 'object') {
685
+ throw new Error(`Invalid JSON data`);
459
686
  }
460
687
  const res = await fetch(url, {
461
688
  method: 'POST',
462
689
  headers: {
463
690
  'Content-Type': 'application/json'
464
691
  },
465
- body: dataJson
692
+ body: JSON.stringify(dataJson),
693
+ signal
466
694
  });
467
695
  return res;
468
696
  } catch (er) {
469
- console.error(er);
697
+ if (er.name === 'AbortError') {
698
+ console.warn('Fetch aborted:', url);
699
+ } else {
700
+ console.error(er);
701
+ }
470
702
  }
471
703
  }
472
704
 
@@ -477,18 +709,23 @@ async function reqPostJson(url, dataJson) {
477
709
  * @returns {Promise<Object>} - Returns response if response is ok, otherwise it throws an Error.
478
710
  * @throws {Error} - Throws Error if an error is detected.
479
711
  */
480
- async function reqPostForm(url, dataForm) {
712
+ async function reqPostForm(url, dataForm, signal = null) {
481
713
  try {
482
714
  if (!(dataForm instanceof FormData)) {
483
- throw new Error(`The data provided was not form data`);
715
+ throw new Error(`Provided data is not FormData`);
484
716
  }
485
717
  const res = await fetch(url, {
486
718
  method: 'POST',
487
- body: dataForm
719
+ body: dataForm,
720
+ signal
488
721
  });
489
722
  return res;
490
723
  } catch (er) {
491
- console.error(er);
724
+ if (er.name === 'AbortError') {
725
+ console.warn('Fetch aborted:', url);
726
+ } else {
727
+ console.error(er);
728
+ }
492
729
  }
493
730
  }
494
731
 
@@ -497,6 +734,207 @@ const listUpChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
497
734
  const listLowChar = 'abcdefghijklmnopqrstuvwxyz';
498
735
  const listSpecChar = '!@#$%^&*()';
499
736
  const listHtmlTags = ["html", "body", "div", "span", "applet", "object", "iframe", "h1", "h2", "h3", "h4", "h5", "h6", "p", "blockquote", "pre", "a", "abbr", "acronym", "address", "big", "cite", "code", "del", "dfn", "em", "img", "ins", "kbd", "q", "s", "samp", "small", "strike", "strong", "sub", "sup", "tt", "var", "b", "u", "i", "center", "dl", "dt", "dd", "ol", "ul", "li", "fieldset", "form", "label", "legend", "table", "caption", "tbody", "tfoot", "thead", "tr", "th", "td", "article", "aside", "canvas", "details", "embed", "figure", "figcaption", "footer", "header", "hgroup", "menu", "nav", "output", "ruby", "section", "summary", "time", "mark", "audio", "video"];
737
+ const listSubnets = [{
738
+ bits: 8,
739
+ cidr: '/8',
740
+ subnetMask: '255.0.0.0',
741
+ wildcardMask: '0.255.255.255',
742
+ totalAddresses: 16_777_216,
743
+ usableHosts: 16_777_214,
744
+ networks: 1
745
+ }, {
746
+ bits: 9,
747
+ cidr: '/9',
748
+ subnetMask: '255.128.0.0',
749
+ wildcardMask: '0.127.255.255',
750
+ totalAddresses: 8_388_608,
751
+ usableHosts: 8_388_606,
752
+ networks: 2
753
+ }, {
754
+ bits: 10,
755
+ cidr: '/10',
756
+ subnetMask: '255.192.0.0',
757
+ wildcardMask: '0.63.255.255',
758
+ totalAddresses: 4_194_304,
759
+ usableHosts: 4_194_302,
760
+ networks: 4
761
+ }, {
762
+ bits: 11,
763
+ cidr: '/11',
764
+ subnetMask: '255.224.0.0',
765
+ wildcardMask: '0.31.255.255',
766
+ totalAddresses: 2_097_152,
767
+ usableHosts: 2_097_150,
768
+ networks: 8
769
+ }, {
770
+ bits: 12,
771
+ cidr: '/12',
772
+ subnetMask: '255.240.0.0',
773
+ wildcardMask: '0.15.255.255',
774
+ totalAddresses: 1_048_576,
775
+ usableHosts: 1_048_574,
776
+ networks: 16
777
+ }, {
778
+ bits: 13,
779
+ cidr: '/13',
780
+ subnetMask: '255.248.0.0',
781
+ wildcardMask: '0.7.255.255',
782
+ totalAddresses: 524_288,
783
+ usableHosts: 524_286,
784
+ networks: 32
785
+ }, {
786
+ bits: 14,
787
+ cidr: '/14',
788
+ subnetMask: '255.252.0.0',
789
+ wildcardMask: '0.3.255.255',
790
+ totalAddresses: 262_144,
791
+ usableHosts: 262_142,
792
+ networks: 64
793
+ }, {
794
+ bits: 15,
795
+ cidr: '/15',
796
+ subnetMask: '255.254.0.0',
797
+ wildcardMask: '0.1.255.255',
798
+ totalAddresses: 131_072,
799
+ usableHosts: 131_070,
800
+ networks: 128
801
+ }, {
802
+ bits: 16,
803
+ cidr: '/16',
804
+ subnetMask: '255.255.0.0',
805
+ wildcardMask: '0.0.255.255',
806
+ totalAddresses: 65_536,
807
+ usableHosts: 65_534,
808
+ networks: 256
809
+ }, {
810
+ bits: 17,
811
+ cidr: '/17',
812
+ subnetMask: '255.255.128.0',
813
+ wildcardMask: '0.0.127.255',
814
+ totalAddresses: 32_768,
815
+ usableHosts: 32_766,
816
+ networks: 512
817
+ }, {
818
+ bits: 18,
819
+ cidr: '/18',
820
+ subnetMask: '255.255.192.0',
821
+ wildcardMask: '0.0.63.255',
822
+ totalAddresses: 16_384,
823
+ usableHosts: 16_382,
824
+ networks: 1_024
825
+ }, {
826
+ bits: 19,
827
+ cidr: '/19',
828
+ subnetMask: '255.255.224.0',
829
+ wildcardMask: '0.0.31.255',
830
+ totalAddresses: 8_192,
831
+ usableHosts: 8_190,
832
+ networks: 2_048
833
+ }, {
834
+ bits: 20,
835
+ cidr: '/20',
836
+ subnetMask: '255.255.240.0',
837
+ wildcardMask: '0.0.15.255',
838
+ totalAddresses: 4_096,
839
+ usableHosts: 4_094,
840
+ networks: 4_096
841
+ }, {
842
+ bits: 21,
843
+ cidr: '/21',
844
+ subnetMask: '255.255.248.0',
845
+ wildcardMask: '0.0.7.255',
846
+ totalAddresses: 2_048,
847
+ usableHosts: 2_046,
848
+ networks: 8_192
849
+ }, {
850
+ bits: 22,
851
+ cidr: '/22',
852
+ subnetMask: '255.255.252.0',
853
+ wildcardMask: '0.0.3.255',
854
+ totalAddresses: 1_024,
855
+ usableHosts: 1_022,
856
+ networks: 16_384
857
+ }, {
858
+ bits: 23,
859
+ cidr: '/23',
860
+ subnetMask: '255.255.254.0',
861
+ wildcardMask: '0.0.1.255',
862
+ totalAddresses: 512,
863
+ usableHosts: 510,
864
+ networks: 32_768
865
+ }, {
866
+ bits: 24,
867
+ cidr: '/24',
868
+ subnetMask: '255.255.255.0',
869
+ wildcardMask: '0.0.0.255',
870
+ totalAddresses: 256,
871
+ usableHosts: 254,
872
+ networks: 65_536
873
+ }, {
874
+ bits: 25,
875
+ cidr: '/25',
876
+ subnetMask: '255.255.255.128',
877
+ wildcardMask: '0.0.0.127',
878
+ totalAddresses: 128,
879
+ usableHosts: 126,
880
+ networks: 131_072
881
+ }, {
882
+ bits: 26,
883
+ cidr: '/26',
884
+ subnetMask: '255.255.255.192',
885
+ wildcardMask: '0.0.0.63',
886
+ totalAddresses: 64,
887
+ usableHosts: 62,
888
+ networks: 262_144
889
+ }, {
890
+ bits: 27,
891
+ cidr: '/27',
892
+ subnetMask: '255.255.255.224',
893
+ wildcardMask: '0.0.0.31',
894
+ totalAddresses: 32,
895
+ usableHosts: 30,
896
+ networks: 524_288
897
+ }, {
898
+ bits: 28,
899
+ cidr: '/28',
900
+ subnetMask: '255.255.255.240',
901
+ wildcardMask: '0.0.0.15',
902
+ totalAddresses: 16,
903
+ usableHosts: 14,
904
+ networks: 1_048_576
905
+ }, {
906
+ bits: 29,
907
+ cidr: '/29',
908
+ subnetMask: '255.255.255.248',
909
+ wildcardMask: '0.0.0.7',
910
+ totalAddresses: 8,
911
+ usableHosts: 6,
912
+ networks: 2_097_152
913
+ }, {
914
+ bits: 30,
915
+ cidr: '/30',
916
+ subnetMask: '255.255.255.252',
917
+ wildcardMask: '0.0.0.3',
918
+ totalAddresses: 4,
919
+ usableHosts: 2,
920
+ networks: 4_194_304
921
+ }, {
922
+ bits: 31,
923
+ cidr: '/31',
924
+ subnetMask: '255.255.255.254',
925
+ wildcardMask: '0.0.0.1',
926
+ totalAddresses: 2,
927
+ usableHosts: '2 (P2P)',
928
+ networks: 8_388_608
929
+ }, {
930
+ bits: 32,
931
+ cidr: '/32',
932
+ subnetMask: '255.255.255.255',
933
+ wildcardMask: '0.0.0.0',
934
+ totalAddresses: 1,
935
+ usableHosts: 0,
936
+ networks: 16_777_216
937
+ }];
500
938
 
501
939
  /**
502
940
  * Adds zero in front of numbers less than 10 and returns as a string.
@@ -611,6 +1049,33 @@ function scrollIntoView() {
611
1049
  removeAllObservers
612
1050
  };
613
1051
  }
1052
+ function convertBitsToMask(bits) {
1053
+ try {
1054
+ if (bits < 0 || bits > 32) {
1055
+ throw new Error("Bits must be between 0 and 32");
1056
+ }
1057
+ const mask = 0xffffffff << 32 - bits >>> 0;
1058
+ return [mask >>> 24 & 0xff, mask >>> 16 & 0xff, mask >>> 8 & 0xff, mask & 0xff].join('.');
1059
+ } catch (er) {
1060
+ console.error(er);
1061
+ return;
1062
+ }
1063
+ }
1064
+ function convertMaskToBits(mask) {
1065
+ try {
1066
+ if (!checkSubnetMask(mask)) {
1067
+ throw new Error("Invalid subnet mask.");
1068
+ }
1069
+ return maskArray.map(num => num.toString(2).padStart(8, '0')) // ['11111111', '11111111', '11111111', '00000000']
1070
+ .join('') // '11111111111111111111111100000000'
1071
+ .split('') // ['1','1','1',...,'0','0']
1072
+ .filter(bit => bit === '1') // Keep only the '1's
1073
+ .length; // Count them
1074
+ } catch (er) {
1075
+ console.error(er);
1076
+ return;
1077
+ }
1078
+ }
614
1079
 
615
1080
  /**
616
1081
  * Parses a function and its parameters when it is in the form of a string.
@@ -645,17 +1110,25 @@ function parseFunctionString(string) {
645
1110
  exports.addLeadZero = addLeadZero;
646
1111
  exports.checkEmail = checkEmail;
647
1112
  exports.checkFqdn = checkFqdn;
1113
+ exports.checkIp = checkIp;
1114
+ exports.checkIpv4 = checkIpv4;
1115
+ exports.checkIpv6 = checkIpv6;
648
1116
  exports.checkIsArray = checkIsArray;
649
1117
  exports.checkIsElement = checkIsElement;
650
1118
  exports.checkIsFunction = checkIsFunction;
651
1119
  exports.checkIsJson = checkIsJson;
652
1120
  exports.checkIsObject = checkIsObject;
653
1121
  exports.checkLowercase = checkLowercase;
1122
+ exports.checkMac = checkMac;
654
1123
  exports.checkNum = checkNum;
655
1124
  exports.checkSpaces = checkSpaces;
656
1125
  exports.checkSpecialChar = checkSpecialChar;
1126
+ exports.checkSubnetMask = checkSubnetMask;
657
1127
  exports.checkUppercase = checkUppercase;
658
1128
  exports.checkUrl = checkUrl;
1129
+ exports.convertBitsToMask = convertBitsToMask;
1130
+ exports.convertMaskToBits = convertMaskToBits;
1131
+ exports.createReqInstance = createReqInstance;
659
1132
  exports.elmCleaner = elmCleaner;
660
1133
  exports.elmCleanerArray = elmCleanerArray;
661
1134
  exports.elmCleanerTr = elmCleanerTr;
@@ -664,6 +1137,7 @@ exports.listHtmlTags = listHtmlTags;
664
1137
  exports.listLowChar = listLowChar;
665
1138
  exports.listNumChar = listNumChar;
666
1139
  exports.listSpecChar = listSpecChar;
1140
+ exports.listSubnets = listSubnets;
667
1141
  exports.listUpChar = listUpChar;
668
1142
  exports.parseFunctionString = parseFunctionString;
669
1143
  exports.parseTemplate = parseTemplate;
@@ -676,9 +1150,18 @@ exports.regExFqdn = regExFqdn;
676
1150
  exports.regExHex = regExHex;
677
1151
  exports.regExHexChar = regExHexChar;
678
1152
  exports.regExHexNon = regExHexNon;
1153
+ exports.regExIpv4 = regExIpv4;
1154
+ exports.regExIpv6 = regExIpv6;
679
1155
  exports.regExLetters = regExLetters;
680
1156
  exports.regExLettersLower = regExLettersLower;
681
1157
  exports.regExLettersUpper = regExLettersUpper;
1158
+ exports.regExMacColonPairs = regExMacColonPairs;
1159
+ exports.regExMacColonQuads = regExMacColonQuads;
1160
+ exports.regExMacDotPairs = regExMacDotPairs;
1161
+ exports.regExMacDotQuads = regExMacDotQuads;
1162
+ exports.regExMacHyphenPairs = regExMacHyphenPairs;
1163
+ exports.regExMacHyphenQuads = regExMacHyphenQuads;
1164
+ exports.regExMacNoSeparator = regExMacNoSeparator;
682
1165
  exports.regExNumbers = regExNumbers;
683
1166
  exports.regExSpecial = regExSpecial;
684
1167
  exports.regExUrl = regExUrl;
package/src/esm/index.js CHANGED
@@ -1,15 +1,20 @@
1
1
  export {
2
2
  checkEmail,
3
3
  checkFqdn,
4
+ checkIp,
5
+ checkIpv4,
6
+ checkIpv6,
4
7
  checkIsArray,
5
8
  checkIsElement,
6
9
  checkIsFunction,
7
10
  checkIsJson,
8
11
  checkIsObject,
9
12
  checkLowercase,
13
+ checkMac,
10
14
  checkNum,
11
15
  checkSpaces,
12
16
  checkSpecialChar,
17
+ checkSubnetMask,
13
18
  checkUppercase,
14
19
  checkUrl
15
20
  } from './lib/util.check.js';
@@ -20,6 +25,7 @@ export {
20
25
  parseTemplate,
21
26
  } from './lib/util.dom.js';
22
27
  export {
28
+ createReqInstance,
23
29
  reqGet,
24
30
  reqGetJson,
25
31
  reqGetText,
@@ -33,14 +39,17 @@ export {
33
39
  listLowChar,
34
40
  listNumChar,
35
41
  listSpecChar,
42
+ listSubnets,
36
43
  listUpChar
37
44
  } from './lib/util.lists.js';
38
45
  export {
39
46
  addLeadZero,
47
+ convertBitsToMask,
48
+ convertMaskToBits,
40
49
  generateUID,
41
50
  preloadImages,
42
- sleep,
43
- scrollIntoView
51
+ scrollIntoView,
52
+ sleep
44
53
  } from './lib/util.misc.js';
45
54
  export {
46
55
  parseFunctionString
@@ -54,9 +63,18 @@ export {
54
63
  regExHex,
55
64
  regExHexChar,
56
65
  regExHexNon,
66
+ regExIpv4,
67
+ regExIpv6,
57
68
  regExLetters,
58
69
  regExLettersLower,
59
70
  regExLettersUpper,
71
+ regExMacColonPairs,
72
+ regExMacColonQuads,
73
+ regExMacDotPairs,
74
+ regExMacDotQuads,
75
+ regExMacHyphenPairs,
76
+ regExMacHyphenQuads,
77
+ regExMacNoSeparator,
60
78
  regExNumbers,
61
79
  regExSpecial,
62
80
  regExUrl,
@@ -1,4 +1,21 @@
1
- import { regExNumbers, regExLettersLower, regExLettersUpper, regExSpecial, regExFqdn, regExUrl, regExEmail } from "./util.regex.js";
1
+ import {
2
+ regExNumbers,
3
+ regExLettersLower,
4
+ regExLettersUpper,
5
+ regExSpecial,
6
+ regExFqdn,
7
+ regExUrl,
8
+ regExEmail,
9
+ regExIpv4,
10
+ regExIpv6,
11
+ regExMacNoSeparator,
12
+ regExMacColonPairs,
13
+ regExMacColonQuads,
14
+ regExMacHyphenPairs,
15
+ regExMacHyphenQuads,
16
+ regExMacDotPairs,
17
+ regExMacDotQuads
18
+ } from "./util.regex.js";
2
19
 
3
20
  /**
4
21
  * Checks for a valid FQDN (Uses RegEx).
@@ -29,12 +46,68 @@ export function checkUrl(string) {
29
46
  if (typeof string !== 'string' || string.length === 0) {
30
47
  return false;
31
48
  };
32
- return regExUrl.test(string); // Returns false if the url is invalid
49
+ return regExUrl.test(string);
33
50
  } catch (er) {
34
51
  console.error(er);
35
52
  }
36
53
  }
37
54
 
55
+ /**
56
+ * Checks for a valid Mac Address (Uses RegEx).
57
+ * @param {string} string
58
+ * @returns {boolean} - Returns true if test is successful and false if the string is not validated or the RegEx test fails.
59
+ */
60
+ export function checkMac(string) {
61
+ if (typeof string !== 'string' || string.length === 0) {
62
+ return false;
63
+ }
64
+ if (
65
+ regExMacNoSeparator.test(string) ||
66
+ regExMacColonPairs.test(string) ||
67
+ regExMacColonQuads.test(string) ||
68
+ regExMacHyphenPairs.test(string) ||
69
+ regExMacHyphenQuads.test(string) ||
70
+ regExMacDotPairs.test(string) ||
71
+ regExMacDotQuads.test(string)
72
+ ) {
73
+ return true;
74
+ }
75
+ return false;
76
+ }
77
+
78
+ /**
79
+ * Checks for a valid IP (Uses checkIpv4 and checkIpv6).
80
+ * @param {string} string
81
+ * @returns {boolean} - Returns true if test is successful and false if the string is not validated or the RegEx test fails.
82
+ */
83
+ export function checkIp(string) {
84
+ return checkIpv4(string) || checkIpv6(string);
85
+ }
86
+
87
+ /**
88
+ * Checks for a valid IPv4 (Uses RegEx).
89
+ * @param {string} string
90
+ * @returns {boolean} - Returns true if test is successful and false if the string is not validated or the RegEx test fails.
91
+ */
92
+ export function checkIpv4(string) {
93
+ if (typeof string !== 'string' || string.length === 0) {
94
+ return false;
95
+ }
96
+ return regExIpv4.test(string);
97
+ }
98
+
99
+ /**
100
+ * Checks for a valid IPv6 (Uses RegEx).
101
+ * @param {string} string
102
+ * @returns {boolean} - Returns true if test is successful and false if the string is not validated or the RegEx test fails.
103
+ */
104
+ export function checkIpv6(string) {
105
+ if (typeof string !== 'string' || string.length === 0) {
106
+ return false;
107
+ }
108
+ return regExIpv6.test(string);
109
+ }
110
+
38
111
  /**
39
112
  * Checks for special characters (Uses RegEx).
40
113
  * @param {string} string
@@ -212,3 +285,38 @@ export function checkIsFunction(input) {
212
285
  console.error(er);
213
286
  }
214
287
  }
288
+
289
+ /**
290
+ * Checks an input to determine if it is a valid subnet mask.
291
+ * @param {string} mask
292
+ * @returns {boolean} - Returns true if the input is a Function and false if not.
293
+ * @throws {Error} - Throws error message if error occurs.
294
+ */
295
+ export function checkSubnetMask(mask) {
296
+ try {
297
+ if (typeof mask != 'string') {
298
+ return false;
299
+ }
300
+ const maskArray = mask.split('.').map(octet => parseInt(octet, 10));
301
+ if (maskArray.length !== 4) {
302
+ return false;
303
+ }
304
+ if (maskArray.some(num => Number.isNaN(num))) {
305
+ return false;
306
+ }
307
+ const binaryMask = maskArray
308
+ .map(num => num.toString(2).padStart(8, '0'))
309
+ .join('');
310
+ if (/01.*10/.test(binaryMask)) {
311
+ return false;
312
+ }
313
+ for (let i = 0; i < maskArray.length; i++) {
314
+ if (maskArray[i] > 255 || maskArray[i] < 0) {
315
+ return false;
316
+ }
317
+ }
318
+ return true;
319
+ } catch (er) {
320
+ console.error(er);
321
+ }
322
+ }
@@ -40,19 +40,147 @@ export function urlAddHttps(url) {
40
40
  }
41
41
  }
42
42
 
43
+ /**
44
+
45
+ */
46
+ export function createReqInstance() {
47
+ let controllers = new Map()
48
+ function createController(id) {
49
+ if (controllers.has(id)) {
50
+ abortRequest(id); // Ensure previous request is aborted
51
+ }
52
+ const controller = new AbortController();
53
+ controllers.set(id, controller);
54
+ return controller.signal;
55
+ }
56
+
57
+ function abortRequest(id) {
58
+ if (controllers.has(id)) {
59
+ controllers.get(id).abort();
60
+ controllers.delete(id);
61
+ }
62
+ }
63
+
64
+ function abortAll() {
65
+ controllers.forEach(controller => controller.abort());
66
+ controllers.clear();
67
+ }
68
+
69
+ async function reqGet(url, id) {
70
+ try {
71
+ const signal = createController(id);
72
+ const res = await fetch(url, { method: 'GET', signal });
73
+ return res;
74
+ } catch (er) {
75
+ if (er.name === 'AbortError') {
76
+ console.warn('Fetch aborted:', url);
77
+ } else {
78
+ console.error(er);
79
+ }
80
+ }
81
+ }
82
+
83
+ async function reqGetJson(url, id) {
84
+ try {
85
+ const signal = createController(id);
86
+ const res = await fetch(url, { method: 'GET', signal });
87
+ return await res.json();
88
+ } catch (er) {
89
+ if (er.name === 'AbortError') {
90
+ console.warn('Fetch aborted:', url);
91
+ } else {
92
+ console.error(er);
93
+ }
94
+ }
95
+ }
96
+
97
+ async function reqGetText(url, id) {
98
+ try {
99
+ const signal = createController(id);
100
+ const res = await fetch(url, { method: 'GET', signal });
101
+ return await res.text();
102
+ } catch (er) {
103
+ if (er.name === 'AbortError') {
104
+ console.warn('Fetch aborted:', url);
105
+ } else {
106
+ console.error(er);
107
+ }
108
+ }
109
+ }
110
+
111
+ async function reqPostJson(url, dataJson, id) {
112
+ try {
113
+ const signal = createController(id);
114
+ if (!dataJson || typeof dataJson !== 'object') {
115
+ throw new Error(`Invalid JSON data`);
116
+ }
117
+ const res = await fetch(url, {
118
+ method: 'POST',
119
+ headers: { 'Content-Type': 'application/json' },
120
+ body: JSON.stringify(dataJson),
121
+ signal
122
+ });
123
+ return res;
124
+ } catch (er) {
125
+ if (er.name === 'AbortError') {
126
+ console.warn('Fetch aborted:', url);
127
+ } else {
128
+ console.error(er);
129
+ }
130
+ }
131
+ }
132
+
133
+ async function reqPostForm(url, dataForm, id) {
134
+ try {
135
+ const signal = createController(id);
136
+ if (!(dataForm instanceof FormData)) {
137
+ throw new Error(`Provided data is not FormData`);
138
+ }
139
+ const res = await fetch(url, {
140
+ method: 'POST',
141
+ body: dataForm,
142
+ signal
143
+ });
144
+ return res;
145
+ } catch (er) {
146
+ if (er.name === 'AbortError') {
147
+ console.warn('Fetch aborted:', url);
148
+ } else {
149
+ console.error(er);
150
+ }
151
+ }
152
+ }
153
+
154
+ return {
155
+ createController,
156
+ abortRequest,
157
+ abortAll,
158
+ reqGet,
159
+ reqGetJson,
160
+ reqGetText,
161
+ reqPostJson,
162
+ reqPostForm
163
+ };
164
+ }
165
+
43
166
  /**
44
167
  * Sends GET request to specified URL
45
168
  * @async
46
169
  * @param {string} url
170
+ * @param { }
47
171
  * @returns {Promise<Object>} - Returns response if response is ok, otherwise it throws an Error.
48
172
  * @throws {Error} - Throws Error if an error is detected.
49
173
  */
50
- export async function reqGet(url) {
174
+ export async function reqGet(url, signal = null) {
51
175
  try {
52
- const res = await fetch(url, { method: 'GET' });
176
+ const res = await fetch(url, { method: 'GET', signal });
53
177
  return res;
54
178
  } catch (er) {
55
- console.error(er);
179
+ if (er.name === 'AbortError') {
180
+ console.warn('Fetch aborted:', url);
181
+ } else {
182
+ console.error(er);
183
+ }
56
184
  }
57
185
  }
58
186
 
@@ -63,13 +191,16 @@ export async function reqGet(url) {
63
191
  * @returns {Promise<Object>} - Returns data if response is ok, otherwise it throws an Error.
64
192
  * @throws {Error} - Throws Error if an error is detected.
65
193
  */
66
- export async function reqGetJson(url) {
194
+ export async function reqGetJson(url, signal = null) {
67
195
  try {
68
- const res = await fetch(url, { method: 'GET' });
69
- const data = await res.json();
70
- return data;
196
+ const res = await fetch(url, { method: 'GET', signal });
197
+ return await res.json();
71
198
  } catch (er) {
72
- console.error(er);
199
+ if (er.name === 'AbortError') {
200
+ console.warn('Fetch aborted:', url);
201
+ } else {
202
+ console.error(er);
203
+ }
73
204
  }
74
205
  }
75
206
 
@@ -80,13 +211,16 @@ export async function reqGetJson(url) {
80
211
  * @returns {Promise<Object>} - Returns data if response is ok, otherwise it throws an Error.
81
212
  * @throws {Error} - Throws Error if an error is detected.
82
213
  */
83
- export async function reqGetText(url) {
214
+ export async function reqGetText(url, signal = null) {
84
215
  try {
85
- const res = await fetch(url, { method: 'GET' });
86
- const data = await res.text();
87
- return data;
216
+ const res = await fetch(url, { method: 'GET', signal });
217
+ return await res.text();
88
218
  } catch (er) {
89
- console.error(er);
219
+ if (er.name === 'AbortError') {
220
+ console.warn('Fetch aborted:', url);
221
+ } else {
222
+ console.error(er);
223
+ }
90
224
  }
91
225
  }
92
226
 
@@ -98,24 +232,24 @@ export async function reqGetText(url) {
98
232
  * @returns {Promise<Object>} - Returns response if response is ok, otherwise it throws an Error.
99
233
  * @throws {Error} - Throws Error if an error is detected.
100
234
  */
101
- export async function reqPostJson(url, dataJson) {
235
+ export async function reqPostJson(url, dataJson, signal = null) {
102
236
  try {
103
- if (dataJson === null || dataJson === undefined) {
104
- throw new Error(`No data provided.`);
105
- }
106
- if (!checkIsJson(dataJson)) {
107
- throw new Error(`Provided data is not JSON.`);
237
+ if (!dataJson || typeof dataJson !== 'object') {
238
+ throw new Error(`Invalid JSON data`);
108
239
  }
109
240
  const res = await fetch(url, {
110
241
  method: 'POST',
111
- headers: {
112
- 'Content-Type': 'application/json',
113
- },
114
- body: dataJson
242
+ headers: { 'Content-Type': 'application/json' },
243
+ body: JSON.stringify(dataJson),
244
+ signal
115
245
  });
116
246
  return res;
117
247
  } catch (er) {
118
- console.error(er);
248
+ if (er.name === 'AbortError') {
249
+ console.warn('Fetch aborted:', url);
250
+ } else {
251
+ console.error(er);
252
+ }
119
253
  }
120
254
  }
121
255
 
@@ -126,17 +260,22 @@ export async function reqPostJson(url, dataJson) {
126
260
  * @returns {Promise<Object>} - Returns response if response is ok, otherwise it throws an Error.
127
261
  * @throws {Error} - Throws Error if an error is detected.
128
262
  */
129
- export async function reqPostForm(url, dataForm) {
263
+ export async function reqPostForm(url, dataForm, signal = null) {
130
264
  try {
131
265
  if (!(dataForm instanceof FormData)) {
132
- throw new Error(`The data provided was not form data`);
266
+ throw new Error(`Provided data is not FormData`);
133
267
  }
134
268
  const res = await fetch(url, {
135
269
  method: 'POST',
136
- body: dataForm
270
+ body: dataForm,
271
+ signal
137
272
  });
138
273
  return res;
139
274
  } catch (er) {
140
- console.error(er);
275
+ if (er.name === 'AbortError') {
276
+ console.warn('Fetch aborted:', url);
277
+ } else {
278
+ console.error(er);
279
+ }
141
280
  }
142
281
  }
@@ -85,3 +85,33 @@ export const listHtmlTags = [
85
85
  "audio",
86
86
  "video"
87
87
  ];
88
+
89
+ export const listSubnets = [
90
+ { bits: 8, cidr: '/8', subnetMask: '255.0.0.0', wildcardMask: '0.255.255.255', totalAddresses: 16_777_216, usableHosts: 16_777_214, networks: 1 },
91
+ { bits: 9, cidr: '/9', subnetMask: '255.128.0.0', wildcardMask: '0.127.255.255', totalAddresses: 8_388_608, usableHosts: 8_388_606, networks: 2 },
92
+ { bits: 10, cidr: '/10', subnetMask: '255.192.0.0', wildcardMask: '0.63.255.255', totalAddresses: 4_194_304, usableHosts: 4_194_302, networks: 4 },
93
+ { bits: 11, cidr: '/11', subnetMask: '255.224.0.0', wildcardMask: '0.31.255.255', totalAddresses: 2_097_152, usableHosts: 2_097_150, networks: 8 },
94
+ { bits: 12, cidr: '/12', subnetMask: '255.240.0.0', wildcardMask: '0.15.255.255', totalAddresses: 1_048_576, usableHosts: 1_048_574, networks: 16 },
95
+ { bits: 13, cidr: '/13', subnetMask: '255.248.0.0', wildcardMask: '0.7.255.255', totalAddresses: 524_288, usableHosts: 524_286, networks: 32 },
96
+ { bits: 14, cidr: '/14', subnetMask: '255.252.0.0', wildcardMask: '0.3.255.255', totalAddresses: 262_144, usableHosts: 262_142, networks: 64 },
97
+ { bits: 15, cidr: '/15', subnetMask: '255.254.0.0', wildcardMask: '0.1.255.255', totalAddresses: 131_072, usableHosts: 131_070, networks: 128 },
98
+ { bits: 16, cidr: '/16', subnetMask: '255.255.0.0', wildcardMask: '0.0.255.255', totalAddresses: 65_536, usableHosts: 65_534, networks: 256 },
99
+ { bits: 17, cidr: '/17', subnetMask: '255.255.128.0', wildcardMask: '0.0.127.255', totalAddresses: 32_768, usableHosts: 32_766, networks: 512 },
100
+ { bits: 18, cidr: '/18', subnetMask: '255.255.192.0', wildcardMask: '0.0.63.255', totalAddresses: 16_384, usableHosts: 16_382, networks: 1_024 },
101
+ { bits: 19, cidr: '/19', subnetMask: '255.255.224.0', wildcardMask: '0.0.31.255', totalAddresses: 8_192, usableHosts: 8_190, networks: 2_048 },
102
+ { bits: 20, cidr: '/20', subnetMask: '255.255.240.0', wildcardMask: '0.0.15.255', totalAddresses: 4_096, usableHosts: 4_094, networks: 4_096 },
103
+ { bits: 21, cidr: '/21', subnetMask: '255.255.248.0', wildcardMask: '0.0.7.255', totalAddresses: 2_048, usableHosts: 2_046, networks: 8_192 },
104
+ { bits: 22, cidr: '/22', subnetMask: '255.255.252.0', wildcardMask: '0.0.3.255', totalAddresses: 1_024, usableHosts: 1_022, networks: 16_384 },
105
+ { bits: 23, cidr: '/23', subnetMask: '255.255.254.0', wildcardMask: '0.0.1.255', totalAddresses: 512, usableHosts: 510, networks: 32_768 },
106
+ { bits: 24, cidr: '/24', subnetMask: '255.255.255.0', wildcardMask: '0.0.0.255', totalAddresses: 256, usableHosts: 254, networks: 65_536 },
107
+ { bits: 25, cidr: '/25', subnetMask: '255.255.255.128', wildcardMask: '0.0.0.127', totalAddresses: 128, usableHosts: 126, networks: 131_072 },
108
+ { bits: 26, cidr: '/26', subnetMask: '255.255.255.192', wildcardMask: '0.0.0.63', totalAddresses: 64, usableHosts: 62, networks: 262_144 },
109
+ { bits: 27, cidr: '/27', subnetMask: '255.255.255.224', wildcardMask: '0.0.0.31', totalAddresses: 32, usableHosts: 30, networks: 524_288 },
110
+ { bits: 28, cidr: '/28', subnetMask: '255.255.255.240', wildcardMask: '0.0.0.15', totalAddresses: 16, usableHosts: 14, networks: 1_048_576 },
111
+ { bits: 29, cidr: '/29', subnetMask: '255.255.255.248', wildcardMask: '0.0.0.7', totalAddresses: 8, usableHosts: 6, networks: 2_097_152 },
112
+ { bits: 30, cidr: '/30', subnetMask: '255.255.255.252', wildcardMask: '0.0.0.3', totalAddresses: 4, usableHosts: 2, networks: 4_194_304 },
113
+ { bits: 31, cidr: '/31', subnetMask: '255.255.255.254', wildcardMask: '0.0.0.1', totalAddresses: 2, usableHosts: '2 (P2P)', networks: 8_388_608 },
114
+ { bits: 32, cidr: '/32', subnetMask: '255.255.255.255', wildcardMask: '0.0.0.0', totalAddresses: 1, usableHosts: 0, networks: 16_777_216 }
115
+ ];
116
+
117
+
@@ -1,3 +1,5 @@
1
+ import { checkSubnetMask } from "./util.check.js";
2
+
1
3
  /**
2
4
  * Adds zero in front of numbers less than 10 and returns as a string.
3
5
  * @param {number} num
@@ -83,7 +85,7 @@ export function scrollIntoView() {
83
85
  }, observerOptions);
84
86
  for (let i = 0; i < targets.length; i++) {
85
87
  observer.observe(targets[i])
86
-
88
+
87
89
  }
88
90
  allObservers.push(observer);
89
91
  }
@@ -111,3 +113,40 @@ export function scrollIntoView() {
111
113
  removeAllObservers
112
114
  }
113
115
  }
116
+
117
+ export function convertBitsToMask(bits) {
118
+ try {
119
+ if (bits < 0 || bits > 32) {
120
+ throw new Error("Bits must be between 0 and 32");
121
+ }
122
+ const mask = (0xffffffff << (32 - bits)) >>> 0;
123
+ return [
124
+ (mask >>> 24) & 0xff,
125
+ (mask >>> 16) & 0xff,
126
+ (mask >>> 8) & 0xff,
127
+ mask & 0xff
128
+ ].join('.');
129
+ } catch (er) {
130
+ console.error(er);
131
+ return;
132
+ }
133
+ }
134
+
135
+ export function convertMaskToBits(mask) {
136
+ try {
137
+ if (!checkSubnetMask(mask)) {
138
+ throw new Error("Invalid subnet mask.");
139
+ }
140
+ return maskArray
141
+ .map(num => num.toString(2).padStart(8, '0')) // ['11111111', '11111111', '11111111', '00000000']
142
+ .join('') // '11111111111111111111111100000000'
143
+ .split('') // ['1','1','1',...,'0','0']
144
+ .filter(bit => bit === '1') // Keep only the '1's
145
+ .length; // Count them
146
+ } catch (er) {
147
+ console.error(er);
148
+ return;
149
+ }
150
+ }
151
+
152
+
@@ -20,6 +20,15 @@ export const regExUrl = new RegExp('^(https?:\\/\\/)?' + // protocol
20
20
  '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
21
21
  '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
22
22
  export const regExEmail = /^[\w-\.]+@([\w-]+\.)+[a-zA-Z]{2,}$/;
23
+ export const regExIpv4 = /^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$/;
24
+ export const regExIpv6 = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
25
+ export const regExMacNoSeparator = /^[0-9a-fA-F]{12}$/;
26
+ export const regExMacHyphenPairs = /^[0-9a-fA-F]{2}(-[0-9a-fA-F]{2}){5}$/;
27
+ export const regExMacHyphenQuads = /^[0-9a-fA-F]{4}(-[0-9a-fA-F]{4}){2}$/;
28
+ export const regExMacDotPairs = /^[0-9a-fA-F]{2}(\.[0-9a-fA-F]{2}){5}$/;
29
+ export const regExMacDotQuads = /^[0-9a-fA-F]{4}(\.[0-9a-fA-F]{4}){2}$/;
30
+ export const regExMacColonPairs = /^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}$/;
31
+ export const regExMacColonQuads = /^[0-9a-fA-F]{4}(:[0-9a-fA-F]{4}){2}$/;
23
32
 
24
33
  /**
25
34
  * Removes characters from a string based on a provided regex pattern.