@magic/types 0.1.37 → 0.1.39

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
@@ -140,6 +140,10 @@ isIterable([]) // true
140
140
  isEmail('a@b.c') // true
141
141
  // alias isMail, is.email, is.mail
142
142
 
143
+ isIp('192.168.1.1') // true
144
+ isIp('::1') // true
145
+ // alias ip, is.ip, ipV4, ipV6, isIPv4, isIPv6
146
+
143
147
  isNull(null) // true
144
148
  // alias isNil, is.nil, is.null
145
149
 
@@ -402,6 +406,16 @@ update dependencies
402
406
 
403
407
  - update @magic/test
404
408
 
405
- ##### 0.1.38 - unreleased
409
+ ##### 0.1.38
410
+
411
+ - remove recursive dependencies
412
+ - update dependencies
413
+
414
+ ##### 0.1.39
415
+
416
+ - add isIp and variants to allow ip v4 and v6 checks
417
+ - update dependencies
418
+
419
+ ##### 0.1.40 - unreleased
406
420
 
407
421
  ...
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magic/types",
3
- "version": "0.1.37",
3
+ "version": "0.1.39",
4
4
  "author": "Wizards & Witches",
5
5
  "homepage": "https://github.com/magic/types",
6
6
  "license": "AGPL-3.0",
@@ -8,6 +8,12 @@
8
8
  "main": "src/index.js",
9
9
  "types": "./types/index.d.ts",
10
10
  "type": "module",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./src/index.js",
14
+ "types": "./types/index.d.ts"
15
+ }
16
+ },
11
17
  "scripts": {
12
18
  "start": "t",
13
19
  "build": "tsc && npm run format",
@@ -44,9 +50,9 @@
44
50
  "@magic-modules/no-spy": "0.0.9",
45
51
  "@magic-modules/pre": "0.0.12",
46
52
  "@magic-themes/docs": "0.0.15",
47
- "@magic/core": "0.0.158",
48
- "@magic/format": "0.0.73",
49
- "@magic/test": "0.3.12",
53
+ "@magic/core": "0.0.159",
54
+ "@magic/format": "0.0.75",
55
+ "@magic/test": "0.3.23",
50
56
  "typescript": "6.0.3"
51
57
  },
52
58
  "keywords": [
@@ -61,6 +67,10 @@
61
67
  }
62
68
  ],
63
69
  "dependencies": {
64
- "@types/node": "25.9.2"
70
+ "@types/node": "26.1.0"
71
+ },
72
+ "allowScripts": {
73
+ "@swc/core@1.3.41": true,
74
+ "canvas@3.2.3": true
65
75
  }
66
76
  }
@@ -1,4 +1,4 @@
1
- import is from '../lib.js'
1
+ import { isUndefined } from '../fns.js'
2
2
 
3
3
  import equal from './equal.js'
4
4
 
@@ -19,8 +19,8 @@ import equal from './equal.js'
19
19
  * @returns {boolean | ((c: unknown) => boolean)}
20
20
  */
21
21
  export const different = (a, b) => {
22
- if (is.undefined(b)) {
23
- if (is.undefined(a)) {
22
+ if (isUndefined(b)) {
23
+ if (isUndefined(a)) {
24
24
  return false
25
25
  }
26
26
 
package/src/deep/equal.js CHANGED
@@ -1,6 +1,15 @@
1
1
  // Written by Substack <3
2
2
 
3
- import is from '../lib.js'
3
+ import {
4
+ isArray,
5
+ isBuffer,
6
+ isDate,
7
+ isFunction,
8
+ isNull,
9
+ isObject,
10
+ isObjectNative,
11
+ isUndefined,
12
+ } from '../fns.js'
4
13
 
5
14
  /**
6
15
  * @overload
@@ -25,15 +34,15 @@ export const equal = (a, b, options = {}) => {
25
34
  const { strict = false, arrayOrderStrict = false } = options
26
35
 
27
36
  // curry
28
- if (is.undefined(b)) {
29
- if (is.undefined(a)) {
37
+ if (isUndefined(b)) {
38
+ if (isUndefined(a)) {
30
39
  return true
31
40
  }
32
41
 
33
42
  return c => equal(a, c)
34
43
  }
35
44
 
36
- if (is.null(b)) {
45
+ if (isNull(b)) {
37
46
  return a === b
38
47
  }
39
48
 
@@ -43,11 +52,11 @@ export const equal = (a, b, options = {}) => {
43
52
  }
44
53
 
45
54
  /* functions are handled by their toString value */
46
- if (is.function(a) && is.function(b)) {
55
+ if (isFunction(a) && isFunction(b)) {
47
56
  return a.toString() === b.toString()
48
57
  }
49
58
 
50
- if (!is.object(a) || !is.object(b)) {
59
+ if (!isObject(a) || !isObject(b)) {
51
60
  return a === b
52
61
  }
53
62
 
@@ -62,12 +71,12 @@ export const equal = (a, b, options = {}) => {
62
71
  }
63
72
 
64
73
  // dates
65
- if (is.date(a)) {
74
+ if (isDate(a)) {
66
75
  return a.toString() === b.toString()
67
76
  }
68
77
 
69
78
  // buffers
70
- if (is.buffer(a) && is.buffer(b)) {
79
+ if (isBuffer(a) && isBuffer(b)) {
71
80
  if (a.length !== b.length) {
72
81
  return false
73
82
  }
@@ -81,7 +90,7 @@ export const equal = (a, b, options = {}) => {
81
90
  return true
82
91
  }
83
92
 
84
- if (is.array(a) && is.array(b)) {
93
+ if (isArray(a) && isArray(b)) {
85
94
  if (!strict && !arrayOrderStrict) {
86
95
  a.sort()
87
96
  b.sort()
@@ -91,7 +100,7 @@ export const equal = (a, b, options = {}) => {
91
100
  return allEqual
92
101
  }
93
102
 
94
- if (is.objectNative(a) && is.objectNative(b)) {
103
+ if (isObjectNative(a) && isObjectNative(b)) {
95
104
  const aObj = a
96
105
  const bObj = b
97
106
 
package/src/fns.js CHANGED
@@ -631,3 +631,86 @@ export const isModule = s => Object.prototype.toString.call(s) === '[object Modu
631
631
  export const isCase = (s, c = 'up') => (c === 'up' ? isUpperCase(s) : isLowerCase(s))
632
632
  isCase.upper = isUpperCase
633
633
  isCase.lower = isLowerCase
634
+
635
+ /**
636
+ * Check if a value is a valid IPv4 address
637
+ * @param {unknown} a - value to check
638
+ * @returns {boolean} - true if value is an IPv4 address
639
+ */
640
+ export const isIPv4 = a => {
641
+ if (!isString(a)) return false
642
+ const parts = a.split('.')
643
+ if (parts.length !== 4) return false
644
+ return parts.every(part => {
645
+ const num = Number(part)
646
+ return /^(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$/.test(part) && String(num) === part
647
+ })
648
+ }
649
+
650
+ /**
651
+ * Check if a value is a valid IPv6 address
652
+ * @param {unknown} a - value to check
653
+ * @returns {boolean} - true if value is an IPv6 address
654
+ */
655
+ export const isIPv6 = a => {
656
+ if (!isString(a)) {
657
+ return false
658
+ }
659
+
660
+ const str = a.toLowerCase()
661
+
662
+ // Handle IPv4-mapped IPv6 (::ffff:192.168.1.1)
663
+ if (str.includes('.')) {
664
+ const lastColon = str.lastIndexOf(':')
665
+ const ipv4Part = str.slice(lastColon + 1)
666
+ if (!isIPv4(ipv4Part)) {
667
+ return false
668
+ }
669
+ const beforeIpv4 = str.slice(0, lastColon)
670
+ // Should be ::ffff: or similar, and rest should be empty or valid hex
671
+ const colonCount = beforeIpv4.split(':').length - 1
672
+ return colonCount <= 2 && (beforeIpv4 === '::ffff' || beforeIpv4 === ':' || beforeIpv4 === '')
673
+ }
674
+
675
+ // Handle :: compression
676
+ const doubleColon = str.indexOf('::')
677
+ if (doubleColon !== -1) {
678
+ const parts = str.split('::')
679
+ if (parts.length !== 2) {
680
+ return false
681
+ }
682
+ const leftParts = parts[0] ? parts[0].split(':') : []
683
+ const rightParts = parts[1] ? parts[1].split(':') : []
684
+ const totalGroups = leftParts.length + rightParts.length
685
+ if (totalGroups > 7) {
686
+ return false
687
+ }
688
+ const emptyParts =
689
+ leftParts.filter(p => p === '').length + rightParts.filter(p => p === '').length
690
+ if (emptyParts > 1) {
691
+ return false
692
+ }
693
+ const allValid = [...leftParts, ...rightParts].every(p => p === '' || /^[0-9a-f]{1,4}$/.test(p))
694
+ return allValid
695
+ }
696
+
697
+ // Full form: 8 groups of 1-4 hex digits
698
+ const parts = str.split(':')
699
+ if (parts.length !== 8) {
700
+ return false
701
+ }
702
+ return parts.every(part => /^[0-9a-f]{1,4}$/.test(part))
703
+ }
704
+
705
+ /**
706
+ * Check if a value is a valid IP address (v4 or v6)
707
+ * @param {unknown} a - value to check
708
+ * @returns {boolean} - true if value is an IP address
709
+ */
710
+ export const isIp = a => isIPv4(a) || isIPv6(a)
711
+ isIp.v4 = isIPv4
712
+ isIp.v6 = isIPv6
713
+
714
+ export const ipV4 = isIPv4
715
+
716
+ export const ipV6 = isIPv6
package/src/lib.js CHANGED
@@ -315,6 +315,18 @@ export const is = /** @type {const} */ {
315
315
  isLowerCase: fns.isLowerCase,
316
316
  lowerCase: fns.isLowerCase,
317
317
 
318
+ isIp: fns.isIp,
319
+ ip: fns.isIp,
320
+ isIPv4: fns.isIPv4,
321
+ ipv4: fns.isIPv4,
322
+ v4: fns.isIPv4,
323
+ isIPv6: fns.isIPv6,
324
+ ipv6: fns.isIPv6,
325
+ v6: fns.isIPv6,
326
+
327
+ ipV4: fns.ipV4,
328
+ ipV6: fns.ipV6,
329
+
318
330
  same: fns.isSameType,
319
331
  sameType: fns.isSameType,
320
332
  isSameType: fns.isSameType,
package/types/fns.d.ts CHANGED
@@ -173,3 +173,12 @@ export const isCase: ((s: unknown, c?: 'up' | 'down') => boolean) & {
173
173
  upper: (s: unknown) => boolean
174
174
  lower: (s: unknown) => boolean
175
175
  }
176
+ export function isIPv4(a: unknown): boolean
177
+ export function isIPv6(a: unknown): boolean
178
+ export function isIp(a: unknown): boolean
179
+ export namespace isIp {
180
+ export { isIPv4 as v4 }
181
+ export { isIPv6 as v6 }
182
+ }
183
+ export function ipV4(a: unknown): boolean
184
+ export function ipV6(a: unknown): boolean
package/types/index.d.ts CHANGED
@@ -495,6 +495,24 @@ export const is: {
495
495
  upperCase: (s: unknown) => s is string
496
496
  isLowerCase: (s: unknown) => s is string
497
497
  lowerCase: (s: unknown) => s is string
498
+ isIp: {
499
+ (a: unknown): boolean
500
+ v4: (a: unknown) => boolean
501
+ v6: (a: unknown) => boolean
502
+ }
503
+ ip: {
504
+ (a: unknown): boolean
505
+ v4: (a: unknown) => boolean
506
+ v6: (a: unknown) => boolean
507
+ }
508
+ isIPv4: (a: unknown) => boolean
509
+ ipv4: (a: unknown) => boolean
510
+ v4: (a: unknown) => boolean
511
+ isIPv6: (a: unknown) => boolean
512
+ ipv6: (a: unknown) => boolean
513
+ v6: (a: unknown) => boolean
514
+ ipV4: (a: unknown) => boolean
515
+ ipV6: (a: unknown) => boolean
498
516
  same: (a: unknown, b: unknown) => boolean
499
517
  sameType: (a: unknown, b: unknown) => boolean
500
518
  isSameType: (a: unknown, b: unknown) => boolean
package/types/lib.d.ts CHANGED
@@ -493,6 +493,24 @@ export const is: {
493
493
  upperCase: (s: unknown) => s is string
494
494
  isLowerCase: (s: unknown) => s is string
495
495
  lowerCase: (s: unknown) => s is string
496
+ isIp: {
497
+ (a: unknown): boolean
498
+ v4: (a: unknown) => boolean
499
+ v6: (a: unknown) => boolean
500
+ }
501
+ ip: {
502
+ (a: unknown): boolean
503
+ v4: (a: unknown) => boolean
504
+ v6: (a: unknown) => boolean
505
+ }
506
+ isIPv4: (a: unknown) => boolean
507
+ ipv4: (a: unknown) => boolean
508
+ v4: (a: unknown) => boolean
509
+ isIPv6: (a: unknown) => boolean
510
+ ipv6: (a: unknown) => boolean
511
+ v6: (a: unknown) => boolean
512
+ ipV4: (a: unknown) => boolean
513
+ ipV6: (a: unknown) => boolean
496
514
  same: (a: unknown, b: unknown) => boolean
497
515
  sameType: (a: unknown, b: unknown) => boolean
498
516
  isSameType: (a: unknown, b: unknown) => boolean